]> git.ipfire.org Git - thirdparty/qemu.git/blame - target/mips/translate.c
meson: rename included C source files to .c.inc
[thirdparty/qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c 1/*
ab99e0e4 2 * MIPS emulation for QEMU - main translation routines
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
6af0bf9c
FB
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
8167ee88 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
22 */
23
c684822a 24#include "qemu/osdep.h"
6af0bf9c 25#include "cpu.h"
26aa3d9a 26#include "internal.h"
76cad711 27#include "disas/disas.h"
63c91552 28#include "exec/exec-all.h"
dcb32f1d 29#include "tcg/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"
f1672e6f 35#include "hw/semihosting/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"
0442428a 41#include "qemu/qemu-print.h"
a7e30d84 42
fb7729e2 43#define MIPS_DEBUG_DISAS 0
6af0bf9c 44
7a387fff 45/* MIPS major opcodes */
71375b59 46#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
47
48enum {
49 /* indirect opcode tables */
7a387fff
TS
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 58 /* arithmetic with immediate */
7a387fff
TS
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
324d9e32 63 /* logic with immediate */
7a387fff
TS
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
324d9e32 68 /* arithmetic with immediate */
7a387fff
TS
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
e37e863f 71 /* Jump and branches */
7a387fff
TS
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
b231c103 82 OPC_JALX = (0x1D << 26),
d4ea6acd 83 OPC_DAUI = (0x1D << 26),
e37e863f 84 /* Load and stores */
7a387fff
TS
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
364d4831 91 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
364d4831 106 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
e37e863f 110 /* Floating point load/store */
7a387fff
TS
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
31837be3
YK
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
7a387fff
TS
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
239dfebe
YK
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
e37e863f 148 /* Cache and prefetch */
7a387fff
TS
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
153};
154
155/* PC-relative address computation / loads */
71375b59
AM
156#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
158enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
163
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
170};
171
172/* MIPS special opcodes */
71375b59 173#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 174
e37e863f
FB
175enum {
176 /* Shifts */
7a387fff 177 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 182 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 186 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 194 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 200 /* Multiplication / division */
7a387fff
TS
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 209
e37e863f 210 /* 2 registers arithmetic / logic */
7a387fff
TS
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 225 /* Jumps */
7a387fff
TS
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 228 /* Traps */
7a387fff
TS
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 235 /* HI / LO registers load & stores */
7a387fff
TS
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 240 /* Conditional moves */
7a387fff
TS
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 243
b691d9d2
LA
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246
7a387fff 247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
248
249 /* Special */
a0d700e4 250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
255
7a387fff
TS
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
260};
261
7480515f
AM
262/*
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
265 */
71375b59 266#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
267
268enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
277
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
286
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
292
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
295};
296
e9c71dd1 297/* Multiplication variants of the vr54xx. */
71375b59 298#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
299
300enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
315};
316
7a387fff 317/* REGIMM (rt field) opcodes */
71375b59 318#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
319
320enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
337
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
340};
341
7a387fff 342/* Special2 opcodes */
71375b59 343#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 344
e37e863f 345enum {
7a387fff
TS
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 365 /* Misc */
7a387fff
TS
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 370 /* Special */
7a387fff
TS
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
372};
373
374/* Special3 opcodes */
71375b59 375#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
376
377enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
99029be1 391 OPC_GINV = 0x3D | OPC_SPECIAL3,
161f85e6
AJ
392
393 /* Loongson 2E */
394 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
395 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
396 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
397 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
398 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
399 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
400 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
401 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
402 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
403 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
404 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
405 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
406
407 /* MIPS DSP Load */
408 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
409 /* MIPS DSP Arithmetic */
410 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 411 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 412 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 413 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
414 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
415 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 417 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
418 /* MIPS DSP GPR-Based Shift Sub-class */
419 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 420 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
421 /* MIPS DSP Multiply Sub-class insns */
422 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
423 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
424 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 425 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
426 /* DSP Bit/Manipulation Sub-class */
427 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 428 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 429 /* MIPS DSP Append Sub-class */
26690560 430 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 431 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
432 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
433 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 434 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 435
76964147
JH
436 /* EVA */
437 OPC_LWLE = 0x19 | OPC_SPECIAL3,
438 OPC_LWRE = 0x1A | OPC_SPECIAL3,
439 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
440 OPC_SBE = 0x1C | OPC_SPECIAL3,
441 OPC_SHE = 0x1D | OPC_SPECIAL3,
442 OPC_SCE = 0x1E | OPC_SPECIAL3,
443 OPC_SWE = 0x1F | OPC_SPECIAL3,
444 OPC_SWLE = 0x21 | OPC_SPECIAL3,
445 OPC_SWRE = 0x22 | OPC_SPECIAL3,
446 OPC_PREFE = 0x23 | OPC_SPECIAL3,
447 OPC_LBUE = 0x28 | OPC_SPECIAL3,
448 OPC_LHUE = 0x29 | OPC_SPECIAL3,
449 OPC_LBE = 0x2C | OPC_SPECIAL3,
450 OPC_LHE = 0x2D | OPC_SPECIAL3,
451 OPC_LLE = 0x2E | OPC_SPECIAL3,
452 OPC_LWE = 0x2F | OPC_SPECIAL3,
453
4368b29a 454 /* R6 */
bf7910c6
LA
455 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
456 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
457 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
458 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
459 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
460 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
461};
462
7a387fff 463/* BSHFL opcodes */
71375b59 464#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 465
e37e863f 466enum {
15eacb9b
YK
467 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
468 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
469 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
470 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
471 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
472 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
473 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 474 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
475};
476
7a387fff 477/* DBSHFL opcodes */
71375b59 478#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 479
e37e863f 480enum {
15eacb9b
YK
481 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
482 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
483 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
484 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
485 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
486 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
487 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
488 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
489 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
490 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 491 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
492};
493
e45a93e2
JL
494/* MIPS DSP REGIMM opcodes */
495enum {
496 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 497 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
498};
499
71375b59 500#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
501/* MIPS DSP Load */
502enum {
503 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
504 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
505 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 506 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
507};
508
71375b59 509#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
510enum {
511 /* MIPS DSP Arithmetic Sub-class */
512 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
525 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
527 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
529 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
530 /* MIPS DSP Multiply Sub-class insns */
531 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
536 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
537};
538
539#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 540#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
541enum {
542 /* MIPS DSP Arithmetic Sub-class */
543 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
554 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
555 /* MIPS DSP Multiply Sub-class insns */
556 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
559 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
560};
561
71375b59 562#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
563enum {
564 /* MIPS DSP Arithmetic Sub-class */
565 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
578 /* DSP Bit/Manipulation Sub-class */
579 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
583 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
584};
585
71375b59 586#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
587enum {
588 /* MIPS DSP Arithmetic Sub-class */
589 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
596 /* DSP Compare-Pick Sub-class */
597 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
611 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 612};
a22260ae 613
71375b59 614#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
615enum {
616 /* MIPS DSP GPR-Based Shift Sub-class */
617 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
638 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
639};
461c08df 640
71375b59 641#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
642enum {
643 /* MIPS DSP Multiply Sub-class insns */
644 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
660 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
665 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
666};
667
71375b59 668#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
669enum {
670 /* DSP Bit/Manipulation Sub-class */
671 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
672};
673
71375b59 674#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 675enum {
df6126a7 676 /* MIPS DSP Append Sub-class */
26690560
JL
677 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
678 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
679 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
680};
681
71375b59 682#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
683enum {
684 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
685 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
696 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
698 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
699 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
700 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
701 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
702};
703
71375b59 704#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
705enum {
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
724 /* DSP Bit/Manipulation Sub-class */
725 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 731};
461c08df 732
71375b59 733#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 734enum {
a22260ae
JL
735 /* MIPS DSP Multiply Sub-class insns */
736 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
740 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
741 /* MIPS DSP Arithmetic Sub-class */
742 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
752 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
762 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
763};
461c08df 764
71375b59 765#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 766enum {
26690560
JL
767 /* DSP Compare-Pick Sub-class */
768 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
787 /* MIPS DSP Arithmetic Sub-class */
788 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
796};
461c08df 797
71375b59 798#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 799enum {
df6126a7 800 /* DSP Append Sub-class */
26690560
JL
801 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
803 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
804 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
805};
26690560 806
71375b59 807#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
808enum {
809 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
810 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
811 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
830 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
831};
832
71375b59 833#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
834enum {
835 /* DSP Bit/Manipulation Sub-class */
836 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
837};
1cb6686c 838
71375b59 839#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
840enum {
841 /* MIPS DSP Multiply Sub-class insns */
842 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
868};
a22260ae 869
71375b59 870#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
871enum {
872 /* MIPS DSP GPR-Based Shift Sub-class */
873 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
899};
77c5fa8b 900
7a387fff 901/* Coprocessor 0 (rs field) */
71375b59 902#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 903
6ea83fed 904enum {
7a387fff
TS
905 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
906 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 907 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
908 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
909 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 910 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 911 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
912 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
913 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 914 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
915 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
916 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
917 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
918 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
919 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
920 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
921 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
922 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
923 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
924 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
925 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
926 OPC_C0_A = (0x1A << 21) | OPC_CP0,
927 OPC_C0_B = (0x1B << 21) | OPC_CP0,
928 OPC_C0_C = (0x1C << 21) | OPC_CP0,
929 OPC_C0_D = (0x1D << 21) | OPC_CP0,
930 OPC_C0_E = (0x1E << 21) | OPC_CP0,
931 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 932};
7a387fff
TS
933
934/* MFMC0 opcodes */
71375b59 935#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
936
937enum {
ead9360e
TS
938 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
940 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
941 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
942 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
944 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
945 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
946};
947
948/* Coprocessor 0 (with rs == C0) */
71375b59 949#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
950
951enum {
952 OPC_TLBR = 0x01 | OPC_C0,
953 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
954 OPC_TLBINV = 0x03 | OPC_C0,
955 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
956 OPC_TLBWR = 0x06 | OPC_C0,
957 OPC_TLBP = 0x08 | OPC_C0,
958 OPC_RFE = 0x10 | OPC_C0,
959 OPC_ERET = 0x18 | OPC_C0,
960 OPC_DERET = 0x1F | OPC_C0,
961 OPC_WAIT = 0x20 | OPC_C0,
962};
963
964/* Coprocessor 1 (rs field) */
71375b59 965#define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 966
bf4120ad
NF
967/* Values for the fmt field in FP instructions */
968enum {
969 /* 0 - 15 are reserved */
e459440a
AJ
970 FMT_S = 16, /* single fp */
971 FMT_D = 17, /* double fp */
972 FMT_E = 18, /* extended fp */
973 FMT_Q = 19, /* quad fp */
974 FMT_W = 20, /* 32-bit fixed */
975 FMT_L = 21, /* 64-bit fixed */
976 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
977 /* 23 - 31 are reserved */
978};
979
7a387fff
TS
980enum {
981 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
982 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
983 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 984 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
985 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
986 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
987 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 988 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 989 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
990 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
991 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
992 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
993 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
994 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
995 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
996 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
997 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
998 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
999 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1000 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
1001 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1002 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
1003 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1004 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1005 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1006 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1007 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1008 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1009 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1010 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
1011};
1012
71375b59
AM
1013#define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1014#define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
5a5012ec 1015
7a387fff
TS
1016enum {
1017 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1018 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1019 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1020 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1021};
1022
5a5012ec
TS
1023enum {
1024 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1025 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1026};
1027
1028enum {
1029 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1030 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1031};
7a387fff 1032
71375b59 1033#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
1034
1035enum {
1036 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1037 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1038 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1039 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1040 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1041 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1042 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1043 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1044 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1045 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1046 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1047};
1048
8e2d5831 1049#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1050
1051enum {
71375b59
AM
1052 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1059 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1060
1061 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1068 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1069
1070 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1073 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1074 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1075 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1076 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1077 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1078
1079 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1082 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1086 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1087
1088 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1089 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1093 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1094
1095 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1100 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1101
1102 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1107 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1108
1109 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1114 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1115
1116 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1117 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1118 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1119 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1121 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1122
1123 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1124 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1126 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1128 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1129
1130 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1131 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1133 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1135 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1136
1137 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1138 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1139 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1140 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1141 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1142 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1143};
1144
1145
71375b59 1146#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1147
1148enum {
71375b59
AM
1149 OPC_LWXC1 = 0x00 | OPC_CP3,
1150 OPC_LDXC1 = 0x01 | OPC_CP3,
1151 OPC_LUXC1 = 0x05 | OPC_CP3,
1152 OPC_SWXC1 = 0x08 | OPC_CP3,
1153 OPC_SDXC1 = 0x09 | OPC_CP3,
1154 OPC_SUXC1 = 0x0D | OPC_CP3,
1155 OPC_PREFX = 0x0F | OPC_CP3,
1156 OPC_ALNV_PS = 0x1E | OPC_CP3,
1157 OPC_MADD_S = 0x20 | OPC_CP3,
1158 OPC_MADD_D = 0x21 | OPC_CP3,
1159 OPC_MADD_PS = 0x26 | OPC_CP3,
1160 OPC_MSUB_S = 0x28 | OPC_CP3,
1161 OPC_MSUB_D = 0x29 | OPC_CP3,
1162 OPC_MSUB_PS = 0x2E | OPC_CP3,
1163 OPC_NMADD_S = 0x30 | OPC_CP3,
1164 OPC_NMADD_D = 0x31 | OPC_CP3,
1165 OPC_NMADD_PS = 0x36 | OPC_CP3,
1166 OPC_NMSUB_S = 0x38 | OPC_CP3,
1167 OPC_NMSUB_D = 0x39 | OPC_CP3,
1168 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1169};
1170
239dfebe 1171/* MSA Opcodes */
71375b59 1172#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
239dfebe
YK
1173enum {
1174 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1175 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1176 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1177 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1178 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1179 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1180 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1181 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1182 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1183 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1184 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1185 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1186 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1187 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1188 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1189 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1190 OPC_MSA_ELM = 0x19 | OPC_MSA,
1191 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1192 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1193 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1194 OPC_MSA_VEC = 0x1E | OPC_MSA,
1195
1196 /* MI10 instruction */
71375b59
AM
1197 OPC_LD_B = (0x20) | OPC_MSA,
1198 OPC_LD_H = (0x21) | OPC_MSA,
1199 OPC_LD_W = (0x22) | OPC_MSA,
1200 OPC_LD_D = (0x23) | OPC_MSA,
1201 OPC_ST_B = (0x24) | OPC_MSA,
1202 OPC_ST_H = (0x25) | OPC_MSA,
1203 OPC_ST_W = (0x26) | OPC_MSA,
1204 OPC_ST_D = (0x27) | OPC_MSA,
239dfebe
YK
1205};
1206
1207enum {
1208 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1209 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1210 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1211 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1212 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1213 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1214 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1215 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1216 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1217 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1218 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1219 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1220 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1221
1222 /* I8 instruction */
71375b59
AM
1223 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1224 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1226 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1227 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1229 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1230 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1231 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1232 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
239dfebe
YK
1233
1234 /* VEC/2R/2RF instruction */
71375b59
AM
1235 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1236 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1237 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1238 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1239 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1240 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1241 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
239dfebe
YK
1242
1243 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1244 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1245
1246 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
71375b59
AM
1247 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1248 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1249 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1250 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
239dfebe
YK
1251
1252 /* 2RF instruction df(bit 16) = _w, _d */
1253 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1255 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1256 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1257 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1258 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1259 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1260 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1262 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1263 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1264 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1266 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1268 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1269
1270 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1271 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1272 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1273 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1274 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1275 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1276 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1277 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1278 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1279 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1280 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1281 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1282 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1283 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1284 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1285 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1286 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1287 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1288 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1289 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1290 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1291 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1292 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1293 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1294 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1295 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1296 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1297 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1298 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1299 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1300 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1301 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1302 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1303 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1304 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1305 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1306 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1307 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1308 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1309 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1310 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1311 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1312 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1313 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1314 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1315 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1316 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1317 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1318 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1319 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1320 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1321 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1322 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1323 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1324 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1325 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1326 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1327 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1328 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1329 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1330 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1331 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1332 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1333 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1334
1335 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1336 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1340 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1342 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1345
1346 /* 3RF instruction _df(bit 21) = _w, _d */
1347 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1348 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1349 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1357 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1362 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1363 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1364 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1365 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1366 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1368 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1369 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1371 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1373 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1374 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1375 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1376 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1379 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1382 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1385 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1386 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1387 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1388
1389 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1390 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1391 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1392 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1393 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1394 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1395 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1396 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1397 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1398 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1399 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1401 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1402};
1403
b158d449
AM
1404
1405/*
b158d449 1406 *
84e2c895
AM
1407 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1408 * ============================================
1409 *
1410 *
1411 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
b158d449
AM
1412 * instructions set. It is designed to fit the needs of signal, graphical and
1413 * video processing applications. MXU instruction set is used in Xburst family
1414 * of microprocessors by Ingenic.
1415 *
1416 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1417 * the control register.
1418 *
093ade12 1419 *
84e2c895
AM
1420 * The notation used in MXU assembler mnemonics
1421 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1422 *
1423 * Register operands:
1d0e663c
AM
1424 *
1425 * XRa, XRb, XRc, XRd - MXU registers
1426 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
093ade12 1427 *
84e2c895 1428 * Non-register operands:
093ade12 1429 *
84e2c895
AM
1430 * aptn1 - 1-bit accumulate add/subtract pattern
1431 * aptn2 - 2-bit accumulate add/subtract pattern
1432 * eptn2 - 2-bit execute add/subtract pattern
1433 * optn2 - 2-bit operand pattern
1434 * optn3 - 3-bit operand pattern
1435 * sft4 - 4-bit shift amount
1436 * strd2 - 2-bit stride amount
093ade12
AM
1437 *
1438 * Prefixes:
1439 *
84e2c895
AM
1440 * Level of parallelism: Operand size:
1441 * S - single operation at a time 32 - word
1442 * D - two operations in parallel 16 - half word
1443 * Q - four operations in parallel 8 - byte
093ade12
AM
1444 *
1445 * Operations:
1446 *
1447 * ADD - Add or subtract
1448 * ADDC - Add with carry-in
1449 * ACC - Accumulate
1450 * ASUM - Sum together then accumulate (add or subtract)
1451 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1452 * AVG - Average between 2 operands
1453 * ABD - Absolute difference
1454 * ALN - Align data
1455 * AND - Logical bitwise 'and' operation
1456 * CPS - Copy sign
1457 * EXTR - Extract bits
1458 * I2M - Move from GPR register to MXU register
1459 * LDD - Load data from memory to XRF
1460 * LDI - Load data from memory to XRF (and increase the address base)
1461 * LUI - Load unsigned immediate
1462 * MUL - Multiply
1463 * MULU - Unsigned multiply
1464 * MADD - 64-bit operand add 32x32 product
1465 * MSUB - 64-bit operand subtract 32x32 product
1466 * MAC - Multiply and accumulate (add or subtract)
1467 * MAD - Multiply and add or subtract
1468 * MAX - Maximum between 2 operands
1469 * MIN - Minimum between 2 operands
1470 * M2I - Move from MXU register to GPR register
1471 * MOVZ - Move if zero
1472 * MOVN - Move if non-zero
1473 * NOR - Logical bitwise 'nor' operation
1474 * OR - Logical bitwise 'or' operation
1475 * STD - Store data from XRF to memory
1476 * SDI - Store data from XRF to memory (and increase the address base)
1477 * SLT - Set of less than comparison
1478 * SAD - Sum of absolute differences
1479 * SLL - Logical shift left
1480 * SLR - Logical shift right
1481 * SAR - Arithmetic shift right
1482 * SAT - Saturation
1483 * SFL - Shuffle
1484 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1485 * XOR - Logical bitwise 'exclusive or' operation
1d0e663c 1486 *
84e2c895
AM
1487 * Suffixes:
1488 *
1489 * E - Expand results
1490 * F - Fixed point multiplication
1491 * L - Low part result
1492 * R - Doing rounding
1493 * V - Variable instead of immediate
1494 * W - Combine above L and V
1495 *
1496 *
1497 * The list of MXU instructions grouped by functionality
1498 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1499 *
1d0e663c
AM
1500 * Load/Store instructions Multiplication instructions
1501 * ----------------------- ---------------------------
1502 *
1503 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1504 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
093ade12
AM
1505 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1506 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1d0e663c
AM
1507 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1508 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1509 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1510 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1511 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1512 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1516 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1517 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1518 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1519 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1520 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1521 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1522 * S16SDI XRa, Rb, s10, eptn2
1523 * S8LDD XRa, Rb, s8, eptn3
1524 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1525 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1526 * S8SDI XRa, Rb, s8, eptn3
1527 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1528 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1529 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1530 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1531 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1532 * S32CPS XRa, XRb, XRc
1533 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1534 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1535 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1536 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1537 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1538 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1539 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1540 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1541 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1542 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1543 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1544 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1545 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1546 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1547 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1548 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1549 * Q8SLT XRa, XRb, XRc
1550 * Q8SLTU XRa, XRb, XRc
1551 * Q8MOVZ XRa, XRb, XRc Shift instructions
1552 * Q8MOVN XRa, XRb, XRc ------------------
1553 *
1554 * D32SLL XRa, XRb, XRc, XRd, sft4
1555 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1556 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1557 * D32SARL XRa, XRb, XRc, sft4
1558 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1559 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1560 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1561 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1562 * Q16SLL XRa, XRb, XRc, XRd, sft4
1563 * Q16SLR XRa, XRb, XRc, XRd, sft4
eab0bdb0 1564 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1d0e663c
AM
1565 * ------------------------- Q16SLLV XRa, XRb, Rb
1566 * Q16SLRV XRa, XRb, Rb
1567 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1568 * S32ALN XRa, XRb, XRc, Rb
1569 * S32ALNI XRa, XRb, XRc, s3
1570 * S32LUI XRa, s8, optn3 Move instructions
1571 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1572 * S32EXTRV XRa, XRb, Rs, Rt
1573 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1574 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1575 *
9ef5bff9 1576 *
84e2c895
AM
1577 * The opcode organization of MXU instructions
1578 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1579 *
1580 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1581 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1582 * other bits up to the instruction level is as follows:
1583 *
9ef5bff9
AM
1584 * bits
1585 * 05..00
1586 *
1587 * ┌─ 000000 ─ OPC_MXU_S32MADD
1588 * ├─ 000001 ─ OPC_MXU_S32MADDU
eab0bdb0
AM
1589 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1590 * │
9ef5bff9
AM
1591 * │ 20..18
1592 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1593 * │ ├─ 001 ─ OPC_MXU_S32MIN
1594 * │ ├─ 010 ─ OPC_MXU_D16MAX
1595 * │ ├─ 011 ─ OPC_MXU_D16MIN
1596 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1597 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1598 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1599 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1600 * ├─ 000100 ─ OPC_MXU_S32MSUB
1601 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1602 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1603 * │ ├─ 001 ─ OPC_MXU_D16SLT
1604 * │ ├─ 010 ─ OPC_MXU_D16AVG
1605 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1606 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1607 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1608 * │ └─ 111 ─ OPC_MXU_Q8ADD
1609 * │
1610 * │ 20..18
1611 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1612 * │ ├─ 010 ─ OPC_MXU_D16CPS
1613 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1614 * │ └─ 110 ─ OPC_MXU_Q16SAT
1615 * ├─ 001000 ─ OPC_MXU_D16MUL
1616 * │ 25..24
1617 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1618 * │ └─ 01 ─ OPC_MXU_D16MULE
1619 * ├─ 001010 ─ OPC_MXU_D16MAC
1620 * ├─ 001011 ─ OPC_MXU_D16MACF
1621 * ├─ 001100 ─ OPC_MXU_D16MADL
eab0bdb0 1622 * ├─ 001101 ─ OPC_MXU_S16MAD
9ef5bff9 1623 * ├─ 001110 ─ OPC_MXU_Q16ADD
eab0bdb0
AM
1624 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1625 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1626 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
9ef5bff9
AM
1627 * │
1628 * │ 23
eab0bdb0 1629 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
9ef5bff9
AM
1630 * │ └─ 1 ─ OPC_MXU_S32STDR
1631 * │
1632 * │ 13..10
eab0bdb0 1633 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
9ef5bff9
AM
1634 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1635 * │
1636 * │ 13..10
eab0bdb0 1637 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
9ef5bff9
AM
1638 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1639 * │
1640 * │ 23
eab0bdb0 1641 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
9ef5bff9
AM
1642 * │ └─ 1 ─ OPC_MXU_S32LDIR
1643 * │
1644 * │ 23
eab0bdb0 1645 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
9ef5bff9
AM
1646 * │ └─ 1 ─ OPC_MXU_S32SDIR
1647 * │
1648 * │ 13..10
eab0bdb0 1649 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
9ef5bff9
AM
1650 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1651 * │
1652 * │ 13..10
eab0bdb0 1653 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
9ef5bff9
AM
1654 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1655 * ├─ 011000 ─ OPC_MXU_D32ADD
1656 * │ 23..22
eab0bdb0 1657 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
9ef5bff9
AM
1658 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1659 * │ └─ 10 ─ OPC_MXU_D32ASUM
1660 * ├─ 011010 ─ <not assigned>
1661 * │ 23..22
eab0bdb0 1662 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
9ef5bff9
AM
1663 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1664 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1665 * │
1666 * │ 23..22
eab0bdb0 1667 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
9ef5bff9
AM
1668 * │ ├─ 01 ─ OPC_MXU_D8SUM
1669 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1670 * ├─ 011110 ─ <not assigned>
1671 * ├─ 011111 ─ <not assigned>
eab0bdb0
AM
1672 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1673 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
9ef5bff9 1674 * ├─ 100010 ─ OPC_MXU_S8LDD
eab0bdb0
AM
1675 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1676 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1677 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
9ef5bff9 1678 * │ ├─ 00 ─ OPC_MXU_S32EXTR
eab0bdb0 1679 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
9ef5bff9
AM
1680 * │
1681 * │ 20..18
eab0bdb0 1682 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
9ef5bff9 1683 * │ ├─ 001 ─ OPC_MXU_S32ALN
c233bf07 1684 * │ ├─ 010 ─ OPC_MXU_S32ALNI
b621f018
AM
1685 * │ ├─ 011 ─ OPC_MXU_S32LUI
1686 * │ ├─ 100 ─ OPC_MXU_S32NOR
1687 * │ ├─ 101 ─ OPC_MXU_S32AND
1688 * │ ├─ 110 ─ OPC_MXU_S32OR
1689 * │ └─ 111 ─ OPC_MXU_S32XOR
c233bf07
AM
1690 * │
1691 * │ 7..5
1692 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1693 * │ ├─ 001 ─ OPC_MXU_LXH
1694 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1695 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1696 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1697 * ├─ 101100 ─ OPC_MXU_S16LDI
1698 * ├─ 101101 ─ OPC_MXU_S16SDI
9ef5bff9
AM
1699 * ├─ 101110 ─ OPC_MXU_S32M2I
1700 * ├─ 101111 ─ OPC_MXU_S32I2M
1701 * ├─ 110000 ─ OPC_MXU_D32SLL
eab0bdb0
AM
1702 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1703 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1704 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1705 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1706 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
9ef5bff9 1707 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
c233bf07 1708 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
eab0bdb0 1709 * │
9ef5bff9
AM
1710 * ├─ 110111 ─ OPC_MXU_Q16SAR
1711 * │ 23..22
c233bf07 1712 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
9ef5bff9
AM
1713 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1714 * │
1715 * │ 20..18
c233bf07 1716 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
9ef5bff9
AM
1717 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1718 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1719 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1720 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
84e2c895 1721 * │ └─ 101 ─ OPC_MXU_S32MOVN
9ef5bff9
AM
1722 * │
1723 * │ 23..22
c233bf07 1724 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
9ef5bff9
AM
1725 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1726 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1727 * ├─ 111100 ─ OPC_MXU_Q8MADL
1728 * ├─ 111101 ─ OPC_MXU_S32SFL
1729 * ├─ 111110 ─ OPC_MXU_Q8SAD
eab0bdb0 1730 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
9ef5bff9
AM
1731 *
1732 *
84e2c895 1733 * Compiled after:
b158d449
AM
1734 *
1735 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
84e2c895 1736 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
b158d449
AM
1737 */
1738
8bacd1ff
AM
1739enum {
1740 OPC_MXU_S32MADD = 0x00,
1741 OPC_MXU_S32MADDU = 0x01,
11d56f61 1742 OPC__MXU_MUL = 0x02,
8bacd1ff
AM
1743 OPC_MXU__POOL00 = 0x03,
1744 OPC_MXU_S32MSUB = 0x04,
1745 OPC_MXU_S32MSUBU = 0x05,
1746 OPC_MXU__POOL01 = 0x06,
1747 OPC_MXU__POOL02 = 0x07,
1748 OPC_MXU_D16MUL = 0x08,
1749 OPC_MXU__POOL03 = 0x09,
1750 OPC_MXU_D16MAC = 0x0A,
1751 OPC_MXU_D16MACF = 0x0B,
1752 OPC_MXU_D16MADL = 0x0C,
eab0bdb0 1753 OPC_MXU_S16MAD = 0x0D,
8bacd1ff
AM
1754 OPC_MXU_Q16ADD = 0x0E,
1755 OPC_MXU_D16MACE = 0x0F,
eab0bdb0
AM
1756 OPC_MXU__POOL04 = 0x10,
1757 OPC_MXU__POOL05 = 0x11,
1758 OPC_MXU__POOL06 = 0x12,
1759 OPC_MXU__POOL07 = 0x13,
1760 OPC_MXU__POOL08 = 0x14,
1761 OPC_MXU__POOL09 = 0x15,
1762 OPC_MXU__POOL10 = 0x16,
1763 OPC_MXU__POOL11 = 0x17,
8bacd1ff 1764 OPC_MXU_D32ADD = 0x18,
eab0bdb0 1765 OPC_MXU__POOL12 = 0x19,
8bacd1ff 1766 /* not assigned 0x1A */
eab0bdb0
AM
1767 OPC_MXU__POOL13 = 0x1B,
1768 OPC_MXU__POOL14 = 0x1C,
8bacd1ff
AM
1769 OPC_MXU_Q8ACCE = 0x1D,
1770 /* not assigned 0x1E */
1771 /* not assigned 0x1F */
1772 /* not assigned 0x20 */
1773 /* not assigned 0x21 */
1774 OPC_MXU_S8LDD = 0x22,
1775 OPC_MXU_S8STD = 0x23,
1776 OPC_MXU_S8LDI = 0x24,
1777 OPC_MXU_S8SDI = 0x25,
eab0bdb0
AM
1778 OPC_MXU__POOL15 = 0x26,
1779 OPC_MXU__POOL16 = 0x27,
c233bf07 1780 OPC_MXU__POOL17 = 0x28,
8bacd1ff
AM
1781 /* not assigned 0x29 */
1782 OPC_MXU_S16LDD = 0x2A,
1783 OPC_MXU_S16STD = 0x2B,
1784 OPC_MXU_S16LDI = 0x2C,
1785 OPC_MXU_S16SDI = 0x2D,
1786 OPC_MXU_S32M2I = 0x2E,
1787 OPC_MXU_S32I2M = 0x2F,
1788 OPC_MXU_D32SLL = 0x30,
1789 OPC_MXU_D32SLR = 0x31,
1790 OPC_MXU_D32SARL = 0x32,
1791 OPC_MXU_D32SAR = 0x33,
1792 OPC_MXU_Q16SLL = 0x34,
1793 OPC_MXU_Q16SLR = 0x35,
c233bf07 1794 OPC_MXU__POOL18 = 0x36,
8bacd1ff 1795 OPC_MXU_Q16SAR = 0x37,
c233bf07
AM
1796 OPC_MXU__POOL19 = 0x38,
1797 OPC_MXU__POOL20 = 0x39,
1798 OPC_MXU__POOL21 = 0x3A,
8bacd1ff
AM
1799 OPC_MXU_Q16SCOP = 0x3B,
1800 OPC_MXU_Q8MADL = 0x3C,
1801 OPC_MXU_S32SFL = 0x3D,
1802 OPC_MXU_Q8SAD = 0x3E,
1803 /* not assigned 0x3F */
1804};
1805
1806
1807/*
1808 * MXU pool 00
1809 */
1810enum {
1811 OPC_MXU_S32MAX = 0x00,
1812 OPC_MXU_S32MIN = 0x01,
1813 OPC_MXU_D16MAX = 0x02,
1814 OPC_MXU_D16MIN = 0x03,
1815 OPC_MXU_Q8MAX = 0x04,
1816 OPC_MXU_Q8MIN = 0x05,
1817 OPC_MXU_Q8SLT = 0x06,
1818 OPC_MXU_Q8SLTU = 0x07,
1819};
1820
1821/*
1822 * MXU pool 01
1823 */
1824enum {
1825 OPC_MXU_S32SLT = 0x00,
1826 OPC_MXU_D16SLT = 0x01,
1827 OPC_MXU_D16AVG = 0x02,
1828 OPC_MXU_D16AVGR = 0x03,
1829 OPC_MXU_Q8AVG = 0x04,
1830 OPC_MXU_Q8AVGR = 0x05,
1831 OPC_MXU_Q8ADD = 0x07,
1832};
1833
1834/*
1835 * MXU pool 02
1836 */
1837enum {
1838 OPC_MXU_S32CPS = 0x00,
1839 OPC_MXU_D16CPS = 0x02,
1840 OPC_MXU_Q8ABD = 0x04,
1841 OPC_MXU_Q16SAT = 0x06,
1842};
1843
1844/*
1845 * MXU pool 03
1846 */
1847enum {
1848 OPC_MXU_D16MULF = 0x00,
1849 OPC_MXU_D16MULE = 0x01,
1850};
1851
1852/*
1853 * MXU pool 04
1854 */
8bacd1ff
AM
1855enum {
1856 OPC_MXU_S32LDD = 0x00,
1857 OPC_MXU_S32LDDR = 0x01,
1858};
1859
1860/*
eab0bdb0 1861 * MXU pool 05
8bacd1ff
AM
1862 */
1863enum {
1864 OPC_MXU_S32STD = 0x00,
1865 OPC_MXU_S32STDR = 0x01,
1866};
1867
1868/*
eab0bdb0 1869 * MXU pool 06
8bacd1ff
AM
1870 */
1871enum {
1872 OPC_MXU_S32LDDV = 0x00,
1873 OPC_MXU_S32LDDVR = 0x01,
1874};
1875
1876/*
eab0bdb0 1877 * MXU pool 07
8bacd1ff
AM
1878 */
1879enum {
1880 OPC_MXU_S32STDV = 0x00,
1881 OPC_MXU_S32STDVR = 0x01,
1882};
1883
1884/*
eab0bdb0 1885 * MXU pool 08
8bacd1ff
AM
1886 */
1887enum {
1888 OPC_MXU_S32LDI = 0x00,
1889 OPC_MXU_S32LDIR = 0x01,
1890};
1891
1892/*
eab0bdb0 1893 * MXU pool 09
8bacd1ff
AM
1894 */
1895enum {
1896 OPC_MXU_S32SDI = 0x00,
1897 OPC_MXU_S32SDIR = 0x01,
1898};
1899
1900/*
eab0bdb0 1901 * MXU pool 10
8bacd1ff
AM
1902 */
1903enum {
1904 OPC_MXU_S32LDIV = 0x00,
1905 OPC_MXU_S32LDIVR = 0x01,
1906};
1907
1908/*
eab0bdb0 1909 * MXU pool 11
8bacd1ff
AM
1910 */
1911enum {
1912 OPC_MXU_S32SDIV = 0x00,
1913 OPC_MXU_S32SDIVR = 0x01,
1914};
1915
1916/*
eab0bdb0 1917 * MXU pool 12
8bacd1ff
AM
1918 */
1919enum {
1920 OPC_MXU_D32ACC = 0x00,
1921 OPC_MXU_D32ACCM = 0x01,
1922 OPC_MXU_D32ASUM = 0x02,
1923};
1924
1925/*
eab0bdb0 1926 * MXU pool 13
8bacd1ff
AM
1927 */
1928enum {
1929 OPC_MXU_Q16ACC = 0x00,
1930 OPC_MXU_Q16ACCM = 0x01,
1931 OPC_MXU_Q16ASUM = 0x02,
1932};
1933
1934/*
eab0bdb0 1935 * MXU pool 14
8bacd1ff
AM
1936 */
1937enum {
1938 OPC_MXU_Q8ADDE = 0x00,
1939 OPC_MXU_D8SUM = 0x01,
1940 OPC_MXU_D8SUMC = 0x02,
1941};
1942
1943/*
eab0bdb0 1944 * MXU pool 15
8bacd1ff
AM
1945 */
1946enum {
1947 OPC_MXU_S32MUL = 0x00,
1948 OPC_MXU_S32MULU = 0x01,
1949 OPC_MXU_S32EXTR = 0x02,
1950 OPC_MXU_S32EXTRV = 0x03,
1951};
1952
1953/*
eab0bdb0 1954 * MXU pool 16
8bacd1ff
AM
1955 */
1956enum {
1957 OPC_MXU_D32SARW = 0x00,
1958 OPC_MXU_S32ALN = 0x01,
1959 OPC_MXU_S32ALNI = 0x02,
b621f018
AM
1960 OPC_MXU_S32LUI = 0x03,
1961 OPC_MXU_S32NOR = 0x04,
1962 OPC_MXU_S32AND = 0x05,
1963 OPC_MXU_S32OR = 0x06,
1964 OPC_MXU_S32XOR = 0x07,
8bacd1ff
AM
1965};
1966
1967/*
eab0bdb0 1968 * MXU pool 17
8bacd1ff 1969 */
c233bf07
AM
1970enum {
1971 OPC_MXU_LXB = 0x00,
1972 OPC_MXU_LXH = 0x01,
1973 OPC_MXU_LXW = 0x03,
1974 OPC_MXU_LXBU = 0x04,
1975 OPC_MXU_LXHU = 0x05,
1976};
1977
1978/*
1979 * MXU pool 18
1980 */
8bacd1ff
AM
1981enum {
1982 OPC_MXU_D32SLLV = 0x00,
1983 OPC_MXU_D32SLRV = 0x01,
1984 OPC_MXU_D32SARV = 0x03,
1985 OPC_MXU_Q16SLLV = 0x04,
1986 OPC_MXU_Q16SLRV = 0x05,
1987 OPC_MXU_Q16SARV = 0x07,
1988};
1989
1990/*
c233bf07 1991 * MXU pool 19
8bacd1ff
AM
1992 */
1993enum {
1994 OPC_MXU_Q8MUL = 0x00,
1995 OPC_MXU_Q8MULSU = 0x01,
1996};
1997
1998/*
c233bf07 1999 * MXU pool 20
8bacd1ff
AM
2000 */
2001enum {
2002 OPC_MXU_Q8MOVZ = 0x00,
2003 OPC_MXU_Q8MOVN = 0x01,
2004 OPC_MXU_D16MOVZ = 0x02,
2005 OPC_MXU_D16MOVN = 0x03,
2006 OPC_MXU_S32MOVZ = 0x04,
2007 OPC_MXU_S32MOVN = 0x05,
2008};
2009
2010/*
c233bf07 2011 * MXU pool 21
8bacd1ff
AM
2012 */
2013enum {
2014 OPC_MXU_Q8MAC = 0x00,
2015 OPC_MXU_Q8MACSU = 0x01,
2016};
2017
497f072b
FN
2018/*
2019 * Overview of the TX79-specific instruction set
2020 * =============================================
2021 *
2022 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2023 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2024 * instructions and certain multimedia instructions (MMIs). These MMIs
2025 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2026 * or sixteen 8-bit paths.
2027 *
2028 * Reference:
2029 *
2030 * The Toshiba TX System RISC TX79 Core Architecture manual,
2031 * https://wiki.qemu.org/File:C790.pdf
2032 *
2033 * Three-Operand Multiply and Multiply-Add (4 instructions)
2034 * --------------------------------------------------------
2035 * MADD [rd,] rs, rt Multiply/Add
2036 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2037 * MULT [rd,] rs, rt Multiply (3-operand)
2038 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2039 *
2040 * Multiply Instructions for Pipeline 1 (10 instructions)
2041 * ------------------------------------------------------
2042 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2043 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2044 * DIV1 rs, rt Divide Pipeline 1
2045 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2046 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2047 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2048 * MFHI1 rd Move From HI1 Register
2049 * MFLO1 rd Move From LO1 Register
2050 * MTHI1 rs Move To HI1 Register
2051 * MTLO1 rs Move To LO1 Register
2052 *
2053 * Arithmetic (19 instructions)
2054 * ----------------------------
2055 * PADDB rd, rs, rt Parallel Add Byte
2056 * PSUBB rd, rs, rt Parallel Subtract Byte
2057 * PADDH rd, rs, rt Parallel Add Halfword
2058 * PSUBH rd, rs, rt Parallel Subtract Halfword
2059 * PADDW rd, rs, rt Parallel Add Word
2060 * PSUBW rd, rs, rt Parallel Subtract Word
2061 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2062 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2063 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2064 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2065 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2066 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2067 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2068 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2069 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2070 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2071 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2072 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2073 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2074 *
2075 * Min/Max (4 instructions)
2076 * ------------------------
2077 * PMAXH rd, rs, rt Parallel Maximum Halfword
2078 * PMINH rd, rs, rt Parallel Minimum Halfword
2079 * PMAXW rd, rs, rt Parallel Maximum Word
2080 * PMINW rd, rs, rt Parallel Minimum Word
2081 *
2082 * Absolute (2 instructions)
2083 * -------------------------
2084 * PABSH rd, rt Parallel Absolute Halfword
2085 * PABSW rd, rt Parallel Absolute Word
2086 *
2087 * Logical (4 instructions)
2088 * ------------------------
2089 * PAND rd, rs, rt Parallel AND
2090 * POR rd, rs, rt Parallel OR
2091 * PXOR rd, rs, rt Parallel XOR
2092 * PNOR rd, rs, rt Parallel NOR
2093 *
2094 * Shift (9 instructions)
2095 * ----------------------
2096 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2097 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2098 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2099 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2100 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2101 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2102 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2103 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2104 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2105 *
2106 * Compare (6 instructions)
2107 * ------------------------
2108 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2109 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2110 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2111 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2112 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2113 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2114 *
2115 * LZC (1 instruction)
2116 * -------------------
2117 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2118 *
2119 * Quadword Load and Store (2 instructions)
2120 * ----------------------------------------
2121 * LQ rt, offset(base) Load Quadword
2122 * SQ rt, offset(base) Store Quadword
2123 *
2124 * Multiply and Divide (19 instructions)
2125 * -------------------------------------
2126 * PMULTW rd, rs, rt Parallel Multiply Word
2127 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2128 * PDIVW rs, rt Parallel Divide Word
2129 * PDIVUW rs, rt Parallel Divide Unsigned Word
2130 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2131 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2132 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2133 * PMULTH rd, rs, rt Parallel Multiply Halfword
2134 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2135 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2136 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2137 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2138 * PDIVBW rs, rt Parallel Divide Broadcast Word
2139 * PMFHI rd Parallel Move From HI Register
2140 * PMFLO rd Parallel Move From LO Register
2141 * PMTHI rs Parallel Move To HI Register
2142 * PMTLO rs Parallel Move To LO Register
2143 * PMFHL rd Parallel Move From HI/LO Register
2144 * PMTHL rs Parallel Move To HI/LO Register
2145 *
2146 * Pack/Extend (11 instructions)
2147 * -----------------------------
2148 * PPAC5 rd, rt Parallel Pack to 5 bits
2149 * PPACB rd, rs, rt Parallel Pack to Byte
2150 * PPACH rd, rs, rt Parallel Pack to Halfword
2151 * PPACW rd, rs, rt Parallel Pack to Word
2152 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2153 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2154 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2155 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2156 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2157 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2158 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2159 *
2160 * Others (16 instructions)
2161 * ------------------------
2162 * PCPYH rd, rt Parallel Copy Halfword
2163 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2164 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2165 * PREVH rd, rt Parallel Reverse Halfword
2166 * PINTH rd, rs, rt Parallel Interleave Halfword
2167 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2168 * PEXEH rd, rt Parallel Exchange Even Halfword
2169 * PEXCH rd, rt Parallel Exchange Center Halfword
2170 * PEXEW rd, rt Parallel Exchange Even Word
2171 * PEXCW rd, rt Parallel Exchange Center Word
2172 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2173 * MFSA rd Move from Shift Amount Register
2174 * MTSA rs Move to Shift Amount Register
2175 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2176 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2177 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d 2178 *
baa609db
AM
2179 * MMI (MultiMedia Instruction) encodings
2180 * ======================================
f99c0d6d 2181 *
baa609db 2182 * MMI instructions encoding table keys:
f99c0d6d
FN
2183 *
2184 * * This code is reserved for future use. An attempt to execute it
2185 * causes a Reserved Instruction exception.
2186 * % This code indicates an instruction class. The instruction word
2187 * must be further decoded by examining additional tables that show
2188 * the values for other instruction fields.
2189 * # This code is reserved for the unsupported instructions DMULT,
2190 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2191 * to execute it causes a Reserved Instruction exception.
2192 *
baa609db 2193 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
2194 *
2195 * 31 26 0
2196 * +--------+----------------------------------------+
2197 * | opcode | |
2198 * +--------+----------------------------------------+
2199 *
2200 * opcode bits 28..26
2201 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2202 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2203 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2204 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2205 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2206 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2207 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2208 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2209 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2210 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2211 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2212 */
b158d449 2213
f99c0d6d 2214enum {
baa609db
AM
2215 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2216 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2217 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
2218};
2219
d3297211 2220/*
baa609db 2221 * MMI instructions with opcode field = MMI:
d3297211
FN
2222 *
2223 * 31 26 5 0
2224 * +--------+-------------------------------+--------+
2225 * | MMI | |function|
2226 * +--------+-------------------------------+--------+
2227 *
2228 * function bits 2..0
2229 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2230 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2231 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2232 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2233 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2234 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2235 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2236 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2237 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2238 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2239 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2240 */
2241
c8341e00 2242#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 2243enum {
baa609db
AM
2244 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2245 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2246 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2249 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2250 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2251 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2252 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2253 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2254 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2255 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2256 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2257 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2268 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
d3297211
FN
2269};
2270
3ef65697 2271/*
baa609db 2272 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
3ef65697
FN
2273 *
2274 * 31 26 10 6 5 0
2275 * +--------+----------------------+--------+--------+
2276 * | MMI | |function| MMI0 |
2277 * +--------+----------------------+--------+--------+
2278 *
2279 * function bits 7..6
2280 * bits | 0 | 1 | 2 | 3
2281 * 10..8 | 00 | 01 | 10 | 11
2282 * -------+-------+-------+-------+-------
2283 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2284 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2285 * 2 010 | PADDB | PSUBB | PCGTB | *
2286 * 3 011 | * | * | * | *
2287 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2288 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2289 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2290 * 7 111 | * | * | PEXT5 | PPAC5
2291 */
2292
c8341e00 2293#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
3ef65697 2294enum {
baa609db
AM
2295 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2319 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
3ef65697
FN
2320};
2321
77596541 2322/*
baa609db 2323 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
77596541
FN
2324 *
2325 * 31 26 10 6 5 0
2326 * +--------+----------------------+--------+--------+
2327 * | MMI | |function| MMI1 |
2328 * +--------+----------------------+--------+--------+
2329 *
2330 * function bits 7..6
2331 * bits | 0 | 1 | 2 | 3
2332 * 10..8 | 00 | 01 | 10 | 11
2333 * -------+-------+-------+-------+-------
2334 * 0 000 | * | PABSW | PCEQW | PMINW
2335 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2336 * 2 010 | * | * | PCEQB | *
2337 * 3 011 | * | * | * | *
2338 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2339 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2340 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2341 * 7 111 | * | * | * | *
2342 */
2343
c8341e00 2344#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
77596541 2345enum {
baa609db
AM
2346 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2363 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
77596541
FN
2364};
2365
6c03ef6a 2366/*
baa609db 2367 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
6c03ef6a
FN
2368 *
2369 * 31 26 10 6 5 0
2370 * +--------+----------------------+--------+--------+
2371 * | MMI | |function| MMI2 |
2372 * +--------+----------------------+--------+--------+
2373 *
2374 * function bits 7..6
2375 * bits | 0 | 1 | 2 | 3
2376 * 10..8 | 00 | 01 | 10 | 11
2377 * -------+-------+-------+-------+-------
2378 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2379 * 1 001 | PMSUBW| * | * | *
2380 * 2 010 | PMFHI | PMFLO | PINTH | *
2381 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2382 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2383 * 5 101 | PMSUBH| PHMSBH| * | *
2384 * 6 110 | * | * | PEXEH | PREVH
2385 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2386 */
2387
c8341e00 2388#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
6c03ef6a 2389enum {
baa609db
AM
2390 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2411 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
6c03ef6a
FN
2412};
2413
dd581bf9 2414/*
baa609db 2415 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
dd581bf9
FN
2416 *
2417 * 31 26 10 6 5 0
2418 * +--------+----------------------+--------+--------+
2419 * | MMI | |function| MMI3 |
2420 * +--------+----------------------+--------+--------+
2421 *
2422 * function bits 7..6
2423 * bits | 0 | 1 | 2 | 3
2424 * 10..8 | 00 | 01 | 10 | 11
2425 * -------+-------+-------+-------+-------
2426 * 0 000 |PMADDUW| * | * | PSRAVW
2427 * 1 001 | * | * | * | *
2428 * 2 010 | PMTHI | PMTLO | PINTEH| *
2429 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2430 * 4 100 | * | * | POR | PNOR
2431 * 5 101 | * | * | * | *
2432 * 6 110 | * | * | PEXCH | PCPYH
2433 * 7 111 | * | * | PEXCW | *
2434 */
2435
c8341e00 2436#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
dd581bf9 2437enum {
baa609db
AM
2438 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2450 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
dd581bf9
FN
2451};
2452
39454628 2453/* global register indices */
a7812ae4 2454static TCGv cpu_gpr[32], cpu_PC;
340fff72 2455static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607 2456static TCGv cpu_dspctrl, btarget, bcond;
33a07fa2 2457static TCGv cpu_lladdr, cpu_llval;
41db4607 2458static TCGv_i32 hflags;
a7812ae4 2459static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2460static TCGv_i64 fpu_f64[32];
863f264d 2461static TCGv_i64 msa_wr_d[64];
aa0bf00b 2462
a168a796
FN
2463#if defined(TARGET_MIPS64)
2464/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2465static TCGv_i64 cpu_mmr[32];
2466#endif
2467
b621f018 2468#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2469/* MXU registers */
2470static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2471static TCGv mxu_CR;
b621f018 2472#endif
eb5559f6 2473
022c62cb 2474#include "exec/gen-icount.h"
2e70f6ef 2475
895c2d04 2476#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2477 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2478 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 2479 tcg_temp_free_i32(helper_tmp); \
71375b59 2480 } while (0)
be24bb4f 2481
895c2d04 2482#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2483 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2484 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 2485 tcg_temp_free_i32(helper_tmp); \
71375b59 2486 } while (0)
be24bb4f 2487
895c2d04
BS
2488#define gen_helper_1e0i(name, ret, arg1) do { \
2489 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2490 gen_helper_##name(ret, cpu_env, helper_tmp); \
2491 tcg_temp_free_i32(helper_tmp); \
71375b59 2492 } while (0)
895c2d04
BS
2493
2494#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2495 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2496 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2497 tcg_temp_free_i32(helper_tmp); \
71375b59 2498 } while (0)
895c2d04
BS
2499
2500#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2501 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2502 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2503 tcg_temp_free_i32(helper_tmp); \
71375b59 2504 } while (0)
895c2d04
BS
2505
2506#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2507 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2508 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 2509 tcg_temp_free_i32(helper_tmp); \
71375b59 2510 } while (0)
be24bb4f 2511
895c2d04 2512#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2513 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2514 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 2515 tcg_temp_free_i32(helper_tmp); \
71375b59 2516 } while (0)
c239529e 2517
8e9ade68 2518typedef struct DisasContext {
eeb3bba8
EC
2519 DisasContextBase base;
2520 target_ulong saved_pc;
18f440ed 2521 target_ulong page_start;
8e9ade68 2522 uint32_t opcode;
f9c9cd63 2523 uint64_t insn_flags;
5ab5c041 2524 int32_t CP0_Config1;
49735f76 2525 int32_t CP0_Config2;
ab77fc61
DN
2526 int32_t CP0_Config3;
2527 int32_t CP0_Config5;
8e9ade68
TS
2528 /* Routine used to access memory */
2529 int mem_idx;
14776ab5 2530 MemOp default_tcg_memop_mask;
8e9ade68 2531 uint32_t hflags, saved_hflags;
8e9ade68 2532 target_ulong btarget;
d279279e 2533 bool ulri;
e98c0d17 2534 int kscrexist;
7207c7f9 2535 bool rxi;
9456c2fb 2536 int ie;
aea14095
LA
2537 bool bi;
2538 bool bp;
5204ea79
LA
2539 uint64_t PAMask;
2540 bool mvh;
76964147 2541 bool eva;
cec56a73 2542 bool sc;
5204ea79 2543 int CP0_LLAddr_shift;
e29c9628 2544 bool ps;
01bc435b 2545 bool vp;
c870e3f5 2546 bool cmgcr;
f6d4dd81 2547 bool mrp;
87552089 2548 bool nan2008;
6be77480 2549 bool abs2008;
5fb2dcd1 2550 bool saar;
feafe82c 2551 bool mi;
99029be1 2552 int gi;
8e9ade68
TS
2553} DisasContext;
2554
b28425ba
EC
2555#define DISAS_STOP DISAS_TARGET_0
2556#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2557
d73ee8a2
RH
2558static const char * const regnames[] = {
2559 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2560 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2561 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2562 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2563};
6af0bf9c 2564
d73ee8a2
RH
2565static const char * const regnames_HI[] = {
2566 "HI0", "HI1", "HI2", "HI3",
2567};
4b2eb8d2 2568
d73ee8a2
RH
2569static const char * const regnames_LO[] = {
2570 "LO0", "LO1", "LO2", "LO3",
2571};
4b2eb8d2 2572
d73ee8a2
RH
2573static const char * const fregnames[] = {
2574 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2575 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2576 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2577 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2578};
958fb4a9 2579
863f264d
YK
2580static const char * const msaregnames[] = {
2581 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2582 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2583 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2584 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2585 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2586 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2587 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2588 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2589 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2590 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2591 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2592 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2593 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2594 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2595 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2596 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2597};
2598
b621f018 2599#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2600static const char * const mxuregnames[] = {
2601 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2602 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2603};
b621f018 2604#endif
eb5559f6 2605
9d68ac14 2606#define LOG_DISAS(...) \
fb7729e2
RH
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2610 } \
2611 } while (0)
2612
9d68ac14 2613#define MIPS_INVAL(op) \
fb7729e2
RH
2614 do { \
2615 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2616 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2617 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2618 ctx->base.pc_next, ctx->opcode, op, \
2619 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2620 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2621 } \
2622 } while (0)
958fb4a9 2623
8e9ade68 2624/* General purpose registers moves. */
235785e8 2625static inline void gen_load_gpr(TCGv t, int reg)
aaa9128a 2626{
1f8929d2 2627 if (reg == 0) {
8e9ade68 2628 tcg_gen_movi_tl(t, 0);
1f8929d2 2629 } else {
4b2eb8d2 2630 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 2631 }
aaa9128a
TS
2632}
2633
235785e8 2634static inline void gen_store_gpr(TCGv t, int reg)
aaa9128a 2635{
1f8929d2 2636 if (reg != 0) {
4b2eb8d2 2637 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 2638 }
aaa9128a
TS
2639}
2640
8e9ade68 2641/* Moves to/from shadow registers. */
235785e8 2642static inline void gen_load_srsgpr(int from, int to)
aaa9128a 2643{
d9bea114 2644 TCGv t0 = tcg_temp_new();
be24bb4f 2645
1f8929d2 2646 if (from == 0) {
d9bea114 2647 tcg_gen_movi_tl(t0, 0);
1f8929d2 2648 } else {
d9bea114 2649 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2650 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2651
7db13fae 2652 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2653 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2654 tcg_gen_andi_i32(t2, t2, 0xf);
2655 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2656 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2657 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2658
d9bea114 2659 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2660 tcg_temp_free_ptr(addr);
d9bea114 2661 tcg_temp_free_i32(t2);
8e9ade68 2662 }
d9bea114
AJ
2663 gen_store_gpr(t0, to);
2664 tcg_temp_free(t0);
aaa9128a
TS
2665}
2666
71375b59 2667static inline void gen_store_srsgpr(int from, int to)
aaa9128a 2668{
be24bb4f 2669 if (to != 0) {
d9bea114
AJ
2670 TCGv t0 = tcg_temp_new();
2671 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2672 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2673
d9bea114 2674 gen_load_gpr(t0, from);
7db13fae 2675 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2676 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2677 tcg_gen_andi_i32(t2, t2, 0xf);
2678 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2679 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2680 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2681
d9bea114 2682 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2683 tcg_temp_free_ptr(addr);
d9bea114
AJ
2684 tcg_temp_free_i32(t2);
2685 tcg_temp_free(t0);
8e9ade68 2686 }
aaa9128a
TS
2687}
2688
b621f018 2689#if !defined(TARGET_MIPS64)
96992d1a
CJ
2690/* MXU General purpose registers moves. */
2691static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2692{
2693 if (reg == 0) {
2694 tcg_gen_movi_tl(t, 0);
2695 } else if (reg <= 15) {
2696 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2697 }
2698}
2699
2700static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2701{
2702 if (reg > 0 && reg <= 15) {
2703 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2704 }
2705}
2706
2707/* MXU control register moves. */
2708static inline void gen_load_mxu_cr(TCGv t)
2709{
2710 tcg_gen_mov_tl(t, mxu_CR);
2711}
2712
2713static inline void gen_store_mxu_cr(TCGv t)
2714{
2715 /* TODO: Add handling of RW rules for MXU_CR. */
2716 tcg_gen_mov_tl(mxu_CR, t);
2717}
b621f018 2718#endif
96992d1a
CJ
2719
2720
eab9944c
LA
2721/* Tests */
2722static inline void gen_save_pc(target_ulong pc)
2723{
2724 tcg_gen_movi_tl(cpu_PC, pc);
2725}
2726
2727static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2728{
2729 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2730 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2731 gen_save_pc(ctx->base.pc_next);
2732 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2733 }
2734 if (ctx->hflags != ctx->saved_hflags) {
2735 tcg_gen_movi_i32(hflags, ctx->hflags);
2736 ctx->saved_hflags = ctx->hflags;
2737 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2738 case MIPS_HFLAG_BR:
2739 break;
2740 case MIPS_HFLAG_BC:
2741 case MIPS_HFLAG_BL:
2742 case MIPS_HFLAG_B:
2743 tcg_gen_movi_tl(btarget, ctx->btarget);
2744 break;
2745 }
2746 }
2747}
2748
2749static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2750{
2751 ctx->saved_hflags = ctx->hflags;
2752 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2753 case MIPS_HFLAG_BR:
2754 break;
2755 case MIPS_HFLAG_BC:
2756 case MIPS_HFLAG_BL:
2757 case MIPS_HFLAG_B:
2758 ctx->btarget = env->btarget;
2759 break;
2760 }
2761}
2762
2763static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2764{
2765 TCGv_i32 texcp = tcg_const_i32(excp);
2766 TCGv_i32 terr = tcg_const_i32(err);
2767 save_cpu_state(ctx, 1);
2768 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2769 tcg_temp_free_i32(terr);
2770 tcg_temp_free_i32(texcp);
eeb3bba8 2771 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2772}
2773
2774static inline void generate_exception(DisasContext *ctx, int excp)
2775{
eab9944c
LA
2776 gen_helper_0e0i(raise_exception, excp);
2777}
2778
9c708c7f
PD
2779static inline void generate_exception_end(DisasContext *ctx, int excp)
2780{
2781 generate_exception_err(ctx, excp, 0);
2782}
2783
aaa9128a 2784/* Floating point register moves. */
7c979afd 2785static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2786{
7c979afd
LA
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2789 }
ecc7b3aa 2790 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2791}
2792
7c979afd 2793static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2794{
7c979afd
LA
2795 TCGv_i64 t64;
2796 if (ctx->hflags & MIPS_HFLAG_FRE) {
2797 generate_exception(ctx, EXCP_RI);
2798 }
2799 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2800 tcg_gen_extu_i32_i64(t64, t);
2801 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2802 tcg_temp_free_i64(t64);
6d066274
AJ
2803}
2804
7f6613ce 2805static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2806{
7f6613ce 2807 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2808 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2809 } else {
7c979afd 2810 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2811 }
6d066274
AJ
2812}
2813
7f6613ce 2814static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2815{
7f6613ce
PJ
2816 if (ctx->hflags & MIPS_HFLAG_F64) {
2817 TCGv_i64 t64 = tcg_temp_new_i64();
2818 tcg_gen_extu_i32_i64(t64, t);
2819 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2820 tcg_temp_free_i64(t64);
2821 } else {
7c979afd 2822 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2823 }
aa0bf00b 2824}
6ea83fed 2825
d73ee8a2 2826static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2827{
f364515c 2828 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2829 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2830 } else {
d73ee8a2 2831 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2832 }
2833}
6ea83fed 2834
d73ee8a2 2835static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2836{
f364515c 2837 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2838 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2839 } else {
d73ee8a2
RH
2840 TCGv_i64 t0;
2841 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2842 t0 = tcg_temp_new_i64();
6d066274 2843 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2844 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2845 tcg_temp_free_i64(t0);
aa0bf00b
TS
2846 }
2847}
6ea83fed 2848
235785e8 2849static inline int get_fp_bit(int cc)
a16336e4 2850{
1f8929d2 2851 if (cc) {
d94536f4 2852 return 24 + cc;
1f8929d2 2853 } else {
d94536f4 2854 return 23;
1f8929d2 2855 }
a16336e4
TS
2856}
2857
48d38ca5 2858/* Addresses computation */
235785e8
AM
2859static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2860 TCGv arg1)
4ad40f36 2861{
941694d0 2862 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2863
2864#if defined(TARGET_MIPS64)
01f72885 2865 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2866 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2867 }
2868#endif
4ad40f36
FB
2869}
2870
bf0718c5
SM
2871static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2872 target_long ofs)
2873{
2874 tcg_gen_addi_tl(ret, base, ofs);
2875
2876#if defined(TARGET_MIPS64)
2877 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2878 tcg_gen_ext32s_i64(ret, ret);
2879 }
2880#endif
2881}
2882
31837be3
YK
2883/* Addresses computation (translation time) */
2884static target_long addr_add(DisasContext *ctx, target_long base,
2885 target_long offset)
2886{
2887 target_long sum = base + offset;
2888
2889#if defined(TARGET_MIPS64)
2890 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2891 sum = (int32_t)sum;
2892 }
2893#endif
2894 return sum;
2895}
2896
71f303cd 2897/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2898static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2899{
2900#if defined(TARGET_MIPS64)
71f303cd
RH
2901 tcg_gen_ext32s_i64(ret, arg);
2902#else
2903 tcg_gen_extrl_i64_i32(ret, arg);
2904#endif
2905}
2906
2907/* Sign-extract the high 32-bits to a target_long. */
2908static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2909{
2910#if defined(TARGET_MIPS64)
2911 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2912#else
71f303cd 2913 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2914#endif
2915}
2916
356265ae 2917static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2918{
1f8929d2 2919 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
c2c65dab 2920 generate_exception_err(ctx, EXCP_CpU, 0);
1f8929d2 2921 }
387a8fe5
TS
2922}
2923
356265ae 2924static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2925{
1f8929d2 2926 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 2927 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 2928 }
5e755519
TS
2929}
2930
7480515f
AM
2931/*
2932 * Verify that the processor is running with COP1X instructions enabled.
2933 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2934 * opcode tables.
2935 */
356265ae 2936static inline void check_cop1x(DisasContext *ctx)
b8aa4598 2937{
1f8929d2 2938 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
9c708c7f 2939 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2940 }
b8aa4598
TS
2941}
2942
7480515f
AM
2943/*
2944 * Verify that the processor is running with 64-bit floating-point
2945 * operations enabled.
2946 */
356265ae 2947static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2948{
1f8929d2 2949 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
9c708c7f 2950 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2951 }
5e755519
TS
2952}
2953
2954/*
2955 * Verify if floating point register is valid; an operation is not defined
2956 * if bit 0 of any register specification is set and the FR bit in the
2957 * Status register equals zero, since the register numbers specify an
2958 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2959 * in the Status register equals one, both even and odd register numbers
2960 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2961 *
2962 * Multiple 64 bit wide registers can be checked by calling
2963 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2964 */
356265ae 2965static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2966{
1f8929d2 2967 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
9c708c7f 2968 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2969 }
5e755519
TS
2970}
2971
7480515f
AM
2972/*
2973 * Verify that the processor is running with DSP instructions enabled.
2974 * This is enabled by CP0 Status register MX(24) bit.
853c3240 2975 */
853c3240
JL
2976static inline void check_dsp(DisasContext *ctx)
2977{
2978 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2979 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2980 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2981 } else {
9c708c7f 2982 generate_exception_end(ctx, EXCP_RI);
ad153f15 2983 }
853c3240
JL
2984 }
2985}
2986
908f6be1 2987static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2988{
908f6be1 2989 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2990 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2991 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2992 } else {
9c708c7f 2993 generate_exception_end(ctx, EXCP_RI);
ad153f15 2994 }
853c3240
JL
2995 }
2996}
2997
908f6be1 2998static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2999{
908f6be1 3000 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
3001 if (ctx->insn_flags & ASE_DSP) {
3002 generate_exception_end(ctx, EXCP_DSPDIS);
3003 } else {
3004 generate_exception_end(ctx, EXCP_RI);
3005 }
3006 }
3007}
3008
7480515f
AM
3009/*
3010 * This code generates a "reserved instruction" exception if the
3011 * CPU does not support the instruction set corresponding to flags.
3012 */
f9c9cd63 3013static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 3014{
d75c135e 3015 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 3016 generate_exception_end(ctx, EXCP_RI);
d75c135e 3017 }
3a95e3a7
TS
3018}
3019
7480515f
AM
3020/*
3021 * This code generates a "reserved instruction" exception if the
3022 * CPU has corresponding flag set which indicates that the instruction
3023 * has been removed.
3024 */
f9c9cd63 3025static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3026{
3027 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3028 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3029 }
3030}
3031
96631327
FN
3032/*
3033 * The Linux kernel traps certain reserved instruction exceptions to
3034 * emulate the corresponding instructions. QEMU is the kernel in user
3035 * mode, so those traps are emulated by accepting the instructions.
3036 *
3037 * A reserved instruction exception is generated for flagged CPUs if
3038 * QEMU runs in system mode.
3039 */
3040static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3041{
3042#ifndef CONFIG_USER_ONLY
3043 check_insn_opc_removed(ctx, flags);
3044#endif
3045}
3046
7480515f
AM
3047/*
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support 64-bit paired-single (PS) floating point data type.
3050 */
e29c9628
YK
3051static inline void check_ps(DisasContext *ctx)
3052{
3053 if (unlikely(!ctx->ps)) {
3054 generate_exception(ctx, EXCP_RI);
3055 }
3056 check_cp1_64bitmode(ctx);
3057}
3058
c7986fd6 3059#ifdef TARGET_MIPS64
7480515f
AM
3060/*
3061 * This code generates a "reserved instruction" exception if 64-bit
3062 * instructions are not enabled.
3063 */
356265ae 3064static inline void check_mips_64(DisasContext *ctx)
e189e748 3065{
1f8929d2 3066 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
9c708c7f 3067 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3068 }
e189e748 3069}
c7986fd6 3070#endif
e189e748 3071
5204ea79
LA
3072#ifndef CONFIG_USER_ONLY
3073static inline void check_mvh(DisasContext *ctx)
3074{
3075 if (unlikely(!ctx->mvh)) {
3076 generate_exception(ctx, EXCP_RI);
3077 }
3078}
3079#endif
3080
0b16dcd1
AR
3081/*
3082 * This code generates a "reserved instruction" exception if the
3083 * Config5 XNP bit is set.
3084 */
3085static inline void check_xnp(DisasContext *ctx)
3086{
3087 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3088 generate_exception_end(ctx, EXCP_RI);
3089 }
3090}
3091
5e31fdd5
YK
3092#ifndef CONFIG_USER_ONLY
3093/*
3094 * This code generates a "reserved instruction" exception if the
3095 * Config3 PW bit is NOT set.
3096 */
3097static inline void check_pw(DisasContext *ctx)
3098{
3099 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3100 generate_exception_end(ctx, EXCP_RI);
3101 }
3102}
3103#endif
3104
9affc1c5
AR
3105/*
3106 * This code generates a "reserved instruction" exception if the
3107 * Config3 MT bit is NOT set.
3108 */
3109static inline void check_mt(DisasContext *ctx)
3110{
3111 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3112 generate_exception_end(ctx, EXCP_RI);
3113 }
3114}
3115
3116#ifndef CONFIG_USER_ONLY
3117/*
3118 * This code generates a "coprocessor unusable" exception if CP0 is not
3119 * available, and, if that is not the case, generates a "reserved instruction"
3120 * exception if the Config5 MT bit is NOT set. This is needed for availability
3121 * control of some of MT ASE instructions.
3122 */
3123static inline void check_cp0_mt(DisasContext *ctx)
3124{
3125 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3126 generate_exception_err(ctx, EXCP_CpU, 0);
3127 } else {
3128 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3129 generate_exception_err(ctx, EXCP_RI, 0);
3130 }
3131 }
3132}
3133#endif
3134
fb32f8c8
DN
3135/*
3136 * This code generates a "reserved instruction" exception if the
3137 * Config5 NMS bit is set.
3138 */
3139static inline void check_nms(DisasContext *ctx)
3140{
3141 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3142 generate_exception_end(ctx, EXCP_RI);
3143 }
3144}
3145
d046a9ea
DN
3146/*
3147 * This code generates a "reserved instruction" exception if the
3148 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3149 * Config2 TL, and Config5 L2C are unset.
3150 */
3151static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3152{
1f8929d2
AM
3153 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3154 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3155 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3156 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3157 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3158 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
d046a9ea
DN
3159 generate_exception_end(ctx, EXCP_RI);
3160 }
3161}
3162
3163/*
3164 * This code generates a "reserved instruction" exception if the
3165 * Config5 EVA bit is NOT set.
3166 */
3167static inline void check_eva(DisasContext *ctx)
3168{
3169 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3170 generate_exception_end(ctx, EXCP_RI);
3171 }
3172}
3173
0b16dcd1 3174
7480515f
AM
3175/*
3176 * Define small wrappers for gen_load_fpr* so that we have a uniform
3177 * calling interface for 32 and 64-bit FPRs. No sense in changing
3178 * all callers for gen_load_fpr32 when we need the CTX parameter for
3179 * this one use.
3180 */
7c979afd 3181#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3182#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3183#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3184static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3185 int ft, int fs, int cc) \
3186{ \
71375b59
AM
3187 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3188 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
3189 switch (ifmt) { \
3190 case FMT_PS: \
e29c9628 3191 check_ps(ctx); \
8153667c
NF
3192 break; \
3193 case FMT_D: \
3194 if (abs) { \
3195 check_cop1x(ctx); \
3196 } \
3197 check_cp1_registers(ctx, fs | ft); \
3198 break; \
3199 case FMT_S: \
3200 if (abs) { \
3201 check_cop1x(ctx); \
3202 } \
3203 break; \
3204 } \
71375b59
AM
3205 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3206 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 3207 switch (n) { \
1f8929d2
AM
3208 case 0: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3210 break; \
3211 case 1: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3213 break; \
3214 case 2: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3216 break; \
3217 case 3: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3219 break; \
3220 case 4: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3222 break; \
3223 case 5: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3225 break; \
3226 case 6: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3228 break; \
3229 case 7: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3231 break; \
3232 case 8: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3234 break; \
3235 case 9: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3237 break; \
3238 case 10: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3240 break; \
3241 case 11: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3243 break; \
3244 case 12: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3246 break; \
3247 case 13: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3249 break; \
3250 case 14: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3252 break; \
3253 case 15: \
3254 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3255 break; \
3256 default: \
3257 abort(); \
8153667c 3258 } \
71375b59
AM
3259 tcg_temp_free_i##bits(fp0); \
3260 tcg_temp_free_i##bits(fp1); \
8153667c
NF
3261}
3262
3263FOP_CONDS(, 0, d, FMT_D, 64)
3264FOP_CONDS(abs, 1, d, FMT_D, 64)
3265FOP_CONDS(, 0, s, FMT_S, 32)
3266FOP_CONDS(abs, 1, s, FMT_S, 32)
3267FOP_CONDS(, 0, ps, FMT_PS, 64)
3268FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3269#undef FOP_CONDS
3f493883
YK
3270
3271#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 3272static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
3273 int ft, int fs, int fd) \
3274{ \
3275 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3276 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3277 if (ifmt == FMT_D) { \
3f493883 3278 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3279 } \
3280 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3281 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3282 switch (n) { \
3283 case 0: \
3284 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 1: \
3287 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 2: \
3290 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 3: \
3293 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 4: \
3296 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 5: \
3299 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 6: \
3302 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 7: \
3305 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 8: \
3308 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 9: \
3311 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 10: \
3314 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 11: \
3317 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 12: \
3320 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 13: \
3323 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 14: \
3326 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 15: \
3329 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 17: \
3332 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 18: \
3335 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 19: \
3338 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 25: \
3341 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 26: \
3344 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 case 27: \
3347 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3348 break; \
3349 default: \
3350 abort(); \
3351 } \
3352 STORE; \
71375b59
AM
3353 tcg_temp_free_i ## bits(fp0); \
3354 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
3355}
3356
3357FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3358FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3359#undef FOP_CONDNS
8153667c
NF
3360#undef gen_ldcmp_fpr32
3361#undef gen_ldcmp_fpr64
3362
958fb4a9 3363/* load/store instructions. */
e7139c44 3364#ifdef CONFIG_USER_ONLY
71375b59 3365#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3366static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3367 DisasContext *ctx) \
d9bea114
AJ
3368{ \
3369 TCGv t0 = tcg_temp_new(); \
3370 tcg_gen_mov_tl(t0, arg1); \
3371 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
3372 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3373 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3374 tcg_temp_free(t0); \
aaa9128a 3375}
e7139c44 3376#else
71375b59 3377#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3378static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3379 DisasContext *ctx) \
e7139c44 3380{ \
dd4096cd 3381 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3382}
3383#endif
71375b59 3384OP_LD_ATOMIC(ll, ld32s);
aaa9128a 3385#if defined(TARGET_MIPS64)
71375b59 3386OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
3387#endif
3388#undef OP_LD_ATOMIC
3389
235785e8
AM
3390static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3391 int base, int offset)
662d7485
NF
3392{
3393 if (base == 0) {
3394 tcg_gen_movi_tl(addr, offset);
3395 } else if (offset == 0) {
3396 gen_load_gpr(addr, base);
3397 } else {
3398 tcg_gen_movi_tl(addr, offset);
3399 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3400 }
3401}
3402
235785e8 3403static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 3404{
eeb3bba8 3405 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3406
3407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3408 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3409
3410 pc -= branch_bytes;
3411 }
3412
3413 pc &= ~(target_ulong)3;
3414 return pc;
3415}
3416
5c13fdfd 3417/* Load */
d75c135e 3418static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3419 int rt, int base, int offset)
6af0bf9c 3420{
fc40787a 3421 TCGv t0, t1, t2;
dd4096cd 3422 int mem_idx = ctx->mem_idx;
afa88c3a 3423
8e2d5831
JY
3424 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3425 INSN_LOONGSON3A)) {
7480515f
AM
3426 /*
3427 * Loongson CPU uses a load to zero register for prefetch.
3428 * We emulate it as a NOP. On other CPU we must perform the
3429 * actual memory access.
3430 */
afa88c3a
AJ
3431 return;
3432 }
6af0bf9c 3433
afa88c3a 3434 t0 = tcg_temp_new();
662d7485 3435 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3436
6af0bf9c 3437 switch (opc) {
d26bc211 3438#if defined(TARGET_MIPS64)
6e473128 3439 case OPC_LWU:
dd4096cd 3440 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3441 ctx->default_tcg_memop_mask);
78723684 3442 gen_store_gpr(t0, rt);
6e473128 3443 break;
6af0bf9c 3444 case OPC_LD:
dd4096cd 3445 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3446 ctx->default_tcg_memop_mask);
78723684 3447 gen_store_gpr(t0, rt);
6af0bf9c 3448 break;
7a387fff 3449 case OPC_LLD:
bf7910c6 3450 case R6_OPC_LLD:
dd4096cd 3451 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3452 gen_store_gpr(t0, rt);
7a387fff 3453 break;
6af0bf9c 3454 case OPC_LDL:
3cee3050 3455 t1 = tcg_temp_new();
7480515f
AM
3456 /*
3457 * Do a byte access to possibly trigger a page
3458 * fault with the unaligned address.
3459 */
dd4096cd 3460 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3461 tcg_gen_andi_tl(t1, t0, 7);
3462#ifndef TARGET_WORDS_BIGENDIAN
3463 tcg_gen_xori_tl(t1, t1, 7);
3464#endif
3465 tcg_gen_shli_tl(t1, t1, 3);
3466 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3467 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3468 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3469 t2 = tcg_const_tl(-1);
3470 tcg_gen_shl_tl(t2, t2, t1);
78723684 3471 gen_load_gpr(t1, rt);
eb02cc3f 3472 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3473 tcg_temp_free(t2);
3474 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3475 tcg_temp_free(t1);
fc40787a 3476 gen_store_gpr(t0, rt);
6af0bf9c 3477 break;
6af0bf9c 3478 case OPC_LDR:
3cee3050 3479 t1 = tcg_temp_new();
7480515f
AM
3480 /*
3481 * Do a byte access to possibly trigger a page
3482 * fault with the unaligned address.
3483 */
dd4096cd 3484 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3485 tcg_gen_andi_tl(t1, t0, 7);
3486#ifdef TARGET_WORDS_BIGENDIAN
3487 tcg_gen_xori_tl(t1, t1, 7);
3488#endif
3489 tcg_gen_shli_tl(t1, t1, 3);
3490 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3491 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3492 tcg_gen_shr_tl(t0, t0, t1);
3493 tcg_gen_xori_tl(t1, t1, 63);
3494 t2 = tcg_const_tl(0xfffffffffffffffeull);
3495 tcg_gen_shl_tl(t2, t2, t1);
78723684 3496 gen_load_gpr(t1, rt);
fc40787a
AJ
3497 tcg_gen_and_tl(t1, t1, t2);
3498 tcg_temp_free(t2);
3499 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3500 tcg_temp_free(t1);
fc40787a 3501 gen_store_gpr(t0, rt);
6af0bf9c 3502 break;
364d4831 3503 case OPC_LDPC:
3cee3050 3504 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3505 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3506 tcg_temp_free(t1);
dd4096cd 3507 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3508 gen_store_gpr(t0, rt);
3509 break;
6af0bf9c 3510#endif
364d4831 3511 case OPC_LWPC:
3cee3050 3512 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3513 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3514 tcg_temp_free(t1);
dd4096cd 3515 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3516 gen_store_gpr(t0, rt);
3517 break;
76964147
JH
3518 case OPC_LWE:
3519 mem_idx = MIPS_HFLAG_UM;
3520 /* fall through */
6af0bf9c 3521 case OPC_LW:
dd4096cd 3522 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3523 ctx->default_tcg_memop_mask);
78723684 3524 gen_store_gpr(t0, rt);
6af0bf9c 3525 break;
76964147
JH
3526 case OPC_LHE:
3527 mem_idx = MIPS_HFLAG_UM;
3528 /* fall through */
6af0bf9c 3529 case OPC_LH:
dd4096cd 3530 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3531 ctx->default_tcg_memop_mask);
78723684 3532 gen_store_gpr(t0, rt);
6af0bf9c 3533 break;
76964147
JH
3534 case OPC_LHUE:
3535 mem_idx = MIPS_HFLAG_UM;
3536 /* fall through */
6af0bf9c 3537 case OPC_LHU:
dd4096cd 3538 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3539 ctx->default_tcg_memop_mask);
78723684 3540 gen_store_gpr(t0, rt);
6af0bf9c 3541 break;
76964147
JH
3542 case OPC_LBE:
3543 mem_idx = MIPS_HFLAG_UM;
3544 /* fall through */
6af0bf9c 3545 case OPC_LB:
dd4096cd 3546 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3547 gen_store_gpr(t0, rt);
6af0bf9c 3548 break;
76964147
JH
3549 case OPC_LBUE:
3550 mem_idx = MIPS_HFLAG_UM;
3551 /* fall through */
6af0bf9c 3552 case OPC_LBU:
dd4096cd 3553 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3554 gen_store_gpr(t0, rt);
6af0bf9c 3555 break;
76964147
JH
3556 case OPC_LWLE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
6af0bf9c 3559 case OPC_LWL:
3cee3050 3560 t1 = tcg_temp_new();
7480515f
AM
3561 /*
3562 * Do a byte access to possibly trigger a page
3563 * fault with the unaligned address.
3564 */
dd4096cd 3565 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3566 tcg_gen_andi_tl(t1, t0, 3);
3567#ifndef TARGET_WORDS_BIGENDIAN
3568 tcg_gen_xori_tl(t1, t1, 3);
3569#endif
3570 tcg_gen_shli_tl(t1, t1, 3);
3571 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3572 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3573 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3574 t2 = tcg_const_tl(-1);
3575 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3576 gen_load_gpr(t1, rt);
eb02cc3f 3577 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3578 tcg_temp_free(t2);
3579 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3580 tcg_temp_free(t1);
fc40787a
AJ
3581 tcg_gen_ext32s_tl(t0, t0);
3582 gen_store_gpr(t0, rt);
6af0bf9c 3583 break;
76964147
JH
3584 case OPC_LWRE:
3585 mem_idx = MIPS_HFLAG_UM;
3586 /* fall through */
6af0bf9c 3587 case OPC_LWR:
3cee3050 3588 t1 = tcg_temp_new();
7480515f
AM
3589 /*
3590 * Do a byte access to possibly trigger a page
3591 * fault with the unaligned address.
3592 */
dd4096cd 3593 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3594 tcg_gen_andi_tl(t1, t0, 3);
3595#ifdef TARGET_WORDS_BIGENDIAN
3596 tcg_gen_xori_tl(t1, t1, 3);
3597#endif
3598 tcg_gen_shli_tl(t1, t1, 3);
3599 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3600 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3601 tcg_gen_shr_tl(t0, t0, t1);
3602 tcg_gen_xori_tl(t1, t1, 31);
3603 t2 = tcg_const_tl(0xfffffffeull);
3604 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3605 gen_load_gpr(t1, rt);
fc40787a
AJ
3606 tcg_gen_and_tl(t1, t1, t2);
3607 tcg_temp_free(t2);
3608 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3609 tcg_temp_free(t1);
c728154b 3610 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3611 gen_store_gpr(t0, rt);
6af0bf9c 3612 break;
76964147
JH
3613 case OPC_LLE:
3614 mem_idx = MIPS_HFLAG_UM;
3615 /* fall through */
6af0bf9c 3616 case OPC_LL:
4368b29a 3617 case R6_OPC_LL:
dd4096cd 3618 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3619 gen_store_gpr(t0, rt);
6af0bf9c 3620 break;
d66c7132 3621 }
d66c7132 3622 tcg_temp_free(t0);
d66c7132
AJ
3623}
3624
0b16dcd1
AR
3625static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3626 uint32_t reg1, uint32_t reg2)
3627{
3628 TCGv taddr = tcg_temp_new();
3629 TCGv_i64 tval = tcg_temp_new_i64();
3630 TCGv tmp1 = tcg_temp_new();
3631 TCGv tmp2 = tcg_temp_new();
3632
3633 gen_base_offset_addr(ctx, taddr, base, offset);
3634 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3635#ifdef TARGET_WORDS_BIGENDIAN
3636 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3637#else
3638 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3639#endif
3640 gen_store_gpr(tmp1, reg1);
3641 tcg_temp_free(tmp1);
3642 gen_store_gpr(tmp2, reg2);
3643 tcg_temp_free(tmp2);
3644 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3645 tcg_temp_free_i64(tval);
3646 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3647 tcg_temp_free(taddr);
3648}
3649
5c13fdfd 3650/* Store */
235785e8
AM
3651static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3652 int base, int offset)
5c13fdfd 3653{
5c13fdfd
AJ
3654 TCGv t0 = tcg_temp_new();
3655 TCGv t1 = tcg_temp_new();
dd4096cd 3656 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3657
3658 gen_base_offset_addr(ctx, t0, base, offset);
3659 gen_load_gpr(t1, rt);
3660 switch (opc) {
3661#if defined(TARGET_MIPS64)
3662 case OPC_SD:
dd4096cd 3663 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3664 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3665 break;
3666 case OPC_SDL:
dd4096cd 3667 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3668 break;
3669 case OPC_SDR:
dd4096cd 3670 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3671 break;
3672#endif
76964147
JH
3673 case OPC_SWE:
3674 mem_idx = MIPS_HFLAG_UM;
3675 /* fall through */
5c13fdfd 3676 case OPC_SW:
dd4096cd 3677 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3678 ctx->default_tcg_memop_mask);
5c13fdfd 3679 break;
76964147
JH
3680 case OPC_SHE:
3681 mem_idx = MIPS_HFLAG_UM;
3682 /* fall through */
5c13fdfd 3683 case OPC_SH:
dd4096cd 3684 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3685 ctx->default_tcg_memop_mask);
5c13fdfd 3686 break;
76964147
JH
3687 case OPC_SBE:
3688 mem_idx = MIPS_HFLAG_UM;
3689 /* fall through */
5c13fdfd 3690 case OPC_SB:
dd4096cd 3691 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3692 break;
76964147
JH
3693 case OPC_SWLE:
3694 mem_idx = MIPS_HFLAG_UM;
3695 /* fall through */
5c13fdfd 3696 case OPC_SWL:
dd4096cd 3697 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3698 break;
76964147
JH
3699 case OPC_SWRE:
3700 mem_idx = MIPS_HFLAG_UM;
3701 /* fall through */
5c13fdfd 3702 case OPC_SWR:
dd4096cd 3703 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3704 break;
3705 }
5c13fdfd
AJ
3706 tcg_temp_free(t0);
3707 tcg_temp_free(t1);
3708}
3709
3710
d66c7132 3711/* Store conditional */
33a07fa2 3712static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 3713 MemOp tcg_mo, bool eva)
d66c7132 3714{
33a07fa2
LA
3715 TCGv addr, t0, val;
3716 TCGLabel *l1 = gen_new_label();
3717 TCGLabel *done = gen_new_label();
d66c7132 3718
2d2826b9 3719 t0 = tcg_temp_new();
33a07fa2
LA
3720 addr = tcg_temp_new();
3721 /* compare the address against that of the preceeding LL */
3722 gen_base_offset_addr(ctx, addr, base, offset);
3723 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3724 tcg_temp_free(addr);
3725 tcg_gen_movi_tl(t0, 0);
3726 gen_store_gpr(t0, rt);
3727 tcg_gen_br(done);
3728
3729 gen_set_label(l1);
3730 /* generate cmpxchg */
3731 val = tcg_temp_new();
3732 gen_load_gpr(val, rt);
3733 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3734 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3735 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3736 gen_store_gpr(t0, rt);
3737 tcg_temp_free(val);
3738
3739 gen_set_label(done);
d66c7132 3740 tcg_temp_free(t0);
6af0bf9c
FB
3741}
3742
33a07fa2 3743
0b16dcd1 3744static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 3745 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
3746{
3747 TCGv taddr = tcg_temp_local_new();
3748 TCGv lladdr = tcg_temp_local_new();
3749 TCGv_i64 tval = tcg_temp_new_i64();
3750 TCGv_i64 llval = tcg_temp_new_i64();
3751 TCGv_i64 val = tcg_temp_new_i64();
3752 TCGv tmp1 = tcg_temp_new();
3753 TCGv tmp2 = tcg_temp_new();
3754 TCGLabel *lab_fail = gen_new_label();
3755 TCGLabel *lab_done = gen_new_label();
3756
3757 gen_base_offset_addr(ctx, taddr, base, offset);
3758
3759 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3760 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3761
3762 gen_load_gpr(tmp1, reg1);
3763 gen_load_gpr(tmp2, reg2);
3764
3765#ifdef TARGET_WORDS_BIGENDIAN
3766 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3767#else
3768 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3769#endif
3770
3771 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3772 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 3773 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
3774 if (reg1 != 0) {
3775 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3776 }
3777 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3778
3779 gen_set_label(lab_fail);
3780
3781 if (reg1 != 0) {
3782 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3783 }
3784 gen_set_label(lab_done);
3785 tcg_gen_movi_tl(lladdr, -1);
3786 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3787}
3788
6ea83fed 3789/* Load and store */
235785e8
AM
3790static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3791 TCGv t0)
6ea83fed 3792{
7480515f
AM
3793 /*
3794 * Don't do NOP if destination is zero: we must perform the actual
3795 * memory access.
3796 */
6ea83fed
FB
3797 switch (opc) {
3798 case OPC_LWC1:
b6d96bed 3799 {
a7812ae4 3800 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3801 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3802 ctx->default_tcg_memop_mask);
7c979afd 3803 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3804 tcg_temp_free_i32(fp0);
b6d96bed 3805 }
6ea83fed
FB
3806 break;
3807 case OPC_SWC1:
b6d96bed 3808 {
a7812ae4 3809 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3810 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3811 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3812 ctx->default_tcg_memop_mask);
a7812ae4 3813 tcg_temp_free_i32(fp0);
b6d96bed 3814 }
6ea83fed
FB
3815 break;
3816 case OPC_LDC1:
b6d96bed 3817 {
a7812ae4 3818 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3819 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3820 ctx->default_tcg_memop_mask);
b6d96bed 3821 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3822 tcg_temp_free_i64(fp0);
b6d96bed 3823 }
6ea83fed
FB
3824 break;
3825 case OPC_SDC1:
b6d96bed 3826 {
a7812ae4 3827 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3828 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3829 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3830 ctx->default_tcg_memop_mask);
a7812ae4 3831 tcg_temp_free_i64(fp0);
b6d96bed 3832 }
6ea83fed
FB
3833 break;
3834 default:
9d68ac14 3835 MIPS_INVAL("flt_ldst");
9c708c7f 3836 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3837 break;
6ea83fed 3838 }
6ea83fed 3839}
6ea83fed 3840
5ab5c041
AJ
3841static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3842 int rs, int16_t imm)
26ebe468 3843{
b52d3bfa
YK
3844 TCGv t0 = tcg_temp_new();
3845
5ab5c041 3846 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3847 check_cp1_enabled(ctx);
d9224450
MR
3848 switch (op) {
3849 case OPC_LDC1:
3850 case OPC_SDC1:
3851 check_insn(ctx, ISA_MIPS2);
3852 /* Fallthrough */
3853 default:
b52d3bfa
YK
3854 gen_base_offset_addr(ctx, t0, rs, imm);
3855 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3856 }
26ebe468
NF
3857 } else {
3858 generate_exception_err(ctx, EXCP_CpU, 1);
3859 }
b52d3bfa 3860 tcg_temp_free(t0);
26ebe468
NF
3861}
3862
6af0bf9c 3863/* Arithmetic with immediate operand */
d75c135e 3864static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3865 int rt, int rs, int imm)
6af0bf9c 3866{
324d9e32 3867 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3868
7a387fff 3869 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
3870 /*
3871 * If no destination, treat it as a NOP.
3872 * For addi, we must generate the overflow exception when needed.
3873 */
324d9e32 3874 return;
6af0bf9c
FB
3875 }
3876 switch (opc) {
3877 case OPC_ADDI:
48d38ca5 3878 {
324d9e32
AJ
3879 TCGv t0 = tcg_temp_local_new();
3880 TCGv t1 = tcg_temp_new();
3881 TCGv t2 = tcg_temp_new();
42a268c2 3882 TCGLabel *l1 = gen_new_label();
48d38ca5 3883
324d9e32
AJ
3884 gen_load_gpr(t1, rs);
3885 tcg_gen_addi_tl(t0, t1, uimm);
3886 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3887
324d9e32
AJ
3888 tcg_gen_xori_tl(t1, t1, ~uimm);
3889 tcg_gen_xori_tl(t2, t0, uimm);
3890 tcg_gen_and_tl(t1, t1, t2);
3891 tcg_temp_free(t2);
3892 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3893 tcg_temp_free(t1);
48d38ca5
TS
3894 /* operands of same sign, result different sign */
3895 generate_exception(ctx, EXCP_OVERFLOW);
3896 gen_set_label(l1);
78723684 3897 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3898 gen_store_gpr(t0, rt);
3899 tcg_temp_free(t0);
48d38ca5 3900 }
6af0bf9c
FB
3901 break;
3902 case OPC_ADDIU:
324d9e32
AJ
3903 if (rs != 0) {
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3905 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3906 } else {
3907 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3908 }
6af0bf9c 3909 break;
d26bc211 3910#if defined(TARGET_MIPS64)
7a387fff 3911 case OPC_DADDI:
48d38ca5 3912 {
324d9e32
AJ
3913 TCGv t0 = tcg_temp_local_new();
3914 TCGv t1 = tcg_temp_new();
3915 TCGv t2 = tcg_temp_new();
42a268c2 3916 TCGLabel *l1 = gen_new_label();
48d38ca5 3917
324d9e32
AJ
3918 gen_load_gpr(t1, rs);
3919 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3920
324d9e32
AJ
3921 tcg_gen_xori_tl(t1, t1, ~uimm);
3922 tcg_gen_xori_tl(t2, t0, uimm);
3923 tcg_gen_and_tl(t1, t1, t2);
3924 tcg_temp_free(t2);
3925 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3926 tcg_temp_free(t1);
48d38ca5
TS
3927 /* operands of same sign, result different sign */
3928 generate_exception(ctx, EXCP_OVERFLOW);
3929 gen_set_label(l1);
324d9e32
AJ
3930 gen_store_gpr(t0, rt);
3931 tcg_temp_free(t0);
48d38ca5 3932 }
7a387fff
TS
3933 break;
3934 case OPC_DADDIU:
324d9e32
AJ
3935 if (rs != 0) {
3936 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3937 } else {
3938 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3939 }
7a387fff
TS
3940 break;
3941#endif
324d9e32 3942 }
324d9e32
AJ
3943}
3944
3945/* Logic with immediate operand */
d75c135e 3946static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3947 int rt, int rs, int16_t imm)
324d9e32
AJ
3948{
3949 target_ulong uimm;
324d9e32
AJ
3950
3951 if (rt == 0) {
3952 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3953 return;
3954 }
3955 uimm = (uint16_t)imm;
3956 switch (opc) {
6af0bf9c 3957 case OPC_ANDI:
1f8929d2 3958 if (likely(rs != 0)) {
324d9e32 3959 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3960 } else {
324d9e32 3961 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 3962 }
6af0bf9c
FB
3963 break;
3964 case OPC_ORI:
1f8929d2 3965 if (rs != 0) {
324d9e32 3966 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3967 } else {
324d9e32 3968 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3969 }
6af0bf9c
FB
3970 break;
3971 case OPC_XORI:
1f8929d2 3972 if (likely(rs != 0)) {
324d9e32 3973 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3974 } else {
324d9e32 3975 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3976 }
6af0bf9c
FB
3977 break;
3978 case OPC_LUI:
d4ea6acd
LA
3979 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3980 /* OPC_AUI */
3981 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3982 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3983 } else {
3984 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3985 }
7c2c3ea3
EJ
3986 break;
3987
3988 default:
6af0bf9c 3989 break;
324d9e32 3990 }
324d9e32
AJ
3991}
3992
3993/* Set on less than with immediate operand */
d75c135e 3994static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3995 int rt, int rs, int16_t imm)
324d9e32
AJ
3996{
3997 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3998 TCGv t0;
3999
4000 if (rt == 0) {
4001 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4002 return;
4003 }
4004 t0 = tcg_temp_new();
4005 gen_load_gpr(t0, rs);
4006 switch (opc) {
4007 case OPC_SLTI:
e68dd28f 4008 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4009 break;
4010 case OPC_SLTIU:
e68dd28f 4011 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4012 break;
4013 }
324d9e32
AJ
4014 tcg_temp_free(t0);
4015}
4016
4017/* Shifts with immediate operand */
d75c135e 4018static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
4019 int rt, int rs, int16_t imm)
4020{
4021 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
4022 TCGv t0;
4023
4024 if (rt == 0) {
4025 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4026 return;
4027 }
4028
4029 t0 = tcg_temp_new();
4030 gen_load_gpr(t0, rs);
4031 switch (opc) {
6af0bf9c 4032 case OPC_SLL:
78723684 4033 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 4034 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4035 break;
4036 case OPC_SRA:
324d9e32 4037 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4038 break;
4039 case OPC_SRL:
ea63e2c3
NF
4040 if (uimm != 0) {
4041 tcg_gen_ext32u_tl(t0, t0);
4042 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4043 } else {
4044 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4045 }
ea63e2c3
NF
4046 break;
4047 case OPC_ROTR:
4048 if (uimm != 0) {
4049 TCGv_i32 t1 = tcg_temp_new_i32();
4050
4051 tcg_gen_trunc_tl_i32(t1, t0);
4052 tcg_gen_rotri_i32(t1, t1, uimm);
4053 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4054 tcg_temp_free_i32(t1);
3399e30f
NF
4055 } else {
4056 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4057 }
7a387fff 4058 break;
d26bc211 4059#if defined(TARGET_MIPS64)
7a387fff 4060 case OPC_DSLL:
324d9e32 4061 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4062 break;
4063 case OPC_DSRA:
324d9e32 4064 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4065 break;
4066 case OPC_DSRL:
ea63e2c3 4067 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4068 break;
4069 case OPC_DROTR:
4070 if (uimm != 0) {
4071 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4072 } else {
4073 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4074 }
7a387fff
TS
4075 break;
4076 case OPC_DSLL32:
324d9e32 4077 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4078 break;
4079 case OPC_DSRA32:
324d9e32 4080 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4081 break;
4082 case OPC_DSRL32:
ea63e2c3 4083 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4084 break;
4085 case OPC_DROTR32:
4086 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4087 break;
7a387fff 4088#endif
6af0bf9c 4089 }
78723684 4090 tcg_temp_free(t0);
6af0bf9c
FB
4091}
4092
4093/* Arithmetic */
d75c135e
AJ
4094static void gen_arith(DisasContext *ctx, uint32_t opc,
4095 int rd, int rs, int rt)
6af0bf9c 4096{
7a387fff
TS
4097 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4098 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
4099 /*
4100 * If no destination, treat it as a NOP.
4101 * For add & sub, we must generate the overflow exception when needed.
4102 */
460f00c4 4103 return;
185f0762 4104 }
460f00c4 4105
6af0bf9c
FB
4106 switch (opc) {
4107 case OPC_ADD:
48d38ca5 4108 {
460f00c4
AJ
4109 TCGv t0 = tcg_temp_local_new();
4110 TCGv t1 = tcg_temp_new();
4111 TCGv t2 = tcg_temp_new();
42a268c2 4112 TCGLabel *l1 = gen_new_label();
48d38ca5 4113
460f00c4
AJ
4114 gen_load_gpr(t1, rs);
4115 gen_load_gpr(t2, rt);
4116 tcg_gen_add_tl(t0, t1, t2);
4117 tcg_gen_ext32s_tl(t0, t0);
4118 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4119 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4120 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4121 tcg_temp_free(t2);
4122 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4123 tcg_temp_free(t1);
48d38ca5
TS
4124 /* operands of same sign, result different sign */
4125 generate_exception(ctx, EXCP_OVERFLOW);
4126 gen_set_label(l1);
460f00c4
AJ
4127 gen_store_gpr(t0, rd);
4128 tcg_temp_free(t0);
48d38ca5 4129 }
6af0bf9c
FB
4130 break;
4131 case OPC_ADDU:
460f00c4
AJ
4132 if (rs != 0 && rt != 0) {
4133 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4134 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4135 } else if (rs == 0 && rt != 0) {
4136 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4137 } else if (rs != 0 && rt == 0) {
4138 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4139 } else {
4140 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4141 }
6af0bf9c
FB
4142 break;
4143 case OPC_SUB:
48d38ca5 4144 {
460f00c4
AJ
4145 TCGv t0 = tcg_temp_local_new();
4146 TCGv t1 = tcg_temp_new();
4147 TCGv t2 = tcg_temp_new();
42a268c2 4148 TCGLabel *l1 = gen_new_label();
48d38ca5 4149
460f00c4
AJ
4150 gen_load_gpr(t1, rs);
4151 gen_load_gpr(t2, rt);
4152 tcg_gen_sub_tl(t0, t1, t2);
4153 tcg_gen_ext32s_tl(t0, t0);
4154 tcg_gen_xor_tl(t2, t1, t2);
4155 tcg_gen_xor_tl(t1, t0, t1);
4156 tcg_gen_and_tl(t1, t1, t2);
4157 tcg_temp_free(t2);
4158 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4159 tcg_temp_free(t1);
7480515f
AM
4160 /*
4161 * operands of different sign, first operand and the result
4162 * of different sign
4163 */
48d38ca5
TS
4164 generate_exception(ctx, EXCP_OVERFLOW);
4165 gen_set_label(l1);
460f00c4
AJ
4166 gen_store_gpr(t0, rd);
4167 tcg_temp_free(t0);
48d38ca5 4168 }
6af0bf9c
FB
4169 break;
4170 case OPC_SUBU:
460f00c4
AJ
4171 if (rs != 0 && rt != 0) {
4172 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4173 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4174 } else if (rs == 0 && rt != 0) {
4175 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4176 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4177 } else if (rs != 0 && rt == 0) {
4178 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4179 } else {
4180 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4181 }
6af0bf9c 4182 break;
d26bc211 4183#if defined(TARGET_MIPS64)
7a387fff 4184 case OPC_DADD:
48d38ca5 4185 {
460f00c4
AJ
4186 TCGv t0 = tcg_temp_local_new();
4187 TCGv t1 = tcg_temp_new();
4188 TCGv t2 = tcg_temp_new();
42a268c2 4189 TCGLabel *l1 = gen_new_label();
48d38ca5 4190
460f00c4
AJ
4191 gen_load_gpr(t1, rs);
4192 gen_load_gpr(t2, rt);
4193 tcg_gen_add_tl(t0, t1, t2);
4194 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4195 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4196 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4197 tcg_temp_free(t2);
4198 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4199 tcg_temp_free(t1);
48d38ca5
TS
4200 /* operands of same sign, result different sign */
4201 generate_exception(ctx, EXCP_OVERFLOW);
4202 gen_set_label(l1);
460f00c4
AJ
4203 gen_store_gpr(t0, rd);
4204 tcg_temp_free(t0);
48d38ca5 4205 }
7a387fff
TS
4206 break;
4207 case OPC_DADDU:
460f00c4
AJ
4208 if (rs != 0 && rt != 0) {
4209 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4210 } else if (rs == 0 && rt != 0) {
4211 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4212 } else if (rs != 0 && rt == 0) {
4213 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4214 } else {
4215 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4216 }
7a387fff
TS
4217 break;
4218 case OPC_DSUB:
48d38ca5 4219 {
460f00c4
AJ
4220 TCGv t0 = tcg_temp_local_new();
4221 TCGv t1 = tcg_temp_new();
4222 TCGv t2 = tcg_temp_new();
42a268c2 4223 TCGLabel *l1 = gen_new_label();
48d38ca5 4224
460f00c4
AJ
4225 gen_load_gpr(t1, rs);
4226 gen_load_gpr(t2, rt);
4227 tcg_gen_sub_tl(t0, t1, t2);
4228 tcg_gen_xor_tl(t2, t1, t2);
4229 tcg_gen_xor_tl(t1, t0, t1);
4230 tcg_gen_and_tl(t1, t1, t2);
4231 tcg_temp_free(t2);
4232 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4233 tcg_temp_free(t1);
71375b59
AM
4234 /*
4235 * Operands of different sign, first operand and result different
4236 * sign.
4237 */
48d38ca5
TS
4238 generate_exception(ctx, EXCP_OVERFLOW);
4239 gen_set_label(l1);
460f00c4
AJ
4240 gen_store_gpr(t0, rd);
4241 tcg_temp_free(t0);
48d38ca5 4242 }
7a387fff
TS
4243 break;
4244 case OPC_DSUBU:
460f00c4
AJ
4245 if (rs != 0 && rt != 0) {
4246 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4247 } else if (rs == 0 && rt != 0) {
4248 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4249 } else if (rs != 0 && rt == 0) {
4250 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4251 } else {
4252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4253 }
7a387fff
TS
4254 break;
4255#endif
460f00c4
AJ
4256 case OPC_MUL:
4257 if (likely(rs != 0 && rt != 0)) {
4258 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4259 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4260 } else {
4261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4262 }
6af0bf9c 4263 break;
460f00c4 4264 }
460f00c4
AJ
4265}
4266
4267/* Conditional move */
d75c135e 4268static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4269 int rd, int rs, int rt)
460f00c4 4270{
acf12465 4271 TCGv t0, t1, t2;
460f00c4
AJ
4272
4273 if (rd == 0) {
acf12465 4274 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4275 return;
4276 }
4277
acf12465
AJ
4278 t0 = tcg_temp_new();
4279 gen_load_gpr(t0, rt);
4280 t1 = tcg_const_tl(0);
4281 t2 = tcg_temp_new();
4282 gen_load_gpr(t2, rs);
460f00c4
AJ
4283 switch (opc) {
4284 case OPC_MOVN:
acf12465 4285 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4286 break;
460f00c4 4287 case OPC_MOVZ:
acf12465 4288 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4289 break;
b691d9d2
LA
4290 case OPC_SELNEZ:
4291 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4292 break;
4293 case OPC_SELEQZ:
4294 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4295 break;
460f00c4 4296 }
acf12465
AJ
4297 tcg_temp_free(t2);
4298 tcg_temp_free(t1);
4299 tcg_temp_free(t0);
460f00c4
AJ
4300}
4301
4302/* Logic */
d75c135e 4303static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4304 int rd, int rs, int rt)
460f00c4 4305{
460f00c4
AJ
4306 if (rd == 0) {
4307 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4308 return;
4309 }
4310
4311 switch (opc) {
6af0bf9c 4312 case OPC_AND:
460f00c4
AJ
4313 if (likely(rs != 0 && rt != 0)) {
4314 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4315 } else {
4316 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4317 }
6af0bf9c
FB
4318 break;
4319 case OPC_NOR:
460f00c4
AJ
4320 if (rs != 0 && rt != 0) {
4321 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4322 } else if (rs == 0 && rt != 0) {
4323 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4324 } else if (rs != 0 && rt == 0) {
4325 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4326 } else {
4327 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4328 }
6af0bf9c
FB
4329 break;
4330 case OPC_OR:
460f00c4
AJ
4331 if (likely(rs != 0 && rt != 0)) {
4332 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4333 } else if (rs == 0 && rt != 0) {
4334 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4335 } else if (rs != 0 && rt == 0) {
4336 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4337 } else {
4338 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4339 }
6af0bf9c
FB
4340 break;
4341 case OPC_XOR:
460f00c4
AJ
4342 if (likely(rs != 0 && rt != 0)) {
4343 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4344 } else if (rs == 0 && rt != 0) {
4345 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4346 } else if (rs != 0 && rt == 0) {
4347 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4348 } else {
4349 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4350 }
6af0bf9c 4351 break;
460f00c4 4352 }
460f00c4
AJ
4353}
4354
4355/* Set on lower than */
d75c135e 4356static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4357 int rd, int rs, int rt)
460f00c4 4358{
460f00c4
AJ
4359 TCGv t0, t1;
4360
4361 if (rd == 0) {
4362 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4363 return;
4364 }
4365
4366 t0 = tcg_temp_new();
4367 t1 = tcg_temp_new();
4368 gen_load_gpr(t0, rs);
4369 gen_load_gpr(t1, rt);
4370 switch (opc) {
4371 case OPC_SLT:
e68dd28f 4372 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4373 break;
460f00c4 4374 case OPC_SLTU:
e68dd28f 4375 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4376 break;
4377 }
460f00c4
AJ
4378 tcg_temp_free(t0);
4379 tcg_temp_free(t1);
4380}
20c4c97c 4381
460f00c4 4382/* Shifts */
d75c135e
AJ
4383static void gen_shift(DisasContext *ctx, uint32_t opc,
4384 int rd, int rs, int rt)
460f00c4 4385{
460f00c4 4386 TCGv t0, t1;
20c4c97c 4387
460f00c4 4388 if (rd == 0) {
7480515f
AM
4389 /*
4390 * If no destination, treat it as a NOP.
4391 * For add & sub, we must generate the overflow exception when needed.
4392 */
460f00c4
AJ
4393 return;
4394 }
4395
4396 t0 = tcg_temp_new();
4397 t1 = tcg_temp_new();
4398 gen_load_gpr(t0, rs);
4399 gen_load_gpr(t1, rt);
4400 switch (opc) {
6af0bf9c 4401 case OPC_SLLV:
78723684
TS
4402 tcg_gen_andi_tl(t0, t0, 0x1f);
4403 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4404 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4405 break;
4406 case OPC_SRAV:
78723684 4407 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4408 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4409 break;
4410 case OPC_SRLV:
ea63e2c3
NF
4411 tcg_gen_ext32u_tl(t1, t1);
4412 tcg_gen_andi_tl(t0, t0, 0x1f);
4413 tcg_gen_shr_tl(t0, t1, t0);
4414 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4415 break;
4416 case OPC_ROTRV:
4417 {
4418 TCGv_i32 t2 = tcg_temp_new_i32();
4419 TCGv_i32 t3 = tcg_temp_new_i32();
4420
4421 tcg_gen_trunc_tl_i32(t2, t0);
4422 tcg_gen_trunc_tl_i32(t3, t1);
4423 tcg_gen_andi_i32(t2, t2, 0x1f);
4424 tcg_gen_rotr_i32(t2, t3, t2);
4425 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4426 tcg_temp_free_i32(t2);
4427 tcg_temp_free_i32(t3);
5a63bcb2 4428 }
7a387fff 4429 break;
d26bc211 4430#if defined(TARGET_MIPS64)
7a387fff 4431 case OPC_DSLLV:
78723684 4432 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4433 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4434 break;
4435 case OPC_DSRAV:
78723684 4436 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4437 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4438 break;
4439 case OPC_DSRLV:
ea63e2c3
NF
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4442 break;
4443 case OPC_DROTRV:
4444 tcg_gen_andi_tl(t0, t0, 0x3f);
4445 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4446 break;
7a387fff 4447#endif
6af0bf9c 4448 }
78723684
TS
4449 tcg_temp_free(t0);
4450 tcg_temp_free(t1);
6af0bf9c
FB
4451}
4452
37b9aae2 4453#if defined(TARGET_MIPS64)
86efbfb6
FN
4454/* Copy GPR to and from TX79 HI1/LO1 register. */
4455static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4456{
baa609db 4457 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4458 /* Treat as NOP. */
4459 return;
4460 }
4461
4462 switch (opc) {
baa609db 4463 case MMI_OPC_MFHI1:
86efbfb6
FN
4464 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4465 break;
baa609db 4466 case MMI_OPC_MFLO1:
86efbfb6
FN
4467 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4468 break;
baa609db 4469 case MMI_OPC_MTHI1:
86efbfb6
FN
4470 if (reg != 0) {
4471 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4472 } else {
4473 tcg_gen_movi_tl(cpu_HI[1], 0);
4474 }
4475 break;
baa609db 4476 case MMI_OPC_MTLO1:
86efbfb6
FN
4477 if (reg != 0) {
4478 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4479 } else {
4480 tcg_gen_movi_tl(cpu_LO[1], 0);
4481 }
4482 break;
4483 default:
4484 MIPS_INVAL("mfthilo1 TX79");
4485 generate_exception_end(ctx, EXCP_RI);
4486 break;
4487 }
4488}
37b9aae2 4489#endif
86efbfb6 4490
6af0bf9c 4491/* Arithmetic on HI/LO registers */
26135ead 4492static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4493{
86efbfb6 4494 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4495 /* Treat as NOP. */
a1f6684d 4496 return;
6af0bf9c 4497 }
4133498f 4498
4133498f 4499 if (acc != 0) {
86efbfb6 4500 check_dsp(ctx);
4133498f
JL
4501 }
4502
6af0bf9c
FB
4503 switch (opc) {
4504 case OPC_MFHI:
4133498f
JL
4505#if defined(TARGET_MIPS64)
4506 if (acc != 0) {
4507 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4508 } else
4509#endif
4510 {
4511 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4512 }
6af0bf9c
FB
4513 break;
4514 case OPC_MFLO:
4133498f
JL
4515#if defined(TARGET_MIPS64)
4516 if (acc != 0) {
4517 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4518 } else
4519#endif
4520 {
4521 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4522 }
6af0bf9c
FB
4523 break;
4524 case OPC_MTHI:
4133498f
JL
4525 if (reg != 0) {
4526#if defined(TARGET_MIPS64)
4527 if (acc != 0) {
4528 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4529 } else
4530#endif
4531 {
4532 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4533 }
4534 } else {
4535 tcg_gen_movi_tl(cpu_HI[acc], 0);
4536 }
6af0bf9c
FB
4537 break;
4538 case OPC_MTLO:
4133498f
JL
4539 if (reg != 0) {
4540#if defined(TARGET_MIPS64)
4541 if (acc != 0) {
4542 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4543 } else
4544#endif
4545 {
4546 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4547 }
4548 } else {
4549 tcg_gen_movi_tl(cpu_LO[acc], 0);
4550 }
6af0bf9c 4551 break;
6af0bf9c 4552 }
6af0bf9c
FB
4553}
4554
d4ea6acd 4555static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 4556 MemOp memop)
d4ea6acd
LA
4557{
4558 TCGv t0 = tcg_const_tl(addr);
4559 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4560 gen_store_gpr(t0, reg);
4561 tcg_temp_free(t0);
4562}
4563
ab39ee45
YK
4564static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4565 int rs)
d4ea6acd
LA
4566{
4567 target_long offset;
4568 target_long addr;
4569
ab39ee45 4570 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4571 case OPC_ADDIUPC:
4572 if (rs != 0) {
4573 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4574 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4575 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4576 }
4577 break;
4578 case R6_OPC_LWPC:
4579 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4580 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4581 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4582 break;
4583#if defined(TARGET_MIPS64)
4584 case OPC_LWUPC:
4585 check_mips_64(ctx);
4586 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4587 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4588 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4589 break;
4590#endif
4591 default:
ab39ee45 4592 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4593 case OPC_AUIPC:
4594 if (rs != 0) {
ab39ee45
YK
4595 offset = sextract32(ctx->opcode, 0, 16) << 16;
4596 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4597 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4598 }
4599 break;
4600 case OPC_ALUIPC:
4601 if (rs != 0) {
ab39ee45
YK
4602 offset = sextract32(ctx->opcode, 0, 16) << 16;
4603 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4604 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4605 }
4606 break;
4607#if defined(TARGET_MIPS64)
4608 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4609 case R6_OPC_LDPC + (1 << 16):
4610 case R6_OPC_LDPC + (2 << 16):
4611 case R6_OPC_LDPC + (3 << 16):
4612 check_mips_64(ctx);
4613 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4614 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4615 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4616 break;
4617#endif
4618 default:
4619 MIPS_INVAL("OPC_PCREL");
9c708c7f 4620 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4621 break;
4622 }
4623 break;
4624 }
4625}
4626
b42ee5e1
LA
4627static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4628{
b42ee5e1
LA
4629 TCGv t0, t1;
4630
4631 if (rd == 0) {
4632 /* Treat as NOP. */
b42ee5e1
LA
4633 return;
4634 }
4635
4636 t0 = tcg_temp_new();
4637 t1 = tcg_temp_new();
4638
4639 gen_load_gpr(t0, rs);
4640 gen_load_gpr(t1, rt);
4641
4642 switch (opc) {
4643 case R6_OPC_DIV:
4644 {
4645 TCGv t2 = tcg_temp_new();
4646 TCGv t3 = tcg_temp_new();
4647 tcg_gen_ext32s_tl(t0, t0);
4648 tcg_gen_ext32s_tl(t1, t1);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4650 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4651 tcg_gen_and_tl(t2, t2, t3);
4652 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4653 tcg_gen_or_tl(t2, t2, t3);
4654 tcg_gen_movi_tl(t3, 0);
4655 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4656 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4657 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4658 tcg_temp_free(t3);
4659 tcg_temp_free(t2);
4660 }
b42ee5e1
LA
4661 break;
4662 case R6_OPC_MOD:
4663 {
4664 TCGv t2 = tcg_temp_new();
4665 TCGv t3 = tcg_temp_new();
4666 tcg_gen_ext32s_tl(t0, t0);
4667 tcg_gen_ext32s_tl(t1, t1);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4669 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4670 tcg_gen_and_tl(t2, t2, t3);
4671 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4672 tcg_gen_or_tl(t2, t2, t3);
4673 tcg_gen_movi_tl(t3, 0);
4674 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4675 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4676 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4677 tcg_temp_free(t3);
4678 tcg_temp_free(t2);
4679 }
b42ee5e1
LA
4680 break;
4681 case R6_OPC_DIVU:
4682 {
4683 TCGv t2 = tcg_const_tl(0);
4684 TCGv t3 = tcg_const_tl(1);
4685 tcg_gen_ext32u_tl(t0, t0);
4686 tcg_gen_ext32u_tl(t1, t1);
4687 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4688 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4689 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4690 tcg_temp_free(t3);
4691 tcg_temp_free(t2);
4692 }
b42ee5e1
LA
4693 break;
4694 case R6_OPC_MODU:
4695 {
4696 TCGv t2 = tcg_const_tl(0);
4697 TCGv t3 = tcg_const_tl(1);
4698 tcg_gen_ext32u_tl(t0, t0);
4699 tcg_gen_ext32u_tl(t1, t1);
4700 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4701 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4702 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4703 tcg_temp_free(t3);
4704 tcg_temp_free(t2);
4705 }
b42ee5e1
LA
4706 break;
4707 case R6_OPC_MUL:
4708 {
4709 TCGv_i32 t2 = tcg_temp_new_i32();
4710 TCGv_i32 t3 = tcg_temp_new_i32();
4711 tcg_gen_trunc_tl_i32(t2, t0);
4712 tcg_gen_trunc_tl_i32(t3, t1);
4713 tcg_gen_mul_i32(t2, t2, t3);
4714 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4715 tcg_temp_free_i32(t2);
4716 tcg_temp_free_i32(t3);
4717 }
b42ee5e1
LA
4718 break;
4719 case R6_OPC_MUH:
4720 {
4721 TCGv_i32 t2 = tcg_temp_new_i32();
4722 TCGv_i32 t3 = tcg_temp_new_i32();
4723 tcg_gen_trunc_tl_i32(t2, t0);
4724 tcg_gen_trunc_tl_i32(t3, t1);
4725 tcg_gen_muls2_i32(t2, t3, t2, t3);
4726 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4727 tcg_temp_free_i32(t2);
4728 tcg_temp_free_i32(t3);
4729 }
b42ee5e1
LA
4730 break;
4731 case R6_OPC_MULU:
4732 {
4733 TCGv_i32 t2 = tcg_temp_new_i32();
4734 TCGv_i32 t3 = tcg_temp_new_i32();
4735 tcg_gen_trunc_tl_i32(t2, t0);
4736 tcg_gen_trunc_tl_i32(t3, t1);
4737 tcg_gen_mul_i32(t2, t2, t3);
4738 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4739 tcg_temp_free_i32(t2);
4740 tcg_temp_free_i32(t3);
4741 }
b42ee5e1
LA
4742 break;
4743 case R6_OPC_MUHU:
4744 {
4745 TCGv_i32 t2 = tcg_temp_new_i32();
4746 TCGv_i32 t3 = tcg_temp_new_i32();
4747 tcg_gen_trunc_tl_i32(t2, t0);
4748 tcg_gen_trunc_tl_i32(t3, t1);
4749 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4750 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4751 tcg_temp_free_i32(t2);
4752 tcg_temp_free_i32(t3);
4753 }
b42ee5e1
LA
4754 break;
4755#if defined(TARGET_MIPS64)
4756 case R6_OPC_DDIV:
4757 {
4758 TCGv t2 = tcg_temp_new();
4759 TCGv t3 = tcg_temp_new();
4760 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4761 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4762 tcg_gen_and_tl(t2, t2, t3);
4763 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4764 tcg_gen_or_tl(t2, t2, t3);
4765 tcg_gen_movi_tl(t3, 0);
4766 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4767 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4768 tcg_temp_free(t3);
4769 tcg_temp_free(t2);
4770 }
b42ee5e1
LA
4771 break;
4772 case R6_OPC_DMOD:
4773 {
4774 TCGv t2 = tcg_temp_new();
4775 TCGv t3 = tcg_temp_new();
4776 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4777 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4778 tcg_gen_and_tl(t2, t2, t3);
4779 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4780 tcg_gen_or_tl(t2, t2, t3);
4781 tcg_gen_movi_tl(t3, 0);
4782 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4783 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4784 tcg_temp_free(t3);
4785 tcg_temp_free(t2);
4786 }
b42ee5e1
LA
4787 break;
4788 case R6_OPC_DDIVU:
4789 {
4790 TCGv t2 = tcg_const_tl(0);
4791 TCGv t3 = tcg_const_tl(1);
4792 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4793 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4794 tcg_temp_free(t3);
4795 tcg_temp_free(t2);
4796 }
b42ee5e1
LA
4797 break;
4798 case R6_OPC_DMODU:
4799 {
4800 TCGv t2 = tcg_const_tl(0);
4801 TCGv t3 = tcg_const_tl(1);
4802 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4803 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4804 tcg_temp_free(t3);
4805 tcg_temp_free(t2);
4806 }
b42ee5e1
LA
4807 break;
4808 case R6_OPC_DMUL:
4809 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4810 break;
4811 case R6_OPC_DMUH:
4812 {
4813 TCGv t2 = tcg_temp_new();
4814 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4815 tcg_temp_free(t2);
4816 }
b42ee5e1
LA
4817 break;
4818 case R6_OPC_DMULU:
4819 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4820 break;
4821 case R6_OPC_DMUHU:
4822 {
4823 TCGv t2 = tcg_temp_new();
4824 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4825 tcg_temp_free(t2);
4826 }
b42ee5e1
LA
4827 break;
4828#endif
4829 default:
9d68ac14 4830 MIPS_INVAL("r6 mul/div");
9c708c7f 4831 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4832 goto out;
4833 }
b42ee5e1
LA
4834 out:
4835 tcg_temp_free(t0);
4836 tcg_temp_free(t1);
4837}
4838
37b9aae2 4839#if defined(TARGET_MIPS64)
c42171c3
FN
4840static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4841{
4842 TCGv t0, t1;
4843
4844 t0 = tcg_temp_new();
4845 t1 = tcg_temp_new();
4846
4847 gen_load_gpr(t0, rs);
4848 gen_load_gpr(t1, rt);
4849
4850 switch (opc) {
baa609db 4851 case MMI_OPC_DIV1:
c42171c3
FN
4852 {
4853 TCGv t2 = tcg_temp_new();
4854 TCGv t3 = tcg_temp_new();
4855 tcg_gen_ext32s_tl(t0, t0);
4856 tcg_gen_ext32s_tl(t1, t1);
4857 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4858 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4859 tcg_gen_and_tl(t2, t2, t3);
4860 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4861 tcg_gen_or_tl(t2, t2, t3);
4862 tcg_gen_movi_tl(t3, 0);
4863 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4864 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4865 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4866 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4867 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4868 tcg_temp_free(t3);
4869 tcg_temp_free(t2);
4870 }
4871 break;
baa609db 4872 case MMI_OPC_DIVU1:
c42171c3
FN
4873 {
4874 TCGv t2 = tcg_const_tl(0);
4875 TCGv t3 = tcg_const_tl(1);
4876 tcg_gen_ext32u_tl(t0, t0);
4877 tcg_gen_ext32u_tl(t1, t1);
4878 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4879 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4880 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4881 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4882 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4883 tcg_temp_free(t3);
4884 tcg_temp_free(t2);
4885 }
4886 break;
4887 default:
4888 MIPS_INVAL("div1 TX79");
4889 generate_exception_end(ctx, EXCP_RI);
4890 goto out;
4891 }
4892 out:
4893 tcg_temp_free(t0);
4894 tcg_temp_free(t1);
4895}
37b9aae2 4896#endif
c42171c3 4897
26135ead
RS
4898static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4899 int acc, int rs, int rt)
6af0bf9c 4900{
d45f89f4
AJ
4901 TCGv t0, t1;
4902
51127181
AJ
4903 t0 = tcg_temp_new();
4904 t1 = tcg_temp_new();
6af0bf9c 4905
78723684
TS
4906 gen_load_gpr(t0, rs);
4907 gen_load_gpr(t1, rt);
51127181 4908
26135ead 4909 if (acc != 0) {
c42171c3 4910 check_dsp(ctx);
26135ead
RS
4911 }
4912
6af0bf9c
FB
4913 switch (opc) {
4914 case OPC_DIV:
48d38ca5 4915 {
51127181
AJ
4916 TCGv t2 = tcg_temp_new();
4917 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4918 tcg_gen_ext32s_tl(t0, t0);
4919 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4920 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4921 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4922 tcg_gen_and_tl(t2, t2, t3);
4923 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4924 tcg_gen_or_tl(t2, t2, t3);
4925 tcg_gen_movi_tl(t3, 0);
4926 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4927 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4928 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4929 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4930 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4931 tcg_temp_free(t3);
4932 tcg_temp_free(t2);
48d38ca5 4933 }
6af0bf9c
FB
4934 break;
4935 case OPC_DIVU:
48d38ca5 4936 {
51127181
AJ
4937 TCGv t2 = tcg_const_tl(0);
4938 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4939 tcg_gen_ext32u_tl(t0, t0);
4940 tcg_gen_ext32u_tl(t1, t1);
51127181 4941 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4942 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4943 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4944 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4945 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4946 tcg_temp_free(t3);
4947 tcg_temp_free(t2);
48d38ca5 4948 }
6af0bf9c
FB
4949 break;
4950 case OPC_MULT:
214c465f 4951 {
ce1dd5d1
RH
4952 TCGv_i32 t2 = tcg_temp_new_i32();
4953 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4954 tcg_gen_trunc_tl_i32(t2, t0);
4955 tcg_gen_trunc_tl_i32(t3, t1);
4956 tcg_gen_muls2_i32(t2, t3, t2, t3);
4957 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4958 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4959 tcg_temp_free_i32(t2);
4960 tcg_temp_free_i32(t3);
214c465f 4961 }
6af0bf9c
FB
4962 break;
4963 case OPC_MULTU:
214c465f 4964 {
ce1dd5d1
RH
4965 TCGv_i32 t2 = tcg_temp_new_i32();
4966 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4967 tcg_gen_trunc_tl_i32(t2, t0);
4968 tcg_gen_trunc_tl_i32(t3, t1);
4969 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4970 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4971 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4972 tcg_temp_free_i32(t2);
4973 tcg_temp_free_i32(t3);
214c465f 4974 }
6af0bf9c 4975 break;
d26bc211 4976#if defined(TARGET_MIPS64)
7a387fff 4977 case OPC_DDIV:
48d38ca5 4978 {
51127181
AJ
4979 TCGv t2 = tcg_temp_new();
4980 TCGv t3 = tcg_temp_new();
4981 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4982 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4983 tcg_gen_and_tl(t2, t2, t3);
4984 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4985 tcg_gen_or_tl(t2, t2, t3);
4986 tcg_gen_movi_tl(t3, 0);
4987 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4988 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4989 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4990 tcg_temp_free(t3);
4991 tcg_temp_free(t2);
48d38ca5 4992 }
7a387fff
TS
4993 break;
4994 case OPC_DDIVU:
48d38ca5 4995 {
51127181
AJ
4996 TCGv t2 = tcg_const_tl(0);
4997 TCGv t3 = tcg_const_tl(1);
4998 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4999 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
5000 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
5001 tcg_temp_free(t3);
5002 tcg_temp_free(t2);
48d38ca5 5003 }
7a387fff
TS
5004 break;
5005 case OPC_DMULT:
26135ead 5006 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5007 break;
5008 case OPC_DMULTU:
26135ead 5009 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5010 break;
5011#endif
6af0bf9c 5012 case OPC_MADD:
214c465f 5013 {
d45f89f4
AJ
5014 TCGv_i64 t2 = tcg_temp_new_i64();
5015 TCGv_i64 t3 = tcg_temp_new_i64();
5016
5017 tcg_gen_ext_tl_i64(t2, t0);
5018 tcg_gen_ext_tl_i64(t3, t1);
5019 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5020 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5021 tcg_gen_add_i64(t2, t2, t3);
5022 tcg_temp_free_i64(t3);
71f303cd
RH
5023 gen_move_low32(cpu_LO[acc], t2);
5024 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5025 tcg_temp_free_i64(t2);
214c465f 5026 }
6af0bf9c
FB
5027 break;
5028 case OPC_MADDU:
4133498f 5029 {
d45f89f4
AJ
5030 TCGv_i64 t2 = tcg_temp_new_i64();
5031 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5032
78723684
TS
5033 tcg_gen_ext32u_tl(t0, t0);
5034 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5035 tcg_gen_extu_tl_i64(t2, t0);
5036 tcg_gen_extu_tl_i64(t3, t1);
5037 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5038 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5039 tcg_gen_add_i64(t2, t2, t3);
5040 tcg_temp_free_i64(t3);
71f303cd
RH
5041 gen_move_low32(cpu_LO[acc], t2);
5042 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5043 tcg_temp_free_i64(t2);
214c465f 5044 }
6af0bf9c
FB
5045 break;
5046 case OPC_MSUB:
214c465f 5047 {
d45f89f4
AJ
5048 TCGv_i64 t2 = tcg_temp_new_i64();
5049 TCGv_i64 t3 = tcg_temp_new_i64();
5050
5051 tcg_gen_ext_tl_i64(t2, t0);
5052 tcg_gen_ext_tl_i64(t3, t1);
5053 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5054 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5055 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5056 tcg_temp_free_i64(t3);
71f303cd
RH
5057 gen_move_low32(cpu_LO[acc], t2);
5058 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5059 tcg_temp_free_i64(t2);
214c465f 5060 }
6af0bf9c
FB
5061 break;
5062 case OPC_MSUBU:
214c465f 5063 {
d45f89f4
AJ
5064 TCGv_i64 t2 = tcg_temp_new_i64();
5065 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5066
78723684
TS
5067 tcg_gen_ext32u_tl(t0, t0);
5068 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5069 tcg_gen_extu_tl_i64(t2, t0);
5070 tcg_gen_extu_tl_i64(t3, t1);
5071 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5072 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5073 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5074 tcg_temp_free_i64(t3);
71f303cd
RH
5075 gen_move_low32(cpu_LO[acc], t2);
5076 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5077 tcg_temp_free_i64(t2);
214c465f 5078 }
6af0bf9c
FB
5079 break;
5080 default:
9d68ac14 5081 MIPS_INVAL("mul/div");
9c708c7f 5082 generate_exception_end(ctx, EXCP_RI);
78723684 5083 goto out;
6af0bf9c 5084 }
78723684
TS
5085 out:
5086 tcg_temp_free(t0);
5087 tcg_temp_free(t1);
6af0bf9c
FB
5088}
5089
21e8e8b2 5090/*
3b948f05
PMD
5091 * These MULT[U] and MADD[U] instructions implemented in for example
5092 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5093 * architectures are special three-operand variants with the syntax
5094 *
06de726b 5095 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5096 *
5097 * such that
5098 *
5099 * (rd, LO, HI) <- rs * rt
5100 *
3b948f05
PMD
5101 * and
5102 *
a95c4c26 5103 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5104 *
5105 * such that
5106 *
5107 * (rd, LO, HI) <- (LO, HI) + rs * rt
5108 *
21e8e8b2
FN
5109 * where the low-order 32-bits of the result is placed into both the
5110 * GPR rd and the special register LO. The high-order 32-bits of the
5111 * result is placed into the special register HI.
5112 *
5113 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5114 * which is the zero register that always reads as 0.
5115 */
5116static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5117 int rd, int rs, int rt)
5118{
5119 TCGv t0 = tcg_temp_new();
5120 TCGv t1 = tcg_temp_new();
5121 int acc = 0;
5122
5123 gen_load_gpr(t0, rs);
5124 gen_load_gpr(t1, rt);
5125
5126 switch (opc) {
baa609db 5127 case MMI_OPC_MULT1:
06de726b
FN
5128 acc = 1;
5129 /* Fall through */
21e8e8b2
FN
5130 case OPC_MULT:
5131 {
5132 TCGv_i32 t2 = tcg_temp_new_i32();
5133 TCGv_i32 t3 = tcg_temp_new_i32();
5134 tcg_gen_trunc_tl_i32(t2, t0);
5135 tcg_gen_trunc_tl_i32(t3, t1);
5136 tcg_gen_muls2_i32(t2, t3, t2, t3);
5137 if (rd) {
5138 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5139 }
5140 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5141 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5142 tcg_temp_free_i32(t2);
5143 tcg_temp_free_i32(t3);
5144 }
5145 break;
baa609db 5146 case MMI_OPC_MULTU1:
06de726b
FN
5147 acc = 1;
5148 /* Fall through */
21e8e8b2
FN
5149 case OPC_MULTU:
5150 {
5151 TCGv_i32 t2 = tcg_temp_new_i32();
5152 TCGv_i32 t3 = tcg_temp_new_i32();
5153 tcg_gen_trunc_tl_i32(t2, t0);
5154 tcg_gen_trunc_tl_i32(t3, t1);
5155 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5156 if (rd) {
5157 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5158 }
5159 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5160 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5161 tcg_temp_free_i32(t2);
5162 tcg_temp_free_i32(t3);
5163 }
5164 break;
a95c4c26
FN
5165 case MMI_OPC_MADD1:
5166 acc = 1;
5167 /* Fall through */
3b948f05
PMD
5168 case MMI_OPC_MADD:
5169 {
5170 TCGv_i64 t2 = tcg_temp_new_i64();
5171 TCGv_i64 t3 = tcg_temp_new_i64();
5172
5173 tcg_gen_ext_tl_i64(t2, t0);
5174 tcg_gen_ext_tl_i64(t3, t1);
5175 tcg_gen_mul_i64(t2, t2, t3);
5176 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5177 tcg_gen_add_i64(t2, t2, t3);
5178 tcg_temp_free_i64(t3);
5179 gen_move_low32(cpu_LO[acc], t2);
5180 gen_move_high32(cpu_HI[acc], t2);
5181 if (rd) {
5182 gen_move_low32(cpu_gpr[rd], t2);
5183 }
5184 tcg_temp_free_i64(t2);
5185 }
5186 break;
a95c4c26
FN
5187 case MMI_OPC_MADDU1:
5188 acc = 1;
5189 /* Fall through */
3b948f05
PMD
5190 case MMI_OPC_MADDU:
5191 {
5192 TCGv_i64 t2 = tcg_temp_new_i64();
5193 TCGv_i64 t3 = tcg_temp_new_i64();
5194
5195 tcg_gen_ext32u_tl(t0, t0);
5196 tcg_gen_ext32u_tl(t1, t1);
5197 tcg_gen_extu_tl_i64(t2, t0);
5198 tcg_gen_extu_tl_i64(t3, t1);
5199 tcg_gen_mul_i64(t2, t2, t3);
5200 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5201 tcg_gen_add_i64(t2, t2, t3);
5202 tcg_temp_free_i64(t3);
5203 gen_move_low32(cpu_LO[acc], t2);
5204 gen_move_high32(cpu_HI[acc], t2);
5205 if (rd) {
5206 gen_move_low32(cpu_gpr[rd], t2);
5207 }
5208 tcg_temp_free_i64(t2);
5209 }
5210 break;
21e8e8b2 5211 default:
3b948f05 5212 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5213 generate_exception_end(ctx, EXCP_RI);
5214 goto out;
5215 }
5216
5217 out:
5218 tcg_temp_free(t0);
5219 tcg_temp_free(t1);
5220}
5221
235785e8
AM
5222static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5223 int rd, int rs, int rt)
e9c71dd1 5224{
f157bfe1
AJ
5225 TCGv t0 = tcg_temp_new();
5226 TCGv t1 = tcg_temp_new();
e9c71dd1 5227
6c5c1e20
TS
5228 gen_load_gpr(t0, rs);
5229 gen_load_gpr(t1, rt);
e9c71dd1
TS
5230
5231 switch (opc) {
5232 case OPC_VR54XX_MULS:
895c2d04 5233 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5234 break;
e9c71dd1 5235 case OPC_VR54XX_MULSU:
895c2d04 5236 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5237 break;
e9c71dd1 5238 case OPC_VR54XX_MACC:
895c2d04 5239 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5240 break;
e9c71dd1 5241 case OPC_VR54XX_MACCU:
895c2d04 5242 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5243 break;
e9c71dd1 5244 case OPC_VR54XX_MSAC:
895c2d04 5245 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5246 break;
e9c71dd1 5247 case OPC_VR54XX_MSACU:
895c2d04 5248 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5249 break;
e9c71dd1 5250 case OPC_VR54XX_MULHI:
895c2d04 5251 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5252 break;
e9c71dd1 5253 case OPC_VR54XX_MULHIU:
895c2d04 5254 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5255 break;
e9c71dd1 5256 case OPC_VR54XX_MULSHI:
895c2d04 5257 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5258 break;
e9c71dd1 5259 case OPC_VR54XX_MULSHIU:
895c2d04 5260 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5261 break;
e9c71dd1 5262 case OPC_VR54XX_MACCHI:
895c2d04 5263 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5264 break;
e9c71dd1 5265 case OPC_VR54XX_MACCHIU:
895c2d04 5266 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5267 break;
e9c71dd1 5268 case OPC_VR54XX_MSACHI:
895c2d04 5269 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5270 break;
e9c71dd1 5271 case OPC_VR54XX_MSACHIU:
895c2d04 5272 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5273 break;
e9c71dd1
TS
5274 default:
5275 MIPS_INVAL("mul vr54xx");
9c708c7f 5276 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5277 goto out;
e9c71dd1 5278 }
6c5c1e20 5279 gen_store_gpr(t0, rd);
6c5c1e20
TS
5280
5281 out:
5282 tcg_temp_free(t0);
5283 tcg_temp_free(t1);
e9c71dd1
TS
5284}
5285
235785e8
AM
5286static void gen_cl(DisasContext *ctx, uint32_t opc,
5287 int rd, int rs)
6af0bf9c 5288{
20e1fb52 5289 TCGv t0;
6c5c1e20 5290
6af0bf9c 5291 if (rd == 0) {
ead9360e 5292 /* Treat as NOP. */
20e1fb52 5293 return;
6af0bf9c 5294 }
1a0196c5 5295 t0 = cpu_gpr[rd];
6c5c1e20 5296 gen_load_gpr(t0, rs);
1a0196c5 5297
6af0bf9c
FB
5298 switch (opc) {
5299 case OPC_CLO:
4267d3e6 5300 case R6_OPC_CLO:
1a0196c5
RH
5301#if defined(TARGET_MIPS64)
5302 case OPC_DCLO:
5303 case R6_OPC_DCLO:
5304#endif
5305 tcg_gen_not_tl(t0, t0);
6af0bf9c 5306 break;
1a0196c5
RH
5307 }
5308
5309 switch (opc) {
5310 case OPC_CLO:
5311 case R6_OPC_CLO:
6af0bf9c 5312 case OPC_CLZ:
4267d3e6 5313 case R6_OPC_CLZ:
1a0196c5
RH
5314 tcg_gen_ext32u_tl(t0, t0);
5315 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5316 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5317 break;
d26bc211 5318#if defined(TARGET_MIPS64)
7a387fff 5319 case OPC_DCLO:
4267d3e6 5320 case R6_OPC_DCLO:
7a387fff 5321 case OPC_DCLZ:
4267d3e6 5322 case R6_OPC_DCLZ:
1a0196c5 5323 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5324 break;
5325#endif
6af0bf9c 5326 }
6af0bf9c
FB
5327}
5328
161f85e6 5329/* Godson integer instructions */
bd277fa1
RH
5330static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5331 int rd, int rs, int rt)
161f85e6 5332{
161f85e6
AJ
5333 TCGv t0, t1;
5334
5335 if (rd == 0) {
5336 /* Treat as NOP. */
161f85e6
AJ
5337 return;
5338 }
5339
5340 switch (opc) {
5341 case OPC_MULT_G_2E:
5342 case OPC_MULT_G_2F:
5343 case OPC_MULTU_G_2E:
5344 case OPC_MULTU_G_2F:
5345#if defined(TARGET_MIPS64)
5346 case OPC_DMULT_G_2E:
5347 case OPC_DMULT_G_2F:
5348 case OPC_DMULTU_G_2E:
5349 case OPC_DMULTU_G_2F:
5350#endif
5351 t0 = tcg_temp_new();
5352 t1 = tcg_temp_new();
5353 break;
5354 default:
5355 t0 = tcg_temp_local_new();
5356 t1 = tcg_temp_local_new();
5357 break;
5358 }
5359
5360 gen_load_gpr(t0, rs);
5361 gen_load_gpr(t1, rt);
5362
5363 switch (opc) {
5364 case OPC_MULT_G_2E:
5365 case OPC_MULT_G_2F:
5366 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5367 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5368 break;
5369 case OPC_MULTU_G_2E:
5370 case OPC_MULTU_G_2F:
5371 tcg_gen_ext32u_tl(t0, t0);
5372 tcg_gen_ext32u_tl(t1, t1);
5373 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5374 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5375 break;
5376 case OPC_DIV_G_2E:
5377 case OPC_DIV_G_2F:
5378 {
42a268c2
RH
5379 TCGLabel *l1 = gen_new_label();
5380 TCGLabel *l2 = gen_new_label();
5381 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5382 tcg_gen_ext32s_tl(t0, t0);
5383 tcg_gen_ext32s_tl(t1, t1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5385 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5386 tcg_gen_br(l3);
5387 gen_set_label(l1);
5388 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5389 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5390 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5391 tcg_gen_br(l3);
5392 gen_set_label(l2);
5393 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5394 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5395 gen_set_label(l3);
5396 }
161f85e6
AJ
5397 break;
5398 case OPC_DIVU_G_2E:
5399 case OPC_DIVU_G_2F:
5400 {
42a268c2
RH
5401 TCGLabel *l1 = gen_new_label();
5402 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5403 tcg_gen_ext32u_tl(t0, t0);
5404 tcg_gen_ext32u_tl(t1, t1);
5405 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5406 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5407 tcg_gen_br(l2);
5408 gen_set_label(l1);
5409 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5410 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5411 gen_set_label(l2);
5412 }
161f85e6
AJ
5413 break;
5414 case OPC_MOD_G_2E:
5415 case OPC_MOD_G_2F:
5416 {
42a268c2
RH
5417 TCGLabel *l1 = gen_new_label();
5418 TCGLabel *l2 = gen_new_label();
5419 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5420 tcg_gen_ext32u_tl(t0, t0);
5421 tcg_gen_ext32u_tl(t1, t1);
5422 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5423 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5424 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5425 gen_set_label(l1);
5426 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5427 tcg_gen_br(l3);
5428 gen_set_label(l2);
5429 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5430 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5431 gen_set_label(l3);
5432 }
161f85e6
AJ
5433 break;
5434 case OPC_MODU_G_2E:
5435 case OPC_MODU_G_2F:
5436 {
42a268c2
RH
5437 TCGLabel *l1 = gen_new_label();
5438 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5439 tcg_gen_ext32u_tl(t0, t0);
5440 tcg_gen_ext32u_tl(t1, t1);
5441 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5442 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5443 tcg_gen_br(l2);
5444 gen_set_label(l1);
5445 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5446 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5447 gen_set_label(l2);
5448 }
161f85e6
AJ
5449 break;
5450#if defined(TARGET_MIPS64)
5451 case OPC_DMULT_G_2E:
5452 case OPC_DMULT_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5454 break;
5455 case OPC_DMULTU_G_2E:
5456 case OPC_DMULTU_G_2F:
5457 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5458 break;
5459 case OPC_DDIV_G_2E:
5460 case OPC_DDIV_G_2F:
5461 {
42a268c2
RH
5462 TCGLabel *l1 = gen_new_label();
5463 TCGLabel *l2 = gen_new_label();
5464 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5466 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5467 tcg_gen_br(l3);
5468 gen_set_label(l1);
5469 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5470 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5471 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5472 tcg_gen_br(l3);
5473 gen_set_label(l2);
5474 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5475 gen_set_label(l3);
5476 }
161f85e6
AJ
5477 break;
5478 case OPC_DDIVU_G_2E:
5479 case OPC_DDIVU_G_2F:
5480 {
42a268c2
RH
5481 TCGLabel *l1 = gen_new_label();
5482 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5484 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5485 tcg_gen_br(l2);
5486 gen_set_label(l1);
5487 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5488 gen_set_label(l2);
5489 }
161f85e6
AJ
5490 break;
5491 case OPC_DMOD_G_2E:
5492 case OPC_DMOD_G_2F:
5493 {
42a268c2
RH
5494 TCGLabel *l1 = gen_new_label();
5495 TCGLabel *l2 = gen_new_label();
5496 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5497 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5498 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5499 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5500 gen_set_label(l1);
5501 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5502 tcg_gen_br(l3);
5503 gen_set_label(l2);
5504 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5505 gen_set_label(l3);
5506 }
161f85e6
AJ
5507 break;
5508 case OPC_DMODU_G_2E:
5509 case OPC_DMODU_G_2F:
5510 {
42a268c2
RH
5511 TCGLabel *l1 = gen_new_label();
5512 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5513 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5514 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5515 tcg_gen_br(l2);
5516 gen_set_label(l1);
5517 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5518 gen_set_label(l2);
5519 }
161f85e6
AJ
5520 break;
5521#endif
5522 }
5523
161f85e6
AJ
5524 tcg_temp_free(t0);
5525 tcg_temp_free(t1);
5526}
5527
bd277fa1
RH
5528/* Loongson multimedia instructions */
5529static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5530{
bd277fa1
RH
5531 uint32_t opc, shift_max;
5532 TCGv_i64 t0, t1;
84878f4c 5533 TCGCond cond;
bd277fa1 5534
8e2d5831 5535 opc = MASK_LMMI(ctx->opcode);
bd277fa1
RH
5536 switch (opc) {
5537 case OPC_ADD_CP2:
5538 case OPC_SUB_CP2:
5539 case OPC_DADD_CP2:
5540 case OPC_DSUB_CP2:
5541 t0 = tcg_temp_local_new_i64();
5542 t1 = tcg_temp_local_new_i64();
5543 break;
5544 default:
5545 t0 = tcg_temp_new_i64();
5546 t1 = tcg_temp_new_i64();
5547 break;
5548 }
5549
b5a587b6 5550 check_cp1_enabled(ctx);
bd277fa1
RH
5551 gen_load_fpr64(ctx, t0, rs);
5552 gen_load_fpr64(ctx, t1, rt);
5553
bd277fa1 5554 switch (opc) {
b1cf82f0
AM
5555 case OPC_PADDSH:
5556 gen_helper_paddsh(t0, t0, t1);
5557 break;
5558 case OPC_PADDUSH:
5559 gen_helper_paddush(t0, t0, t1);
5560 break;
5561 case OPC_PADDH:
5562 gen_helper_paddh(t0, t0, t1);
5563 break;
5564 case OPC_PADDW:
5565 gen_helper_paddw(t0, t0, t1);
5566 break;
5567 case OPC_PADDSB:
5568 gen_helper_paddsb(t0, t0, t1);
5569 break;
5570 case OPC_PADDUSB:
5571 gen_helper_paddusb(t0, t0, t1);
5572 break;
5573 case OPC_PADDB:
5574 gen_helper_paddb(t0, t0, t1);
5575 break;
5576
5577 case OPC_PSUBSH:
5578 gen_helper_psubsh(t0, t0, t1);
5579 break;
5580 case OPC_PSUBUSH:
5581 gen_helper_psubush(t0, t0, t1);
5582 break;
5583 case OPC_PSUBH:
5584 gen_helper_psubh(t0, t0, t1);
5585 break;
5586 case OPC_PSUBW:
5587 gen_helper_psubw(t0, t0, t1);
5588 break;
5589 case OPC_PSUBSB:
5590 gen_helper_psubsb(t0, t0, t1);
5591 break;
5592 case OPC_PSUBUSB:
5593 gen_helper_psubusb(t0, t0, t1);
5594 break;
5595 case OPC_PSUBB:
5596 gen_helper_psubb(t0, t0, t1);
5597 break;
5598
5599 case OPC_PSHUFH:
5600 gen_helper_pshufh(t0, t0, t1);
5601 break;
5602 case OPC_PACKSSWH:
5603 gen_helper_packsswh(t0, t0, t1);
5604 break;
5605 case OPC_PACKSSHB:
5606 gen_helper_packsshb(t0, t0, t1);
5607 break;
5608 case OPC_PACKUSHB:
5609 gen_helper_packushb(t0, t0, t1);
5610 break;
5611
5612 case OPC_PUNPCKLHW:
5613 gen_helper_punpcklhw(t0, t0, t1);
5614 break;
5615 case OPC_PUNPCKHHW:
5616 gen_helper_punpckhhw(t0, t0, t1);
5617 break;
5618 case OPC_PUNPCKLBH:
5619 gen_helper_punpcklbh(t0, t0, t1);
5620 break;
5621 case OPC_PUNPCKHBH:
5622 gen_helper_punpckhbh(t0, t0, t1);
5623 break;
5624 case OPC_PUNPCKLWD:
5625 gen_helper_punpcklwd(t0, t0, t1);
5626 break;
5627 case OPC_PUNPCKHWD:
5628 gen_helper_punpckhwd(t0, t0, t1);
5629 break;
5630
5631 case OPC_PAVGH:
5632 gen_helper_pavgh(t0, t0, t1);
5633 break;
5634 case OPC_PAVGB:
5635 gen_helper_pavgb(t0, t0, t1);
5636 break;
5637 case OPC_PMAXSH:
5638 gen_helper_pmaxsh(t0, t0, t1);
5639 break;
5640 case OPC_PMINSH:
5641 gen_helper_pminsh(t0, t0, t1);
5642 break;
5643 case OPC_PMAXUB:
5644 gen_helper_pmaxub(t0, t0, t1);
5645 break;
5646 case OPC_PMINUB:
5647 gen_helper_pminub(t0, t0, t1);
5648 break;
5649
5650 case OPC_PCMPEQW:
5651 gen_helper_pcmpeqw(t0, t0, t1);
5652 break;
5653 case OPC_PCMPGTW:
5654 gen_helper_pcmpgtw(t0, t0, t1);
5655 break;
5656 case OPC_PCMPEQH:
5657 gen_helper_pcmpeqh(t0, t0, t1);
5658 break;
5659 case OPC_PCMPGTH:
5660 gen_helper_pcmpgth(t0, t0, t1);
5661 break;
5662 case OPC_PCMPEQB:
5663 gen_helper_pcmpeqb(t0, t0, t1);
5664 break;
5665 case OPC_PCMPGTB:
5666 gen_helper_pcmpgtb(t0, t0, t1);
5667 break;
5668
5669 case OPC_PSLLW:
5670 gen_helper_psllw(t0, t0, t1);
5671 break;
5672 case OPC_PSLLH:
5673 gen_helper_psllh(t0, t0, t1);
5674 break;
5675 case OPC_PSRLW:
5676 gen_helper_psrlw(t0, t0, t1);
5677 break;
5678 case OPC_PSRLH:
5679 gen_helper_psrlh(t0, t0, t1);
5680 break;
5681 case OPC_PSRAW:
5682 gen_helper_psraw(t0, t0, t1);
5683 break;
5684 case OPC_PSRAH:
5685 gen_helper_psrah(t0, t0, t1);
5686 break;
5687
5688 case OPC_PMULLH:
5689 gen_helper_pmullh(t0, t0, t1);
5690 break;
5691 case OPC_PMULHH:
5692 gen_helper_pmulhh(t0, t0, t1);
5693 break;
5694 case OPC_PMULHUH:
5695 gen_helper_pmulhuh(t0, t0, t1);
5696 break;
5697 case OPC_PMADDHW:
5698 gen_helper_pmaddhw(t0, t0, t1);
5699 break;
5700
5701 case OPC_PASUBUB:
5702 gen_helper_pasubub(t0, t0, t1);
5703 break;
5704 case OPC_BIADD:
5705 gen_helper_biadd(t0, t0);
5706 break;
5707 case OPC_PMOVMSKB:
5708 gen_helper_pmovmskb(t0, t0);
5709 break;
5710
5711 case OPC_PADDD:
5712 tcg_gen_add_i64(t0, t0, t1);
5713 break;
5714 case OPC_PSUBD:
5715 tcg_gen_sub_i64(t0, t0, t1);
5716 break;
5717 case OPC_XOR_CP2:
5718 tcg_gen_xor_i64(t0, t0, t1);
5719 break;
5720 case OPC_NOR_CP2:
5721 tcg_gen_nor_i64(t0, t0, t1);
5722 break;
5723 case OPC_AND_CP2:
5724 tcg_gen_and_i64(t0, t0, t1);
5725 break;
5726 case OPC_OR_CP2:
5727 tcg_gen_or_i64(t0, t0, t1);
5728 break;
bd277fa1 5729
9099a36b
H
5730 case OPC_PANDN:
5731 tcg_gen_andc_i64(t0, t1, t0);
5732 break;
5733
bd277fa1
RH
5734 case OPC_PINSRH_0:
5735 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5736 break;
5737 case OPC_PINSRH_1:
5738 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5739 break;
5740 case OPC_PINSRH_2:
5741 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5742 break;
5743 case OPC_PINSRH_3:
5744 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5745 break;
5746
5747 case OPC_PEXTRH:
5748 tcg_gen_andi_i64(t1, t1, 3);
5749 tcg_gen_shli_i64(t1, t1, 4);
5750 tcg_gen_shr_i64(t0, t0, t1);
5751 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5752 break;
5753
5754 case OPC_ADDU_CP2:
5755 tcg_gen_add_i64(t0, t0, t1);
5756 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5757 break;
5758 case OPC_SUBU_CP2:
5759 tcg_gen_sub_i64(t0, t0, t1);
5760 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5761 break;
5762
5763 case OPC_SLL_CP2:
bd277fa1
RH
5764 shift_max = 32;
5765 goto do_shift;
5766 case OPC_SRL_CP2:
bd277fa1
RH
5767 shift_max = 32;
5768 goto do_shift;
5769 case OPC_SRA_CP2:
bd277fa1
RH
5770 shift_max = 32;
5771 goto do_shift;
5772 case OPC_DSLL_CP2:
bd277fa1
RH
5773 shift_max = 64;
5774 goto do_shift;
5775 case OPC_DSRL_CP2:
bd277fa1
RH
5776 shift_max = 64;
5777 goto do_shift;
5778 case OPC_DSRA_CP2:
bd277fa1
RH
5779 shift_max = 64;
5780 goto do_shift;
5781 do_shift:
5782 /* Make sure shift count isn't TCG undefined behaviour. */
5783 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5784
5785 switch (opc) {
5786 case OPC_SLL_CP2:
5787 case OPC_DSLL_CP2:
5788 tcg_gen_shl_i64(t0, t0, t1);
5789 break;
5790 case OPC_SRA_CP2:
5791 case OPC_DSRA_CP2:
7480515f
AM
5792 /*
5793 * Since SRA is UndefinedResult without sign-extended inputs,
5794 * we can treat SRA and DSRA the same.
5795 */
bd277fa1
RH
5796 tcg_gen_sar_i64(t0, t0, t1);
5797 break;
5798 case OPC_SRL_CP2:
5799 /* We want to shift in zeros for SRL; zero-extend first. */
5800 tcg_gen_ext32u_i64(t0, t0);
5801 /* FALLTHRU */
5802 case OPC_DSRL_CP2:
5803 tcg_gen_shr_i64(t0, t0, t1);
5804 break;
5805 }
5806
5807 if (shift_max == 32) {
5808 tcg_gen_ext32s_i64(t0, t0);
5809 }
5810
5811 /* Shifts larger than MAX produce zero. */
5812 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5813 tcg_gen_neg_i64(t1, t1);
5814 tcg_gen_and_i64(t0, t0, t1);
5815 break;
5816
5817 case OPC_ADD_CP2:
5818 case OPC_DADD_CP2:
5819 {
5820 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5821 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5822
5823 tcg_gen_mov_i64(t2, t0);
5824 tcg_gen_add_i64(t0, t1, t2);
5825 if (opc == OPC_ADD_CP2) {
5826 tcg_gen_ext32s_i64(t0, t0);
5827 }
5828 tcg_gen_xor_i64(t1, t1, t2);
5829 tcg_gen_xor_i64(t2, t2, t0);
5830 tcg_gen_andc_i64(t1, t2, t1);
5831 tcg_temp_free_i64(t2);
5832 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5833 generate_exception(ctx, EXCP_OVERFLOW);
5834 gen_set_label(lab);
bd277fa1
RH
5835 break;
5836 }
5837
5838 case OPC_SUB_CP2:
5839 case OPC_DSUB_CP2:
5840 {
5841 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5842 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5843
5844 tcg_gen_mov_i64(t2, t0);
5845 tcg_gen_sub_i64(t0, t1, t2);
5846 if (opc == OPC_SUB_CP2) {
5847 tcg_gen_ext32s_i64(t0, t0);
5848 }
5849 tcg_gen_xor_i64(t1, t1, t2);
5850 tcg_gen_xor_i64(t2, t2, t0);
5851 tcg_gen_and_i64(t1, t1, t2);
5852 tcg_temp_free_i64(t2);
5853 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5854 generate_exception(ctx, EXCP_OVERFLOW);
5855 gen_set_label(lab);
bd277fa1
RH
5856 break;
5857 }
5858
5859 case OPC_PMULUW:
5860 tcg_gen_ext32u_i64(t0, t0);
5861 tcg_gen_ext32u_i64(t1, t1);
5862 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5863 break;
5864
5865 case OPC_SEQU_CP2:
5866 case OPC_SEQ_CP2:
84878f4c
JY
5867 cond = TCG_COND_EQ;
5868 goto do_cc_cond;
5869 break;
bd277fa1 5870 case OPC_SLTU_CP2:
84878f4c
JY
5871 cond = TCG_COND_LTU;
5872 goto do_cc_cond;
5873 break;
bd277fa1 5874 case OPC_SLT_CP2:
84878f4c
JY
5875 cond = TCG_COND_LT;
5876 goto do_cc_cond;
5877 break;
bd277fa1 5878 case OPC_SLEU_CP2:
84878f4c
JY
5879 cond = TCG_COND_LEU;
5880 goto do_cc_cond;
5881 break;
bd277fa1 5882 case OPC_SLE_CP2:
84878f4c
JY
5883 cond = TCG_COND_LE;
5884 do_cc_cond:
5885 {
5886 int cc = (ctx->opcode >> 8) & 0x7;
5887 TCGv_i64 t64 = tcg_temp_new_i64();
5888 TCGv_i32 t32 = tcg_temp_new_i32();
5889
5890 tcg_gen_setcond_i64(cond, t64, t0, t1);
5891 tcg_gen_extrl_i64_i32(t32, t64);
5892 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5893 get_fp_bit(cc), 1);
5894
5895 tcg_temp_free_i32(t32);
5896 tcg_temp_free_i64(t64);
5897 }
5898 goto no_rd;
5899 break;
bd277fa1 5900 default:
9d68ac14 5901 MIPS_INVAL("loongson_cp2");
9c708c7f 5902 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5903 return;
5904 }
5905
bd277fa1
RH
5906 gen_store_fpr64(ctx, t0, rd);
5907
84878f4c 5908no_rd:
bd277fa1
RH
5909 tcg_temp_free_i64(t0);
5910 tcg_temp_free_i64(t1);
5911}
5912
6af0bf9c 5913/* Traps */
71375b59
AM
5914static void gen_trap(DisasContext *ctx, uint32_t opc,
5915 int rs, int rt, int16_t imm)
6af0bf9c
FB
5916{
5917 int cond;
cdc0faa6 5918 TCGv t0 = tcg_temp_new();
1ba74fb8 5919 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5920
5921 cond = 0;
5922 /* Load needed operands */
5923 switch (opc) {
5924 case OPC_TEQ:
5925 case OPC_TGE:
5926 case OPC_TGEU:
5927 case OPC_TLT:
5928 case OPC_TLTU:
5929 case OPC_TNE:
5930 /* Compare two registers */
5931 if (rs != rt) {
be24bb4f
TS
5932 gen_load_gpr(t0, rs);
5933 gen_load_gpr(t1, rt);
6af0bf9c
FB
5934 cond = 1;
5935 }
179e32bb 5936 break;
6af0bf9c
FB
5937 case OPC_TEQI:
5938 case OPC_TGEI:
5939 case OPC_TGEIU:
5940 case OPC_TLTI:
5941 case OPC_TLTIU:
5942 case OPC_TNEI:
5943 /* Compare register to immediate */
5944 if (rs != 0 || imm != 0) {
be24bb4f
TS
5945 gen_load_gpr(t0, rs);
5946 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5947 cond = 1;
5948 }
5949 break;
5950 }
5951 if (cond == 0) {
5952 switch (opc) {
5953 case OPC_TEQ: /* rs == rs */
5954 case OPC_TEQI: /* r0 == 0 */
5955 case OPC_TGE: /* rs >= rs */
5956 case OPC_TGEI: /* r0 >= 0 */
5957 case OPC_TGEU: /* rs >= rs unsigned */
5958 case OPC_TGEIU: /* r0 >= 0 unsigned */
5959 /* Always trap */
9c708c7f 5960 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5961 break;
5962 case OPC_TLT: /* rs < rs */
5963 case OPC_TLTI: /* r0 < 0 */
5964 case OPC_TLTU: /* rs < rs unsigned */
5965 case OPC_TLTIU: /* r0 < 0 unsigned */
5966 case OPC_TNE: /* rs != rs */
5967 case OPC_TNEI: /* r0 != 0 */
ead9360e 5968 /* Never trap: treat as NOP. */
cdc0faa6 5969 break;
6af0bf9c
FB
5970 }
5971 } else {
42a268c2 5972 TCGLabel *l1 = gen_new_label();
cdc0faa6 5973
6af0bf9c
FB
5974 switch (opc) {
5975 case OPC_TEQ:
5976 case OPC_TEQI:
cdc0faa6 5977 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5978 break;
5979 case OPC_TGE:
5980 case OPC_TGEI:
cdc0faa6 5981 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5982 break;
5983 case OPC_TGEU:
5984 case OPC_TGEIU:
cdc0faa6 5985 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5986 break;
5987 case OPC_TLT:
5988 case OPC_TLTI:
cdc0faa6 5989 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5990 break;
5991 case OPC_TLTU:
5992 case OPC_TLTIU:
cdc0faa6 5993 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5994 break;
5995 case OPC_TNE:
5996 case OPC_TNEI:
cdc0faa6 5997 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5998 break;
6af0bf9c 5999 }
cdc0faa6 6000 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
6001 gen_set_label(l1);
6002 }
be24bb4f
TS
6003 tcg_temp_free(t0);
6004 tcg_temp_free(t1);
6af0bf9c
FB
6005}
6006
90aa39a1
SF
6007static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6008{
eeb3bba8 6009 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
6010 return false;
6011 }
6012
6013#ifndef CONFIG_USER_ONLY
eeb3bba8 6014 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
6015#else
6016 return true;
6017#endif
6018}
6019
356265ae 6020static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 6021{
90aa39a1 6022 if (use_goto_tb(ctx, dest)) {
57fec1fe 6023 tcg_gen_goto_tb(n);
9b9e4393 6024 gen_save_pc(dest);
07ea28b4 6025 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 6026 } else {
9b9e4393 6027 gen_save_pc(dest);
eeb3bba8 6028 if (ctx->base.singlestep_enabled) {
7b270ef2 6029 save_cpu_state(ctx, 0);
9c708c7f 6030 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 6031 }
7f11636d 6032 tcg_gen_lookup_and_goto_ptr();
6e256c93 6033 }
c53be334
FB
6034}
6035
6af0bf9c 6036/* Branches (before delay slot) */
71375b59
AM
6037static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6038 int insn_bytes,
6039 int rs, int rt, int32_t offset,
6040 int delayslot_size)
6af0bf9c 6041{
d077b6f7 6042 target_ulong btgt = -1;
3ad4bb2d 6043 int blink = 0;
2fdbad25 6044 int bcond_compute = 0;
1ba74fb8
AJ
6045 TCGv t0 = tcg_temp_new();
6046 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
6047
6048 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 6049#ifdef MIPS_DEBUG_DISAS
339cd2a8 6050 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 6051 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 6052#endif
9c708c7f 6053 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6054 goto out;
3ad4bb2d 6055 }
6af0bf9c 6056
6af0bf9c
FB
6057 /* Load needed operands */
6058 switch (opc) {
6059 case OPC_BEQ:
6060 case OPC_BEQL:
6061 case OPC_BNE:
6062 case OPC_BNEL:
6063 /* Compare two registers */
6064 if (rs != rt) {
6c5c1e20
TS
6065 gen_load_gpr(t0, rs);
6066 gen_load_gpr(t1, rt);
2fdbad25 6067 bcond_compute = 1;
6af0bf9c 6068 }
eeb3bba8 6069 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
6070 break;
6071 case OPC_BGEZ:
6072 case OPC_BGEZAL:
6073 case OPC_BGEZALL:
6074 case OPC_BGEZL:
6075 case OPC_BGTZ:
6076 case OPC_BGTZL:
6077 case OPC_BLEZ:
6078 case OPC_BLEZL:
6079 case OPC_BLTZ:
6080 case OPC_BLTZAL:
6081 case OPC_BLTZALL:
6082 case OPC_BLTZL:
6083 /* Compare to zero */
6084 if (rs != 0) {
6c5c1e20 6085 gen_load_gpr(t0, rs);
2fdbad25 6086 bcond_compute = 1;
6af0bf9c 6087 }
eeb3bba8 6088 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 6089 break;
e45a93e2
JL
6090 case OPC_BPOSGE32:
6091#if defined(TARGET_MIPS64)
6092 case OPC_BPOSGE64:
6093 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6094#else
6095 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6096#endif
6097 bcond_compute = 1;
eeb3bba8 6098 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 6099 break;
6af0bf9c
FB
6100 case OPC_J:
6101 case OPC_JAL:
364d4831 6102 case OPC_JALX:
6af0bf9c 6103 /* Jump to immediate */
eeb3bba8
EC
6104 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6105 (uint32_t)offset;
6af0bf9c
FB
6106 break;
6107 case OPC_JR:
6108 case OPC_JALR:
6109 /* Jump to register */
7a387fff 6110 if (offset != 0 && offset != 16) {
7480515f
AM
6111 /*
6112 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6113 * others are reserved.
6114 */
923617a3 6115 MIPS_INVAL("jump hint");
9c708c7f 6116 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6117 goto out;
6af0bf9c 6118 }
d077b6f7 6119 gen_load_gpr(btarget, rs);
6af0bf9c
FB
6120 break;
6121 default:
6122 MIPS_INVAL("branch/jump");
9c708c7f 6123 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6124 goto out;
6af0bf9c 6125 }
2fdbad25 6126 if (bcond_compute == 0) {
6af0bf9c
FB
6127 /* No condition to be computed */
6128 switch (opc) {
6129 case OPC_BEQ: /* rx == rx */
6130 case OPC_BEQL: /* rx == rx likely */
6131 case OPC_BGEZ: /* 0 >= 0 */
6132 case OPC_BGEZL: /* 0 >= 0 likely */
6133 case OPC_BLEZ: /* 0 <= 0 */
6134 case OPC_BLEZL: /* 0 <= 0 likely */
6135 /* Always take */
4ad40f36 6136 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6137 break;
6138 case OPC_BGEZAL: /* 0 >= 0 */
6139 case OPC_BGEZALL: /* 0 >= 0 likely */
6140 /* Always take and link */
6141 blink = 31;
4ad40f36 6142 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6143 break;
6144 case OPC_BNE: /* rx != rx */
6145 case OPC_BGTZ: /* 0 > 0 */
6146 case OPC_BLTZ: /* 0 < 0 */
ead9360e 6147 /* Treat as NOP. */
6c5c1e20 6148 goto out;
eeef26cd 6149 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
6150 /*
6151 * Handle as an unconditional branch to get correct delay
6152 * slot checking.
6153 */
3c824109 6154 blink = 31;
eeb3bba8 6155 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 6156 ctx->hflags |= MIPS_HFLAG_B;
3c824109 6157 break;
eeef26cd 6158 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 6159 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 6160 /* Skip the instruction in the delay slot */
eeb3bba8 6161 ctx->base.pc_next += 4;
6c5c1e20 6162 goto out;
6af0bf9c
FB
6163 case OPC_BNEL: /* rx != rx likely */
6164 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
6165 case OPC_BLTZL: /* 0 < 0 likely */
6166 /* Skip the instruction in the delay slot */
eeb3bba8 6167 ctx->base.pc_next += 4;
6c5c1e20 6168 goto out;
6af0bf9c 6169 case OPC_J:
4ad40f36 6170 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 6171 break;
364d4831
NF
6172 case OPC_JALX:
6173 ctx->hflags |= MIPS_HFLAG_BX;
6174 /* Fallthrough */
6af0bf9c
FB
6175 case OPC_JAL:
6176 blink = 31;
4ad40f36 6177 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6178 break;
6179 case OPC_JR:
4ad40f36 6180 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6181 break;
6182 case OPC_JALR:
6183 blink = rt;
4ad40f36 6184 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6185 break;
6186 default:
6187 MIPS_INVAL("branch/jump");
9c708c7f 6188 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6189 goto out;
6af0bf9c
FB
6190 }
6191 } else {
6192 switch (opc) {
6193 case OPC_BEQ:
e68dd28f 6194 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6195 goto not_likely;
6196 case OPC_BEQL:
e68dd28f 6197 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6198 goto likely;
6199 case OPC_BNE:
e68dd28f 6200 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6201 goto not_likely;
6202 case OPC_BNEL:
e68dd28f 6203 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6204 goto likely;
6205 case OPC_BGEZ:
e68dd28f 6206 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6207 goto not_likely;
6208 case OPC_BGEZL:
e68dd28f 6209 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6210 goto likely;
6211 case OPC_BGEZAL:
e68dd28f 6212 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6213 blink = 31;
6214 goto not_likely;
6215 case OPC_BGEZALL:
e68dd28f 6216 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6217 blink = 31;
6af0bf9c
FB
6218 goto likely;
6219 case OPC_BGTZ:
e68dd28f 6220 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6221 goto not_likely;
6222 case OPC_BGTZL:
e68dd28f 6223 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6224 goto likely;
6225 case OPC_BLEZ:
e68dd28f 6226 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6227 goto not_likely;
6228 case OPC_BLEZL:
e68dd28f 6229 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6230 goto likely;
6231 case OPC_BLTZ:
e68dd28f 6232 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6233 goto not_likely;
6234 case OPC_BLTZL:
e68dd28f 6235 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6236 goto likely;
e45a93e2
JL
6237 case OPC_BPOSGE32:
6238 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6239 goto not_likely;
6240#if defined(TARGET_MIPS64)
6241 case OPC_BPOSGE64:
6242 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6243 goto not_likely;
6244#endif
6af0bf9c 6245 case OPC_BLTZAL:
e68dd28f 6246 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6247 blink = 31;
6af0bf9c 6248 not_likely:
4ad40f36 6249 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6250 break;
6251 case OPC_BLTZALL:
e68dd28f 6252 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6253 blink = 31;
6af0bf9c 6254 likely:
4ad40f36 6255 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6256 break;
c53f4a62
TS
6257 default:
6258 MIPS_INVAL("conditional branch/jump");
9c708c7f 6259 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6260 goto out;
6af0bf9c 6261 }
6af0bf9c 6262 }
9b9e4393 6263
d077b6f7 6264 ctx->btarget = btgt;
b231c103
YK
6265
6266 switch (delayslot_size) {
6267 case 2:
6268 ctx->hflags |= MIPS_HFLAG_BDS16;
6269 break;
6270 case 4:
6271 ctx->hflags |= MIPS_HFLAG_BDS32;
6272 break;
6273 }
6274
6af0bf9c 6275 if (blink > 0) {
b231c103 6276 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6277 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6278
eeb3bba8
EC
6279 tcg_gen_movi_tl(cpu_gpr[blink],
6280 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6281 }
6c5c1e20
TS
6282
6283 out:
1f8929d2 6284 if (insn_bytes == 2) {
364d4831 6285 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 6286 }
6c5c1e20
TS
6287 tcg_temp_free(t0);
6288 tcg_temp_free(t1);
6af0bf9c
FB
6289}
6290
764371d2
SM
6291
6292/* nanoMIPS Branches */
6293static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6294 int insn_bytes,
6295 int rs, int rt, int32_t offset)
6296{
6297 target_ulong btgt = -1;
6298 int bcond_compute = 0;
6299 TCGv t0 = tcg_temp_new();
6300 TCGv t1 = tcg_temp_new();
6301
6302 /* Load needed operands */
6303 switch (opc) {
6304 case OPC_BEQ:
6305 case OPC_BNE:
6306 /* Compare two registers */
6307 if (rs != rt) {
6308 gen_load_gpr(t0, rs);
6309 gen_load_gpr(t1, rt);
6310 bcond_compute = 1;
6311 }
6312 btgt = ctx->base.pc_next + insn_bytes + offset;
6313 break;
6314 case OPC_BGEZAL:
6315 /* Compare to zero */
6316 if (rs != 0) {
6317 gen_load_gpr(t0, rs);
6318 bcond_compute = 1;
6319 }
6320 btgt = ctx->base.pc_next + insn_bytes + offset;
6321 break;
6322 case OPC_BPOSGE32:
6323 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6324 bcond_compute = 1;
6325 btgt = ctx->base.pc_next + insn_bytes + offset;
6326 break;
6327 case OPC_JR:
6328 case OPC_JALR:
6329 /* Jump to register */
6330 if (offset != 0 && offset != 16) {
7480515f
AM
6331 /*
6332 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6333 * others are reserved.
6334 */
764371d2
SM
6335 MIPS_INVAL("jump hint");
6336 generate_exception_end(ctx, EXCP_RI);
6337 goto out;
6338 }
6339 gen_load_gpr(btarget, rs);
6340 break;
6341 default:
6342 MIPS_INVAL("branch/jump");
6343 generate_exception_end(ctx, EXCP_RI);
6344 goto out;
6345 }
6346 if (bcond_compute == 0) {
6347 /* No condition to be computed */
6348 switch (opc) {
6349 case OPC_BEQ: /* rx == rx */
6350 /* Always take */
6351 ctx->hflags |= MIPS_HFLAG_B;
6352 break;
6353 case OPC_BGEZAL: /* 0 >= 0 */
6354 /* Always take and link */
6355 tcg_gen_movi_tl(cpu_gpr[31],
6356 ctx->base.pc_next + insn_bytes);
6357 ctx->hflags |= MIPS_HFLAG_B;
6358 break;
6359 case OPC_BNE: /* rx != rx */
6360 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6361 /* Skip the instruction in the delay slot */
6362 ctx->base.pc_next += 4;
6363 goto out;
6364 case OPC_JR:
6365 ctx->hflags |= MIPS_HFLAG_BR;
6366 break;
6367 case OPC_JALR:
6368 if (rt > 0) {
6369 tcg_gen_movi_tl(cpu_gpr[rt],
6370 ctx->base.pc_next + insn_bytes);
6371 }
6372 ctx->hflags |= MIPS_HFLAG_BR;
6373 break;
6374 default:
6375 MIPS_INVAL("branch/jump");
6376 generate_exception_end(ctx, EXCP_RI);
6377 goto out;
6378 }
6379 } else {
6380 switch (opc) {
6381 case OPC_BEQ:
6382 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6383 goto not_likely;
6384 case OPC_BNE:
6385 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6386 goto not_likely;
6387 case OPC_BGEZAL:
6388 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6389 tcg_gen_movi_tl(cpu_gpr[31],
6390 ctx->base.pc_next + insn_bytes);
6391 goto not_likely;
6392 case OPC_BPOSGE32:
6393 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6394 not_likely:
6395 ctx->hflags |= MIPS_HFLAG_BC;
6396 break;
6397 default:
6398 MIPS_INVAL("conditional branch/jump");
6399 generate_exception_end(ctx, EXCP_RI);
6400 goto out;
6401 }
6402 }
6403
6404 ctx->btarget = btgt;
6405
6406 out:
6407 if (insn_bytes == 2) {
6408 ctx->hflags |= MIPS_HFLAG_B16;
6409 }
6410 tcg_temp_free(t0);
6411 tcg_temp_free(t1);
6412}
6413
6414
7a387fff 6415/* special3 bitfield operations */
235785e8
AM
6416static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6417 int rs, int lsb, int msb)
7a387fff 6418{
a7812ae4
PB
6419 TCGv t0 = tcg_temp_new();
6420 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6421
6422 gen_load_gpr(t1, rs);
7a387fff
TS
6423 switch (opc) {
6424 case OPC_EXT:
b7f26e52 6425 if (lsb + msb > 31) {
7a387fff 6426 goto fail;
b7f26e52 6427 }
505ad7c2 6428 if (msb != 31) {
6eebb7a4 6429 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6430 } else {
7480515f
AM
6431 /*
6432 * The two checks together imply that lsb == 0,
6433 * so this is a simple sign-extension.
6434 */
6eebb7a4 6435 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6436 }
7a387fff 6437 break;
c6d6dd7c 6438#if defined(TARGET_MIPS64)
7a387fff 6439 case OPC_DEXTU:
b7f26e52
RH
6440 lsb += 32;
6441 goto do_dext;
6442 case OPC_DEXTM:
6443 msb += 32;
6444 goto do_dext;
7a387fff 6445 case OPC_DEXT:
b7f26e52
RH
6446 do_dext:
6447 if (lsb + msb > 63) {
6448 goto fail;
6449 }
6eebb7a4 6450 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6451 break;
c6d6dd7c 6452#endif
7a387fff 6453 case OPC_INS:
b7f26e52 6454 if (lsb > msb) {
7a387fff 6455 goto fail;
b7f26e52 6456 }
6c5c1e20 6457 gen_load_gpr(t0, rt);
e0d002f1 6458 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6459 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6460 break;
c6d6dd7c 6461#if defined(TARGET_MIPS64)
7a387fff 6462 case OPC_DINSU:
b7f26e52
RH
6463 lsb += 32;
6464 /* FALLTHRU */
6465 case OPC_DINSM:
6466 msb += 32;
6467 /* FALLTHRU */
7a387fff 6468 case OPC_DINS:
b7f26e52
RH
6469 if (lsb > msb) {
6470 goto fail;
6471 }
6c5c1e20 6472 gen_load_gpr(t0, rt);
e0d002f1 6473 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6474 break;
c6d6dd7c 6475#endif
7a387fff
TS
6476 default:
6477fail:
6478 MIPS_INVAL("bitops");
9c708c7f 6479 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6480 tcg_temp_free(t0);
6481 tcg_temp_free(t1);
7a387fff
TS
6482 return;
6483 }
6c5c1e20
TS
6484 gen_store_gpr(t0, rt);
6485 tcg_temp_free(t0);
6486 tcg_temp_free(t1);
7a387fff
TS
6487}
6488
235785e8 6489static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 6490{
3a55fa47 6491 TCGv t0;
49bcf33c 6492
3a55fa47
AJ
6493 if (rd == 0) {
6494 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6495 return;
6496 }
6497
6498 t0 = tcg_temp_new();
6499 gen_load_gpr(t0, rt);
49bcf33c
AJ
6500 switch (op2) {
6501 case OPC_WSBH:
3a55fa47
AJ
6502 {
6503 TCGv t1 = tcg_temp_new();
06a57e5c 6504 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6505
6506 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6507 tcg_gen_and_tl(t1, t1, t2);
6508 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6509 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6510 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6511 tcg_temp_free(t2);
3a55fa47
AJ
6512 tcg_temp_free(t1);
6513 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6514 }
49bcf33c
AJ
6515 break;
6516 case OPC_SEB:
3a55fa47 6517 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6518 break;
6519 case OPC_SEH:
3a55fa47 6520 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6521 break;
6522#if defined(TARGET_MIPS64)
6523 case OPC_DSBH:
3a55fa47
AJ
6524 {
6525 TCGv t1 = tcg_temp_new();
06a57e5c 6526 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6527
6528 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6529 tcg_gen_and_tl(t1, t1, t2);
6530 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6531 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6532 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6533 tcg_temp_free(t2);
3a55fa47
AJ
6534 tcg_temp_free(t1);
6535 }
49bcf33c
AJ
6536 break;
6537 case OPC_DSHD:
3a55fa47
AJ
6538 {
6539 TCGv t1 = tcg_temp_new();
06a57e5c 6540 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6541
6542 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6543 tcg_gen_and_tl(t1, t1, t2);
6544 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6545 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6546 tcg_gen_or_tl(t0, t0, t1);
6547 tcg_gen_shri_tl(t1, t0, 32);
6548 tcg_gen_shli_tl(t0, t0, 32);
6549 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6550 tcg_temp_free(t2);
3a55fa47
AJ
6551 tcg_temp_free(t1);
6552 }
49bcf33c
AJ
6553 break;
6554#endif
6555 default:
6556 MIPS_INVAL("bsfhl");
9c708c7f 6557 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6558 tcg_temp_free(t0);
49bcf33c
AJ
6559 return;
6560 }
49bcf33c 6561 tcg_temp_free(t0);
49bcf33c
AJ
6562}
6563
1f1b4c00
YK
6564static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6565 int imm2)
6566{
6567 TCGv t0;
6568 TCGv t1;
6569 if (rd == 0) {
6570 /* Treat as NOP. */
6571 return;
6572 }
6573 t0 = tcg_temp_new();
6574 t1 = tcg_temp_new();
6575 gen_load_gpr(t0, rs);
6576 gen_load_gpr(t1, rt);
6577 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6578 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6579 if (opc == OPC_LSA) {
6580 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6581 }
6582
6583 tcg_temp_free(t1);
6584 tcg_temp_free(t0);
6585
6586 return;
6587}
6588
821f2008
JH
6589static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6590 int rt, int bits)
284b731a 6591{
1f1b4c00
YK
6592 TCGv t0;
6593 if (rd == 0) {
6594 /* Treat as NOP. */
6595 return;
6596 }
6597 t0 = tcg_temp_new();
821f2008
JH
6598 if (bits == 0 || bits == wordsz) {
6599 if (bits == 0) {
6600 gen_load_gpr(t0, rt);
6601 } else {
6602 gen_load_gpr(t0, rs);
6603 }
6604 switch (wordsz) {
6605 case 32:
51243852
MD
6606 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6607 break;
6608#if defined(TARGET_MIPS64)
821f2008 6609 case 64:
51243852
MD
6610 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6611 break;
6612#endif
6613 }
1f1b4c00
YK
6614 } else {
6615 TCGv t1 = tcg_temp_new();
821f2008 6616 gen_load_gpr(t0, rt);
1f1b4c00 6617 gen_load_gpr(t1, rs);
821f2008
JH
6618 switch (wordsz) {
6619 case 32:
1f1b4c00
YK
6620 {
6621 TCGv_i64 t2 = tcg_temp_new_i64();
6622 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6623 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6624 gen_move_low32(cpu_gpr[rd], t2);
6625 tcg_temp_free_i64(t2);
6626 }
6627 break;
284b731a 6628#if defined(TARGET_MIPS64)
821f2008
JH
6629 case 64:
6630 tcg_gen_shli_tl(t0, t0, bits);
6631 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6632 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6633 break;
284b731a 6634#endif
1f1b4c00
YK
6635 }
6636 tcg_temp_free(t1);
6637 }
6638
6639 tcg_temp_free(t0);
6640}
6641
821f2008
JH
6642static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6643 int bp)
6644{
6645 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6646}
6647
6648static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6649 int shift)
6650{
6651 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6652}
6653
1f1b4c00
YK
6654static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6655{
6656 TCGv t0;
6657 if (rd == 0) {
6658 /* Treat as NOP. */
6659 return;
6660 }
6661 t0 = tcg_temp_new();
6662 gen_load_gpr(t0, rt);
6663 switch (opc) {
6664 case OPC_BITSWAP:
6665 gen_helper_bitswap(cpu_gpr[rd], t0);
6666 break;
6667#if defined(TARGET_MIPS64)
6668 case OPC_DBITSWAP:
6669 gen_helper_dbitswap(cpu_gpr[rd], t0);
6670 break;
6671#endif
6672 }
6673 tcg_temp_free(t0);
284b731a
LA
6674}
6675
1f1b4c00
YK
6676#ifndef CONFIG_USER_ONLY
6677/* CP0 (MMU and control) */
5204ea79
LA
6678static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6679{
6680 TCGv_i64 t0 = tcg_temp_new_i64();
6681 TCGv_i64 t1 = tcg_temp_new_i64();
6682
6683 tcg_gen_ext_tl_i64(t0, arg);
6684 tcg_gen_ld_i64(t1, cpu_env, off);
6685#if defined(TARGET_MIPS64)
6686 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6687#else
6688 tcg_gen_concat32_i64(t1, t1, t0);
6689#endif
6690 tcg_gen_st_i64(t1, cpu_env, off);
6691 tcg_temp_free_i64(t1);
6692 tcg_temp_free_i64(t0);
6693}
6694
6695static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6696{
6697 TCGv_i64 t0 = tcg_temp_new_i64();
6698 TCGv_i64 t1 = tcg_temp_new_i64();
6699
6700 tcg_gen_ext_tl_i64(t0, arg);
6701 tcg_gen_ld_i64(t1, cpu_env, off);
6702 tcg_gen_concat32_i64(t1, t1, t0);
6703 tcg_gen_st_i64(t1, cpu_env, off);
6704 tcg_temp_free_i64(t1);
6705 tcg_temp_free_i64(t0);
6706}
6707
6708static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6709{
6710 TCGv_i64 t0 = tcg_temp_new_i64();
6711
6712 tcg_gen_ld_i64(t0, cpu_env, off);
6713#if defined(TARGET_MIPS64)
6714 tcg_gen_shri_i64(t0, t0, 30);
6715#else
6716 tcg_gen_shri_i64(t0, t0, 32);
6717#endif
6718 gen_move_low32(arg, t0);
6719 tcg_temp_free_i64(t0);
6720}
6721
6722static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6723{
6724 TCGv_i64 t0 = tcg_temp_new_i64();
6725
6726 tcg_gen_ld_i64(t0, cpu_env, off);
6727 tcg_gen_shri_i64(t0, t0, 32 + shift);
6728 gen_move_low32(arg, t0);
6729 tcg_temp_free_i64(t0);
6730}
6731
235785e8 6732static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 6733{
d9bea114 6734 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6735
d9bea114
AJ
6736 tcg_gen_ld_i32(t0, cpu_env, off);
6737 tcg_gen_ext_i32_tl(arg, t0);
6738 tcg_temp_free_i32(t0);
4f57689a
TS
6739}
6740
235785e8 6741static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 6742{
d9bea114
AJ
6743 tcg_gen_ld_tl(arg, cpu_env, off);
6744 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6745}
6746
235785e8 6747static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 6748{
d9bea114 6749 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6750
d9bea114
AJ
6751 tcg_gen_trunc_tl_i32(t0, arg);
6752 tcg_gen_st_i32(t0, cpu_env, off);
6753 tcg_temp_free_i32(t0);
f1aa6320
TS
6754}
6755
c98d3d79
YK
6756#define CP0_CHECK(c) \
6757 do { \
6758 if (!(c)) { \
6759 goto cp0_unimplemented; \
6760 } \
6761 } while (0)
6762
5204ea79
LA
6763static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6764{
294fc2ea 6765 const char *register_name = "invalid";
5204ea79 6766
5204ea79 6767 switch (reg) {
04992c8c 6768 case CP0_REGISTER_02:
5204ea79
LA
6769 switch (sel) {
6770 case 0:
59488dda 6771 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6772 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6773 register_name = "EntryLo0";
5204ea79
LA
6774 break;
6775 default:
c98d3d79 6776 goto cp0_unimplemented;
5204ea79
LA
6777 }
6778 break;
04992c8c 6779 case CP0_REGISTER_03:
5204ea79 6780 switch (sel) {
acd37316 6781 case CP0_REG03__ENTRYLO1:
59488dda 6782 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6783 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6784 register_name = "EntryLo1";
5204ea79
LA
6785 break;
6786 default:
c98d3d79 6787 goto cp0_unimplemented;
5204ea79
LA
6788 }
6789 break;
04992c8c 6790 case CP0_REGISTER_09:
5fb2dcd1 6791 switch (sel) {
e5a98a72 6792 case CP0_REG09__SAAR:
5fb2dcd1
YK
6793 CP0_CHECK(ctx->saar);
6794 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 6795 register_name = "SAAR";
5fb2dcd1
YK
6796 break;
6797 default:
6798 goto cp0_unimplemented;
6799 }
6800 break;
04992c8c 6801 case CP0_REGISTER_17:
5204ea79 6802 switch (sel) {
706ce142 6803 case CP0_REG17__LLADDR:
c7c7e1e9 6804 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 6805 ctx->CP0_LLAddr_shift);
294fc2ea 6806 register_name = "LLAddr";
5204ea79 6807 break;
706ce142 6808 case CP0_REG17__MAAR:
f6d4dd81
YK
6809 CP0_CHECK(ctx->mrp);
6810 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 6811 register_name = "MAAR";
f6d4dd81 6812 break;
5204ea79 6813 default:
c98d3d79 6814 goto cp0_unimplemented;
5204ea79
LA
6815 }
6816 break;
feafe82c
YK
6817 case CP0_REGISTER_19:
6818 switch (sel) {
6819 case CP0_REG19__WATCHHI0:
6820 case CP0_REG19__WATCHHI1:
6821 case CP0_REG19__WATCHHI2:
6822 case CP0_REG19__WATCHHI3:
6823 case CP0_REG19__WATCHHI4:
6824 case CP0_REG19__WATCHHI5:
6825 case CP0_REG19__WATCHHI6:
6826 case CP0_REG19__WATCHHI7:
6827 /* upper 32 bits are only available when Config5MI != 0 */
6828 CP0_CHECK(ctx->mi);
6829 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6830 register_name = "WatchHi";
6831 break;
6832 default:
6833 goto cp0_unimplemented;
6834 }
6835 break;
04992c8c 6836 case CP0_REGISTER_28:
5204ea79
LA
6837 switch (sel) {
6838 case 0:
6839 case 2:
6840 case 4:
6841 case 6:
6842 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 6843 register_name = "TagLo";
5204ea79
LA
6844 break;
6845 default:
c98d3d79 6846 goto cp0_unimplemented;
5204ea79
LA
6847 }
6848 break;
6849 default:
c98d3d79 6850 goto cp0_unimplemented;
5204ea79 6851 }
294fc2ea 6852 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
6853 return;
6854
c98d3d79 6855cp0_unimplemented:
294fc2ea
AM
6856 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6857 register_name, reg, sel);
5204ea79
LA
6858 tcg_gen_movi_tl(arg, 0);
6859}
6860
6861static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6862{
294fc2ea 6863 const char *register_name = "invalid";
5204ea79
LA
6864 uint64_t mask = ctx->PAMask >> 36;
6865
5204ea79 6866 switch (reg) {
04992c8c 6867 case CP0_REGISTER_02:
5204ea79
LA
6868 switch (sel) {
6869 case 0:
59488dda 6870 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6871 tcg_gen_andi_tl(arg, arg, mask);
6872 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6873 register_name = "EntryLo0";
5204ea79
LA
6874 break;
6875 default:
c98d3d79 6876 goto cp0_unimplemented;
5204ea79
LA
6877 }
6878 break;
04992c8c 6879 case CP0_REGISTER_03:
5204ea79 6880 switch (sel) {
acd37316 6881 case CP0_REG03__ENTRYLO1:
59488dda 6882 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6883 tcg_gen_andi_tl(arg, arg, mask);
6884 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6885 register_name = "EntryLo1";
5204ea79
LA
6886 break;
6887 default:
c98d3d79 6888 goto cp0_unimplemented;
5204ea79
LA
6889 }
6890 break;
04992c8c 6891 case CP0_REGISTER_09:
5fb2dcd1 6892 switch (sel) {
e5a98a72 6893 case CP0_REG09__SAAR:
5fb2dcd1
YK
6894 CP0_CHECK(ctx->saar);
6895 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 6896 register_name = "SAAR";
5fb2dcd1
YK
6897 break;
6898 default:
6899 goto cp0_unimplemented;
6900 }
ab8c3410 6901 break;
04992c8c 6902 case CP0_REGISTER_17:
5204ea79 6903 switch (sel) {
706ce142 6904 case CP0_REG17__LLADDR:
7480515f
AM
6905 /*
6906 * LLAddr is read-only (the only exception is bit 0 if LLB is
6907 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6908 * relevant for modern MIPS cores supporting MTHC0, therefore
6909 * treating MTHC0 to LLAddr as NOP.
6910 */
294fc2ea 6911 register_name = "LLAddr";
5204ea79 6912 break;
706ce142 6913 case CP0_REG17__MAAR:
f6d4dd81
YK
6914 CP0_CHECK(ctx->mrp);
6915 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 6916 register_name = "MAAR";
f6d4dd81 6917 break;
5204ea79 6918 default:
c98d3d79 6919 goto cp0_unimplemented;
5204ea79
LA
6920 }
6921 break;
feafe82c
YK
6922 case CP0_REGISTER_19:
6923 switch (sel) {
6924 case CP0_REG19__WATCHHI0:
6925 case CP0_REG19__WATCHHI1:
6926 case CP0_REG19__WATCHHI2:
6927 case CP0_REG19__WATCHHI3:
6928 case CP0_REG19__WATCHHI4:
6929 case CP0_REG19__WATCHHI5:
6930 case CP0_REG19__WATCHHI6:
6931 case CP0_REG19__WATCHHI7:
6932 /* upper 32 bits are only available when Config5MI != 0 */
6933 CP0_CHECK(ctx->mi);
6934 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6935 register_name = "WatchHi";
6936 break;
6937 default:
6938 goto cp0_unimplemented;
6939 }
6940 break;
04992c8c 6941 case CP0_REGISTER_28:
5204ea79
LA
6942 switch (sel) {
6943 case 0:
6944 case 2:
6945 case 4:
6946 case 6:
6947 tcg_gen_andi_tl(arg, arg, mask);
6948 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 6949 register_name = "TagLo";
5204ea79
LA
6950 break;
6951 default:
c98d3d79 6952 goto cp0_unimplemented;
5204ea79
LA
6953 }
6954 break;
6955 default:
c98d3d79 6956 goto cp0_unimplemented;
5204ea79 6957 }
294fc2ea 6958 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 6959
c98d3d79 6960cp0_unimplemented:
294fc2ea
AM
6961 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6962 register_name, reg, sel);
5204ea79
LA
6963}
6964
e98c0d17
LA
6965static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6966{
6967 if (ctx->insn_flags & ISA_MIPS32R6) {
6968 tcg_gen_movi_tl(arg, 0);
6969 } else {
6970 tcg_gen_movi_tl(arg, ~0);
6971 }
6972}
6973
d75c135e 6974static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6975{
294fc2ea 6976 const char *register_name = "invalid";
873eb012 6977
1f8929d2 6978 if (sel != 0) {
d75c135e 6979 check_insn(ctx, ISA_MIPS32);
1f8929d2 6980 }
e189e748 6981
873eb012 6982 switch (reg) {
04992c8c 6983 case CP0_REGISTER_00:
7a387fff 6984 switch (sel) {
1b142da5 6985 case CP0_REG00__INDEX:
7db13fae 6986 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6987 register_name = "Index";
7a387fff 6988 break;
1b142da5 6989 case CP0_REG00__MVPCONTROL:
f31b035a 6990 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6991 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 6992 register_name = "MVPControl";
ead9360e 6993 break;
1b142da5 6994 case CP0_REG00__MVPCONF0:
f31b035a 6995 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6996 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 6997 register_name = "MVPConf0";
ead9360e 6998 break;
1b142da5 6999 case CP0_REG00__MVPCONF1:
f31b035a 7000 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7001 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 7002 register_name = "MVPConf1";
ead9360e 7003 break;
1b142da5 7004 case CP0_REG00__VPCONTROL:
01bc435b
YK
7005 CP0_CHECK(ctx->vp);
7006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 7007 register_name = "VPControl";
01bc435b 7008 break;
7a387fff 7009 default:
f31b035a 7010 goto cp0_unimplemented;
7a387fff 7011 }
873eb012 7012 break;
04992c8c 7013 case CP0_REGISTER_01:
7a387fff 7014 switch (sel) {
30deb460 7015 case CP0_REG01__RANDOM:
f31b035a 7016 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 7017 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 7018 register_name = "Random";
2423f660 7019 break;
30deb460 7020 case CP0_REG01__VPECONTROL:
f31b035a 7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 7023 register_name = "VPEControl";
ead9360e 7024 break;
30deb460 7025 case CP0_REG01__VPECONF0:
f31b035a 7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7027 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 7028 register_name = "VPEConf0";
ead9360e 7029 break;
30deb460 7030 case CP0_REG01__VPECONF1:
f31b035a 7031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 7033 register_name = "VPEConf1";
ead9360e 7034 break;
30deb460 7035 case CP0_REG01__YQMASK:
f31b035a 7036 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7037 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 7038 register_name = "YQMask";
ead9360e 7039 break;
30deb460 7040 case CP0_REG01__VPESCHEDULE:
f31b035a 7041 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7042 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7043 register_name = "VPESchedule";
ead9360e 7044 break;
30deb460 7045 case CP0_REG01__VPESCHEFBACK:
f31b035a 7046 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7047 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7048 register_name = "VPEScheFBack";
ead9360e 7049 break;
30deb460 7050 case CP0_REG01__VPEOPT:
f31b035a 7051 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 7053 register_name = "VPEOpt";
ead9360e 7054 break;
7a387fff 7055 default:
f31b035a 7056 goto cp0_unimplemented;
7a387fff 7057 }
873eb012 7058 break;
04992c8c 7059 case CP0_REGISTER_02:
7a387fff 7060 switch (sel) {
6d27d5bd 7061 case CP0_REG02__ENTRYLO0:
284b731a
LA
7062 {
7063 TCGv_i64 tmp = tcg_temp_new_i64();
7064 tcg_gen_ld_i64(tmp, cpu_env,
7065 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 7066#if defined(TARGET_MIPS64)
284b731a
LA
7067 if (ctx->rxi) {
7068 /* Move RI/XI fields to bits 31:30 */
7069 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7070 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7071 }
7207c7f9 7072#endif
284b731a
LA
7073 gen_move_low32(arg, tmp);
7074 tcg_temp_free_i64(tmp);
7075 }
294fc2ea 7076 register_name = "EntryLo0";
2423f660 7077 break;
6d27d5bd 7078 case CP0_REG02__TCSTATUS:
f31b035a 7079 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7080 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 7081 register_name = "TCStatus";
ead9360e 7082 break;
6d27d5bd 7083 case CP0_REG02__TCBIND:
f31b035a 7084 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7085 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 7086 register_name = "TCBind";
ead9360e 7087 break;
6d27d5bd 7088 case CP0_REG02__TCRESTART:
f31b035a 7089 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7090 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 7091 register_name = "TCRestart";
ead9360e 7092 break;
6d27d5bd 7093 case CP0_REG02__TCHALT:
f31b035a 7094 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7095 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 7096 register_name = "TCHalt";
ead9360e 7097 break;
6d27d5bd 7098 case CP0_REG02__TCCONTEXT:
f31b035a 7099 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7100 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 7101 register_name = "TCContext";
ead9360e 7102 break;
6d27d5bd 7103 case CP0_REG02__TCSCHEDULE:
f31b035a 7104 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7105 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 7106 register_name = "TCSchedule";
ead9360e 7107 break;
6d27d5bd 7108 case CP0_REG02__TCSCHEFBACK:
f31b035a 7109 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7110 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 7111 register_name = "TCScheFBack";
ead9360e 7112 break;
7a387fff 7113 default:
f31b035a 7114 goto cp0_unimplemented;
7a387fff 7115 }
873eb012 7116 break;
04992c8c 7117 case CP0_REGISTER_03:
7a387fff 7118 switch (sel) {
acd37316 7119 case CP0_REG03__ENTRYLO1:
284b731a
LA
7120 {
7121 TCGv_i64 tmp = tcg_temp_new_i64();
7122 tcg_gen_ld_i64(tmp, cpu_env,
7123 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 7124#if defined(TARGET_MIPS64)
284b731a
LA
7125 if (ctx->rxi) {
7126 /* Move RI/XI fields to bits 31:30 */
7127 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7128 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7129 }
7207c7f9 7130#endif
284b731a
LA
7131 gen_move_low32(arg, tmp);
7132 tcg_temp_free_i64(tmp);
7133 }
294fc2ea 7134 register_name = "EntryLo1";
2423f660 7135 break;
acd37316 7136 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7137 CP0_CHECK(ctx->vp);
7138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7139 register_name = "GlobalNumber";
01bc435b 7140 break;
7a387fff 7141 default:
f31b035a 7142 goto cp0_unimplemented;
1579a72e 7143 }
873eb012 7144 break;
04992c8c 7145 case CP0_REGISTER_04:
7a387fff 7146 switch (sel) {
020fe379 7147 case CP0_REG04__CONTEXT:
7db13fae 7148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 7149 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7150 register_name = "Context";
2423f660 7151 break;
020fe379
AM
7152 case CP0_REG04__CONTEXTCONFIG:
7153 /* SmartMIPS ASE */
7154 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 7155 register_name = "ContextConfig";
f31b035a 7156 goto cp0_unimplemented;
020fe379 7157 case CP0_REG04__USERLOCAL:
f31b035a 7158 CP0_CHECK(ctx->ulri);
e40df9a8
JH
7159 tcg_gen_ld_tl(arg, cpu_env,
7160 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7161 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7162 register_name = "UserLocal";
d279279e 7163 break;
99029be1
YK
7164 case CP0_REG04__MMID:
7165 CP0_CHECK(ctx->mi);
7166 gen_helper_mtc0_memorymapid(cpu_env, arg);
7167 register_name = "MMID";
7168 break;
7a387fff 7169 default:
f31b035a 7170 goto cp0_unimplemented;
1579a72e 7171 }
873eb012 7172 break;
04992c8c 7173 case CP0_REGISTER_05:
7a387fff 7174 switch (sel) {
a1e76353 7175 case CP0_REG05__PAGEMASK:
7db13fae 7176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7177 register_name = "PageMask";
2423f660 7178 break;
a1e76353 7179 case CP0_REG05__PAGEGRAIN:
d75c135e 7180 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7182 register_name = "PageGrain";
2423f660 7183 break;
a1e76353 7184 case CP0_REG05__SEGCTL0:
cec56a73
JH
7185 CP0_CHECK(ctx->sc);
7186 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7187 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7188 register_name = "SegCtl0";
cec56a73 7189 break;
a1e76353 7190 case CP0_REG05__SEGCTL1:
cec56a73
JH
7191 CP0_CHECK(ctx->sc);
7192 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7193 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7194 register_name = "SegCtl1";
cec56a73 7195 break;
a1e76353 7196 case CP0_REG05__SEGCTL2:
cec56a73
JH
7197 CP0_CHECK(ctx->sc);
7198 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7199 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7200 register_name = "SegCtl2";
cec56a73 7201 break;
a1e76353 7202 case CP0_REG05__PWBASE:
5e31fdd5
YK
7203 check_pw(ctx);
7204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7205 register_name = "PWBase";
5e31fdd5 7206 break;
a1e76353 7207 case CP0_REG05__PWFIELD:
fa75ad14
YK
7208 check_pw(ctx);
7209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7210 register_name = "PWField";
fa75ad14 7211 break;
a1e76353 7212 case CP0_REG05__PWSIZE:
20b28ebc
YK
7213 check_pw(ctx);
7214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7215 register_name = "PWSize";
20b28ebc 7216 break;
7a387fff 7217 default:
f31b035a 7218 goto cp0_unimplemented;
1579a72e 7219 }
873eb012 7220 break;
04992c8c 7221 case CP0_REGISTER_06:
7a387fff 7222 switch (sel) {
9023594b 7223 case CP0_REG06__WIRED:
7db13fae 7224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7225 register_name = "Wired";
2423f660 7226 break;
9023594b 7227 case CP0_REG06__SRSCONF0:
d75c135e 7228 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7230 register_name = "SRSConf0";
ead9360e 7231 break;
9023594b 7232 case CP0_REG06__SRSCONF1:
d75c135e 7233 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7235 register_name = "SRSConf1";
ead9360e 7236 break;
9023594b 7237 case CP0_REG06__SRSCONF2:
d75c135e 7238 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7240 register_name = "SRSConf2";
ead9360e 7241 break;
9023594b 7242 case CP0_REG06__SRSCONF3:
d75c135e 7243 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7245 register_name = "SRSConf3";
ead9360e 7246 break;
9023594b 7247 case CP0_REG06__SRSCONF4:
d75c135e 7248 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7250 register_name = "SRSConf4";
ead9360e 7251 break;
9023594b 7252 case CP0_REG06__PWCTL:
103be64c
YK
7253 check_pw(ctx);
7254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7255 register_name = "PWCtl";
103be64c 7256 break;
7a387fff 7257 default:
f31b035a 7258 goto cp0_unimplemented;
1579a72e 7259 }
873eb012 7260 break;
04992c8c 7261 case CP0_REGISTER_07:
7a387fff 7262 switch (sel) {
143a9875 7263 case CP0_REG07__HWRENA:
d75c135e 7264 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7266 register_name = "HWREna";
2423f660 7267 break;
7a387fff 7268 default:
f31b035a 7269 goto cp0_unimplemented;
1579a72e 7270 }
8c0fdd85 7271 break;
04992c8c 7272 case CP0_REGISTER_08:
7a387fff 7273 switch (sel) {
67d167d2 7274 case CP0_REG08__BADVADDR:
7db13fae 7275 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7276 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7277 register_name = "BadVAddr";
2423f660 7278 break;
67d167d2 7279 case CP0_REG08__BADINSTR:
f31b035a
LA
7280 CP0_CHECK(ctx->bi);
7281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7282 register_name = "BadInstr";
aea14095 7283 break;
67d167d2 7284 case CP0_REG08__BADINSTRP:
f31b035a
LA
7285 CP0_CHECK(ctx->bp);
7286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7287 register_name = "BadInstrP";
aea14095 7288 break;
67d167d2 7289 case CP0_REG08__BADINSTRX:
25beba9b
SM
7290 CP0_CHECK(ctx->bi);
7291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7292 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7293 register_name = "BadInstrX";
25beba9b 7294 break;
05aa7e93 7295 default:
f31b035a 7296 goto cp0_unimplemented;
aea14095 7297 }
873eb012 7298 break;
04992c8c 7299 case CP0_REGISTER_09:
7a387fff 7300 switch (sel) {
e5a98a72 7301 case CP0_REG09__COUNT:
2e70f6ef 7302 /* Mark as an IO operation because we read the time. */
eeb3bba8 7303 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7304 gen_io_start();
7d37435b 7305 }
895c2d04 7306 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7307 /*
7308 * Break the TB to be able to take timer interrupts immediately
7309 * after reading count. DISAS_STOP isn't sufficient, we need to
7310 * ensure we break completely out of translated code.
7311 */
eeb3bba8
EC
7312 gen_save_pc(ctx->base.pc_next + 4);
7313 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7314 register_name = "Count";
2423f660 7315 break;
e5a98a72 7316 case CP0_REG09__SAARI:
5fb2dcd1
YK
7317 CP0_CHECK(ctx->saar);
7318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7319 register_name = "SAARI";
5fb2dcd1 7320 break;
e5a98a72 7321 case CP0_REG09__SAAR:
5fb2dcd1
YK
7322 CP0_CHECK(ctx->saar);
7323 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7324 register_name = "SAAR";
5fb2dcd1 7325 break;
7a387fff 7326 default:
f31b035a 7327 goto cp0_unimplemented;
2423f660 7328 }
873eb012 7329 break;
04992c8c 7330 case CP0_REGISTER_10:
7a387fff 7331 switch (sel) {
860ffef0 7332 case CP0_REG10__ENTRYHI:
7db13fae 7333 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7334 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7335 register_name = "EntryHi";
2423f660 7336 break;
7a387fff 7337 default:
f31b035a 7338 goto cp0_unimplemented;
1579a72e 7339 }
873eb012 7340 break;
04992c8c 7341 case CP0_REGISTER_11:
7a387fff 7342 switch (sel) {
f5f3834f 7343 case CP0_REG11__COMPARE:
7db13fae 7344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7345 register_name = "Compare";
2423f660
TS
7346 break;
7347 /* 6,7 are implementation dependent */
7a387fff 7348 default:
f31b035a 7349 goto cp0_unimplemented;
2423f660 7350 }
873eb012 7351 break;
04992c8c 7352 case CP0_REGISTER_12:
7a387fff 7353 switch (sel) {
2b084867 7354 case CP0_REG12__STATUS:
7db13fae 7355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7356 register_name = "Status";
2423f660 7357 break;
2b084867 7358 case CP0_REG12__INTCTL:
d75c135e 7359 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7361 register_name = "IntCtl";
2423f660 7362 break;
2b084867 7363 case CP0_REG12__SRSCTL:
d75c135e 7364 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7366 register_name = "SRSCtl";
2423f660 7367 break;
2b084867 7368 case CP0_REG12__SRSMAP:
d75c135e 7369 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7371 register_name = "SRSMap";
fd88b6ab 7372 break;
7a387fff 7373 default:
f31b035a 7374 goto cp0_unimplemented;
7a387fff 7375 }
873eb012 7376 break;
04992c8c 7377 case CP0_REGISTER_13:
7a387fff 7378 switch (sel) {
e3c7559d 7379 case CP0_REG13__CAUSE:
7db13fae 7380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7381 register_name = "Cause";
2423f660 7382 break;
7a387fff 7383 default:
f31b035a 7384 goto cp0_unimplemented;
7a387fff 7385 }
873eb012 7386 break;
04992c8c 7387 case CP0_REGISTER_14:
7a387fff 7388 switch (sel) {
35e4b54d 7389 case CP0_REG14__EPC:
7db13fae 7390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7391 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7392 register_name = "EPC";
2423f660 7393 break;
7a387fff 7394 default:
f31b035a 7395 goto cp0_unimplemented;
1579a72e 7396 }
873eb012 7397 break;
04992c8c 7398 case CP0_REGISTER_15:
7a387fff 7399 switch (sel) {
4466cd49 7400 case CP0_REG15__PRID:
7db13fae 7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7402 register_name = "PRid";
2423f660 7403 break;
4466cd49 7404 case CP0_REG15__EBASE:
d75c135e 7405 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
7406 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7407 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7408 register_name = "EBase";
2423f660 7409 break;
4466cd49 7410 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
7411 check_insn(ctx, ISA_MIPS32R2);
7412 CP0_CHECK(ctx->cmgcr);
7413 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7414 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7415 register_name = "CMGCRBase";
c870e3f5 7416 break;
7a387fff 7417 default:
f31b035a 7418 goto cp0_unimplemented;
7a387fff 7419 }
873eb012 7420 break;
04992c8c 7421 case CP0_REGISTER_16:
873eb012 7422 switch (sel) {
433efb4c 7423 case CP0_REG16__CONFIG:
7db13fae 7424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7425 register_name = "Config";
873eb012 7426 break;
433efb4c 7427 case CP0_REG16__CONFIG1:
7db13fae 7428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7429 register_name = "Config1";
873eb012 7430 break;
433efb4c 7431 case CP0_REG16__CONFIG2:
7db13fae 7432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7433 register_name = "Config2";
7a387fff 7434 break;
433efb4c 7435 case CP0_REG16__CONFIG3:
7db13fae 7436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7437 register_name = "Config3";
7a387fff 7438 break;
433efb4c 7439 case CP0_REG16__CONFIG4:
b4160af1 7440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7441 register_name = "Config4";
b4160af1 7442 break;
433efb4c 7443 case CP0_REG16__CONFIG5:
b4dd99a3 7444 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7445 register_name = "Config5";
b4dd99a3 7446 break;
e397ee33 7447 /* 6,7 are implementation dependent */
433efb4c 7448 case CP0_REG16__CONFIG6:
7db13fae 7449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7450 register_name = "Config6";
e397ee33 7451 break;
433efb4c 7452 case CP0_REG16__CONFIG7:
7db13fae 7453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7454 register_name = "Config7";
e397ee33 7455 break;
873eb012 7456 default:
f31b035a 7457 goto cp0_unimplemented;
873eb012
TS
7458 }
7459 break;
04992c8c 7460 case CP0_REGISTER_17:
7a387fff 7461 switch (sel) {
706ce142 7462 case CP0_REG17__LLADDR:
895c2d04 7463 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7464 register_name = "LLAddr";
2423f660 7465 break;
706ce142 7466 case CP0_REG17__MAAR:
f6d4dd81
YK
7467 CP0_CHECK(ctx->mrp);
7468 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7469 register_name = "MAAR";
f6d4dd81 7470 break;
706ce142 7471 case CP0_REG17__MAARI:
f6d4dd81
YK
7472 CP0_CHECK(ctx->mrp);
7473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7474 register_name = "MAARI";
f6d4dd81 7475 break;
7a387fff 7476 default:
f31b035a 7477 goto cp0_unimplemented;
7a387fff 7478 }
873eb012 7479 break;
04992c8c 7480 case CP0_REGISTER_18:
7a387fff 7481 switch (sel) {
e8dcfe82
AM
7482 case CP0_REG18__WATCHLO0:
7483 case CP0_REG18__WATCHLO1:
7484 case CP0_REG18__WATCHLO2:
7485 case CP0_REG18__WATCHLO3:
7486 case CP0_REG18__WATCHLO4:
7487 case CP0_REG18__WATCHLO5:
7488 case CP0_REG18__WATCHLO6:
7489 case CP0_REG18__WATCHLO7:
fa192d49 7490 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7491 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7492 register_name = "WatchLo";
2423f660 7493 break;
7a387fff 7494 default:
f31b035a 7495 goto cp0_unimplemented;
7a387fff 7496 }
873eb012 7497 break;
04992c8c 7498 case CP0_REGISTER_19:
7a387fff 7499 switch (sel) {
be274dc1
AM
7500 case CP0_REG19__WATCHHI0:
7501 case CP0_REG19__WATCHHI1:
7502 case CP0_REG19__WATCHHI2:
7503 case CP0_REG19__WATCHHI3:
7504 case CP0_REG19__WATCHHI4:
7505 case CP0_REG19__WATCHHI5:
7506 case CP0_REG19__WATCHHI6:
7507 case CP0_REG19__WATCHHI7:
fa192d49 7508 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7509 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7510 register_name = "WatchHi";
2423f660 7511 break;
7a387fff 7512 default:
f31b035a 7513 goto cp0_unimplemented;
7a387fff 7514 }
873eb012 7515 break;
04992c8c 7516 case CP0_REGISTER_20:
7a387fff 7517 switch (sel) {
14f92b0b 7518 case CP0_REG20__XCONTEXT:
d26bc211 7519#if defined(TARGET_MIPS64)
d75c135e 7520 check_insn(ctx, ISA_MIPS3);
7db13fae 7521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7522 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7523 register_name = "XContext";
2423f660 7524 break;
703eaf37 7525#endif
7a387fff 7526 default:
f31b035a 7527 goto cp0_unimplemented;
7a387fff 7528 }
8c0fdd85 7529 break;
04992c8c 7530 case CP0_REGISTER_21:
7a387fff 7531 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7532 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7533 switch (sel) {
7534 case 0:
7db13fae 7535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7536 register_name = "Framemask";
2423f660 7537 break;
7a387fff 7538 default:
f31b035a 7539 goto cp0_unimplemented;
7a387fff 7540 }
8c0fdd85 7541 break;
04992c8c 7542 case CP0_REGISTER_22:
d9bea114 7543 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7544 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7545 break;
04992c8c 7546 case CP0_REGISTER_23:
7a387fff 7547 switch (sel) {
4cbf4b6d 7548 case CP0_REG23__DEBUG:
895c2d04 7549 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7550 register_name = "Debug";
2423f660 7551 break;
4cbf4b6d
AM
7552 case CP0_REG23__TRACECONTROL:
7553 /* PDtrace support */
7554 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 7555 register_name = "TraceControl";
3570d7f6 7556 goto cp0_unimplemented;
4cbf4b6d
AM
7557 case CP0_REG23__TRACECONTROL2:
7558 /* PDtrace support */
7559 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 7560 register_name = "TraceControl2";
3570d7f6 7561 goto cp0_unimplemented;
4cbf4b6d
AM
7562 case CP0_REG23__USERTRACEDATA1:
7563 /* PDtrace support */
7564 /* gen_helper_mfc0_usertracedata1(arg);*/
7565 register_name = "UserTraceData1";
3570d7f6 7566 goto cp0_unimplemented;
4cbf4b6d
AM
7567 case CP0_REG23__TRACEIBPC:
7568 /* PDtrace support */
7569 /* gen_helper_mfc0_traceibpc(arg); */
7570 register_name = "TraceIBPC";
7571 goto cp0_unimplemented;
7572 case CP0_REG23__TRACEDBPC:
7573 /* PDtrace support */
7574 /* gen_helper_mfc0_tracedbpc(arg); */
7575 register_name = "TraceDBPC";
3570d7f6 7576 goto cp0_unimplemented;
7a387fff 7577 default:
f31b035a 7578 goto cp0_unimplemented;
7a387fff 7579 }
873eb012 7580 break;
04992c8c 7581 case CP0_REGISTER_24:
7a387fff 7582 switch (sel) {
8d7b4b6e 7583 case CP0_REG24__DEPC:
f0b3f3ae 7584 /* EJTAG support */
7db13fae 7585 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7586 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7587 register_name = "DEPC";
2423f660 7588 break;
7a387fff 7589 default:
f31b035a 7590 goto cp0_unimplemented;
7a387fff 7591 }
873eb012 7592 break;
04992c8c 7593 case CP0_REGISTER_25:
7a387fff 7594 switch (sel) {
1176b328 7595 case CP0_REG25__PERFCTL0:
7db13fae 7596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7597 register_name = "Performance0";
7a387fff 7598 break;
1176b328 7599 case CP0_REG25__PERFCNT0:
7480515f 7600 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 7601 register_name = "Performance1";
3570d7f6 7602 goto cp0_unimplemented;
1176b328 7603 case CP0_REG25__PERFCTL1:
7480515f 7604 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 7605 register_name = "Performance2";
3570d7f6 7606 goto cp0_unimplemented;
1176b328 7607 case CP0_REG25__PERFCNT1:
7480515f 7608 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 7609 register_name = "Performance3";
3570d7f6 7610 goto cp0_unimplemented;
1176b328 7611 case CP0_REG25__PERFCTL2:
7480515f 7612 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 7613 register_name = "Performance4";
3570d7f6 7614 goto cp0_unimplemented;
1176b328 7615 case CP0_REG25__PERFCNT2:
7480515f 7616 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 7617 register_name = "Performance5";
3570d7f6 7618 goto cp0_unimplemented;
1176b328 7619 case CP0_REG25__PERFCTL3:
7480515f 7620 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 7621 register_name = "Performance6";
3570d7f6 7622 goto cp0_unimplemented;
1176b328 7623 case CP0_REG25__PERFCNT3:
7480515f 7624 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 7625 register_name = "Performance7";
3570d7f6 7626 goto cp0_unimplemented;
7a387fff 7627 default:
f31b035a 7628 goto cp0_unimplemented;
7a387fff 7629 }
8c0fdd85 7630 break;
04992c8c 7631 case CP0_REGISTER_26:
0d74a222 7632 switch (sel) {
dbbf08b2 7633 case CP0_REG26__ERRCTL:
0d74a222 7634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7635 register_name = "ErrCtl";
0d74a222
LA
7636 break;
7637 default:
7638 goto cp0_unimplemented;
7639 }
da80682b 7640 break;
04992c8c 7641 case CP0_REGISTER_27:
7a387fff 7642 switch (sel) {
5a10873d 7643 case CP0_REG27__CACHERR:
d9bea114 7644 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7645 register_name = "CacheErr";
2423f660 7646 break;
7a387fff 7647 default:
f31b035a 7648 goto cp0_unimplemented;
7a387fff 7649 }
8c0fdd85 7650 break;
04992c8c 7651 case CP0_REGISTER_28:
873eb012 7652 switch (sel) {
a30e2f21
AM
7653 case CP0_REG28__TAGLO:
7654 case CP0_REG28__TAGLO1:
7655 case CP0_REG28__TAGLO2:
7656 case CP0_REG28__TAGLO3:
284b731a
LA
7657 {
7658 TCGv_i64 tmp = tcg_temp_new_i64();
7659 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7660 gen_move_low32(arg, tmp);
7661 tcg_temp_free_i64(tmp);
7662 }
294fc2ea 7663 register_name = "TagLo";
873eb012 7664 break;
a30e2f21
AM
7665 case CP0_REG28__DATALO:
7666 case CP0_REG28__DATALO1:
7667 case CP0_REG28__DATALO2:
7668 case CP0_REG28__DATALO3:
7db13fae 7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7670 register_name = "DataLo";
873eb012
TS
7671 break;
7672 default:
f31b035a 7673 goto cp0_unimplemented;
873eb012
TS
7674 }
7675 break;
04992c8c 7676 case CP0_REGISTER_29:
7a387fff 7677 switch (sel) {
af4bb6da
AM
7678 case CP0_REG29__TAGHI:
7679 case CP0_REG29__TAGHI1:
7680 case CP0_REG29__TAGHI2:
7681 case CP0_REG29__TAGHI3:
7db13fae 7682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7683 register_name = "TagHi";
7a387fff 7684 break;
af4bb6da
AM
7685 case CP0_REG29__DATAHI:
7686 case CP0_REG29__DATAHI1:
7687 case CP0_REG29__DATAHI2:
7688 case CP0_REG29__DATAHI3:
7db13fae 7689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7690 register_name = "DataHi";
7a387fff
TS
7691 break;
7692 default:
f31b035a 7693 goto cp0_unimplemented;
7a387fff 7694 }
8c0fdd85 7695 break;
04992c8c 7696 case CP0_REGISTER_30:
7a387fff 7697 switch (sel) {
4bcf121e 7698 case CP0_REG30__ERROREPC:
7db13fae 7699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7700 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7701 register_name = "ErrorEPC";
2423f660 7702 break;
7a387fff 7703 default:
f31b035a 7704 goto cp0_unimplemented;
7a387fff 7705 }
873eb012 7706 break;
04992c8c 7707 case CP0_REGISTER_31:
7a387fff 7708 switch (sel) {
14d92efd 7709 case CP0_REG31__DESAVE:
f0b3f3ae 7710 /* EJTAG support */
7db13fae 7711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7712 register_name = "DESAVE";
2423f660 7713 break;
14d92efd
AM
7714 case CP0_REG31__KSCRATCH1:
7715 case CP0_REG31__KSCRATCH2:
7716 case CP0_REG31__KSCRATCH3:
7717 case CP0_REG31__KSCRATCH4:
7718 case CP0_REG31__KSCRATCH5:
7719 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7720 CP0_CHECK(ctx->kscrexist & (1 << sel));
7721 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 7722 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 7723 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7724 register_name = "KScratch";
e98c0d17 7725 break;
7a387fff 7726 default:
f31b035a 7727 goto cp0_unimplemented;
7a387fff 7728 }
873eb012
TS
7729 break;
7730 default:
f31b035a 7731 goto cp0_unimplemented;
873eb012 7732 }
294fc2ea 7733 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
7734 return;
7735
f31b035a 7736cp0_unimplemented:
294fc2ea
AM
7737 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7738 register_name, reg, sel);
f31b035a 7739 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7740}
7741
d75c135e 7742static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7743{
294fc2ea 7744 const char *register_name = "invalid";
7a387fff 7745
1f8929d2 7746 if (sel != 0) {
d75c135e 7747 check_insn(ctx, ISA_MIPS32);
1f8929d2 7748 }
e189e748 7749
eeb3bba8 7750 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7751 gen_io_start();
bd79255d 7752 }
2e70f6ef 7753
8c0fdd85 7754 switch (reg) {
04992c8c 7755 case CP0_REGISTER_00:
7a387fff 7756 switch (sel) {
1b142da5 7757 case CP0_REG00__INDEX:
895c2d04 7758 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 7759 register_name = "Index";
7a387fff 7760 break;
1b142da5 7761 case CP0_REG00__MVPCONTROL:
f31b035a 7762 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7763 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 7764 register_name = "MVPControl";
ead9360e 7765 break;
1b142da5 7766 case CP0_REG00__MVPCONF0:
f31b035a 7767 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7768 /* ignored */
294fc2ea 7769 register_name = "MVPConf0";
ead9360e 7770 break;
1b142da5 7771 case CP0_REG00__MVPCONF1:
f31b035a 7772 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7773 /* ignored */
294fc2ea 7774 register_name = "MVPConf1";
ead9360e 7775 break;
1b142da5 7776 case CP0_REG00__VPCONTROL:
01bc435b
YK
7777 CP0_CHECK(ctx->vp);
7778 /* ignored */
294fc2ea 7779 register_name = "VPControl";
01bc435b 7780 break;
7a387fff 7781 default:
f31b035a 7782 goto cp0_unimplemented;
7a387fff 7783 }
8c0fdd85 7784 break;
04992c8c 7785 case CP0_REGISTER_01:
7a387fff 7786 switch (sel) {
30deb460 7787 case CP0_REG01__RANDOM:
2423f660 7788 /* ignored */
294fc2ea 7789 register_name = "Random";
2423f660 7790 break;
30deb460 7791 case CP0_REG01__VPECONTROL:
f31b035a 7792 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7793 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 7794 register_name = "VPEControl";
ead9360e 7795 break;
30deb460 7796 case CP0_REG01__VPECONF0:
f31b035a 7797 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7798 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 7799 register_name = "VPEConf0";
ead9360e 7800 break;
30deb460 7801 case CP0_REG01__VPECONF1:
f31b035a 7802 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7803 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 7804 register_name = "VPEConf1";
ead9360e 7805 break;
30deb460 7806 case CP0_REG01__YQMASK:
f31b035a 7807 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7808 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 7809 register_name = "YQMask";
ead9360e 7810 break;
30deb460 7811 case CP0_REG01__VPESCHEDULE:
f31b035a 7812 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7813 tcg_gen_st_tl(arg, cpu_env,
7814 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7815 register_name = "VPESchedule";
ead9360e 7816 break;
30deb460 7817 case CP0_REG01__VPESCHEFBACK:
f31b035a 7818 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7819 tcg_gen_st_tl(arg, cpu_env,
7820 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7821 register_name = "VPEScheFBack";
ead9360e 7822 break;
30deb460 7823 case CP0_REG01__VPEOPT:
f31b035a 7824 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7825 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 7826 register_name = "VPEOpt";
ead9360e 7827 break;
7a387fff 7828 default:
f31b035a 7829 goto cp0_unimplemented;
7a387fff 7830 }
8c0fdd85 7831 break;
04992c8c 7832 case CP0_REGISTER_02:
7a387fff 7833 switch (sel) {
6d27d5bd 7834 case CP0_REG02__ENTRYLO0:
895c2d04 7835 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 7836 register_name = "EntryLo0";
2423f660 7837 break;
6d27d5bd 7838 case CP0_REG02__TCSTATUS:
f31b035a 7839 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7840 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 7841 register_name = "TCStatus";
ead9360e 7842 break;
6d27d5bd 7843 case CP0_REG02__TCBIND:
f31b035a 7844 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7845 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 7846 register_name = "TCBind";
ead9360e 7847 break;
6d27d5bd 7848 case CP0_REG02__TCRESTART:
f31b035a 7849 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7850 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 7851 register_name = "TCRestart";
ead9360e 7852 break;
6d27d5bd 7853 case CP0_REG02__TCHALT:
f31b035a 7854 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7855 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 7856 register_name = "TCHalt";
ead9360e 7857 break;
6d27d5bd 7858 case CP0_REG02__TCCONTEXT:
f31b035a 7859 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7860 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 7861 register_name = "TCContext";
ead9360e 7862 break;
6d27d5bd 7863 case CP0_REG02__TCSCHEDULE:
f31b035a 7864 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7865 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 7866 register_name = "TCSchedule";
ead9360e 7867 break;
6d27d5bd 7868 case CP0_REG02__TCSCHEFBACK:
f31b035a 7869 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7870 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 7871 register_name = "TCScheFBack";
ead9360e 7872 break;
7a387fff 7873 default:
f31b035a 7874 goto cp0_unimplemented;
7a387fff 7875 }
8c0fdd85 7876 break;
04992c8c 7877 case CP0_REGISTER_03:
7a387fff 7878 switch (sel) {
acd37316 7879 case CP0_REG03__ENTRYLO1:
895c2d04 7880 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 7881 register_name = "EntryLo1";
2423f660 7882 break;
acd37316 7883 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7884 CP0_CHECK(ctx->vp);
7885 /* ignored */
294fc2ea 7886 register_name = "GlobalNumber";
01bc435b 7887 break;
7a387fff 7888 default:
f31b035a 7889 goto cp0_unimplemented;
876d4b07 7890 }
8c0fdd85 7891 break;
04992c8c 7892 case CP0_REGISTER_04:
7a387fff 7893 switch (sel) {
020fe379 7894 case CP0_REG04__CONTEXT:
895c2d04 7895 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 7896 register_name = "Context";
2423f660 7897 break;
020fe379
AM
7898 case CP0_REG04__CONTEXTCONFIG:
7899 /* SmartMIPS ASE */
7900 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 7901 register_name = "ContextConfig";
f31b035a 7902 goto cp0_unimplemented;
020fe379 7903 case CP0_REG04__USERLOCAL:
f31b035a
LA
7904 CP0_CHECK(ctx->ulri);
7905 tcg_gen_st_tl(arg, cpu_env,
7906 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7907 register_name = "UserLocal";
d279279e 7908 break;
99029be1
YK
7909 case CP0_REG04__MMID:
7910 CP0_CHECK(ctx->mi);
7911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7912 register_name = "MMID";
7913 break;
7a387fff 7914 default:
f31b035a 7915 goto cp0_unimplemented;
876d4b07 7916 }
8c0fdd85 7917 break;
04992c8c 7918 case CP0_REGISTER_05:
7a387fff 7919 switch (sel) {
a1e76353 7920 case CP0_REG05__PAGEMASK:
895c2d04 7921 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 7922 register_name = "PageMask";
2423f660 7923 break;
a1e76353 7924 case CP0_REG05__PAGEGRAIN:
d75c135e 7925 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7926 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 7927 register_name = "PageGrain";
eeb3bba8 7928 ctx->base.is_jmp = DISAS_STOP;
2423f660 7929 break;
a1e76353 7930 case CP0_REG05__SEGCTL0:
cec56a73
JH
7931 CP0_CHECK(ctx->sc);
7932 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 7933 register_name = "SegCtl0";
cec56a73 7934 break;
a1e76353 7935 case CP0_REG05__SEGCTL1:
cec56a73
JH
7936 CP0_CHECK(ctx->sc);
7937 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 7938 register_name = "SegCtl1";
cec56a73 7939 break;
a1e76353 7940 case CP0_REG05__SEGCTL2:
cec56a73
JH
7941 CP0_CHECK(ctx->sc);
7942 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 7943 register_name = "SegCtl2";
cec56a73 7944 break;
a1e76353 7945 case CP0_REG05__PWBASE:
5e31fdd5
YK
7946 check_pw(ctx);
7947 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7948 register_name = "PWBase";
5e31fdd5 7949 break;
a1e76353 7950 case CP0_REG05__PWFIELD:
fa75ad14
YK
7951 check_pw(ctx);
7952 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 7953 register_name = "PWField";
fa75ad14 7954 break;
a1e76353 7955 case CP0_REG05__PWSIZE:
20b28ebc
YK
7956 check_pw(ctx);
7957 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 7958 register_name = "PWSize";
20b28ebc 7959 break;
7a387fff 7960 default:
f31b035a 7961 goto cp0_unimplemented;
876d4b07 7962 }
8c0fdd85 7963 break;
04992c8c 7964 case CP0_REGISTER_06:
7a387fff 7965 switch (sel) {
9023594b 7966 case CP0_REG06__WIRED:
895c2d04 7967 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 7968 register_name = "Wired";
2423f660 7969 break;
9023594b 7970 case CP0_REG06__SRSCONF0:
d75c135e 7971 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7972 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 7973 register_name = "SRSConf0";
ead9360e 7974 break;
9023594b 7975 case CP0_REG06__SRSCONF1:
d75c135e 7976 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7977 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 7978 register_name = "SRSConf1";
ead9360e 7979 break;
9023594b 7980 case CP0_REG06__SRSCONF2:
d75c135e 7981 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7982 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 7983 register_name = "SRSConf2";
ead9360e 7984 break;
9023594b 7985 case CP0_REG06__SRSCONF3:
d75c135e 7986 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7987 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 7988 register_name = "SRSConf3";
ead9360e 7989 break;
9023594b 7990 case CP0_REG06__SRSCONF4:
d75c135e 7991 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7992 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 7993 register_name = "SRSConf4";
ead9360e 7994 break;
9023594b 7995 case CP0_REG06__PWCTL:
103be64c
YK
7996 check_pw(ctx);
7997 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 7998 register_name = "PWCtl";
103be64c 7999 break;
7a387fff 8000 default:
f31b035a 8001 goto cp0_unimplemented;
876d4b07 8002 }
8c0fdd85 8003 break;
04992c8c 8004 case CP0_REGISTER_07:
7a387fff 8005 switch (sel) {
143a9875 8006 case CP0_REG07__HWRENA:
d75c135e 8007 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8008 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 8009 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8010 register_name = "HWREna";
2423f660 8011 break;
7a387fff 8012 default:
f31b035a 8013 goto cp0_unimplemented;
876d4b07 8014 }
8c0fdd85 8015 break;
04992c8c 8016 case CP0_REGISTER_08:
aea14095 8017 switch (sel) {
67d167d2 8018 case CP0_REG08__BADVADDR:
aea14095 8019 /* ignored */
294fc2ea 8020 register_name = "BadVAddr";
aea14095 8021 break;
67d167d2 8022 case CP0_REG08__BADINSTR:
aea14095 8023 /* ignored */
294fc2ea 8024 register_name = "BadInstr";
aea14095 8025 break;
67d167d2 8026 case CP0_REG08__BADINSTRP:
aea14095 8027 /* ignored */
294fc2ea 8028 register_name = "BadInstrP";
aea14095 8029 break;
67d167d2 8030 case CP0_REG08__BADINSTRX:
25beba9b 8031 /* ignored */
294fc2ea 8032 register_name = "BadInstrX";
25beba9b 8033 break;
aea14095 8034 default:
f31b035a 8035 goto cp0_unimplemented;
aea14095 8036 }
8c0fdd85 8037 break;
04992c8c 8038 case CP0_REGISTER_09:
7a387fff 8039 switch (sel) {
e5a98a72 8040 case CP0_REG09__COUNT:
895c2d04 8041 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 8042 register_name = "Count";
2423f660 8043 break;
e5a98a72 8044 case CP0_REG09__SAARI:
5fb2dcd1
YK
8045 CP0_CHECK(ctx->saar);
8046 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 8047 register_name = "SAARI";
5fb2dcd1 8048 break;
e5a98a72 8049 case CP0_REG09__SAAR:
5fb2dcd1
YK
8050 CP0_CHECK(ctx->saar);
8051 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 8052 register_name = "SAAR";
5fb2dcd1 8053 break;
7a387fff 8054 default:
f31b035a 8055 goto cp0_unimplemented;
876d4b07 8056 }
8c0fdd85 8057 break;
04992c8c 8058 case CP0_REGISTER_10:
7a387fff 8059 switch (sel) {
860ffef0 8060 case CP0_REG10__ENTRYHI:
895c2d04 8061 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 8062 register_name = "EntryHi";
2423f660 8063 break;
7a387fff 8064 default:
f31b035a 8065 goto cp0_unimplemented;
876d4b07 8066 }
8c0fdd85 8067 break;
04992c8c 8068 case CP0_REGISTER_11:
7a387fff 8069 switch (sel) {
f5f3834f 8070 case CP0_REG11__COMPARE:
895c2d04 8071 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 8072 register_name = "Compare";
2423f660
TS
8073 break;
8074 /* 6,7 are implementation dependent */
7a387fff 8075 default:
f31b035a 8076 goto cp0_unimplemented;
876d4b07 8077 }
8c0fdd85 8078 break;
04992c8c 8079 case CP0_REGISTER_12:
7a387fff 8080 switch (sel) {
2b084867 8081 case CP0_REG12__STATUS:
867abc7e 8082 save_cpu_state(ctx, 1);
895c2d04 8083 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8084 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8085 gen_save_pc(ctx->base.pc_next + 4);
8086 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8087 register_name = "Status";
2423f660 8088 break;
2b084867 8089 case CP0_REG12__INTCTL:
d75c135e 8090 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8091 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8092 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8093 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8094 register_name = "IntCtl";
2423f660 8095 break;
2b084867 8096 case CP0_REG12__SRSCTL:
d75c135e 8097 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8098 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8099 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8100 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8101 register_name = "SRSCtl";
2423f660 8102 break;
2b084867 8103 case CP0_REG12__SRSMAP:
d75c135e 8104 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8105 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8106 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8107 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8108 register_name = "SRSMap";
fd88b6ab 8109 break;
7a387fff 8110 default:
f31b035a 8111 goto cp0_unimplemented;
876d4b07 8112 }
8c0fdd85 8113 break;
04992c8c 8114 case CP0_REGISTER_13:
7a387fff 8115 switch (sel) {
e3c7559d 8116 case CP0_REG13__CAUSE:
867abc7e 8117 save_cpu_state(ctx, 1);
895c2d04 8118 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
8119 /*
8120 * Stop translation as we may have triggered an interrupt.
b28425ba 8121 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
8122 * translated code to check for pending interrupts.
8123 */
eeb3bba8
EC
8124 gen_save_pc(ctx->base.pc_next + 4);
8125 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8126 register_name = "Cause";
2423f660 8127 break;
7a387fff 8128 default:
f31b035a 8129 goto cp0_unimplemented;
876d4b07 8130 }
8c0fdd85 8131 break;
04992c8c 8132 case CP0_REGISTER_14:
7a387fff 8133 switch (sel) {
35e4b54d 8134 case CP0_REG14__EPC:
d54a299b 8135 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8136 register_name = "EPC";
2423f660 8137 break;
7a387fff 8138 default:
f31b035a 8139 goto cp0_unimplemented;
876d4b07 8140 }
8c0fdd85 8141 break;
04992c8c 8142 case CP0_REGISTER_15:
7a387fff 8143 switch (sel) {
4466cd49 8144 case CP0_REG15__PRID:
2423f660 8145 /* ignored */
294fc2ea 8146 register_name = "PRid";
2423f660 8147 break;
4466cd49 8148 case CP0_REG15__EBASE:
d75c135e 8149 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8150 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 8151 register_name = "EBase";
2423f660 8152 break;
7a387fff 8153 default:
f31b035a 8154 goto cp0_unimplemented;
1579a72e 8155 }
8c0fdd85 8156 break;
04992c8c 8157 case CP0_REGISTER_16:
8c0fdd85 8158 switch (sel) {
433efb4c 8159 case CP0_REG16__CONFIG:
895c2d04 8160 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 8161 register_name = "Config";
2423f660 8162 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8163 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8164 break;
433efb4c 8165 case CP0_REG16__CONFIG1:
e397ee33 8166 /* ignored, read only */
294fc2ea 8167 register_name = "Config1";
7a387fff 8168 break;
433efb4c 8169 case CP0_REG16__CONFIG2:
895c2d04 8170 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 8171 register_name = "Config2";
2423f660 8172 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8173 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 8174 break;
433efb4c 8175 case CP0_REG16__CONFIG3:
90f12d73 8176 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 8177 register_name = "Config3";
90f12d73 8178 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8179 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8180 break;
433efb4c 8181 case CP0_REG16__CONFIG4:
b4160af1 8182 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 8183 register_name = "Config4";
eeb3bba8 8184 ctx->base.is_jmp = DISAS_STOP;
b4160af1 8185 break;
433efb4c 8186 case CP0_REG16__CONFIG5:
b4dd99a3 8187 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8188 register_name = "Config5";
b4dd99a3 8189 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8190 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 8191 break;
e397ee33 8192 /* 6,7 are implementation dependent */
433efb4c 8193 case CP0_REG16__CONFIG6:
e397ee33 8194 /* ignored */
294fc2ea 8195 register_name = "Config6";
e397ee33 8196 break;
433efb4c 8197 case CP0_REG16__CONFIG7:
e397ee33 8198 /* ignored */
294fc2ea 8199 register_name = "Config7";
e397ee33 8200 break;
8c0fdd85 8201 default:
294fc2ea 8202 register_name = "Invalid config selector";
f31b035a 8203 goto cp0_unimplemented;
8c0fdd85
TS
8204 }
8205 break;
04992c8c 8206 case CP0_REGISTER_17:
7a387fff 8207 switch (sel) {
706ce142 8208 case CP0_REG17__LLADDR:
895c2d04 8209 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8210 register_name = "LLAddr";
2423f660 8211 break;
706ce142 8212 case CP0_REG17__MAAR:
f6d4dd81
YK
8213 CP0_CHECK(ctx->mrp);
8214 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8215 register_name = "MAAR";
f6d4dd81 8216 break;
706ce142 8217 case CP0_REG17__MAARI:
f6d4dd81
YK
8218 CP0_CHECK(ctx->mrp);
8219 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8220 register_name = "MAARI";
f6d4dd81 8221 break;
7a387fff 8222 default:
f31b035a 8223 goto cp0_unimplemented;
7a387fff 8224 }
8c0fdd85 8225 break;
04992c8c 8226 case CP0_REGISTER_18:
7a387fff 8227 switch (sel) {
e8dcfe82
AM
8228 case CP0_REG18__WATCHLO0:
8229 case CP0_REG18__WATCHLO1:
8230 case CP0_REG18__WATCHLO2:
8231 case CP0_REG18__WATCHLO3:
8232 case CP0_REG18__WATCHLO4:
8233 case CP0_REG18__WATCHLO5:
8234 case CP0_REG18__WATCHLO6:
8235 case CP0_REG18__WATCHLO7:
fa192d49 8236 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8237 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8238 register_name = "WatchLo";
2423f660 8239 break;
7a387fff 8240 default:
f31b035a 8241 goto cp0_unimplemented;
7a387fff 8242 }
8c0fdd85 8243 break;
04992c8c 8244 case CP0_REGISTER_19:
7a387fff 8245 switch (sel) {
be274dc1
AM
8246 case CP0_REG19__WATCHHI0:
8247 case CP0_REG19__WATCHHI1:
8248 case CP0_REG19__WATCHHI2:
8249 case CP0_REG19__WATCHHI3:
8250 case CP0_REG19__WATCHHI4:
8251 case CP0_REG19__WATCHHI5:
8252 case CP0_REG19__WATCHHI6:
8253 case CP0_REG19__WATCHHI7:
fa192d49 8254 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8255 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8256 register_name = "WatchHi";
2423f660 8257 break;
7a387fff 8258 default:
f31b035a 8259 goto cp0_unimplemented;
7a387fff 8260 }
8c0fdd85 8261 break;
04992c8c 8262 case CP0_REGISTER_20:
7a387fff 8263 switch (sel) {
14f92b0b 8264 case CP0_REG20__XCONTEXT:
d26bc211 8265#if defined(TARGET_MIPS64)
d75c135e 8266 check_insn(ctx, ISA_MIPS3);
895c2d04 8267 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8268 register_name = "XContext";
2423f660 8269 break;
703eaf37 8270#endif
7a387fff 8271 default:
f31b035a 8272 goto cp0_unimplemented;
7a387fff 8273 }
8c0fdd85 8274 break;
04992c8c 8275 case CP0_REGISTER_21:
7a387fff 8276 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8277 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
8278 switch (sel) {
8279 case 0:
895c2d04 8280 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8281 register_name = "Framemask";
2423f660 8282 break;
7a387fff 8283 default:
f31b035a 8284 goto cp0_unimplemented;
7a387fff
TS
8285 }
8286 break;
04992c8c 8287 case CP0_REGISTER_22:
7a387fff 8288 /* ignored */
294fc2ea 8289 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8290 break;
04992c8c 8291 case CP0_REGISTER_23:
7a387fff 8292 switch (sel) {
4cbf4b6d 8293 case CP0_REG23__DEBUG:
895c2d04 8294 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8295 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8296 gen_save_pc(ctx->base.pc_next + 4);
8297 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8298 register_name = "Debug";
2423f660 8299 break;
4cbf4b6d
AM
8300 case CP0_REG23__TRACECONTROL:
8301 /* PDtrace support */
8302 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 8303 register_name = "TraceControl";
8487327a 8304 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8305 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8306 goto cp0_unimplemented;
4cbf4b6d
AM
8307 case CP0_REG23__TRACECONTROL2:
8308 /* PDtrace support */
8309 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 8310 register_name = "TraceControl2";
8487327a 8311 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8312 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8313 goto cp0_unimplemented;
4cbf4b6d 8314 case CP0_REG23__USERTRACEDATA1:
8487327a 8315 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8316 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8317 /* PDtrace support */
8318 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 8319 register_name = "UserTraceData";
8487327a 8320 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8321 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8322 goto cp0_unimplemented;
4cbf4b6d
AM
8323 case CP0_REG23__TRACEIBPC:
8324 /* PDtrace support */
8325 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 8326 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8327 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8328 register_name = "TraceIBPC";
8329 goto cp0_unimplemented;
8330 case CP0_REG23__TRACEDBPC:
8331 /* PDtrace support */
8332 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8333 /* Stop translation as we may have switched the execution mode */
8334 ctx->base.is_jmp = DISAS_STOP;
8335 register_name = "TraceDBPC";
3570d7f6 8336 goto cp0_unimplemented;
7a387fff 8337 default:
f31b035a 8338 goto cp0_unimplemented;
7a387fff 8339 }
8c0fdd85 8340 break;
04992c8c 8341 case CP0_REGISTER_24:
7a387fff 8342 switch (sel) {
8d7b4b6e 8343 case CP0_REG24__DEPC:
f1aa6320 8344 /* EJTAG support */
d54a299b 8345 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8346 register_name = "DEPC";
2423f660 8347 break;
7a387fff 8348 default:
f31b035a 8349 goto cp0_unimplemented;
7a387fff 8350 }
8c0fdd85 8351 break;
04992c8c 8352 case CP0_REGISTER_25:
7a387fff 8353 switch (sel) {
1176b328 8354 case CP0_REG25__PERFCTL0:
895c2d04 8355 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8356 register_name = "Performance0";
2423f660 8357 break;
1176b328 8358 case CP0_REG25__PERFCNT0:
7480515f 8359 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 8360 register_name = "Performance1";
3570d7f6 8361 goto cp0_unimplemented;
1176b328 8362 case CP0_REG25__PERFCTL1:
7480515f 8363 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 8364 register_name = "Performance2";
3570d7f6 8365 goto cp0_unimplemented;
1176b328 8366 case CP0_REG25__PERFCNT1:
7480515f 8367 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 8368 register_name = "Performance3";
3570d7f6 8369 goto cp0_unimplemented;
1176b328 8370 case CP0_REG25__PERFCTL2:
7480515f 8371 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 8372 register_name = "Performance4";
3570d7f6 8373 goto cp0_unimplemented;
1176b328 8374 case CP0_REG25__PERFCNT2:
7480515f 8375 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 8376 register_name = "Performance5";
3570d7f6 8377 goto cp0_unimplemented;
1176b328 8378 case CP0_REG25__PERFCTL3:
7480515f 8379 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 8380 register_name = "Performance6";
3570d7f6 8381 goto cp0_unimplemented;
1176b328 8382 case CP0_REG25__PERFCNT3:
7480515f 8383 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 8384 register_name = "Performance7";
3570d7f6 8385 goto cp0_unimplemented;
7a387fff 8386 default:
f31b035a 8387 goto cp0_unimplemented;
7a387fff 8388 }
8c0fdd85 8389 break;
04992c8c 8390 case CP0_REGISTER_26:
0d74a222 8391 switch (sel) {
dbbf08b2 8392 case CP0_REG26__ERRCTL:
0d74a222 8393 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8394 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8395 register_name = "ErrCtl";
0d74a222
LA
8396 break;
8397 default:
8398 goto cp0_unimplemented;
8399 }
2423f660 8400 break;
04992c8c 8401 case CP0_REGISTER_27:
7a387fff 8402 switch (sel) {
5a10873d 8403 case CP0_REG27__CACHERR:
2423f660 8404 /* ignored */
294fc2ea 8405 register_name = "CacheErr";
2423f660 8406 break;
7a387fff 8407 default:
f31b035a 8408 goto cp0_unimplemented;
7a387fff 8409 }
8c0fdd85 8410 break;
04992c8c 8411 case CP0_REGISTER_28:
8c0fdd85 8412 switch (sel) {
a30e2f21
AM
8413 case CP0_REG28__TAGLO:
8414 case CP0_REG28__TAGLO1:
8415 case CP0_REG28__TAGLO2:
8416 case CP0_REG28__TAGLO3:
895c2d04 8417 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8418 register_name = "TagLo";
8c0fdd85 8419 break;
a30e2f21
AM
8420 case CP0_REG28__DATALO:
8421 case CP0_REG28__DATALO1:
8422 case CP0_REG28__DATALO2:
8423 case CP0_REG28__DATALO3:
895c2d04 8424 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8425 register_name = "DataLo";
7a387fff 8426 break;
8c0fdd85 8427 default:
f31b035a 8428 goto cp0_unimplemented;
8c0fdd85
TS
8429 }
8430 break;
04992c8c 8431 case CP0_REGISTER_29:
7a387fff 8432 switch (sel) {
af4bb6da
AM
8433 case CP0_REG29__TAGHI:
8434 case CP0_REG29__TAGHI1:
8435 case CP0_REG29__TAGHI2:
8436 case CP0_REG29__TAGHI3:
895c2d04 8437 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8438 register_name = "TagHi";
7a387fff 8439 break;
af4bb6da
AM
8440 case CP0_REG29__DATAHI:
8441 case CP0_REG29__DATAHI1:
8442 case CP0_REG29__DATAHI2:
8443 case CP0_REG29__DATAHI3:
895c2d04 8444 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8445 register_name = "DataHi";
7a387fff
TS
8446 break;
8447 default:
294fc2ea 8448 register_name = "invalid sel";
f31b035a 8449 goto cp0_unimplemented;
7a387fff 8450 }
8c0fdd85 8451 break;
04992c8c 8452 case CP0_REGISTER_30:
7a387fff 8453 switch (sel) {
4bcf121e 8454 case CP0_REG30__ERROREPC:
d54a299b 8455 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8456 register_name = "ErrorEPC";
2423f660 8457 break;
7a387fff 8458 default:
f31b035a 8459 goto cp0_unimplemented;
7a387fff 8460 }
8c0fdd85 8461 break;
04992c8c 8462 case CP0_REGISTER_31:
7a387fff 8463 switch (sel) {
14d92efd 8464 case CP0_REG31__DESAVE:
f1aa6320 8465 /* EJTAG support */
7db13fae 8466 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8467 register_name = "DESAVE";
2423f660 8468 break;
14d92efd
AM
8469 case CP0_REG31__KSCRATCH1:
8470 case CP0_REG31__KSCRATCH2:
8471 case CP0_REG31__KSCRATCH3:
8472 case CP0_REG31__KSCRATCH4:
8473 case CP0_REG31__KSCRATCH5:
8474 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8475 CP0_CHECK(ctx->kscrexist & (1 << sel));
8476 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 8477 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8478 register_name = "KScratch";
e98c0d17 8479 break;
7a387fff 8480 default:
f31b035a 8481 goto cp0_unimplemented;
7a387fff 8482 }
8c0fdd85
TS
8483 break;
8484 default:
f31b035a 8485 goto cp0_unimplemented;
8c0fdd85 8486 }
294fc2ea 8487 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8488
bf20dc07 8489 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8490 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8491 /*
8492 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8493 * translated code to check for pending interrupts.
8494 */
eeb3bba8
EC
8495 gen_save_pc(ctx->base.pc_next + 4);
8496 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8497 }
8c0fdd85
TS
8498 return;
8499
f31b035a 8500cp0_unimplemented:
294fc2ea
AM
8501 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8502 register_name, reg, sel);
8c0fdd85
TS
8503}
8504
d26bc211 8505#if defined(TARGET_MIPS64)
d75c135e 8506static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8507{
294fc2ea 8508 const char *register_name = "invalid";
9c2149c8 8509
1f8929d2 8510 if (sel != 0) {
d75c135e 8511 check_insn(ctx, ISA_MIPS64);
1f8929d2 8512 }
e189e748 8513
9c2149c8 8514 switch (reg) {
04992c8c 8515 case CP0_REGISTER_00:
9c2149c8 8516 switch (sel) {
1b142da5 8517 case CP0_REG00__INDEX:
7db13fae 8518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8519 register_name = "Index";
9c2149c8 8520 break;
1b142da5 8521 case CP0_REG00__MVPCONTROL:
f31b035a 8522 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8523 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8524 register_name = "MVPControl";
ead9360e 8525 break;
1b142da5 8526 case CP0_REG00__MVPCONF0:
f31b035a 8527 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8528 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8529 register_name = "MVPConf0";
ead9360e 8530 break;
1b142da5 8531 case CP0_REG00__MVPCONF1:
f31b035a 8532 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8533 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8534 register_name = "MVPConf1";
ead9360e 8535 break;
1b142da5 8536 case CP0_REG00__VPCONTROL:
01bc435b
YK
8537 CP0_CHECK(ctx->vp);
8538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8539 register_name = "VPControl";
01bc435b 8540 break;
9c2149c8 8541 default:
f31b035a 8542 goto cp0_unimplemented;
9c2149c8
TS
8543 }
8544 break;
04992c8c 8545 case CP0_REGISTER_01:
9c2149c8 8546 switch (sel) {
30deb460 8547 case CP0_REG01__RANDOM:
f31b035a 8548 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 8549 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8550 register_name = "Random";
2423f660 8551 break;
30deb460 8552 case CP0_REG01__VPECONTROL:
f31b035a 8553 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8555 register_name = "VPEControl";
ead9360e 8556 break;
30deb460 8557 case CP0_REG01__VPECONF0:
f31b035a 8558 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8560 register_name = "VPEConf0";
ead9360e 8561 break;
30deb460 8562 case CP0_REG01__VPECONF1:
f31b035a 8563 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8564 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 8565 register_name = "VPEConf1";
ead9360e 8566 break;
30deb460 8567 case CP0_REG01__YQMASK:
f31b035a 8568 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8569 tcg_gen_ld_tl(arg, cpu_env,
8570 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 8571 register_name = "YQMask";
ead9360e 8572 break;
30deb460 8573 case CP0_REG01__VPESCHEDULE:
f31b035a 8574 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8575 tcg_gen_ld_tl(arg, cpu_env,
8576 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8577 register_name = "VPESchedule";
ead9360e 8578 break;
30deb460 8579 case CP0_REG01__VPESCHEFBACK:
f31b035a 8580 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8581 tcg_gen_ld_tl(arg, cpu_env,
8582 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8583 register_name = "VPEScheFBack";
ead9360e 8584 break;
30deb460 8585 case CP0_REG01__VPEOPT:
f31b035a 8586 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 8588 register_name = "VPEOpt";
ead9360e 8589 break;
9c2149c8 8590 default:
f31b035a 8591 goto cp0_unimplemented;
9c2149c8
TS
8592 }
8593 break;
04992c8c 8594 case CP0_REGISTER_02:
9c2149c8 8595 switch (sel) {
6d27d5bd 8596 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
8597 tcg_gen_ld_tl(arg, cpu_env,
8598 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 8599 register_name = "EntryLo0";
2423f660 8600 break;
6d27d5bd 8601 case CP0_REG02__TCSTATUS:
f31b035a 8602 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8603 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 8604 register_name = "TCStatus";
ead9360e 8605 break;
6d27d5bd 8606 case CP0_REG02__TCBIND:
f31b035a 8607 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8608 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 8609 register_name = "TCBind";
ead9360e 8610 break;
6d27d5bd 8611 case CP0_REG02__TCRESTART:
f31b035a 8612 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8613 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 8614 register_name = "TCRestart";
ead9360e 8615 break;
6d27d5bd 8616 case CP0_REG02__TCHALT:
f31b035a 8617 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8618 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 8619 register_name = "TCHalt";
ead9360e 8620 break;
6d27d5bd 8621 case CP0_REG02__TCCONTEXT:
f31b035a 8622 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8623 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 8624 register_name = "TCContext";
ead9360e 8625 break;
6d27d5bd 8626 case CP0_REG02__TCSCHEDULE:
f31b035a 8627 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8628 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 8629 register_name = "TCSchedule";
ead9360e 8630 break;
6d27d5bd 8631 case CP0_REG02__TCSCHEFBACK:
f31b035a 8632 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8633 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 8634 register_name = "TCScheFBack";
ead9360e 8635 break;
9c2149c8 8636 default:
f31b035a 8637 goto cp0_unimplemented;
9c2149c8
TS
8638 }
8639 break;
04992c8c 8640 case CP0_REGISTER_03:
9c2149c8 8641 switch (sel) {
acd37316 8642 case CP0_REG03__ENTRYLO1:
7db13fae 8643 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 8644 register_name = "EntryLo1";
2423f660 8645 break;
acd37316 8646 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8647 CP0_CHECK(ctx->vp);
8648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 8649 register_name = "GlobalNumber";
01bc435b 8650 break;
9c2149c8 8651 default:
f31b035a 8652 goto cp0_unimplemented;
1579a72e 8653 }
9c2149c8 8654 break;
04992c8c 8655 case CP0_REGISTER_04:
9c2149c8 8656 switch (sel) {
020fe379 8657 case CP0_REG04__CONTEXT:
7db13fae 8658 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 8659 register_name = "Context";
2423f660 8660 break;
020fe379
AM
8661 case CP0_REG04__CONTEXTCONFIG:
8662 /* SmartMIPS ASE */
8663 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 8664 register_name = "ContextConfig";
f31b035a 8665 goto cp0_unimplemented;
020fe379 8666 case CP0_REG04__USERLOCAL:
f31b035a
LA
8667 CP0_CHECK(ctx->ulri);
8668 tcg_gen_ld_tl(arg, cpu_env,
8669 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8670 register_name = "UserLocal";
d279279e 8671 break;
99029be1
YK
8672 case CP0_REG04__MMID:
8673 CP0_CHECK(ctx->mi);
8674 gen_helper_mtc0_memorymapid(cpu_env, arg);
8675 register_name = "MMID";
8676 break;
9c2149c8 8677 default:
f31b035a 8678 goto cp0_unimplemented;
876d4b07 8679 }
9c2149c8 8680 break;
04992c8c 8681 case CP0_REGISTER_05:
9c2149c8 8682 switch (sel) {
a1e76353 8683 case CP0_REG05__PAGEMASK:
7db13fae 8684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 8685 register_name = "PageMask";
2423f660 8686 break;
a1e76353 8687 case CP0_REG05__PAGEGRAIN:
d75c135e 8688 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 8690 register_name = "PageGrain";
2423f660 8691 break;
a1e76353 8692 case CP0_REG05__SEGCTL0:
cec56a73
JH
8693 CP0_CHECK(ctx->sc);
8694 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 8695 register_name = "SegCtl0";
cec56a73 8696 break;
a1e76353 8697 case CP0_REG05__SEGCTL1:
cec56a73
JH
8698 CP0_CHECK(ctx->sc);
8699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 8700 register_name = "SegCtl1";
cec56a73 8701 break;
a1e76353 8702 case CP0_REG05__SEGCTL2:
cec56a73
JH
8703 CP0_CHECK(ctx->sc);
8704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 8705 register_name = "SegCtl2";
cec56a73 8706 break;
a1e76353 8707 case CP0_REG05__PWBASE:
5e31fdd5
YK
8708 check_pw(ctx);
8709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8710 register_name = "PWBase";
5e31fdd5 8711 break;
a1e76353 8712 case CP0_REG05__PWFIELD:
fa75ad14
YK
8713 check_pw(ctx);
8714 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 8715 register_name = "PWField";
fa75ad14 8716 break;
a1e76353 8717 case CP0_REG05__PWSIZE:
20b28ebc
YK
8718 check_pw(ctx);
8719 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 8720 register_name = "PWSize";
20b28ebc 8721 break;
9c2149c8 8722 default:
f31b035a 8723 goto cp0_unimplemented;
876d4b07 8724 }
9c2149c8 8725 break;
04992c8c 8726 case CP0_REGISTER_06:
9c2149c8 8727 switch (sel) {
9023594b 8728 case CP0_REG06__WIRED:
7db13fae 8729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 8730 register_name = "Wired";
2423f660 8731 break;
9023594b 8732 case CP0_REG06__SRSCONF0:
d75c135e 8733 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 8735 register_name = "SRSConf0";
ead9360e 8736 break;
9023594b 8737 case CP0_REG06__SRSCONF1:
d75c135e 8738 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 8740 register_name = "SRSConf1";
ead9360e 8741 break;
9023594b 8742 case CP0_REG06__SRSCONF2:
d75c135e 8743 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 8745 register_name = "SRSConf2";
ead9360e 8746 break;
9023594b 8747 case CP0_REG06__SRSCONF3:
d75c135e 8748 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 8750 register_name = "SRSConf3";
ead9360e 8751 break;
9023594b 8752 case CP0_REG06__SRSCONF4:
d75c135e 8753 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8754 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 8755 register_name = "SRSConf4";
ead9360e 8756 break;
9023594b 8757 case CP0_REG06__PWCTL:
103be64c
YK
8758 check_pw(ctx);
8759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 8760 register_name = "PWCtl";
103be64c 8761 break;
9c2149c8 8762 default:
f31b035a 8763 goto cp0_unimplemented;
876d4b07 8764 }
9c2149c8 8765 break;
04992c8c 8766 case CP0_REGISTER_07:
9c2149c8 8767 switch (sel) {
143a9875 8768 case CP0_REG07__HWRENA:
d75c135e 8769 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 8771 register_name = "HWREna";
2423f660 8772 break;
9c2149c8 8773 default:
f31b035a 8774 goto cp0_unimplemented;
876d4b07 8775 }
9c2149c8 8776 break;
04992c8c 8777 case CP0_REGISTER_08:
9c2149c8 8778 switch (sel) {
67d167d2 8779 case CP0_REG08__BADVADDR:
7db13fae 8780 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 8781 register_name = "BadVAddr";
2423f660 8782 break;
67d167d2 8783 case CP0_REG08__BADINSTR:
f31b035a
LA
8784 CP0_CHECK(ctx->bi);
8785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 8786 register_name = "BadInstr";
aea14095 8787 break;
67d167d2 8788 case CP0_REG08__BADINSTRP:
f31b035a
LA
8789 CP0_CHECK(ctx->bp);
8790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 8791 register_name = "BadInstrP";
aea14095 8792 break;
67d167d2 8793 case CP0_REG08__BADINSTRX:
25beba9b
SM
8794 CP0_CHECK(ctx->bi);
8795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8796 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 8797 register_name = "BadInstrX";
25beba9b 8798 break;
9c2149c8 8799 default:
f31b035a 8800 goto cp0_unimplemented;
876d4b07 8801 }
9c2149c8 8802 break;
04992c8c 8803 case CP0_REGISTER_09:
9c2149c8 8804 switch (sel) {
e5a98a72 8805 case CP0_REG09__COUNT:
2e70f6ef 8806 /* Mark as an IO operation because we read the time. */
eeb3bba8 8807 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8808 gen_io_start();
bd79255d 8809 }
895c2d04 8810 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
8811 /*
8812 * Break the TB to be able to take timer interrupts immediately
8813 * after reading count. DISAS_STOP isn't sufficient, we need to
8814 * ensure we break completely out of translated code.
8815 */
eeb3bba8
EC
8816 gen_save_pc(ctx->base.pc_next + 4);
8817 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8818 register_name = "Count";
2423f660 8819 break;
e5a98a72 8820 case CP0_REG09__SAARI:
5fb2dcd1
YK
8821 CP0_CHECK(ctx->saar);
8822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 8823 register_name = "SAARI";
5fb2dcd1 8824 break;
e5a98a72 8825 case CP0_REG09__SAAR:
5fb2dcd1
YK
8826 CP0_CHECK(ctx->saar);
8827 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 8828 register_name = "SAAR";
5fb2dcd1 8829 break;
9c2149c8 8830 default:
f31b035a 8831 goto cp0_unimplemented;
876d4b07 8832 }
9c2149c8 8833 break;
04992c8c 8834 case CP0_REGISTER_10:
9c2149c8 8835 switch (sel) {
860ffef0 8836 case CP0_REG10__ENTRYHI:
7db13fae 8837 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 8838 register_name = "EntryHi";
2423f660 8839 break;
9c2149c8 8840 default:
f31b035a 8841 goto cp0_unimplemented;
876d4b07 8842 }
9c2149c8 8843 break;
04992c8c 8844 case CP0_REGISTER_11:
9c2149c8 8845 switch (sel) {
f5f3834f 8846 case CP0_REG11__COMPARE:
7db13fae 8847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 8848 register_name = "Compare";
2423f660 8849 break;
876d4b07 8850 /* 6,7 are implementation dependent */
9c2149c8 8851 default:
f31b035a 8852 goto cp0_unimplemented;
876d4b07 8853 }
9c2149c8 8854 break;
04992c8c 8855 case CP0_REGISTER_12:
9c2149c8 8856 switch (sel) {
2b084867 8857 case CP0_REG12__STATUS:
7db13fae 8858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 8859 register_name = "Status";
2423f660 8860 break;
2b084867 8861 case CP0_REG12__INTCTL:
d75c135e 8862 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 8864 register_name = "IntCtl";
2423f660 8865 break;
2b084867 8866 case CP0_REG12__SRSCTL:
d75c135e 8867 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 8869 register_name = "SRSCtl";
2423f660 8870 break;
2b084867 8871 case CP0_REG12__SRSMAP:
d75c135e 8872 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 8874 register_name = "SRSMap";
2423f660 8875 break;
9c2149c8 8876 default:
f31b035a 8877 goto cp0_unimplemented;
876d4b07 8878 }
9c2149c8 8879 break;
04992c8c 8880 case CP0_REGISTER_13:
9c2149c8 8881 switch (sel) {
e3c7559d 8882 case CP0_REG13__CAUSE:
7db13fae 8883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 8884 register_name = "Cause";
2423f660 8885 break;
9c2149c8 8886 default:
f31b035a 8887 goto cp0_unimplemented;
876d4b07 8888 }
9c2149c8 8889 break;
04992c8c 8890 case CP0_REGISTER_14:
9c2149c8 8891 switch (sel) {
35e4b54d 8892 case CP0_REG14__EPC:
7db13fae 8893 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8894 register_name = "EPC";
2423f660 8895 break;
9c2149c8 8896 default:
f31b035a 8897 goto cp0_unimplemented;
876d4b07 8898 }
9c2149c8 8899 break;
04992c8c 8900 case CP0_REGISTER_15:
9c2149c8 8901 switch (sel) {
4466cd49 8902 case CP0_REG15__PRID:
7db13fae 8903 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 8904 register_name = "PRid";
2423f660 8905 break;
4466cd49 8906 case CP0_REG15__EBASE:
d75c135e 8907 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8908 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 8909 register_name = "EBase";
2423f660 8910 break;
4466cd49 8911 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
8912 check_insn(ctx, ISA_MIPS32R2);
8913 CP0_CHECK(ctx->cmgcr);
8914 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 8915 register_name = "CMGCRBase";
c870e3f5 8916 break;
9c2149c8 8917 default:
f31b035a 8918 goto cp0_unimplemented;
876d4b07 8919 }
9c2149c8 8920 break;
04992c8c 8921 case CP0_REGISTER_16:
9c2149c8 8922 switch (sel) {
433efb4c 8923 case CP0_REG16__CONFIG:
7db13fae 8924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 8925 register_name = "Config";
9c2149c8 8926 break;
433efb4c 8927 case CP0_REG16__CONFIG1:
7db13fae 8928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 8929 register_name = "Config1";
9c2149c8 8930 break;
433efb4c 8931 case CP0_REG16__CONFIG2:
7db13fae 8932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 8933 register_name = "Config2";
9c2149c8 8934 break;
433efb4c 8935 case CP0_REG16__CONFIG3:
7db13fae 8936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 8937 register_name = "Config3";
9c2149c8 8938 break;
433efb4c 8939 case CP0_REG16__CONFIG4:
faf1f68b 8940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 8941 register_name = "Config4";
faf1f68b 8942 break;
433efb4c 8943 case CP0_REG16__CONFIG5:
faf1f68b 8944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 8945 register_name = "Config5";
faf1f68b 8946 break;
05aa7e93 8947 /* 6,7 are implementation dependent */
433efb4c 8948 case CP0_REG16__CONFIG6:
7db13fae 8949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 8950 register_name = "Config6";
f0b3f3ae 8951 break;
433efb4c 8952 case CP0_REG16__CONFIG7:
7db13fae 8953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 8954 register_name = "Config7";
f0b3f3ae 8955 break;
9c2149c8 8956 default:
f31b035a 8957 goto cp0_unimplemented;
9c2149c8
TS
8958 }
8959 break;
04992c8c 8960 case CP0_REGISTER_17:
9c2149c8 8961 switch (sel) {
706ce142 8962 case CP0_REG17__LLADDR:
895c2d04 8963 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 8964 register_name = "LLAddr";
2423f660 8965 break;
706ce142 8966 case CP0_REG17__MAAR:
f6d4dd81
YK
8967 CP0_CHECK(ctx->mrp);
8968 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 8969 register_name = "MAAR";
f6d4dd81 8970 break;
706ce142 8971 case CP0_REG17__MAARI:
f6d4dd81
YK
8972 CP0_CHECK(ctx->mrp);
8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 8974 register_name = "MAARI";
f6d4dd81 8975 break;
9c2149c8 8976 default:
f31b035a 8977 goto cp0_unimplemented;
9c2149c8
TS
8978 }
8979 break;
04992c8c 8980 case CP0_REGISTER_18:
9c2149c8 8981 switch (sel) {
e8dcfe82
AM
8982 case CP0_REG18__WATCHLO0:
8983 case CP0_REG18__WATCHLO1:
8984 case CP0_REG18__WATCHLO2:
8985 case CP0_REG18__WATCHLO3:
8986 case CP0_REG18__WATCHLO4:
8987 case CP0_REG18__WATCHLO5:
8988 case CP0_REG18__WATCHLO6:
8989 case CP0_REG18__WATCHLO7:
fa192d49 8990 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8991 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 8992 register_name = "WatchLo";
2423f660 8993 break;
9c2149c8 8994 default:
f31b035a 8995 goto cp0_unimplemented;
9c2149c8
TS
8996 }
8997 break;
04992c8c 8998 case CP0_REGISTER_19:
9c2149c8 8999 switch (sel) {
be274dc1
AM
9000 case CP0_REG19__WATCHHI0:
9001 case CP0_REG19__WATCHHI1:
9002 case CP0_REG19__WATCHHI2:
9003 case CP0_REG19__WATCHHI3:
9004 case CP0_REG19__WATCHHI4:
9005 case CP0_REG19__WATCHHI5:
9006 case CP0_REG19__WATCHHI6:
9007 case CP0_REG19__WATCHHI7:
fa192d49 9008 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 9009 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 9010 register_name = "WatchHi";
2423f660 9011 break;
9c2149c8 9012 default:
f31b035a 9013 goto cp0_unimplemented;
9c2149c8
TS
9014 }
9015 break;
04992c8c 9016 case CP0_REGISTER_20:
9c2149c8 9017 switch (sel) {
14f92b0b 9018 case CP0_REG20__XCONTEXT:
d75c135e 9019 check_insn(ctx, ISA_MIPS3);
7db13fae 9020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 9021 register_name = "XContext";
2423f660 9022 break;
9c2149c8 9023 default:
f31b035a 9024 goto cp0_unimplemented;
9c2149c8
TS
9025 }
9026 break;
04992c8c 9027 case CP0_REGISTER_21:
05aa7e93 9028 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9029 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9030 switch (sel) {
9031 case 0:
7db13fae 9032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 9033 register_name = "Framemask";
2423f660 9034 break;
9c2149c8 9035 default:
f31b035a 9036 goto cp0_unimplemented;
9c2149c8
TS
9037 }
9038 break;
04992c8c 9039 case CP0_REGISTER_22:
d9bea114 9040 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 9041 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 9042 break;
04992c8c 9043 case CP0_REGISTER_23:
9c2149c8 9044 switch (sel) {
4cbf4b6d 9045 case CP0_REG23__DEBUG:
895c2d04 9046 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 9047 register_name = "Debug";
2423f660 9048 break;
4cbf4b6d
AM
9049 case CP0_REG23__TRACECONTROL:
9050 /* PDtrace support */
9051 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 9052 register_name = "TraceControl";
3570d7f6 9053 goto cp0_unimplemented;
4cbf4b6d
AM
9054 case CP0_REG23__TRACECONTROL2:
9055 /* PDtrace support */
9056 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 9057 register_name = "TraceControl2";
3570d7f6 9058 goto cp0_unimplemented;
4cbf4b6d
AM
9059 case CP0_REG23__USERTRACEDATA1:
9060 /* PDtrace support */
9061 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9062 register_name = "UserTraceData1";
3570d7f6 9063 goto cp0_unimplemented;
4cbf4b6d
AM
9064 case CP0_REG23__TRACEIBPC:
9065 /* PDtrace support */
9066 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9067 register_name = "TraceIBPC";
9068 goto cp0_unimplemented;
9069 case CP0_REG23__TRACEDBPC:
9070 /* PDtrace support */
9071 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9072 register_name = "TraceDBPC";
3570d7f6 9073 goto cp0_unimplemented;
9c2149c8 9074 default:
f31b035a 9075 goto cp0_unimplemented;
9c2149c8
TS
9076 }
9077 break;
04992c8c 9078 case CP0_REGISTER_24:
9c2149c8 9079 switch (sel) {
8d7b4b6e 9080 case CP0_REG24__DEPC:
f0b3f3ae 9081 /* EJTAG support */
7db13fae 9082 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9083 register_name = "DEPC";
2423f660 9084 break;
9c2149c8 9085 default:
f31b035a 9086 goto cp0_unimplemented;
9c2149c8
TS
9087 }
9088 break;
04992c8c 9089 case CP0_REGISTER_25:
9c2149c8 9090 switch (sel) {
1176b328 9091 case CP0_REG25__PERFCTL0:
7db13fae 9092 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 9093 register_name = "Performance0";
9c2149c8 9094 break;
1176b328 9095 case CP0_REG25__PERFCNT0:
7480515f 9096 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 9097 register_name = "Performance1";
3570d7f6 9098 goto cp0_unimplemented;
1176b328 9099 case CP0_REG25__PERFCTL1:
7480515f 9100 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 9101 register_name = "Performance2";
3570d7f6 9102 goto cp0_unimplemented;
1176b328 9103 case CP0_REG25__PERFCNT1:
7480515f 9104 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 9105 register_name = "Performance3";
3570d7f6 9106 goto cp0_unimplemented;
1176b328 9107 case CP0_REG25__PERFCTL2:
7480515f 9108 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 9109 register_name = "Performance4";
3570d7f6 9110 goto cp0_unimplemented;
1176b328 9111 case CP0_REG25__PERFCNT2:
7480515f 9112 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 9113 register_name = "Performance5";
3570d7f6 9114 goto cp0_unimplemented;
1176b328 9115 case CP0_REG25__PERFCTL3:
7480515f 9116 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 9117 register_name = "Performance6";
3570d7f6 9118 goto cp0_unimplemented;
1176b328 9119 case CP0_REG25__PERFCNT3:
7480515f 9120 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 9121 register_name = "Performance7";
3570d7f6 9122 goto cp0_unimplemented;
9c2149c8 9123 default:
f31b035a 9124 goto cp0_unimplemented;
9c2149c8
TS
9125 }
9126 break;
04992c8c 9127 case CP0_REGISTER_26:
0d74a222 9128 switch (sel) {
dbbf08b2 9129 case CP0_REG26__ERRCTL:
0d74a222 9130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 9131 register_name = "ErrCtl";
0d74a222
LA
9132 break;
9133 default:
9134 goto cp0_unimplemented;
9135 }
da80682b 9136 break;
04992c8c 9137 case CP0_REGISTER_27:
9c2149c8
TS
9138 switch (sel) {
9139 /* ignored */
5a10873d 9140 case CP0_REG27__CACHERR:
d9bea114 9141 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 9142 register_name = "CacheErr";
2423f660 9143 break;
9c2149c8 9144 default:
f31b035a 9145 goto cp0_unimplemented;
9c2149c8
TS
9146 }
9147 break;
04992c8c 9148 case CP0_REGISTER_28:
9c2149c8 9149 switch (sel) {
a30e2f21
AM
9150 case CP0_REG28__TAGLO:
9151 case CP0_REG28__TAGLO1:
9152 case CP0_REG28__TAGLO2:
9153 case CP0_REG28__TAGLO3:
7db13fae 9154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 9155 register_name = "TagLo";
9c2149c8 9156 break;
a30e2f21
AM
9157 case CP0_REG28__DATALO:
9158 case CP0_REG28__DATALO1:
9159 case CP0_REG28__DATALO2:
9160 case CP0_REG28__DATALO3:
7db13fae 9161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 9162 register_name = "DataLo";
9c2149c8
TS
9163 break;
9164 default:
f31b035a 9165 goto cp0_unimplemented;
9c2149c8
TS
9166 }
9167 break;
04992c8c 9168 case CP0_REGISTER_29:
9c2149c8 9169 switch (sel) {
af4bb6da
AM
9170 case CP0_REG29__TAGHI:
9171 case CP0_REG29__TAGHI1:
9172 case CP0_REG29__TAGHI2:
9173 case CP0_REG29__TAGHI3:
7db13fae 9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 9175 register_name = "TagHi";
9c2149c8 9176 break;
af4bb6da
AM
9177 case CP0_REG29__DATAHI:
9178 case CP0_REG29__DATAHI1:
9179 case CP0_REG29__DATAHI2:
9180 case CP0_REG29__DATAHI3:
7db13fae 9181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 9182 register_name = "DataHi";
9c2149c8
TS
9183 break;
9184 default:
f31b035a 9185 goto cp0_unimplemented;
9c2149c8
TS
9186 }
9187 break;
04992c8c 9188 case CP0_REGISTER_30:
9c2149c8 9189 switch (sel) {
4bcf121e 9190 case CP0_REG30__ERROREPC:
7db13fae 9191 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9192 register_name = "ErrorEPC";
2423f660 9193 break;
9c2149c8 9194 default:
f31b035a 9195 goto cp0_unimplemented;
9c2149c8
TS
9196 }
9197 break;
04992c8c 9198 case CP0_REGISTER_31:
9c2149c8 9199 switch (sel) {
14d92efd 9200 case CP0_REG31__DESAVE:
f0b3f3ae 9201 /* EJTAG support */
7db13fae 9202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9203 register_name = "DESAVE";
2423f660 9204 break;
14d92efd
AM
9205 case CP0_REG31__KSCRATCH1:
9206 case CP0_REG31__KSCRATCH2:
9207 case CP0_REG31__KSCRATCH3:
9208 case CP0_REG31__KSCRATCH4:
9209 case CP0_REG31__KSCRATCH5:
9210 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9211 CP0_CHECK(ctx->kscrexist & (1 << sel));
9212 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 9213 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9214 register_name = "KScratch";
e98c0d17 9215 break;
9c2149c8 9216 default:
f31b035a 9217 goto cp0_unimplemented;
9c2149c8
TS
9218 }
9219 break;
9220 default:
f31b035a 9221 goto cp0_unimplemented;
9c2149c8 9222 }
294fc2ea 9223 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
9224 return;
9225
f31b035a 9226cp0_unimplemented:
294fc2ea
AM
9227 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9228 register_name, reg, sel);
f31b035a 9229 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
9230}
9231
d75c135e 9232static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 9233{
294fc2ea 9234 const char *register_name = "invalid";
9c2149c8 9235
1f8929d2 9236 if (sel != 0) {
d75c135e 9237 check_insn(ctx, ISA_MIPS64);
1f8929d2 9238 }
e189e748 9239
eeb3bba8 9240 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9241 gen_io_start();
bd79255d 9242 }
2e70f6ef 9243
9c2149c8 9244 switch (reg) {
04992c8c 9245 case CP0_REGISTER_00:
9c2149c8 9246 switch (sel) {
1b142da5 9247 case CP0_REG00__INDEX:
895c2d04 9248 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 9249 register_name = "Index";
9c2149c8 9250 break;
1b142da5 9251 case CP0_REG00__MVPCONTROL:
f31b035a 9252 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9253 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 9254 register_name = "MVPControl";
ead9360e 9255 break;
1b142da5 9256 case CP0_REG00__MVPCONF0:
f31b035a 9257 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9258 /* ignored */
294fc2ea 9259 register_name = "MVPConf0";
ead9360e 9260 break;
1b142da5 9261 case CP0_REG00__MVPCONF1:
f31b035a 9262 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9263 /* ignored */
294fc2ea 9264 register_name = "MVPConf1";
ead9360e 9265 break;
1b142da5 9266 case CP0_REG00__VPCONTROL:
01bc435b
YK
9267 CP0_CHECK(ctx->vp);
9268 /* ignored */
294fc2ea 9269 register_name = "VPControl";
01bc435b 9270 break;
9c2149c8 9271 default:
f31b035a 9272 goto cp0_unimplemented;
9c2149c8
TS
9273 }
9274 break;
04992c8c 9275 case CP0_REGISTER_01:
9c2149c8 9276 switch (sel) {
30deb460 9277 case CP0_REG01__RANDOM:
2423f660 9278 /* ignored */
294fc2ea 9279 register_name = "Random";
2423f660 9280 break;
30deb460 9281 case CP0_REG01__VPECONTROL:
f31b035a 9282 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9283 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9284 register_name = "VPEControl";
ead9360e 9285 break;
30deb460 9286 case CP0_REG01__VPECONF0:
f31b035a 9287 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9288 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9289 register_name = "VPEConf0";
ead9360e 9290 break;
30deb460 9291 case CP0_REG01__VPECONF1:
f31b035a 9292 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9293 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9294 register_name = "VPEConf1";
ead9360e 9295 break;
30deb460 9296 case CP0_REG01__YQMASK:
f31b035a 9297 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9298 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9299 register_name = "YQMask";
ead9360e 9300 break;
30deb460 9301 case CP0_REG01__VPESCHEDULE:
f31b035a 9302 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9303 tcg_gen_st_tl(arg, cpu_env,
9304 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9305 register_name = "VPESchedule";
ead9360e 9306 break;
30deb460 9307 case CP0_REG01__VPESCHEFBACK:
f31b035a 9308 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9309 tcg_gen_st_tl(arg, cpu_env,
9310 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9311 register_name = "VPEScheFBack";
ead9360e 9312 break;
30deb460 9313 case CP0_REG01__VPEOPT:
f31b035a 9314 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9315 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9316 register_name = "VPEOpt";
ead9360e 9317 break;
9c2149c8 9318 default:
f31b035a 9319 goto cp0_unimplemented;
9c2149c8
TS
9320 }
9321 break;
04992c8c 9322 case CP0_REGISTER_02:
9c2149c8 9323 switch (sel) {
6d27d5bd 9324 case CP0_REG02__ENTRYLO0:
7207c7f9 9325 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9326 register_name = "EntryLo0";
2423f660 9327 break;
6d27d5bd 9328 case CP0_REG02__TCSTATUS:
f31b035a 9329 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9330 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9331 register_name = "TCStatus";
ead9360e 9332 break;
6d27d5bd 9333 case CP0_REG02__TCBIND:
f31b035a 9334 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9335 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9336 register_name = "TCBind";
ead9360e 9337 break;
6d27d5bd 9338 case CP0_REG02__TCRESTART:
f31b035a 9339 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9340 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9341 register_name = "TCRestart";
ead9360e 9342 break;
6d27d5bd 9343 case CP0_REG02__TCHALT:
f31b035a 9344 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9345 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9346 register_name = "TCHalt";
ead9360e 9347 break;
6d27d5bd 9348 case CP0_REG02__TCCONTEXT:
f31b035a 9349 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9350 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9351 register_name = "TCContext";
ead9360e 9352 break;
6d27d5bd 9353 case CP0_REG02__TCSCHEDULE:
f31b035a 9354 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9355 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9356 register_name = "TCSchedule";
ead9360e 9357 break;
6d27d5bd 9358 case CP0_REG02__TCSCHEFBACK:
f31b035a 9359 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9360 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9361 register_name = "TCScheFBack";
ead9360e 9362 break;
9c2149c8 9363 default:
f31b035a 9364 goto cp0_unimplemented;
9c2149c8
TS
9365 }
9366 break;
04992c8c 9367 case CP0_REGISTER_03:
9c2149c8 9368 switch (sel) {
acd37316 9369 case CP0_REG03__ENTRYLO1:
7207c7f9 9370 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9371 register_name = "EntryLo1";
2423f660 9372 break;
acd37316 9373 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9374 CP0_CHECK(ctx->vp);
9375 /* ignored */
294fc2ea 9376 register_name = "GlobalNumber";
01bc435b 9377 break;
9c2149c8 9378 default:
f31b035a 9379 goto cp0_unimplemented;
876d4b07 9380 }
9c2149c8 9381 break;
04992c8c 9382 case CP0_REGISTER_04:
9c2149c8 9383 switch (sel) {
020fe379 9384 case CP0_REG04__CONTEXT:
895c2d04 9385 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9386 register_name = "Context";
2423f660 9387 break;
020fe379
AM
9388 case CP0_REG04__CONTEXTCONFIG:
9389 /* SmartMIPS ASE */
9390 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 9391 register_name = "ContextConfig";
f31b035a 9392 goto cp0_unimplemented;
020fe379 9393 case CP0_REG04__USERLOCAL:
f31b035a
LA
9394 CP0_CHECK(ctx->ulri);
9395 tcg_gen_st_tl(arg, cpu_env,
9396 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9397 register_name = "UserLocal";
d279279e 9398 break;
99029be1
YK
9399 case CP0_REG04__MMID:
9400 CP0_CHECK(ctx->mi);
9401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9402 register_name = "MMID";
9403 break;
9c2149c8 9404 default:
f31b035a 9405 goto cp0_unimplemented;
876d4b07 9406 }
9c2149c8 9407 break;
04992c8c 9408 case CP0_REGISTER_05:
9c2149c8 9409 switch (sel) {
a1e76353 9410 case CP0_REG05__PAGEMASK:
895c2d04 9411 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9412 register_name = "PageMask";
2423f660 9413 break;
a1e76353 9414 case CP0_REG05__PAGEGRAIN:
d75c135e 9415 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9416 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9417 register_name = "PageGrain";
2423f660 9418 break;
a1e76353 9419 case CP0_REG05__SEGCTL0:
cec56a73
JH
9420 CP0_CHECK(ctx->sc);
9421 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9422 register_name = "SegCtl0";
cec56a73 9423 break;
a1e76353 9424 case CP0_REG05__SEGCTL1:
cec56a73
JH
9425 CP0_CHECK(ctx->sc);
9426 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9427 register_name = "SegCtl1";
cec56a73 9428 break;
a1e76353 9429 case CP0_REG05__SEGCTL2:
cec56a73
JH
9430 CP0_CHECK(ctx->sc);
9431 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9432 register_name = "SegCtl2";
cec56a73 9433 break;
a1e76353 9434 case CP0_REG05__PWBASE:
5e31fdd5
YK
9435 check_pw(ctx);
9436 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9437 register_name = "PWBase";
5e31fdd5 9438 break;
a1e76353 9439 case CP0_REG05__PWFIELD:
fa75ad14
YK
9440 check_pw(ctx);
9441 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9442 register_name = "PWField";
fa75ad14 9443 break;
a1e76353 9444 case CP0_REG05__PWSIZE:
20b28ebc
YK
9445 check_pw(ctx);
9446 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9447 register_name = "PWSize";
20b28ebc 9448 break;
9c2149c8 9449 default:
f31b035a 9450 goto cp0_unimplemented;
876d4b07 9451 }
9c2149c8 9452 break;
04992c8c 9453 case CP0_REGISTER_06:
9c2149c8 9454 switch (sel) {
9023594b 9455 case CP0_REG06__WIRED:
895c2d04 9456 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9457 register_name = "Wired";
2423f660 9458 break;
9023594b 9459 case CP0_REG06__SRSCONF0:
d75c135e 9460 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9461 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9462 register_name = "SRSConf0";
ead9360e 9463 break;
9023594b 9464 case CP0_REG06__SRSCONF1:
d75c135e 9465 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9466 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9467 register_name = "SRSConf1";
ead9360e 9468 break;
9023594b 9469 case CP0_REG06__SRSCONF2:
d75c135e 9470 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9471 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9472 register_name = "SRSConf2";
ead9360e 9473 break;
9023594b 9474 case CP0_REG06__SRSCONF3:
d75c135e 9475 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9476 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9477 register_name = "SRSConf3";
ead9360e 9478 break;
9023594b 9479 case CP0_REG06__SRSCONF4:
d75c135e 9480 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9481 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9482 register_name = "SRSConf4";
ead9360e 9483 break;
9023594b 9484 case CP0_REG06__PWCTL:
103be64c
YK
9485 check_pw(ctx);
9486 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9487 register_name = "PWCtl";
103be64c 9488 break;
9c2149c8 9489 default:
f31b035a 9490 goto cp0_unimplemented;
876d4b07 9491 }
9c2149c8 9492 break;
04992c8c 9493 case CP0_REGISTER_07:
9c2149c8 9494 switch (sel) {
143a9875 9495 case CP0_REG07__HWRENA:
d75c135e 9496 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9497 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9498 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9499 register_name = "HWREna";
2423f660 9500 break;
9c2149c8 9501 default:
f31b035a 9502 goto cp0_unimplemented;
876d4b07 9503 }
9c2149c8 9504 break;
04992c8c 9505 case CP0_REGISTER_08:
aea14095 9506 switch (sel) {
67d167d2 9507 case CP0_REG08__BADVADDR:
aea14095 9508 /* ignored */
294fc2ea 9509 register_name = "BadVAddr";
aea14095 9510 break;
67d167d2 9511 case CP0_REG08__BADINSTR:
aea14095 9512 /* ignored */
294fc2ea 9513 register_name = "BadInstr";
aea14095 9514 break;
67d167d2 9515 case CP0_REG08__BADINSTRP:
aea14095 9516 /* ignored */
294fc2ea 9517 register_name = "BadInstrP";
aea14095 9518 break;
67d167d2 9519 case CP0_REG08__BADINSTRX:
25beba9b 9520 /* ignored */
294fc2ea 9521 register_name = "BadInstrX";
25beba9b 9522 break;
aea14095 9523 default:
f31b035a 9524 goto cp0_unimplemented;
aea14095 9525 }
9c2149c8 9526 break;
04992c8c 9527 case CP0_REGISTER_09:
9c2149c8 9528 switch (sel) {
e5a98a72 9529 case CP0_REG09__COUNT:
895c2d04 9530 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9531 register_name = "Count";
2423f660 9532 break;
e5a98a72 9533 case CP0_REG09__SAARI:
5fb2dcd1
YK
9534 CP0_CHECK(ctx->saar);
9535 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9536 register_name = "SAARI";
5fb2dcd1 9537 break;
e5a98a72 9538 case CP0_REG09__SAAR:
5fb2dcd1
YK
9539 CP0_CHECK(ctx->saar);
9540 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9541 register_name = "SAAR";
5fb2dcd1 9542 break;
9c2149c8 9543 default:
f31b035a 9544 goto cp0_unimplemented;
876d4b07
TS
9545 }
9546 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9547 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9548 break;
04992c8c 9549 case CP0_REGISTER_10:
9c2149c8 9550 switch (sel) {
860ffef0 9551 case CP0_REG10__ENTRYHI:
895c2d04 9552 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9553 register_name = "EntryHi";
2423f660 9554 break;
9c2149c8 9555 default:
f31b035a 9556 goto cp0_unimplemented;
876d4b07 9557 }
9c2149c8 9558 break;
04992c8c 9559 case CP0_REGISTER_11:
9c2149c8 9560 switch (sel) {
f5f3834f 9561 case CP0_REG11__COMPARE:
895c2d04 9562 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9563 register_name = "Compare";
2423f660 9564 break;
876d4b07 9565 /* 6,7 are implementation dependent */
9c2149c8 9566 default:
f31b035a 9567 goto cp0_unimplemented;
876d4b07 9568 }
de9a95f0 9569 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9570 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9571 break;
04992c8c 9572 case CP0_REGISTER_12:
9c2149c8 9573 switch (sel) {
2b084867 9574 case CP0_REG12__STATUS:
867abc7e 9575 save_cpu_state(ctx, 1);
895c2d04 9576 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 9577 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9578 gen_save_pc(ctx->base.pc_next + 4);
9579 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9580 register_name = "Status";
2423f660 9581 break;
2b084867 9582 case CP0_REG12__INTCTL:
d75c135e 9583 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9584 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 9585 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9586 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9587 register_name = "IntCtl";
2423f660 9588 break;
2b084867 9589 case CP0_REG12__SRSCTL:
d75c135e 9590 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9591 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 9592 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9593 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9594 register_name = "SRSCtl";
2423f660 9595 break;
2b084867 9596 case CP0_REG12__SRSMAP:
d75c135e 9597 check_insn(ctx, ISA_MIPS32R2);
7db13fae 9598 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 9599 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9600 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9601 register_name = "SRSMap";
2423f660
TS
9602 break;
9603 default:
f31b035a 9604 goto cp0_unimplemented;
876d4b07 9605 }
9c2149c8 9606 break;
04992c8c 9607 case CP0_REGISTER_13:
9c2149c8 9608 switch (sel) {
e3c7559d 9609 case CP0_REG13__CAUSE:
867abc7e 9610 save_cpu_state(ctx, 1);
895c2d04 9611 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
9612 /*
9613 * Stop translation as we may have triggered an interrupt.
b28425ba 9614 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
9615 * translated code to check for pending interrupts.
9616 */
eeb3bba8
EC
9617 gen_save_pc(ctx->base.pc_next + 4);
9618 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9619 register_name = "Cause";
2423f660 9620 break;
9c2149c8 9621 default:
f31b035a 9622 goto cp0_unimplemented;
876d4b07 9623 }
9c2149c8 9624 break;
04992c8c 9625 case CP0_REGISTER_14:
9c2149c8 9626 switch (sel) {
35e4b54d 9627 case CP0_REG14__EPC:
7db13fae 9628 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9629 register_name = "EPC";
2423f660 9630 break;
9c2149c8 9631 default:
f31b035a 9632 goto cp0_unimplemented;
876d4b07 9633 }
9c2149c8 9634 break;
04992c8c 9635 case CP0_REGISTER_15:
9c2149c8 9636 switch (sel) {
4466cd49 9637 case CP0_REG15__PRID:
2423f660 9638 /* ignored */
294fc2ea 9639 register_name = "PRid";
2423f660 9640 break;
4466cd49 9641 case CP0_REG15__EBASE:
d75c135e 9642 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9643 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 9644 register_name = "EBase";
2423f660 9645 break;
9c2149c8 9646 default:
f31b035a 9647 goto cp0_unimplemented;
876d4b07 9648 }
9c2149c8 9649 break;
04992c8c 9650 case CP0_REGISTER_16:
9c2149c8 9651 switch (sel) {
433efb4c 9652 case CP0_REG16__CONFIG:
895c2d04 9653 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 9654 register_name = "Config";
2423f660 9655 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9656 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9657 break;
433efb4c 9658 case CP0_REG16__CONFIG1:
1fc7bf6e 9659 /* ignored, read only */
294fc2ea 9660 register_name = "Config1";
9c2149c8 9661 break;
433efb4c 9662 case CP0_REG16__CONFIG2:
895c2d04 9663 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 9664 register_name = "Config2";
2423f660 9665 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9666 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9667 break;
433efb4c 9668 case CP0_REG16__CONFIG3:
90f12d73 9669 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 9670 register_name = "Config3";
90f12d73 9671 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9672 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9673 break;
433efb4c 9674 case CP0_REG16__CONFIG4:
faf1f68b 9675 /* currently ignored */
294fc2ea 9676 register_name = "Config4";
faf1f68b 9677 break;
433efb4c 9678 case CP0_REG16__CONFIG5:
faf1f68b 9679 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 9680 register_name = "Config5";
faf1f68b 9681 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9682 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9683 break;
9c2149c8
TS
9684 /* 6,7 are implementation dependent */
9685 default:
294fc2ea 9686 register_name = "Invalid config selector";
f31b035a 9687 goto cp0_unimplemented;
9c2149c8 9688 }
9c2149c8 9689 break;
04992c8c 9690 case CP0_REGISTER_17:
9c2149c8 9691 switch (sel) {
706ce142 9692 case CP0_REG17__LLADDR:
895c2d04 9693 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 9694 register_name = "LLAddr";
2423f660 9695 break;
706ce142 9696 case CP0_REG17__MAAR:
f6d4dd81
YK
9697 CP0_CHECK(ctx->mrp);
9698 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 9699 register_name = "MAAR";
f6d4dd81 9700 break;
706ce142 9701 case CP0_REG17__MAARI:
f6d4dd81
YK
9702 CP0_CHECK(ctx->mrp);
9703 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 9704 register_name = "MAARI";
f6d4dd81 9705 break;
9c2149c8 9706 default:
f31b035a 9707 goto cp0_unimplemented;
9c2149c8
TS
9708 }
9709 break;
04992c8c 9710 case CP0_REGISTER_18:
9c2149c8 9711 switch (sel) {
e8dcfe82
AM
9712 case CP0_REG18__WATCHLO0:
9713 case CP0_REG18__WATCHLO1:
9714 case CP0_REG18__WATCHLO2:
9715 case CP0_REG18__WATCHLO3:
9716 case CP0_REG18__WATCHLO4:
9717 case CP0_REG18__WATCHLO5:
9718 case CP0_REG18__WATCHLO6:
9719 case CP0_REG18__WATCHLO7:
fa192d49 9720 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9721 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 9722 register_name = "WatchLo";
2423f660 9723 break;
9c2149c8 9724 default:
f31b035a 9725 goto cp0_unimplemented;
9c2149c8
TS
9726 }
9727 break;
04992c8c 9728 case CP0_REGISTER_19:
9c2149c8 9729 switch (sel) {
be274dc1
AM
9730 case CP0_REG19__WATCHHI0:
9731 case CP0_REG19__WATCHHI1:
9732 case CP0_REG19__WATCHHI2:
9733 case CP0_REG19__WATCHHI3:
9734 case CP0_REG19__WATCHHI4:
9735 case CP0_REG19__WATCHHI5:
9736 case CP0_REG19__WATCHHI6:
9737 case CP0_REG19__WATCHHI7:
fa192d49 9738 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9739 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 9740 register_name = "WatchHi";
2423f660 9741 break;
9c2149c8 9742 default:
f31b035a 9743 goto cp0_unimplemented;
9c2149c8
TS
9744 }
9745 break;
04992c8c 9746 case CP0_REGISTER_20:
9c2149c8 9747 switch (sel) {
14f92b0b 9748 case CP0_REG20__XCONTEXT:
d75c135e 9749 check_insn(ctx, ISA_MIPS3);
895c2d04 9750 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 9751 register_name = "XContext";
2423f660 9752 break;
9c2149c8 9753 default:
f31b035a 9754 goto cp0_unimplemented;
9c2149c8
TS
9755 }
9756 break;
04992c8c 9757 case CP0_REGISTER_21:
9c2149c8 9758 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9759 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9760 switch (sel) {
9761 case 0:
895c2d04 9762 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 9763 register_name = "Framemask";
2423f660 9764 break;
9c2149c8 9765 default:
f31b035a 9766 goto cp0_unimplemented;
9c2149c8
TS
9767 }
9768 break;
04992c8c 9769 case CP0_REGISTER_22:
9c2149c8 9770 /* ignored */
294fc2ea 9771 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 9772 break;
04992c8c 9773 case CP0_REGISTER_23:
9c2149c8 9774 switch (sel) {
4cbf4b6d 9775 case CP0_REG23__DEBUG:
895c2d04 9776 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9777 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9778 gen_save_pc(ctx->base.pc_next + 4);
9779 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9780 register_name = "Debug";
2423f660 9781 break;
4cbf4b6d
AM
9782 case CP0_REG23__TRACECONTROL:
9783 /* PDtrace support */
9784 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 9785 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9786 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9787 register_name = "TraceControl";
3570d7f6 9788 goto cp0_unimplemented;
4cbf4b6d
AM
9789 case CP0_REG23__TRACECONTROL2:
9790 /* PDtrace support */
9791 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 9792 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9793 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9794 register_name = "TraceControl2";
3570d7f6 9795 goto cp0_unimplemented;
4cbf4b6d
AM
9796 case CP0_REG23__USERTRACEDATA1:
9797 /* PDtrace support */
9798 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 9799 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9800 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9801 register_name = "UserTraceData1";
3570d7f6 9802 goto cp0_unimplemented;
4cbf4b6d
AM
9803 case CP0_REG23__TRACEIBPC:
9804 /* PDtrace support */
9805 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9806 /* Stop translation as we may have switched the execution mode */
9807 ctx->base.is_jmp = DISAS_STOP;
9808 register_name = "TraceIBPC";
9809 goto cp0_unimplemented;
9810 case CP0_REG23__TRACEDBPC:
9811 /* PDtrace support */
9812 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 9813 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9814 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9815 register_name = "TraceDBPC";
3570d7f6 9816 goto cp0_unimplemented;
9c2149c8 9817 default:
f31b035a 9818 goto cp0_unimplemented;
9c2149c8 9819 }
9c2149c8 9820 break;
04992c8c 9821 case CP0_REGISTER_24:
9c2149c8 9822 switch (sel) {
8d7b4b6e 9823 case CP0_REG24__DEPC:
f1aa6320 9824 /* EJTAG support */
7db13fae 9825 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9826 register_name = "DEPC";
2423f660 9827 break;
9c2149c8 9828 default:
f31b035a 9829 goto cp0_unimplemented;
9c2149c8
TS
9830 }
9831 break;
04992c8c 9832 case CP0_REGISTER_25:
9c2149c8 9833 switch (sel) {
1176b328 9834 case CP0_REG25__PERFCTL0:
895c2d04 9835 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 9836 register_name = "Performance0";
2423f660 9837 break;
1176b328 9838 case CP0_REG25__PERFCNT0:
7480515f 9839 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 9840 register_name = "Performance1";
3570d7f6 9841 goto cp0_unimplemented;
1176b328 9842 case CP0_REG25__PERFCTL1:
7480515f 9843 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 9844 register_name = "Performance2";
3570d7f6 9845 goto cp0_unimplemented;
1176b328 9846 case CP0_REG25__PERFCNT1:
7480515f 9847 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 9848 register_name = "Performance3";
3570d7f6 9849 goto cp0_unimplemented;
1176b328 9850 case CP0_REG25__PERFCTL2:
7480515f 9851 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 9852 register_name = "Performance4";
3570d7f6 9853 goto cp0_unimplemented;
1176b328 9854 case CP0_REG25__PERFCNT2:
7480515f 9855 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 9856 register_name = "Performance5";
3570d7f6 9857 goto cp0_unimplemented;
1176b328 9858 case CP0_REG25__PERFCTL3:
7480515f 9859 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 9860 register_name = "Performance6";
3570d7f6 9861 goto cp0_unimplemented;
1176b328 9862 case CP0_REG25__PERFCNT3:
7480515f 9863 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 9864 register_name = "Performance7";
3570d7f6 9865 goto cp0_unimplemented;
9c2149c8 9866 default:
f31b035a 9867 goto cp0_unimplemented;
9c2149c8 9868 }
876d4b07 9869 break;
04992c8c 9870 case CP0_REGISTER_26:
0d74a222 9871 switch (sel) {
dbbf08b2 9872 case CP0_REG26__ERRCTL:
0d74a222 9873 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9874 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9875 register_name = "ErrCtl";
0d74a222
LA
9876 break;
9877 default:
9878 goto cp0_unimplemented;
9879 }
876d4b07 9880 break;
04992c8c 9881 case CP0_REGISTER_27:
9c2149c8 9882 switch (sel) {
5a10873d 9883 case CP0_REG27__CACHERR:
2423f660 9884 /* ignored */
294fc2ea 9885 register_name = "CacheErr";
2423f660 9886 break;
9c2149c8 9887 default:
f31b035a 9888 goto cp0_unimplemented;
9c2149c8 9889 }
876d4b07 9890 break;
04992c8c 9891 case CP0_REGISTER_28:
9c2149c8 9892 switch (sel) {
a30e2f21
AM
9893 case CP0_REG28__TAGLO:
9894 case CP0_REG28__TAGLO1:
9895 case CP0_REG28__TAGLO2:
9896 case CP0_REG28__TAGLO3:
895c2d04 9897 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 9898 register_name = "TagLo";
9c2149c8 9899 break;
a30e2f21
AM
9900 case CP0_REG28__DATALO:
9901 case CP0_REG28__DATALO1:
9902 case CP0_REG28__DATALO2:
9903 case CP0_REG28__DATALO3:
895c2d04 9904 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 9905 register_name = "DataLo";
9c2149c8
TS
9906 break;
9907 default:
f31b035a 9908 goto cp0_unimplemented;
9c2149c8
TS
9909 }
9910 break;
04992c8c 9911 case CP0_REGISTER_29:
9c2149c8 9912 switch (sel) {
af4bb6da
AM
9913 case CP0_REG29__TAGHI:
9914 case CP0_REG29__TAGHI1:
9915 case CP0_REG29__TAGHI2:
9916 case CP0_REG29__TAGHI3:
895c2d04 9917 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 9918 register_name = "TagHi";
9c2149c8 9919 break;
af4bb6da
AM
9920 case CP0_REG29__DATAHI:
9921 case CP0_REG29__DATAHI1:
9922 case CP0_REG29__DATAHI2:
9923 case CP0_REG29__DATAHI3:
895c2d04 9924 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 9925 register_name = "DataHi";
9c2149c8
TS
9926 break;
9927 default:
294fc2ea 9928 register_name = "invalid sel";
f31b035a 9929 goto cp0_unimplemented;
9c2149c8 9930 }
876d4b07 9931 break;
04992c8c 9932 case CP0_REGISTER_30:
9c2149c8 9933 switch (sel) {
4bcf121e 9934 case CP0_REG30__ERROREPC:
7db13fae 9935 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9936 register_name = "ErrorEPC";
2423f660 9937 break;
9c2149c8 9938 default:
f31b035a 9939 goto cp0_unimplemented;
9c2149c8
TS
9940 }
9941 break;
04992c8c 9942 case CP0_REGISTER_31:
9c2149c8 9943 switch (sel) {
14d92efd 9944 case CP0_REG31__DESAVE:
f1aa6320 9945 /* EJTAG support */
7db13fae 9946 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9947 register_name = "DESAVE";
2423f660 9948 break;
14d92efd
AM
9949 case CP0_REG31__KSCRATCH1:
9950 case CP0_REG31__KSCRATCH2:
9951 case CP0_REG31__KSCRATCH3:
9952 case CP0_REG31__KSCRATCH4:
9953 case CP0_REG31__KSCRATCH5:
9954 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9955 CP0_CHECK(ctx->kscrexist & (1 << sel));
9956 tcg_gen_st_tl(arg, cpu_env,
71375b59 9957 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9958 register_name = "KScratch";
e98c0d17 9959 break;
9c2149c8 9960 default:
f31b035a 9961 goto cp0_unimplemented;
9c2149c8 9962 }
9c2149c8
TS
9963 break;
9964 default:
f31b035a 9965 goto cp0_unimplemented;
9c2149c8 9966 }
294fc2ea 9967 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 9968
bf20dc07 9969 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9970 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
9971 /*
9972 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9973 * translated code to check for pending interrupts.
9974 */
eeb3bba8
EC
9975 gen_save_pc(ctx->base.pc_next + 4);
9976 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9977 }
9c2149c8
TS
9978 return;
9979
f31b035a 9980cp0_unimplemented:
294fc2ea
AM
9981 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9982 register_name, reg, sel);
9c2149c8 9983}
d26bc211 9984#endif /* TARGET_MIPS64 */
9c2149c8 9985
7db13fae 9986static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9987 int u, int sel, int h)
9988{
9989 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9990 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9991
9992 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9993 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9994 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 9995 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
9996 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9997 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 9998 tcg_gen_movi_tl(t0, -1);
1f8929d2 9999 } else if (u == 0) {
ead9360e 10000 switch (rt) {
5a25ce94
EI
10001 case 1:
10002 switch (sel) {
10003 case 1:
895c2d04 10004 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
10005 break;
10006 case 2:
895c2d04 10007 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
10008 break;
10009 default:
10010 goto die;
10011 break;
10012 }
10013 break;
ead9360e
TS
10014 case 2:
10015 switch (sel) {
10016 case 1:
895c2d04 10017 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
10018 break;
10019 case 2:
895c2d04 10020 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
10021 break;
10022 case 3:
895c2d04 10023 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
10024 break;
10025 case 4:
895c2d04 10026 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
10027 break;
10028 case 5:
895c2d04 10029 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
10030 break;
10031 case 6:
895c2d04 10032 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
10033 break;
10034 case 7:
895c2d04 10035 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
10036 break;
10037 default:
d75c135e 10038 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10039 break;
10040 }
10041 break;
10042 case 10:
10043 switch (sel) {
10044 case 0:
895c2d04 10045 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
10046 break;
10047 default:
d75c135e 10048 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10049 break;
10050 }
f1fadbb2 10051 break;
ead9360e
TS
10052 case 12:
10053 switch (sel) {
10054 case 0:
895c2d04 10055 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
10056 break;
10057 default:
d75c135e 10058 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10059 break;
10060 }
f1fadbb2 10061 break;
5a25ce94
EI
10062 case 13:
10063 switch (sel) {
10064 case 0:
895c2d04 10065 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
10066 break;
10067 default:
10068 goto die;
10069 break;
10070 }
10071 break;
10072 case 14:
10073 switch (sel) {
10074 case 0:
895c2d04 10075 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
10076 break;
10077 default:
10078 goto die;
10079 break;
10080 }
10081 break;
10082 case 15:
10083 switch (sel) {
10084 case 1:
895c2d04 10085 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
10086 break;
10087 default:
10088 goto die;
10089 break;
10090 }
10091 break;
10092 case 16:
10093 switch (sel) {
c2e19f3c
AM
10094 case 0:
10095 case 1:
10096 case 2:
10097 case 3:
10098 case 4:
10099 case 5:
10100 case 6:
10101 case 7:
895c2d04 10102 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
10103 break;
10104 default:
10105 goto die;
10106 break;
10107 }
10108 break;
ead9360e
TS
10109 case 23:
10110 switch (sel) {
10111 case 0:
895c2d04 10112 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
10113 break;
10114 default:
d75c135e 10115 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10116 break;
10117 }
10118 break;
10119 default:
d75c135e 10120 gen_mfc0(ctx, t0, rt, sel);
ead9360e 10121 }
71375b59
AM
10122 } else {
10123 switch (sel) {
10124 /* GPR registers. */
ead9360e 10125 case 0:
71375b59 10126 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 10127 break;
71375b59 10128 /* Auxiliary CPU registers */
ead9360e 10129 case 1:
71375b59
AM
10130 switch (rt) {
10131 case 0:
10132 gen_helper_1e0i(mftlo, t0, 0);
10133 break;
10134 case 1:
10135 gen_helper_1e0i(mfthi, t0, 0);
10136 break;
10137 case 2:
10138 gen_helper_1e0i(mftacx, t0, 0);
10139 break;
10140 case 4:
10141 gen_helper_1e0i(mftlo, t0, 1);
10142 break;
10143 case 5:
10144 gen_helper_1e0i(mfthi, t0, 1);
10145 break;
10146 case 6:
10147 gen_helper_1e0i(mftacx, t0, 1);
10148 break;
10149 case 8:
10150 gen_helper_1e0i(mftlo, t0, 2);
10151 break;
10152 case 9:
10153 gen_helper_1e0i(mfthi, t0, 2);
10154 break;
10155 case 10:
10156 gen_helper_1e0i(mftacx, t0, 2);
10157 break;
10158 case 12:
10159 gen_helper_1e0i(mftlo, t0, 3);
10160 break;
10161 case 13:
10162 gen_helper_1e0i(mfthi, t0, 3);
10163 break;
10164 case 14:
10165 gen_helper_1e0i(mftacx, t0, 3);
10166 break;
10167 case 16:
10168 gen_helper_mftdsp(t0, cpu_env);
10169 break;
10170 default:
10171 goto die;
10172 }
ead9360e 10173 break;
71375b59 10174 /* Floating point (COP1). */
ead9360e 10175 case 2:
71375b59
AM
10176 /* XXX: For now we support only a single FPU context. */
10177 if (h == 0) {
10178 TCGv_i32 fp0 = tcg_temp_new_i32();
10179
10180 gen_load_fpr32(ctx, fp0, rt);
10181 tcg_gen_ext_i32_tl(t0, fp0);
10182 tcg_temp_free_i32(fp0);
10183 } else {
10184 TCGv_i32 fp0 = tcg_temp_new_i32();
10185
10186 gen_load_fpr32h(ctx, fp0, rt);
10187 tcg_gen_ext_i32_tl(t0, fp0);
10188 tcg_temp_free_i32(fp0);
10189 }
ead9360e 10190 break;
71375b59
AM
10191 case 3:
10192 /* XXX: For now we support only a single FPU context. */
10193 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 10194 break;
71375b59
AM
10195 /* COP2: Not implemented. */
10196 case 4:
ead9360e 10197 case 5:
71375b59 10198 /* fall through */
ead9360e
TS
10199 default:
10200 goto die;
10201 }
ead9360e 10202 }
b44a7fb1 10203 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
10204 gen_store_gpr(t0, rd);
10205 tcg_temp_free(t0);
ead9360e
TS
10206 return;
10207
10208die:
1a3fd9c3 10209 tcg_temp_free(t0);
d12d51d5 10210 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 10211 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10212}
10213
7db13fae 10214static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
10215 int u, int sel, int h)
10216{
10217 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10218 TCGv t0 = tcg_temp_local_new();
ead9360e 10219
1a3fd9c3 10220 gen_load_gpr(t0, rt);
ead9360e 10221 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10222 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10223 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
10224 /* NOP */
10225 ;
1f8929d2
AM
10226 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10227 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
10228 /* NOP */
10229 ;
1f8929d2 10230 } else if (u == 0) {
ead9360e 10231 switch (rd) {
5a25ce94
EI
10232 case 1:
10233 switch (sel) {
10234 case 1:
895c2d04 10235 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
10236 break;
10237 case 2:
895c2d04 10238 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
10239 break;
10240 default:
10241 goto die;
10242 break;
10243 }
10244 break;
ead9360e
TS
10245 case 2:
10246 switch (sel) {
10247 case 1:
895c2d04 10248 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
10249 break;
10250 case 2:
895c2d04 10251 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
10252 break;
10253 case 3:
895c2d04 10254 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
10255 break;
10256 case 4:
895c2d04 10257 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
10258 break;
10259 case 5:
895c2d04 10260 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
10261 break;
10262 case 6:
895c2d04 10263 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
10264 break;
10265 case 7:
895c2d04 10266 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
10267 break;
10268 default:
d75c135e 10269 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10270 break;
10271 }
10272 break;
10273 case 10:
10274 switch (sel) {
10275 case 0:
895c2d04 10276 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
10277 break;
10278 default:
d75c135e 10279 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10280 break;
10281 }
0d0304f2 10282 break;
ead9360e
TS
10283 case 12:
10284 switch (sel) {
10285 case 0:
895c2d04 10286 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
10287 break;
10288 default:
d75c135e 10289 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10290 break;
10291 }
0d0304f2 10292 break;
5a25ce94
EI
10293 case 13:
10294 switch (sel) {
10295 case 0:
895c2d04 10296 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
10297 break;
10298 default:
10299 goto die;
10300 break;
10301 }
10302 break;
10303 case 15:
10304 switch (sel) {
10305 case 1:
895c2d04 10306 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10307 break;
10308 default:
10309 goto die;
10310 break;
10311 }
10312 break;
ead9360e
TS
10313 case 23:
10314 switch (sel) {
10315 case 0:
895c2d04 10316 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10317 break;
10318 default:
d75c135e 10319 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10320 break;
10321 }
10322 break;
10323 default:
d75c135e 10324 gen_mtc0(ctx, t0, rd, sel);
ead9360e 10325 }
71375b59
AM
10326 } else {
10327 switch (sel) {
10328 /* GPR registers. */
ead9360e 10329 case 0:
71375b59 10330 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 10331 break;
71375b59 10332 /* Auxiliary CPU registers */
ead9360e 10333 case 1:
71375b59
AM
10334 switch (rd) {
10335 case 0:
10336 gen_helper_0e1i(mttlo, t0, 0);
10337 break;
10338 case 1:
10339 gen_helper_0e1i(mtthi, t0, 0);
10340 break;
10341 case 2:
10342 gen_helper_0e1i(mttacx, t0, 0);
10343 break;
10344 case 4:
10345 gen_helper_0e1i(mttlo, t0, 1);
10346 break;
10347 case 5:
10348 gen_helper_0e1i(mtthi, t0, 1);
10349 break;
10350 case 6:
10351 gen_helper_0e1i(mttacx, t0, 1);
10352 break;
10353 case 8:
10354 gen_helper_0e1i(mttlo, t0, 2);
10355 break;
10356 case 9:
10357 gen_helper_0e1i(mtthi, t0, 2);
10358 break;
10359 case 10:
10360 gen_helper_0e1i(mttacx, t0, 2);
10361 break;
10362 case 12:
10363 gen_helper_0e1i(mttlo, t0, 3);
10364 break;
10365 case 13:
10366 gen_helper_0e1i(mtthi, t0, 3);
10367 break;
10368 case 14:
10369 gen_helper_0e1i(mttacx, t0, 3);
10370 break;
10371 case 16:
10372 gen_helper_mttdsp(cpu_env, t0);
10373 break;
10374 default:
10375 goto die;
10376 }
ead9360e 10377 break;
71375b59 10378 /* Floating point (COP1). */
ead9360e 10379 case 2:
71375b59
AM
10380 /* XXX: For now we support only a single FPU context. */
10381 if (h == 0) {
10382 TCGv_i32 fp0 = tcg_temp_new_i32();
10383
10384 tcg_gen_trunc_tl_i32(fp0, t0);
10385 gen_store_fpr32(ctx, fp0, rd);
10386 tcg_temp_free_i32(fp0);
10387 } else {
10388 TCGv_i32 fp0 = tcg_temp_new_i32();
10389
10390 tcg_gen_trunc_tl_i32(fp0, t0);
10391 gen_store_fpr32h(ctx, fp0, rd);
10392 tcg_temp_free_i32(fp0);
10393 }
ead9360e 10394 break;
71375b59
AM
10395 case 3:
10396 /* XXX: For now we support only a single FPU context. */
10397 {
10398 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10399
10400 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10401 tcg_temp_free_i32(fs_tmp);
10402 }
10403 /* Stop translation as we may have changed hflags */
10404 ctx->base.is_jmp = DISAS_STOP;
ead9360e 10405 break;
71375b59
AM
10406 /* COP2: Not implemented. */
10407 case 4:
ead9360e 10408 case 5:
71375b59 10409 /* fall through */
ead9360e
TS
10410 default:
10411 goto die;
10412 }
ead9360e 10413 }
b44a7fb1 10414 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10415 tcg_temp_free(t0);
ead9360e
TS
10416 return;
10417
10418die:
1a3fd9c3 10419 tcg_temp_free(t0);
d12d51d5 10420 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10421 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10422}
10423
235785e8
AM
10424static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10425 int rt, int rd)
6af0bf9c 10426{
287c4b84 10427 const char *opn = "ldst";
6af0bf9c 10428
2e15497c 10429 check_cp0_enabled(ctx);
6af0bf9c
FB
10430 switch (opc) {
10431 case OPC_MFC0:
10432 if (rt == 0) {
ead9360e 10433 /* Treat as NOP. */
6af0bf9c
FB
10434 return;
10435 }
d75c135e 10436 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10437 opn = "mfc0";
10438 break;
10439 case OPC_MTC0:
1a3fd9c3 10440 {
1fc7bf6e 10441 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10442
10443 gen_load_gpr(t0, rt);
d75c135e 10444 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10445 tcg_temp_free(t0);
10446 }
6af0bf9c
FB
10447 opn = "mtc0";
10448 break;
d26bc211 10449#if defined(TARGET_MIPS64)
9c2149c8 10450 case OPC_DMFC0:
d75c135e 10451 check_insn(ctx, ISA_MIPS3);
9c2149c8 10452 if (rt == 0) {
ead9360e 10453 /* Treat as NOP. */
9c2149c8
TS
10454 return;
10455 }
d75c135e 10456 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10457 opn = "dmfc0";
10458 break;
10459 case OPC_DMTC0:
d75c135e 10460 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10461 {
1fc7bf6e 10462 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10463
10464 gen_load_gpr(t0, rt);
d75c135e 10465 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10466 tcg_temp_free(t0);
10467 }
9c2149c8
TS
10468 opn = "dmtc0";
10469 break;
534ce69f 10470#endif
5204ea79
LA
10471 case OPC_MFHC0:
10472 check_mvh(ctx);
10473 if (rt == 0) {
10474 /* Treat as NOP. */
10475 return;
10476 }
10477 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10478 opn = "mfhc0";
10479 break;
10480 case OPC_MTHC0:
10481 check_mvh(ctx);
10482 {
10483 TCGv t0 = tcg_temp_new();
10484 gen_load_gpr(t0, rt);
10485 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10486 tcg_temp_free(t0);
10487 }
10488 opn = "mthc0";
10489 break;
ead9360e 10490 case OPC_MFTR:
9affc1c5 10491 check_cp0_enabled(ctx);
ead9360e
TS
10492 if (rd == 0) {
10493 /* Treat as NOP. */
10494 return;
10495 }
6c5c1e20 10496 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10497 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10498 opn = "mftr";
10499 break;
10500 case OPC_MTTR:
9affc1c5 10501 check_cp0_enabled(ctx);
6c5c1e20 10502 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10503 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10504 opn = "mttr";
10505 break;
6af0bf9c 10506 case OPC_TLBWI:
6af0bf9c 10507 opn = "tlbwi";
1f8929d2 10508 if (!env->tlb->helper_tlbwi) {
29929e34 10509 goto die;
1f8929d2 10510 }
895c2d04 10511 gen_helper_tlbwi(cpu_env);
6af0bf9c 10512 break;
9456c2fb
LA
10513 case OPC_TLBINV:
10514 opn = "tlbinv";
10515 if (ctx->ie >= 2) {
10516 if (!env->tlb->helper_tlbinv) {
10517 goto die;
10518 }
10519 gen_helper_tlbinv(cpu_env);
10520 } /* treat as nop if TLBINV not supported */
10521 break;
10522 case OPC_TLBINVF:
10523 opn = "tlbinvf";
10524 if (ctx->ie >= 2) {
10525 if (!env->tlb->helper_tlbinvf) {
10526 goto die;
10527 }
10528 gen_helper_tlbinvf(cpu_env);
10529 } /* treat as nop if TLBINV not supported */
10530 break;
6af0bf9c 10531 case OPC_TLBWR:
6af0bf9c 10532 opn = "tlbwr";
1f8929d2 10533 if (!env->tlb->helper_tlbwr) {
29929e34 10534 goto die;
1f8929d2 10535 }
895c2d04 10536 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10537 break;
10538 case OPC_TLBP:
6af0bf9c 10539 opn = "tlbp";
1f8929d2 10540 if (!env->tlb->helper_tlbp) {
29929e34 10541 goto die;
1f8929d2 10542 }
895c2d04 10543 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10544 break;
10545 case OPC_TLBR:
6af0bf9c 10546 opn = "tlbr";
1f8929d2 10547 if (!env->tlb->helper_tlbr) {
29929e34 10548 goto die;
1f8929d2 10549 }
895c2d04 10550 gen_helper_tlbr(cpu_env);
6af0bf9c 10551 break;
ce9782f4 10552 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
10553 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10554 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10555 goto die;
ce9782f4
LA
10556 } else {
10557 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10558 if (ctx->opcode & (1 << bit_shift)) {
10559 /* OPC_ERETNC */
10560 opn = "eretnc";
10561 check_insn(ctx, ISA_MIPS32R5);
10562 gen_helper_eretnc(cpu_env);
10563 } else {
10564 /* OPC_ERET */
10565 opn = "eret";
10566 check_insn(ctx, ISA_MIPS2);
10567 gen_helper_eret(cpu_env);
10568 }
eeb3bba8 10569 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 10570 }
6af0bf9c
FB
10571 break;
10572 case OPC_DERET:
10573 opn = "deret";
d75c135e 10574 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
10575 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10576 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10577 goto die;
10578 }
6af0bf9c 10579 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 10580 MIPS_INVAL(opn);
9c708c7f 10581 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 10582 } else {
895c2d04 10583 gen_helper_deret(cpu_env);
eeb3bba8 10584 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
10585 }
10586 break;
4ad40f36
FB
10587 case OPC_WAIT:
10588 opn = "wait";
d75c135e 10589 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
10590 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10591 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10592 goto die;
10593 }
4ad40f36 10594 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 10595 ctx->base.pc_next += 4;
4ad40f36 10596 save_cpu_state(ctx, 1);
eeb3bba8 10597 ctx->base.pc_next -= 4;
895c2d04 10598 gen_helper_wait(cpu_env);
eeb3bba8 10599 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 10600 break;
6af0bf9c 10601 default:
29929e34 10602 die:
923617a3 10603 MIPS_INVAL(opn);
9c708c7f 10604 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
10605 return;
10606 }
2abf314d 10607 (void)opn; /* avoid a compiler warning */
6af0bf9c 10608}
f1aa6320 10609#endif /* !CONFIG_USER_ONLY */
6af0bf9c 10610
6ea83fed 10611/* CP1 Branches (before delay slot) */
d75c135e
AJ
10612static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10613 int32_t cc, int32_t offset)
6ea83fed
FB
10614{
10615 target_ulong btarget;
a7812ae4 10616 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 10617
339cd2a8 10618 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 10619 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
10620 goto out;
10621 }
10622
1f8929d2 10623 if (cc != 0) {
d75c135e 10624 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
1f8929d2 10625 }
e189e748 10626
eeb3bba8 10627 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 10628
7a387fff
TS
10629 switch (op) {
10630 case OPC_BC1F:
d94536f4
AJ
10631 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10632 tcg_gen_not_i32(t0, t0);
10633 tcg_gen_andi_i32(t0, t0, 1);
10634 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10635 goto not_likely;
7a387fff 10636 case OPC_BC1FL:
d94536f4
AJ
10637 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10638 tcg_gen_not_i32(t0, t0);
10639 tcg_gen_andi_i32(t0, t0, 1);
10640 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10641 goto likely;
7a387fff 10642 case OPC_BC1T:
d94536f4
AJ
10643 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10644 tcg_gen_andi_i32(t0, t0, 1);
10645 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10646 goto not_likely;
7a387fff 10647 case OPC_BC1TL:
d94536f4
AJ
10648 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10649 tcg_gen_andi_i32(t0, t0, 1);
10650 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10651 likely:
10652 ctx->hflags |= MIPS_HFLAG_BL;
10653 break;
5a5012ec 10654 case OPC_BC1FANY2:
a16336e4 10655 {
d94536f4
AJ
10656 TCGv_i32 t1 = tcg_temp_new_i32();
10657 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10658 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10659 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10660 tcg_temp_free_i32(t1);
d94536f4
AJ
10661 tcg_gen_andi_i32(t0, t0, 1);
10662 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10663 }
5a5012ec
TS
10664 goto not_likely;
10665 case OPC_BC1TANY2:
a16336e4 10666 {
d94536f4
AJ
10667 TCGv_i32 t1 = tcg_temp_new_i32();
10668 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10669 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
10670 tcg_gen_or_i32(t0, t0, t1);
10671 tcg_temp_free_i32(t1);
10672 tcg_gen_andi_i32(t0, t0, 1);
10673 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10674 }
5a5012ec
TS
10675 goto not_likely;
10676 case OPC_BC1FANY4:
a16336e4 10677 {
d94536f4
AJ
10678 TCGv_i32 t1 = tcg_temp_new_i32();
10679 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10680 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10681 tcg_gen_and_i32(t0, t0, t1);
71375b59 10682 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 10683 tcg_gen_and_i32(t0, t0, t1);
71375b59 10684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 10685 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10686 tcg_temp_free_i32(t1);
d94536f4
AJ
10687 tcg_gen_andi_i32(t0, t0, 1);
10688 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10689 }
5a5012ec
TS
10690 goto not_likely;
10691 case OPC_BC1TANY4:
a16336e4 10692 {
d94536f4
AJ
10693 TCGv_i32 t1 = tcg_temp_new_i32();
10694 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10695 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 10696 tcg_gen_or_i32(t0, t0, t1);
71375b59 10697 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 10698 tcg_gen_or_i32(t0, t0, t1);
71375b59 10699 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
10700 tcg_gen_or_i32(t0, t0, t1);
10701 tcg_temp_free_i32(t1);
10702 tcg_gen_andi_i32(t0, t0, 1);
10703 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10704 }
5a5012ec
TS
10705 not_likely:
10706 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10707 break;
10708 default:
9d68ac14 10709 MIPS_INVAL("cp1 cond branch");
9c708c7f 10710 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10711 goto out;
6ea83fed 10712 }
6ea83fed 10713 ctx->btarget = btarget;
b231c103 10714 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10715 out:
a7812ae4 10716 tcg_temp_free_i32(t0);
6ea83fed
FB
10717}
10718
31837be3
YK
10719/* R6 CP1 Branches */
10720static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10721 int32_t ft, int32_t offset,
10722 int delayslot_size)
31837be3
YK
10723{
10724 target_ulong btarget;
31837be3
YK
10725 TCGv_i64 t0 = tcg_temp_new_i64();
10726
10727 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10728#ifdef MIPS_DEBUG_DISAS
339cd2a8 10729 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10730 "\n", ctx->base.pc_next);
31837be3 10731#endif
9c708c7f 10732 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10733 goto out;
10734 }
10735
10736 gen_load_fpr64(ctx, t0, ft);
10737 tcg_gen_andi_i64(t0, t0, 1);
10738
eeb3bba8 10739 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10740
10741 switch (op) {
10742 case OPC_BC1EQZ:
10743 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10744 ctx->hflags |= MIPS_HFLAG_BC;
10745 break;
10746 case OPC_BC1NEZ:
10747 /* t0 already set */
31837be3
YK
10748 ctx->hflags |= MIPS_HFLAG_BC;
10749 break;
10750 default:
9d68ac14 10751 MIPS_INVAL("cp1 cond branch");
9c708c7f 10752 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10753 goto out;
10754 }
10755
10756 tcg_gen_trunc_i64_tl(bcond, t0);
10757
31837be3 10758 ctx->btarget = btarget;
65935f07
YK
10759
10760 switch (delayslot_size) {
10761 case 2:
10762 ctx->hflags |= MIPS_HFLAG_BDS16;
10763 break;
10764 case 4:
10765 ctx->hflags |= MIPS_HFLAG_BDS32;
10766 break;
10767 }
31837be3
YK
10768
10769out:
10770 tcg_temp_free_i64(t0);
10771}
10772
6af0bf9c 10773/* Coprocessor 1 (FPU) */
5a5012ec 10774
5a5012ec
TS
10775#define FOP(func, fmt) (((fmt) << 21) | (func))
10776
bf4120ad
NF
10777enum fopcode {
10778 OPC_ADD_S = FOP(0, FMT_S),
10779 OPC_SUB_S = FOP(1, FMT_S),
10780 OPC_MUL_S = FOP(2, FMT_S),
10781 OPC_DIV_S = FOP(3, FMT_S),
10782 OPC_SQRT_S = FOP(4, FMT_S),
10783 OPC_ABS_S = FOP(5, FMT_S),
10784 OPC_MOV_S = FOP(6, FMT_S),
10785 OPC_NEG_S = FOP(7, FMT_S),
10786 OPC_ROUND_L_S = FOP(8, FMT_S),
10787 OPC_TRUNC_L_S = FOP(9, FMT_S),
10788 OPC_CEIL_L_S = FOP(10, FMT_S),
10789 OPC_FLOOR_L_S = FOP(11, FMT_S),
10790 OPC_ROUND_W_S = FOP(12, FMT_S),
10791 OPC_TRUNC_W_S = FOP(13, FMT_S),
10792 OPC_CEIL_W_S = FOP(14, FMT_S),
10793 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10794 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10795 OPC_MOVCF_S = FOP(17, FMT_S),
10796 OPC_MOVZ_S = FOP(18, FMT_S),
10797 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10798 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10799 OPC_RECIP_S = FOP(21, FMT_S),
10800 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10801 OPC_SELNEZ_S = FOP(23, FMT_S),
10802 OPC_MADDF_S = FOP(24, FMT_S),
10803 OPC_MSUBF_S = FOP(25, FMT_S),
10804 OPC_RINT_S = FOP(26, FMT_S),
10805 OPC_CLASS_S = FOP(27, FMT_S),
10806 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10807 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10808 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10809 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10810 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10811 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10812 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10813 OPC_RSQRT2_S = FOP(31, FMT_S),
10814 OPC_CVT_D_S = FOP(33, FMT_S),
10815 OPC_CVT_W_S = FOP(36, FMT_S),
10816 OPC_CVT_L_S = FOP(37, FMT_S),
10817 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
10818 OPC_CMP_F_S = FOP(48, FMT_S),
10819 OPC_CMP_UN_S = FOP(49, FMT_S),
10820 OPC_CMP_EQ_S = FOP(50, FMT_S),
10821 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10822 OPC_CMP_OLT_S = FOP(52, FMT_S),
10823 OPC_CMP_ULT_S = FOP(53, FMT_S),
10824 OPC_CMP_OLE_S = FOP(54, FMT_S),
10825 OPC_CMP_ULE_S = FOP(55, FMT_S),
10826 OPC_CMP_SF_S = FOP(56, FMT_S),
10827 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10828 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10829 OPC_CMP_NGL_S = FOP(59, FMT_S),
10830 OPC_CMP_LT_S = FOP(60, FMT_S),
10831 OPC_CMP_NGE_S = FOP(61, FMT_S),
10832 OPC_CMP_LE_S = FOP(62, FMT_S),
10833 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
10834
10835 OPC_ADD_D = FOP(0, FMT_D),
10836 OPC_SUB_D = FOP(1, FMT_D),
10837 OPC_MUL_D = FOP(2, FMT_D),
10838 OPC_DIV_D = FOP(3, FMT_D),
10839 OPC_SQRT_D = FOP(4, FMT_D),
10840 OPC_ABS_D = FOP(5, FMT_D),
10841 OPC_MOV_D = FOP(6, FMT_D),
10842 OPC_NEG_D = FOP(7, FMT_D),
10843 OPC_ROUND_L_D = FOP(8, FMT_D),
10844 OPC_TRUNC_L_D = FOP(9, FMT_D),
10845 OPC_CEIL_L_D = FOP(10, FMT_D),
10846 OPC_FLOOR_L_D = FOP(11, FMT_D),
10847 OPC_ROUND_W_D = FOP(12, FMT_D),
10848 OPC_TRUNC_W_D = FOP(13, FMT_D),
10849 OPC_CEIL_W_D = FOP(14, FMT_D),
10850 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10851 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10852 OPC_MOVCF_D = FOP(17, FMT_D),
10853 OPC_MOVZ_D = FOP(18, FMT_D),
10854 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10855 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10856 OPC_RECIP_D = FOP(21, FMT_D),
10857 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10858 OPC_SELNEZ_D = FOP(23, FMT_D),
10859 OPC_MADDF_D = FOP(24, FMT_D),
10860 OPC_MSUBF_D = FOP(25, FMT_D),
10861 OPC_RINT_D = FOP(26, FMT_D),
10862 OPC_CLASS_D = FOP(27, FMT_D),
10863 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10864 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10865 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10866 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10867 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10868 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10869 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10870 OPC_RSQRT2_D = FOP(31, FMT_D),
10871 OPC_CVT_S_D = FOP(32, FMT_D),
10872 OPC_CVT_W_D = FOP(36, FMT_D),
10873 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
10874 OPC_CMP_F_D = FOP(48, FMT_D),
10875 OPC_CMP_UN_D = FOP(49, FMT_D),
10876 OPC_CMP_EQ_D = FOP(50, FMT_D),
10877 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10878 OPC_CMP_OLT_D = FOP(52, FMT_D),
10879 OPC_CMP_ULT_D = FOP(53, FMT_D),
10880 OPC_CMP_OLE_D = FOP(54, FMT_D),
10881 OPC_CMP_ULE_D = FOP(55, FMT_D),
10882 OPC_CMP_SF_D = FOP(56, FMT_D),
10883 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10884 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10885 OPC_CMP_NGL_D = FOP(59, FMT_D),
10886 OPC_CMP_LT_D = FOP(60, FMT_D),
10887 OPC_CMP_NGE_D = FOP(61, FMT_D),
10888 OPC_CMP_LE_D = FOP(62, FMT_D),
10889 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
10890
10891 OPC_CVT_S_W = FOP(32, FMT_W),
10892 OPC_CVT_D_W = FOP(33, FMT_W),
10893 OPC_CVT_S_L = FOP(32, FMT_L),
10894 OPC_CVT_D_L = FOP(33, FMT_L),
10895 OPC_CVT_PS_PW = FOP(38, FMT_W),
10896
10897 OPC_ADD_PS = FOP(0, FMT_PS),
10898 OPC_SUB_PS = FOP(1, FMT_PS),
10899 OPC_MUL_PS = FOP(2, FMT_PS),
10900 OPC_DIV_PS = FOP(3, FMT_PS),
10901 OPC_ABS_PS = FOP(5, FMT_PS),
10902 OPC_MOV_PS = FOP(6, FMT_PS),
10903 OPC_NEG_PS = FOP(7, FMT_PS),
10904 OPC_MOVCF_PS = FOP(17, FMT_PS),
10905 OPC_MOVZ_PS = FOP(18, FMT_PS),
10906 OPC_MOVN_PS = FOP(19, FMT_PS),
10907 OPC_ADDR_PS = FOP(24, FMT_PS),
10908 OPC_MULR_PS = FOP(26, FMT_PS),
10909 OPC_RECIP2_PS = FOP(28, FMT_PS),
10910 OPC_RECIP1_PS = FOP(29, FMT_PS),
10911 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10912 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10913
10914 OPC_CVT_S_PU = FOP(32, FMT_PS),
10915 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10916 OPC_CVT_S_PL = FOP(40, FMT_PS),
10917 OPC_PLL_PS = FOP(44, FMT_PS),
10918 OPC_PLU_PS = FOP(45, FMT_PS),
10919 OPC_PUL_PS = FOP(46, FMT_PS),
10920 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
10921 OPC_CMP_F_PS = FOP(48, FMT_PS),
10922 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10923 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10924 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10925 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10926 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10927 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10928 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10929 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10930 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10931 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10932 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10933 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10934 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10935 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10936 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
10937};
10938
3f493883
YK
10939enum r6_f_cmp_op {
10940 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10941 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10942 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10943 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10944 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10945 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10946 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10947 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10948 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10949 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10950 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10951 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10952 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10953 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10954 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10955 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10956 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10957 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10958 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10959 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10960 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10961 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10962
10963 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10964 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10965 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10966 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10967 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10968 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10969 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10970 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10971 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10972 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10973 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10974 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10975 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10976 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10977 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10978 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10979 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10980 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10981 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10982 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10983 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10984 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10985};
235785e8
AM
10986
10987static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10988{
72c3a3ee 10989 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10990
10991 switch (opc) {
10992 case OPC_MFC1:
b6d96bed 10993 {
a7812ae4 10994 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10995
7c979afd 10996 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10997 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10998 tcg_temp_free_i32(fp0);
6958549d 10999 }
6c5c1e20 11000 gen_store_gpr(t0, rt);
6ea83fed
FB
11001 break;
11002 case OPC_MTC1:
6c5c1e20 11003 gen_load_gpr(t0, rt);
b6d96bed 11004 {
a7812ae4 11005 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
11006
11007 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 11008 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 11009 tcg_temp_free_i32(fp0);
6958549d 11010 }
6ea83fed
FB
11011 break;
11012 case OPC_CFC1:
895c2d04 11013 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 11014 gen_store_gpr(t0, rt);
6ea83fed
FB
11015 break;
11016 case OPC_CTC1:
6c5c1e20 11017 gen_load_gpr(t0, rt);
9c708c7f 11018 save_cpu_state(ctx, 0);
736d120a
PJ
11019 {
11020 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11021
11022 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11023 tcg_temp_free_i32(fs_tmp);
11024 }
4cf8a45f 11025 /* Stop translation as we may have changed hflags */
eeb3bba8 11026 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 11027 break;
72c3a3ee 11028#if defined(TARGET_MIPS64)
9c2149c8 11029 case OPC_DMFC1:
72c3a3ee 11030 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 11031 gen_store_gpr(t0, rt);
5a5012ec 11032 break;
9c2149c8 11033 case OPC_DMTC1:
6c5c1e20 11034 gen_load_gpr(t0, rt);
72c3a3ee 11035 gen_store_fpr64(ctx, t0, fs);
5a5012ec 11036 break;
72c3a3ee 11037#endif
5a5012ec 11038 case OPC_MFHC1:
b6d96bed 11039 {
a7812ae4 11040 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11041
7f6613ce 11042 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 11043 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 11044 tcg_temp_free_i32(fp0);
6958549d 11045 }
6c5c1e20 11046 gen_store_gpr(t0, rt);
5a5012ec
TS
11047 break;
11048 case OPC_MTHC1:
6c5c1e20 11049 gen_load_gpr(t0, rt);
b6d96bed 11050 {
a7812ae4 11051 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
11052
11053 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 11054 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 11055 tcg_temp_free_i32(fp0);
6958549d 11056 }
5a5012ec 11057 break;
6ea83fed 11058 default:
9d68ac14 11059 MIPS_INVAL("cp1 move");
9c708c7f 11060 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 11061 goto out;
6ea83fed 11062 }
6c5c1e20
TS
11063
11064 out:
11065 tcg_temp_free(t0);
6ea83fed
FB
11066}
11067
235785e8 11068static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 11069{
42a268c2 11070 TCGLabel *l1;
e214b9bb 11071 TCGCond cond;
af58f9ca
AJ
11072 TCGv_i32 t0;
11073
11074 if (rd == 0) {
11075 /* Treat as NOP. */
11076 return;
11077 }
6ea83fed 11078
1f8929d2 11079 if (tf) {
e214b9bb 11080 cond = TCG_COND_EQ;
1f8929d2 11081 } else {
27848470 11082 cond = TCG_COND_NE;
1f8929d2 11083 }
27848470 11084
af58f9ca
AJ
11085 l1 = gen_new_label();
11086 t0 = tcg_temp_new_i32();
fa31af0e 11087 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 11088 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11089 tcg_temp_free_i32(t0);
af58f9ca
AJ
11090 if (rs == 0) {
11091 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11092 } else {
11093 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11094 }
e214b9bb 11095 gen_set_label(l1);
5a5012ec
TS
11096}
11097
7c979afd
LA
11098static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11099 int tf)
a16336e4 11100{
a16336e4 11101 int cond;
cbc37b28 11102 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 11103 TCGLabel *l1 = gen_new_label();
a16336e4 11104
1f8929d2 11105 if (tf) {
a16336e4 11106 cond = TCG_COND_EQ;
1f8929d2 11107 } else {
a16336e4 11108 cond = TCG_COND_NE;
1f8929d2 11109 }
a16336e4 11110
fa31af0e 11111 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11112 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11113 gen_load_fpr32(ctx, t0, fs);
11114 gen_store_fpr32(ctx, t0, fd);
a16336e4 11115 gen_set_label(l1);
cbc37b28 11116 tcg_temp_free_i32(t0);
5a5012ec 11117}
a16336e4 11118
235785e8
AM
11119static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11120 int tf)
a16336e4 11121{
a16336e4 11122 int cond;
cbc37b28
AJ
11123 TCGv_i32 t0 = tcg_temp_new_i32();
11124 TCGv_i64 fp0;
42a268c2 11125 TCGLabel *l1 = gen_new_label();
a16336e4 11126
1f8929d2 11127 if (tf) {
a16336e4 11128 cond = TCG_COND_EQ;
1f8929d2 11129 } else {
a16336e4 11130 cond = TCG_COND_NE;
1f8929d2 11131 }
a16336e4 11132
fa31af0e 11133 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11134 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11135 tcg_temp_free_i32(t0);
11f94258 11136 fp0 = tcg_temp_new_i64();
9bf3eb2c 11137 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 11138 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11139 tcg_temp_free_i64(fp0);
cbc37b28 11140 gen_set_label(l1);
a16336e4
TS
11141}
11142
7f6613ce
PJ
11143static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11144 int cc, int tf)
a16336e4
TS
11145{
11146 int cond;
cbc37b28 11147 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
11148 TCGLabel *l1 = gen_new_label();
11149 TCGLabel *l2 = gen_new_label();
a16336e4 11150
1f8929d2 11151 if (tf) {
a16336e4 11152 cond = TCG_COND_EQ;
1f8929d2 11153 } else {
a16336e4 11154 cond = TCG_COND_NE;
1f8929d2 11155 }
a16336e4 11156
fa31af0e 11157 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11158 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11159 gen_load_fpr32(ctx, t0, fs);
11160 gen_store_fpr32(ctx, t0, fd);
a16336e4 11161 gen_set_label(l1);
9bf3eb2c 11162
71375b59 11163 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 11164 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
11165 gen_load_fpr32h(ctx, t0, fs);
11166 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 11167 tcg_temp_free_i32(t0);
a16336e4 11168 gen_set_label(l2);
a16336e4
TS
11169}
11170
e7f16abb
LA
11171static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11172 int fs)
11173{
11174 TCGv_i32 t1 = tcg_const_i32(0);
11175 TCGv_i32 fp0 = tcg_temp_new_i32();
11176 TCGv_i32 fp1 = tcg_temp_new_i32();
11177 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11178 gen_load_fpr32(ctx, fp0, fd);
11179 gen_load_fpr32(ctx, fp1, ft);
11180 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
11181
11182 switch (op1) {
11183 case OPC_SEL_S:
11184 tcg_gen_andi_i32(fp0, fp0, 1);
11185 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11186 break;
11187 case OPC_SELEQZ_S:
11188 tcg_gen_andi_i32(fp1, fp1, 1);
11189 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11190 break;
11191 case OPC_SELNEZ_S:
11192 tcg_gen_andi_i32(fp1, fp1, 1);
11193 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11194 break;
11195 default:
11196 MIPS_INVAL("gen_sel_s");
9c708c7f 11197 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11198 break;
11199 }
11200
7c979afd 11201 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11202 tcg_temp_free_i32(fp2);
11203 tcg_temp_free_i32(fp1);
11204 tcg_temp_free_i32(fp0);
11205 tcg_temp_free_i32(t1);
11206}
11207
11208static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11209 int fs)
11210{
11211 TCGv_i64 t1 = tcg_const_i64(0);
11212 TCGv_i64 fp0 = tcg_temp_new_i64();
11213 TCGv_i64 fp1 = tcg_temp_new_i64();
11214 TCGv_i64 fp2 = tcg_temp_new_i64();
11215 gen_load_fpr64(ctx, fp0, fd);
11216 gen_load_fpr64(ctx, fp1, ft);
11217 gen_load_fpr64(ctx, fp2, fs);
11218
11219 switch (op1) {
11220 case OPC_SEL_D:
11221 tcg_gen_andi_i64(fp0, fp0, 1);
11222 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11223 break;
11224 case OPC_SELEQZ_D:
11225 tcg_gen_andi_i64(fp1, fp1, 1);
11226 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11227 break;
11228 case OPC_SELNEZ_D:
11229 tcg_gen_andi_i64(fp1, fp1, 1);
11230 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11231 break;
11232 default:
11233 MIPS_INVAL("gen_sel_d");
9c708c7f 11234 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11235 break;
11236 }
11237
11238 gen_store_fpr64(ctx, fp0, fd);
11239 tcg_temp_free_i64(fp2);
11240 tcg_temp_free_i64(fp1);
11241 tcg_temp_free_i64(fp0);
11242 tcg_temp_free_i64(t1);
11243}
6ea83fed 11244
235785e8
AM
11245static void gen_farith(DisasContext *ctx, enum fopcode op1,
11246 int ft, int fs, int fd, int cc)
6ea83fed 11247{
7a387fff 11248 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
11249 switch (op1) {
11250 case OPC_ADD_S:
b6d96bed 11251 {
a7812ae4
PB
11252 TCGv_i32 fp0 = tcg_temp_new_i32();
11253 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11254
7c979afd
LA
11255 gen_load_fpr32(ctx, fp0, fs);
11256 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11257 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11258 tcg_temp_free_i32(fp1);
7c979afd 11259 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11260 tcg_temp_free_i32(fp0);
b6d96bed 11261 }
5a5012ec 11262 break;
bf4120ad 11263 case OPC_SUB_S:
b6d96bed 11264 {
a7812ae4
PB
11265 TCGv_i32 fp0 = tcg_temp_new_i32();
11266 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11267
7c979afd
LA
11268 gen_load_fpr32(ctx, fp0, fs);
11269 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11270 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11271 tcg_temp_free_i32(fp1);
7c979afd 11272 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11273 tcg_temp_free_i32(fp0);
b6d96bed 11274 }
5a5012ec 11275 break;
bf4120ad 11276 case OPC_MUL_S:
b6d96bed 11277 {
a7812ae4
PB
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11279 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11280
7c979afd
LA
11281 gen_load_fpr32(ctx, fp0, fs);
11282 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11283 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11284 tcg_temp_free_i32(fp1);
7c979afd 11285 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11286 tcg_temp_free_i32(fp0);
b6d96bed 11287 }
5a5012ec 11288 break;
bf4120ad 11289 case OPC_DIV_S:
b6d96bed 11290 {
a7812ae4
PB
11291 TCGv_i32 fp0 = tcg_temp_new_i32();
11292 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11293
7c979afd
LA
11294 gen_load_fpr32(ctx, fp0, fs);
11295 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11296 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11297 tcg_temp_free_i32(fp1);
7c979afd 11298 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11299 tcg_temp_free_i32(fp0);
b6d96bed 11300 }
5a5012ec 11301 break;
bf4120ad 11302 case OPC_SQRT_S:
b6d96bed 11303 {
a7812ae4 11304 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11305
7c979afd 11306 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11307 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 11308 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11309 tcg_temp_free_i32(fp0);
b6d96bed 11310 }
5a5012ec 11311 break;
bf4120ad 11312 case OPC_ABS_S:
b6d96bed 11313 {
a7812ae4 11314 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11315
7c979afd 11316 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11317 if (ctx->abs2008) {
11318 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11319 } else {
11320 gen_helper_float_abs_s(fp0, fp0);
11321 }
7c979afd 11322 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11323 tcg_temp_free_i32(fp0);
b6d96bed 11324 }
5a5012ec 11325 break;
bf4120ad 11326 case OPC_MOV_S:
b6d96bed 11327 {
a7812ae4 11328 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11329
7c979afd
LA
11330 gen_load_fpr32(ctx, fp0, fs);
11331 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11332 tcg_temp_free_i32(fp0);
b6d96bed 11333 }
5a5012ec 11334 break;
bf4120ad 11335 case OPC_NEG_S:
b6d96bed 11336 {
a7812ae4 11337 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11338
7c979afd 11339 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11340 if (ctx->abs2008) {
11341 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11342 } else {
11343 gen_helper_float_chs_s(fp0, fp0);
11344 }
7c979afd 11345 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11346 tcg_temp_free_i32(fp0);
b6d96bed 11347 }
5a5012ec 11348 break;
bf4120ad 11349 case OPC_ROUND_L_S:
5e755519 11350 check_cp1_64bitmode(ctx);
b6d96bed 11351 {
a7812ae4
PB
11352 TCGv_i32 fp32 = tcg_temp_new_i32();
11353 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11354
7c979afd 11355 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11356 if (ctx->nan2008) {
11357 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11358 } else {
11359 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11360 }
a7812ae4 11361 tcg_temp_free_i32(fp32);
b6d96bed 11362 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11363 tcg_temp_free_i64(fp64);
b6d96bed 11364 }
5a5012ec 11365 break;
bf4120ad 11366 case OPC_TRUNC_L_S:
5e755519 11367 check_cp1_64bitmode(ctx);
b6d96bed 11368 {
a7812ae4
PB
11369 TCGv_i32 fp32 = tcg_temp_new_i32();
11370 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11371
7c979afd 11372 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11373 if (ctx->nan2008) {
11374 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11375 } else {
11376 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11377 }
a7812ae4 11378 tcg_temp_free_i32(fp32);
b6d96bed 11379 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11380 tcg_temp_free_i64(fp64);
b6d96bed 11381 }
5a5012ec 11382 break;
bf4120ad 11383 case OPC_CEIL_L_S:
5e755519 11384 check_cp1_64bitmode(ctx);
b6d96bed 11385 {
a7812ae4
PB
11386 TCGv_i32 fp32 = tcg_temp_new_i32();
11387 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11388
7c979afd 11389 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11390 if (ctx->nan2008) {
11391 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11392 } else {
11393 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11394 }
a7812ae4 11395 tcg_temp_free_i32(fp32);
b6d96bed 11396 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11397 tcg_temp_free_i64(fp64);
b6d96bed 11398 }
5a5012ec 11399 break;
bf4120ad 11400 case OPC_FLOOR_L_S:
5e755519 11401 check_cp1_64bitmode(ctx);
b6d96bed 11402 {
a7812ae4
PB
11403 TCGv_i32 fp32 = tcg_temp_new_i32();
11404 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11405
7c979afd 11406 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11407 if (ctx->nan2008) {
11408 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11409 } else {
11410 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11411 }
a7812ae4 11412 tcg_temp_free_i32(fp32);
b6d96bed 11413 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11414 tcg_temp_free_i64(fp64);
b6d96bed 11415 }
5a5012ec 11416 break;
bf4120ad 11417 case OPC_ROUND_W_S:
b6d96bed 11418 {
a7812ae4 11419 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11420
7c979afd 11421 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11422 if (ctx->nan2008) {
11423 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11424 } else {
11425 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11426 }
7c979afd 11427 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11428 tcg_temp_free_i32(fp0);
b6d96bed 11429 }
5a5012ec 11430 break;
bf4120ad 11431 case OPC_TRUNC_W_S:
b6d96bed 11432 {
a7812ae4 11433 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11434
7c979afd 11435 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11436 if (ctx->nan2008) {
11437 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11438 } else {
11439 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11440 }
7c979afd 11441 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11442 tcg_temp_free_i32(fp0);
b6d96bed 11443 }
5a5012ec 11444 break;
bf4120ad 11445 case OPC_CEIL_W_S:
b6d96bed 11446 {
a7812ae4 11447 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11448
7c979afd 11449 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11450 if (ctx->nan2008) {
11451 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11452 } else {
11453 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11454 }
7c979afd 11455 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11456 tcg_temp_free_i32(fp0);
b6d96bed 11457 }
5a5012ec 11458 break;
bf4120ad 11459 case OPC_FLOOR_W_S:
b6d96bed 11460 {
a7812ae4 11461 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11462
7c979afd 11463 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11464 if (ctx->nan2008) {
11465 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11466 } else {
11467 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11468 }
7c979afd 11469 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11470 tcg_temp_free_i32(fp0);
b6d96bed 11471 }
5a5012ec 11472 break;
e7f16abb
LA
11473 case OPC_SEL_S:
11474 check_insn(ctx, ISA_MIPS32R6);
11475 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11476 break;
11477 case OPC_SELEQZ_S:
11478 check_insn(ctx, ISA_MIPS32R6);
11479 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11480 break;
11481 case OPC_SELNEZ_S:
11482 check_insn(ctx, ISA_MIPS32R6);
11483 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11484 break;
bf4120ad 11485 case OPC_MOVCF_S:
fecd2646 11486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 11487 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11488 break;
bf4120ad 11489 case OPC_MOVZ_S:
fecd2646 11490 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11491 {
42a268c2 11492 TCGLabel *l1 = gen_new_label();
c9297f4d 11493 TCGv_i32 fp0;
a16336e4 11494
c9297f4d
AJ
11495 if (ft != 0) {
11496 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11497 }
11498 fp0 = tcg_temp_new_i32();
7c979afd
LA
11499 gen_load_fpr32(ctx, fp0, fs);
11500 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11501 tcg_temp_free_i32(fp0);
a16336e4
TS
11502 gen_set_label(l1);
11503 }
5a5012ec 11504 break;
bf4120ad 11505 case OPC_MOVN_S:
fecd2646 11506 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11507 {
42a268c2 11508 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11509 TCGv_i32 fp0;
11510
11511 if (ft != 0) {
11512 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11513 fp0 = tcg_temp_new_i32();
7c979afd
LA
11514 gen_load_fpr32(ctx, fp0, fs);
11515 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11516 tcg_temp_free_i32(fp0);
11517 gen_set_label(l1);
11518 }
a16336e4 11519 }
5a5012ec 11520 break;
bf4120ad 11521 case OPC_RECIP_S:
b6d96bed 11522 {
a7812ae4 11523 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11524
7c979afd 11525 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11526 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11527 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11528 tcg_temp_free_i32(fp0);
b6d96bed 11529 }
57fa1fb3 11530 break;
bf4120ad 11531 case OPC_RSQRT_S:
b6d96bed 11532 {
a7812ae4 11533 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11534
7c979afd 11535 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11536 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11537 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11538 tcg_temp_free_i32(fp0);
b6d96bed 11539 }
57fa1fb3 11540 break;
e7f16abb
LA
11541 case OPC_MADDF_S:
11542 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11543 {
a7812ae4
PB
11544 TCGv_i32 fp0 = tcg_temp_new_i32();
11545 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11546 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11547 gen_load_fpr32(ctx, fp0, fs);
11548 gen_load_fpr32(ctx, fp1, ft);
11549 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11550 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11551 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11552 tcg_temp_free_i32(fp2);
a7812ae4 11553 tcg_temp_free_i32(fp1);
a7812ae4 11554 tcg_temp_free_i32(fp0);
b6d96bed 11555 }
57fa1fb3 11556 break;
e7f16abb
LA
11557 case OPC_MSUBF_S:
11558 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11559 {
a7812ae4 11560 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11561 TCGv_i32 fp1 = tcg_temp_new_i32();
11562 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11563 gen_load_fpr32(ctx, fp0, fs);
11564 gen_load_fpr32(ctx, fp1, ft);
11565 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11566 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11567 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11568 tcg_temp_free_i32(fp2);
11569 tcg_temp_free_i32(fp1);
a7812ae4 11570 tcg_temp_free_i32(fp0);
b6d96bed 11571 }
57fa1fb3 11572 break;
e7f16abb
LA
11573 case OPC_RINT_S:
11574 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11575 {
a7812ae4 11576 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11577 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11578 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 11579 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11580 tcg_temp_free_i32(fp0);
b6d96bed 11581 }
57fa1fb3 11582 break;
e7f16abb
LA
11583 case OPC_CLASS_S:
11584 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11585 {
e7f16abb 11586 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11587 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 11588 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 11589 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 11590 tcg_temp_free_i32(fp0);
e7f16abb
LA
11591 }
11592 break;
11593 case OPC_MIN_S: /* OPC_RECIP2_S */
11594 if (ctx->insn_flags & ISA_MIPS32R6) {
11595 /* OPC_MIN_S */
a7812ae4
PB
11596 TCGv_i32 fp0 = tcg_temp_new_i32();
11597 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11598 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11599 gen_load_fpr32(ctx, fp0, fs);
11600 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11601 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 11602 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11603 tcg_temp_free_i32(fp2);
11604 tcg_temp_free_i32(fp1);
11605 tcg_temp_free_i32(fp0);
e7f16abb
LA
11606 } else {
11607 /* OPC_RECIP2_S */
11608 check_cp1_64bitmode(ctx);
11609 {
11610 TCGv_i32 fp0 = tcg_temp_new_i32();
11611 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11612
7c979afd
LA
11613 gen_load_fpr32(ctx, fp0, fs);
11614 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11615 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11616 tcg_temp_free_i32(fp1);
7c979afd 11617 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11618 tcg_temp_free_i32(fp0);
11619 }
e7f16abb
LA
11620 }
11621 break;
11622 case OPC_MINA_S: /* OPC_RECIP1_S */
11623 if (ctx->insn_flags & ISA_MIPS32R6) {
11624 /* OPC_MINA_S */
11625 TCGv_i32 fp0 = tcg_temp_new_i32();
11626 TCGv_i32 fp1 = tcg_temp_new_i32();
11627 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11628 gen_load_fpr32(ctx, fp0, fs);
11629 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11630 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 11631 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11632 tcg_temp_free_i32(fp2);
11633 tcg_temp_free_i32(fp1);
11634 tcg_temp_free_i32(fp0);
e7f16abb
LA
11635 } else {
11636 /* OPC_RECIP1_S */
11637 check_cp1_64bitmode(ctx);
11638 {
11639 TCGv_i32 fp0 = tcg_temp_new_i32();
11640
7c979afd 11641 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11642 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 11643 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11644 tcg_temp_free_i32(fp0);
11645 }
e7f16abb
LA
11646 }
11647 break;
11648 case OPC_MAX_S: /* OPC_RSQRT1_S */
11649 if (ctx->insn_flags & ISA_MIPS32R6) {
11650 /* OPC_MAX_S */
11651 TCGv_i32 fp0 = tcg_temp_new_i32();
11652 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11653 gen_load_fpr32(ctx, fp0, fs);
11654 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11655 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11656 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11657 tcg_temp_free_i32(fp1);
11658 tcg_temp_free_i32(fp0);
e7f16abb
LA
11659 } else {
11660 /* OPC_RSQRT1_S */
11661 check_cp1_64bitmode(ctx);
11662 {
11663 TCGv_i32 fp0 = tcg_temp_new_i32();
11664
7c979afd 11665 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11666 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11667 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11668 tcg_temp_free_i32(fp0);
11669 }
e7f16abb
LA
11670 }
11671 break;
11672 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11673 if (ctx->insn_flags & ISA_MIPS32R6) {
11674 /* OPC_MAXA_S */
11675 TCGv_i32 fp0 = tcg_temp_new_i32();
11676 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11677 gen_load_fpr32(ctx, fp0, fs);
11678 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11679 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11680 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11681 tcg_temp_free_i32(fp1);
a7812ae4 11682 tcg_temp_free_i32(fp0);
e7f16abb
LA
11683 } else {
11684 /* OPC_RSQRT2_S */
11685 check_cp1_64bitmode(ctx);
11686 {
11687 TCGv_i32 fp0 = tcg_temp_new_i32();
11688 TCGv_i32 fp1 = tcg_temp_new_i32();
11689
7c979afd
LA
11690 gen_load_fpr32(ctx, fp0, fs);
11691 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11692 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11693 tcg_temp_free_i32(fp1);
7c979afd 11694 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11695 tcg_temp_free_i32(fp0);
11696 }
b6d96bed 11697 }
57fa1fb3 11698 break;
bf4120ad 11699 case OPC_CVT_D_S:
5e755519 11700 check_cp1_registers(ctx, fd);
b6d96bed 11701 {
a7812ae4
PB
11702 TCGv_i32 fp32 = tcg_temp_new_i32();
11703 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11704
7c979afd 11705 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11706 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11707 tcg_temp_free_i32(fp32);
b6d96bed 11708 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11709 tcg_temp_free_i64(fp64);
b6d96bed 11710 }
5a5012ec 11711 break;
bf4120ad 11712 case OPC_CVT_W_S:
b6d96bed 11713 {
a7812ae4 11714 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11715
7c979afd 11716 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11717 if (ctx->nan2008) {
11718 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11719 } else {
11720 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11721 }
7c979afd 11722 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11723 tcg_temp_free_i32(fp0);
b6d96bed 11724 }
5a5012ec 11725 break;
bf4120ad 11726 case OPC_CVT_L_S:
5e755519 11727 check_cp1_64bitmode(ctx);
b6d96bed 11728 {
a7812ae4
PB
11729 TCGv_i32 fp32 = tcg_temp_new_i32();
11730 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11731
7c979afd 11732 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11733 if (ctx->nan2008) {
11734 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11735 } else {
11736 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11737 }
a7812ae4 11738 tcg_temp_free_i32(fp32);
b6d96bed 11739 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11740 tcg_temp_free_i64(fp64);
b6d96bed 11741 }
5a5012ec 11742 break;
bf4120ad 11743 case OPC_CVT_PS_S:
e29c9628 11744 check_ps(ctx);
b6d96bed 11745 {
a7812ae4
PB
11746 TCGv_i64 fp64 = tcg_temp_new_i64();
11747 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11748 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11749
7c979afd
LA
11750 gen_load_fpr32(ctx, fp32_0, fs);
11751 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11752 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11753 tcg_temp_free_i32(fp32_1);
11754 tcg_temp_free_i32(fp32_0);
36aa55dc 11755 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11756 tcg_temp_free_i64(fp64);
b6d96bed 11757 }
5a5012ec 11758 break;
bf4120ad
NF
11759 case OPC_CMP_F_S:
11760 case OPC_CMP_UN_S:
11761 case OPC_CMP_EQ_S:
11762 case OPC_CMP_UEQ_S:
11763 case OPC_CMP_OLT_S:
11764 case OPC_CMP_ULT_S:
11765 case OPC_CMP_OLE_S:
11766 case OPC_CMP_ULE_S:
11767 case OPC_CMP_SF_S:
11768 case OPC_CMP_NGLE_S:
11769 case OPC_CMP_SEQ_S:
11770 case OPC_CMP_NGL_S:
11771 case OPC_CMP_LT_S:
11772 case OPC_CMP_NGE_S:
11773 case OPC_CMP_LE_S:
11774 case OPC_CMP_NGT_S:
fecd2646 11775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 11776 if (ctx->opcode & (1 << 6)) {
71375b59 11777 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 11778 } else {
71375b59 11779 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11780 }
5a5012ec 11781 break;
bf4120ad 11782 case OPC_ADD_D:
5e755519 11783 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11784 {
a7812ae4
PB
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11786 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11787
11788 gen_load_fpr64(ctx, fp0, fs);
11789 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11790 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11791 tcg_temp_free_i64(fp1);
b6d96bed 11792 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11793 tcg_temp_free_i64(fp0);
b6d96bed 11794 }
6ea83fed 11795 break;
bf4120ad 11796 case OPC_SUB_D:
5e755519 11797 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11798 {
a7812ae4
PB
11799 TCGv_i64 fp0 = tcg_temp_new_i64();
11800 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11801
11802 gen_load_fpr64(ctx, fp0, fs);
11803 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11804 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11805 tcg_temp_free_i64(fp1);
b6d96bed 11806 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11807 tcg_temp_free_i64(fp0);
b6d96bed 11808 }
6ea83fed 11809 break;
bf4120ad 11810 case OPC_MUL_D:
5e755519 11811 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11812 {
a7812ae4
PB
11813 TCGv_i64 fp0 = tcg_temp_new_i64();
11814 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11815
11816 gen_load_fpr64(ctx, fp0, fs);
11817 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11818 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11819 tcg_temp_free_i64(fp1);
b6d96bed 11820 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11821 tcg_temp_free_i64(fp0);
b6d96bed 11822 }
6ea83fed 11823 break;
bf4120ad 11824 case OPC_DIV_D:
5e755519 11825 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11826 {
a7812ae4
PB
11827 TCGv_i64 fp0 = tcg_temp_new_i64();
11828 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11829
11830 gen_load_fpr64(ctx, fp0, fs);
11831 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11832 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11833 tcg_temp_free_i64(fp1);
b6d96bed 11834 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11835 tcg_temp_free_i64(fp0);
b6d96bed 11836 }
6ea83fed 11837 break;
bf4120ad 11838 case OPC_SQRT_D:
5e755519 11839 check_cp1_registers(ctx, fs | fd);
b6d96bed 11840 {
a7812ae4 11841 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11842
11843 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11844 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11845 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11846 tcg_temp_free_i64(fp0);
b6d96bed 11847 }
6ea83fed 11848 break;
bf4120ad 11849 case OPC_ABS_D:
5e755519 11850 check_cp1_registers(ctx, fs | fd);
b6d96bed 11851 {
a7812ae4 11852 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11853
11854 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11855 if (ctx->abs2008) {
11856 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11857 } else {
11858 gen_helper_float_abs_d(fp0, fp0);
11859 }
b6d96bed 11860 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11861 tcg_temp_free_i64(fp0);
b6d96bed 11862 }
6ea83fed 11863 break;
bf4120ad 11864 case OPC_MOV_D:
5e755519 11865 check_cp1_registers(ctx, fs | fd);
b6d96bed 11866 {
a7812ae4 11867 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11868
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11871 tcg_temp_free_i64(fp0);
b6d96bed 11872 }
6ea83fed 11873 break;
bf4120ad 11874 case OPC_NEG_D:
5e755519 11875 check_cp1_registers(ctx, fs | fd);
b6d96bed 11876 {
a7812ae4 11877 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11878
11879 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11880 if (ctx->abs2008) {
11881 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11882 } else {
11883 gen_helper_float_chs_d(fp0, fp0);
11884 }
b6d96bed 11885 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11886 tcg_temp_free_i64(fp0);
b6d96bed 11887 }
6ea83fed 11888 break;
bf4120ad 11889 case OPC_ROUND_L_D:
5e755519 11890 check_cp1_64bitmode(ctx);
b6d96bed 11891 {
a7812ae4 11892 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11893
11894 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11895 if (ctx->nan2008) {
11896 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11897 } else {
11898 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11899 }
b6d96bed 11900 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11901 tcg_temp_free_i64(fp0);
b6d96bed 11902 }
5a5012ec 11903 break;
bf4120ad 11904 case OPC_TRUNC_L_D:
5e755519 11905 check_cp1_64bitmode(ctx);
b6d96bed 11906 {
a7812ae4 11907 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11908
11909 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11910 if (ctx->nan2008) {
11911 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11912 } else {
11913 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11914 }
b6d96bed 11915 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11916 tcg_temp_free_i64(fp0);
b6d96bed 11917 }
5a5012ec 11918 break;
bf4120ad 11919 case OPC_CEIL_L_D:
5e755519 11920 check_cp1_64bitmode(ctx);
b6d96bed 11921 {
a7812ae4 11922 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11923
11924 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11925 if (ctx->nan2008) {
11926 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11927 } else {
11928 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11929 }
b6d96bed 11930 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11931 tcg_temp_free_i64(fp0);
b6d96bed 11932 }
5a5012ec 11933 break;
bf4120ad 11934 case OPC_FLOOR_L_D:
5e755519 11935 check_cp1_64bitmode(ctx);
b6d96bed 11936 {
a7812ae4 11937 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11938
11939 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11940 if (ctx->nan2008) {
11941 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11942 } else {
11943 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11944 }
b6d96bed 11945 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11946 tcg_temp_free_i64(fp0);
b6d96bed 11947 }
5a5012ec 11948 break;
bf4120ad 11949 case OPC_ROUND_W_D:
5e755519 11950 check_cp1_registers(ctx, fs);
b6d96bed 11951 {
a7812ae4
PB
11952 TCGv_i32 fp32 = tcg_temp_new_i32();
11953 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11954
11955 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11956 if (ctx->nan2008) {
11957 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11958 } else {
11959 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11960 }
a7812ae4 11961 tcg_temp_free_i64(fp64);
7c979afd 11962 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11963 tcg_temp_free_i32(fp32);
b6d96bed 11964 }
6ea83fed 11965 break;
bf4120ad 11966 case OPC_TRUNC_W_D:
5e755519 11967 check_cp1_registers(ctx, fs);
b6d96bed 11968 {
a7812ae4
PB
11969 TCGv_i32 fp32 = tcg_temp_new_i32();
11970 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11971
11972 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11973 if (ctx->nan2008) {
11974 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11975 } else {
11976 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11977 }
a7812ae4 11978 tcg_temp_free_i64(fp64);
7c979afd 11979 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11980 tcg_temp_free_i32(fp32);
b6d96bed 11981 }
6ea83fed 11982 break;
bf4120ad 11983 case OPC_CEIL_W_D:
5e755519 11984 check_cp1_registers(ctx, fs);
b6d96bed 11985 {
a7812ae4
PB
11986 TCGv_i32 fp32 = tcg_temp_new_i32();
11987 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11988
11989 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11990 if (ctx->nan2008) {
11991 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11992 } else {
11993 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11994 }
a7812ae4 11995 tcg_temp_free_i64(fp64);
7c979afd 11996 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11997 tcg_temp_free_i32(fp32);
b6d96bed 11998 }
6ea83fed 11999 break;
bf4120ad 12000 case OPC_FLOOR_W_D:
5e755519 12001 check_cp1_registers(ctx, fs);
b6d96bed 12002 {
a7812ae4
PB
12003 TCGv_i32 fp32 = tcg_temp_new_i32();
12004 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12005
12006 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12007 if (ctx->nan2008) {
12008 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12009 } else {
12010 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12011 }
a7812ae4 12012 tcg_temp_free_i64(fp64);
7c979afd 12013 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12014 tcg_temp_free_i32(fp32);
b6d96bed 12015 }
6ea83fed 12016 break;
e7f16abb
LA
12017 case OPC_SEL_D:
12018 check_insn(ctx, ISA_MIPS32R6);
12019 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
12020 break;
12021 case OPC_SELEQZ_D:
12022 check_insn(ctx, ISA_MIPS32R6);
12023 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
12024 break;
12025 case OPC_SELNEZ_D:
12026 check_insn(ctx, ISA_MIPS32R6);
12027 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 12028 break;
bf4120ad 12029 case OPC_MOVCF_D:
fecd2646 12030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 12031 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 12032 break;
bf4120ad 12033 case OPC_MOVZ_D:
fecd2646 12034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 12035 {
42a268c2 12036 TCGLabel *l1 = gen_new_label();
c9297f4d 12037 TCGv_i64 fp0;
a16336e4 12038
c9297f4d
AJ
12039 if (ft != 0) {
12040 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12041 }
12042 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12043 gen_load_fpr64(ctx, fp0, fs);
12044 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12045 tcg_temp_free_i64(fp0);
a16336e4
TS
12046 gen_set_label(l1);
12047 }
5a5012ec 12048 break;
bf4120ad 12049 case OPC_MOVN_D:
fecd2646 12050 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 12051 {
42a268c2 12052 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
12053 TCGv_i64 fp0;
12054
12055 if (ft != 0) {
12056 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12057 fp0 = tcg_temp_new_i64();
12058 gen_load_fpr64(ctx, fp0, fs);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12061 gen_set_label(l1);
12062 }
a16336e4 12063 }
6ea83fed 12064 break;
bf4120ad 12065 case OPC_RECIP_D:
ca6c7803 12066 check_cp1_registers(ctx, fs | fd);
b6d96bed 12067 {
a7812ae4 12068 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12069
12070 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12071 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 12072 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12073 tcg_temp_free_i64(fp0);
b6d96bed 12074 }
57fa1fb3 12075 break;
bf4120ad 12076 case OPC_RSQRT_D:
ca6c7803 12077 check_cp1_registers(ctx, fs | fd);
b6d96bed 12078 {
a7812ae4 12079 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12080
12081 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12082 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 12083 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12084 tcg_temp_free_i64(fp0);
b6d96bed 12085 }
57fa1fb3 12086 break;
e7f16abb
LA
12087 case OPC_MADDF_D:
12088 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12089 {
a7812ae4
PB
12090 TCGv_i64 fp0 = tcg_temp_new_i64();
12091 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 12092 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12093 gen_load_fpr64(ctx, fp0, fs);
12094 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12095 gen_load_fpr64(ctx, fp2, fd);
12096 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12097 gen_store_fpr64(ctx, fp2, fd);
12098 tcg_temp_free_i64(fp2);
a7812ae4 12099 tcg_temp_free_i64(fp1);
a7812ae4 12100 tcg_temp_free_i64(fp0);
b6d96bed 12101 }
57fa1fb3 12102 break;
e7f16abb
LA
12103 case OPC_MSUBF_D:
12104 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12105 {
a7812ae4 12106 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
12107 TCGv_i64 fp1 = tcg_temp_new_i64();
12108 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 12109 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
12110 gen_load_fpr64(ctx, fp1, ft);
12111 gen_load_fpr64(ctx, fp2, fd);
12112 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12113 gen_store_fpr64(ctx, fp2, fd);
12114 tcg_temp_free_i64(fp2);
12115 tcg_temp_free_i64(fp1);
a7812ae4 12116 tcg_temp_free_i64(fp0);
b6d96bed 12117 }
57fa1fb3 12118 break;
e7f16abb
LA
12119 case OPC_RINT_D:
12120 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12121 {
a7812ae4 12122 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12123 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 12124 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 12125 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12126 tcg_temp_free_i64(fp0);
b6d96bed 12127 }
57fa1fb3 12128 break;
e7f16abb
LA
12129 case OPC_CLASS_D:
12130 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12131 {
e7f16abb
LA
12132 TCGv_i64 fp0 = tcg_temp_new_i64();
12133 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 12134 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
12135 gen_store_fpr64(ctx, fp0, fd);
12136 tcg_temp_free_i64(fp0);
e7f16abb
LA
12137 }
12138 break;
12139 case OPC_MIN_D: /* OPC_RECIP2_D */
12140 if (ctx->insn_flags & ISA_MIPS32R6) {
12141 /* OPC_MIN_D */
a7812ae4
PB
12142 TCGv_i64 fp0 = tcg_temp_new_i64();
12143 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
12144 gen_load_fpr64(ctx, fp0, fs);
12145 gen_load_fpr64(ctx, fp1, ft);
12146 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12147 gen_store_fpr64(ctx, fp1, fd);
12148 tcg_temp_free_i64(fp1);
12149 tcg_temp_free_i64(fp0);
e7f16abb
LA
12150 } else {
12151 /* OPC_RECIP2_D */
12152 check_cp1_64bitmode(ctx);
12153 {
12154 TCGv_i64 fp0 = tcg_temp_new_i64();
12155 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 12156
e7f16abb
LA
12157 gen_load_fpr64(ctx, fp0, fs);
12158 gen_load_fpr64(ctx, fp1, ft);
12159 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12160 tcg_temp_free_i64(fp1);
12161 gen_store_fpr64(ctx, fp0, fd);
12162 tcg_temp_free_i64(fp0);
12163 }
e7f16abb
LA
12164 }
12165 break;
12166 case OPC_MINA_D: /* OPC_RECIP1_D */
12167 if (ctx->insn_flags & ISA_MIPS32R6) {
12168 /* OPC_MINA_D */
12169 TCGv_i64 fp0 = tcg_temp_new_i64();
12170 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12171 gen_load_fpr64(ctx, fp0, fs);
12172 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12173 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12174 gen_store_fpr64(ctx, fp1, fd);
12175 tcg_temp_free_i64(fp1);
12176 tcg_temp_free_i64(fp0);
e7f16abb
LA
12177 } else {
12178 /* OPC_RECIP1_D */
12179 check_cp1_64bitmode(ctx);
12180 {
12181 TCGv_i64 fp0 = tcg_temp_new_i64();
12182
12183 gen_load_fpr64(ctx, fp0, fs);
12184 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12185 gen_store_fpr64(ctx, fp0, fd);
12186 tcg_temp_free_i64(fp0);
12187 }
e7f16abb
LA
12188 }
12189 break;
12190 case OPC_MAX_D: /* OPC_RSQRT1_D */
12191 if (ctx->insn_flags & ISA_MIPS32R6) {
12192 /* OPC_MAX_D */
12193 TCGv_i64 fp0 = tcg_temp_new_i64();
12194 TCGv_i64 fp1 = tcg_temp_new_i64();
12195 gen_load_fpr64(ctx, fp0, fs);
12196 gen_load_fpr64(ctx, fp1, ft);
12197 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12198 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 12199 tcg_temp_free_i64(fp1);
a7812ae4 12200 tcg_temp_free_i64(fp0);
e7f16abb
LA
12201 } else {
12202 /* OPC_RSQRT1_D */
12203 check_cp1_64bitmode(ctx);
12204 {
12205 TCGv_i64 fp0 = tcg_temp_new_i64();
12206
12207 gen_load_fpr64(ctx, fp0, fs);
12208 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12209 gen_store_fpr64(ctx, fp0, fd);
12210 tcg_temp_free_i64(fp0);
12211 }
e7f16abb
LA
12212 }
12213 break;
12214 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12215 if (ctx->insn_flags & ISA_MIPS32R6) {
12216 /* OPC_MAXA_D */
12217 TCGv_i64 fp0 = tcg_temp_new_i64();
12218 TCGv_i64 fp1 = tcg_temp_new_i64();
12219 gen_load_fpr64(ctx, fp0, fs);
12220 gen_load_fpr64(ctx, fp1, ft);
12221 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12222 gen_store_fpr64(ctx, fp1, fd);
12223 tcg_temp_free_i64(fp1);
12224 tcg_temp_free_i64(fp0);
e7f16abb
LA
12225 } else {
12226 /* OPC_RSQRT2_D */
12227 check_cp1_64bitmode(ctx);
12228 {
12229 TCGv_i64 fp0 = tcg_temp_new_i64();
12230 TCGv_i64 fp1 = tcg_temp_new_i64();
12231
12232 gen_load_fpr64(ctx, fp0, fs);
12233 gen_load_fpr64(ctx, fp1, ft);
12234 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12235 tcg_temp_free_i64(fp1);
12236 gen_store_fpr64(ctx, fp0, fd);
12237 tcg_temp_free_i64(fp0);
12238 }
b6d96bed 12239 }
57fa1fb3 12240 break;
bf4120ad
NF
12241 case OPC_CMP_F_D:
12242 case OPC_CMP_UN_D:
12243 case OPC_CMP_EQ_D:
12244 case OPC_CMP_UEQ_D:
12245 case OPC_CMP_OLT_D:
12246 case OPC_CMP_ULT_D:
12247 case OPC_CMP_OLE_D:
12248 case OPC_CMP_ULE_D:
12249 case OPC_CMP_SF_D:
12250 case OPC_CMP_NGLE_D:
12251 case OPC_CMP_SEQ_D:
12252 case OPC_CMP_NGL_D:
12253 case OPC_CMP_LT_D:
12254 case OPC_CMP_NGE_D:
12255 case OPC_CMP_LE_D:
12256 case OPC_CMP_NGT_D:
fecd2646 12257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 12258 if (ctx->opcode & (1 << 6)) {
71375b59 12259 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 12260 } else {
71375b59 12261 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12262 }
6ea83fed 12263 break;
bf4120ad 12264 case OPC_CVT_S_D:
5e755519 12265 check_cp1_registers(ctx, fs);
b6d96bed 12266 {
a7812ae4
PB
12267 TCGv_i32 fp32 = tcg_temp_new_i32();
12268 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12269
12270 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12271 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 12272 tcg_temp_free_i64(fp64);
7c979afd 12273 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12274 tcg_temp_free_i32(fp32);
b6d96bed 12275 }
5a5012ec 12276 break;
bf4120ad 12277 case OPC_CVT_W_D:
5e755519 12278 check_cp1_registers(ctx, fs);
b6d96bed 12279 {
a7812ae4
PB
12280 TCGv_i32 fp32 = tcg_temp_new_i32();
12281 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12282
12283 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12284 if (ctx->nan2008) {
12285 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12286 } else {
12287 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12288 }
a7812ae4 12289 tcg_temp_free_i64(fp64);
7c979afd 12290 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12291 tcg_temp_free_i32(fp32);
b6d96bed 12292 }
5a5012ec 12293 break;
bf4120ad 12294 case OPC_CVT_L_D:
5e755519 12295 check_cp1_64bitmode(ctx);
b6d96bed 12296 {
a7812ae4 12297 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12298
12299 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12300 if (ctx->nan2008) {
12301 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12302 } else {
12303 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12304 }
b6d96bed 12305 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12306 tcg_temp_free_i64(fp0);
b6d96bed 12307 }
5a5012ec 12308 break;
bf4120ad 12309 case OPC_CVT_S_W:
b6d96bed 12310 {
a7812ae4 12311 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12312
7c979afd 12313 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12314 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 12315 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12316 tcg_temp_free_i32(fp0);
b6d96bed 12317 }
6ea83fed 12318 break;
bf4120ad 12319 case OPC_CVT_D_W:
5e755519 12320 check_cp1_registers(ctx, fd);
b6d96bed 12321 {
a7812ae4
PB
12322 TCGv_i32 fp32 = tcg_temp_new_i32();
12323 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12324
7c979afd 12325 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12326 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12327 tcg_temp_free_i32(fp32);
b6d96bed 12328 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12329 tcg_temp_free_i64(fp64);
b6d96bed 12330 }
5a5012ec 12331 break;
bf4120ad 12332 case OPC_CVT_S_L:
5e755519 12333 check_cp1_64bitmode(ctx);
b6d96bed 12334 {
a7812ae4
PB
12335 TCGv_i32 fp32 = tcg_temp_new_i32();
12336 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12337
12338 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12339 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12340 tcg_temp_free_i64(fp64);
7c979afd 12341 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12342 tcg_temp_free_i32(fp32);
b6d96bed 12343 }
5a5012ec 12344 break;
bf4120ad 12345 case OPC_CVT_D_L:
5e755519 12346 check_cp1_64bitmode(ctx);
b6d96bed 12347 {
a7812ae4 12348 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12349
12350 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12351 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12352 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12353 tcg_temp_free_i64(fp0);
b6d96bed 12354 }
5a5012ec 12355 break;
bf4120ad 12356 case OPC_CVT_PS_PW:
e29c9628 12357 check_ps(ctx);
b6d96bed 12358 {
a7812ae4 12359 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12360
12361 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12362 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12363 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12364 tcg_temp_free_i64(fp0);
b6d96bed 12365 }
5a5012ec 12366 break;
bf4120ad 12367 case OPC_ADD_PS:
e29c9628 12368 check_ps(ctx);
b6d96bed 12369 {
a7812ae4
PB
12370 TCGv_i64 fp0 = tcg_temp_new_i64();
12371 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12372
12373 gen_load_fpr64(ctx, fp0, fs);
12374 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12375 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12376 tcg_temp_free_i64(fp1);
b6d96bed 12377 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12378 tcg_temp_free_i64(fp0);
b6d96bed 12379 }
6ea83fed 12380 break;
bf4120ad 12381 case OPC_SUB_PS:
e29c9628 12382 check_ps(ctx);
b6d96bed 12383 {
a7812ae4
PB
12384 TCGv_i64 fp0 = tcg_temp_new_i64();
12385 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12386
12387 gen_load_fpr64(ctx, fp0, fs);
12388 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12389 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12390 tcg_temp_free_i64(fp1);
b6d96bed 12391 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12392 tcg_temp_free_i64(fp0);
b6d96bed 12393 }
6ea83fed 12394 break;
bf4120ad 12395 case OPC_MUL_PS:
e29c9628 12396 check_ps(ctx);
b6d96bed 12397 {
a7812ae4
PB
12398 TCGv_i64 fp0 = tcg_temp_new_i64();
12399 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12400
12401 gen_load_fpr64(ctx, fp0, fs);
12402 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12403 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12404 tcg_temp_free_i64(fp1);
b6d96bed 12405 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12406 tcg_temp_free_i64(fp0);
b6d96bed 12407 }
6ea83fed 12408 break;
bf4120ad 12409 case OPC_ABS_PS:
e29c9628 12410 check_ps(ctx);
b6d96bed 12411 {
a7812ae4 12412 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12413
12414 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12415 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12416 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12417 tcg_temp_free_i64(fp0);
b6d96bed 12418 }
6ea83fed 12419 break;
bf4120ad 12420 case OPC_MOV_PS:
e29c9628 12421 check_ps(ctx);
b6d96bed 12422 {
a7812ae4 12423 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12424
12425 gen_load_fpr64(ctx, fp0, fs);
12426 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12427 tcg_temp_free_i64(fp0);
b6d96bed 12428 }
6ea83fed 12429 break;
bf4120ad 12430 case OPC_NEG_PS:
e29c9628 12431 check_ps(ctx);
b6d96bed 12432 {
a7812ae4 12433 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12434
12435 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12436 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12437 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12438 tcg_temp_free_i64(fp0);
b6d96bed 12439 }
6ea83fed 12440 break;
bf4120ad 12441 case OPC_MOVCF_PS:
e29c9628 12442 check_ps(ctx);
7f6613ce 12443 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12444 break;
bf4120ad 12445 case OPC_MOVZ_PS:
e29c9628 12446 check_ps(ctx);
a16336e4 12447 {
42a268c2 12448 TCGLabel *l1 = gen_new_label();
30a3848b 12449 TCGv_i64 fp0;
a16336e4 12450
1f8929d2 12451 if (ft != 0) {
c9297f4d 12452 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 12453 }
c9297f4d
AJ
12454 fp0 = tcg_temp_new_i64();
12455 gen_load_fpr64(ctx, fp0, fs);
12456 gen_store_fpr64(ctx, fp0, fd);
12457 tcg_temp_free_i64(fp0);
a16336e4
TS
12458 gen_set_label(l1);
12459 }
6ea83fed 12460 break;
bf4120ad 12461 case OPC_MOVN_PS:
e29c9628 12462 check_ps(ctx);
a16336e4 12463 {
42a268c2 12464 TCGLabel *l1 = gen_new_label();
30a3848b 12465 TCGv_i64 fp0;
c9297f4d
AJ
12466
12467 if (ft != 0) {
12468 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12469 fp0 = tcg_temp_new_i64();
12470 gen_load_fpr64(ctx, fp0, fs);
12471 gen_store_fpr64(ctx, fp0, fd);
12472 tcg_temp_free_i64(fp0);
12473 gen_set_label(l1);
12474 }
a16336e4 12475 }
6ea83fed 12476 break;
bf4120ad 12477 case OPC_ADDR_PS:
e29c9628 12478 check_ps(ctx);
b6d96bed 12479 {
a7812ae4
PB
12480 TCGv_i64 fp0 = tcg_temp_new_i64();
12481 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12482
12483 gen_load_fpr64(ctx, fp0, ft);
12484 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12485 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12486 tcg_temp_free_i64(fp1);
b6d96bed 12487 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12488 tcg_temp_free_i64(fp0);
b6d96bed 12489 }
fbcc6828 12490 break;
bf4120ad 12491 case OPC_MULR_PS:
e29c9628 12492 check_ps(ctx);
b6d96bed 12493 {
a7812ae4
PB
12494 TCGv_i64 fp0 = tcg_temp_new_i64();
12495 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12496
12497 gen_load_fpr64(ctx, fp0, ft);
12498 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12499 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12500 tcg_temp_free_i64(fp1);
b6d96bed 12501 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12502 tcg_temp_free_i64(fp0);
b6d96bed 12503 }
57fa1fb3 12504 break;
bf4120ad 12505 case OPC_RECIP2_PS:
e29c9628 12506 check_ps(ctx);
b6d96bed 12507 {
a7812ae4
PB
12508 TCGv_i64 fp0 = tcg_temp_new_i64();
12509 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12510
12511 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12512 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12513 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12514 tcg_temp_free_i64(fp1);
b6d96bed 12515 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12516 tcg_temp_free_i64(fp0);
b6d96bed 12517 }
57fa1fb3 12518 break;
bf4120ad 12519 case OPC_RECIP1_PS:
e29c9628 12520 check_ps(ctx);
b6d96bed 12521 {
a7812ae4 12522 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12523
12524 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12525 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12526 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12527 tcg_temp_free_i64(fp0);
b6d96bed 12528 }
57fa1fb3 12529 break;
bf4120ad 12530 case OPC_RSQRT1_PS:
e29c9628 12531 check_ps(ctx);
b6d96bed 12532 {
a7812ae4 12533 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12534
12535 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12536 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12537 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12538 tcg_temp_free_i64(fp0);
b6d96bed 12539 }
57fa1fb3 12540 break;
bf4120ad 12541 case OPC_RSQRT2_PS:
e29c9628 12542 check_ps(ctx);
b6d96bed 12543 {
a7812ae4
PB
12544 TCGv_i64 fp0 = tcg_temp_new_i64();
12545 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12546
12547 gen_load_fpr64(ctx, fp0, fs);
12548 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12549 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12550 tcg_temp_free_i64(fp1);
b6d96bed 12551 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12552 tcg_temp_free_i64(fp0);
b6d96bed 12553 }
57fa1fb3 12554 break;
bf4120ad 12555 case OPC_CVT_S_PU:
5e755519 12556 check_cp1_64bitmode(ctx);
b6d96bed 12557 {
a7812ae4 12558 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12559
7f6613ce 12560 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12561 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12562 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12563 tcg_temp_free_i32(fp0);
b6d96bed 12564 }
dd016883 12565 break;
bf4120ad 12566 case OPC_CVT_PW_PS:
e29c9628 12567 check_ps(ctx);
b6d96bed 12568 {
a7812ae4 12569 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12570
12571 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12572 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 12573 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12574 tcg_temp_free_i64(fp0);
b6d96bed 12575 }
6ea83fed 12576 break;
bf4120ad 12577 case OPC_CVT_S_PL:
5e755519 12578 check_cp1_64bitmode(ctx);
b6d96bed 12579 {
a7812ae4 12580 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12581
7c979afd 12582 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12583 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 12584 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12585 tcg_temp_free_i32(fp0);
b6d96bed 12586 }
6ea83fed 12587 break;
bf4120ad 12588 case OPC_PLL_PS:
e29c9628 12589 check_ps(ctx);
b6d96bed 12590 {
a7812ae4
PB
12591 TCGv_i32 fp0 = tcg_temp_new_i32();
12592 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12593
7c979afd
LA
12594 gen_load_fpr32(ctx, fp0, fs);
12595 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 12596 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 12597 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
12598 tcg_temp_free_i32(fp0);
12599 tcg_temp_free_i32(fp1);
b6d96bed 12600 }
6ea83fed 12601 break;
bf4120ad 12602 case OPC_PLU_PS:
e29c9628 12603 check_ps(ctx);
b6d96bed 12604 {
a7812ae4
PB
12605 TCGv_i32 fp0 = tcg_temp_new_i32();
12606 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12607
7c979afd 12608 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 12609 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12610 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12611 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12612 tcg_temp_free_i32(fp0);
12613 tcg_temp_free_i32(fp1);
b6d96bed 12614 }
5a5012ec 12615 break;
bf4120ad 12616 case OPC_PUL_PS:
e29c9628 12617 check_ps(ctx);
b6d96bed 12618 {
a7812ae4
PB
12619 TCGv_i32 fp0 = tcg_temp_new_i32();
12620 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12621
7f6613ce 12622 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
12623 gen_load_fpr32(ctx, fp1, ft);
12624 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12625 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12626 tcg_temp_free_i32(fp0);
12627 tcg_temp_free_i32(fp1);
b6d96bed 12628 }
5a5012ec 12629 break;
bf4120ad 12630 case OPC_PUU_PS:
e29c9628 12631 check_ps(ctx);
b6d96bed 12632 {
a7812ae4
PB
12633 TCGv_i32 fp0 = tcg_temp_new_i32();
12634 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12635
7f6613ce
PJ
12636 gen_load_fpr32h(ctx, fp0, fs);
12637 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12638 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12639 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12640 tcg_temp_free_i32(fp0);
12641 tcg_temp_free_i32(fp1);
b6d96bed 12642 }
5a5012ec 12643 break;
bf4120ad
NF
12644 case OPC_CMP_F_PS:
12645 case OPC_CMP_UN_PS:
12646 case OPC_CMP_EQ_PS:
12647 case OPC_CMP_UEQ_PS:
12648 case OPC_CMP_OLT_PS:
12649 case OPC_CMP_ULT_PS:
12650 case OPC_CMP_OLE_PS:
12651 case OPC_CMP_ULE_PS:
12652 case OPC_CMP_SF_PS:
12653 case OPC_CMP_NGLE_PS:
12654 case OPC_CMP_SEQ_PS:
12655 case OPC_CMP_NGL_PS:
12656 case OPC_CMP_LT_PS:
12657 case OPC_CMP_NGE_PS:
12658 case OPC_CMP_LE_PS:
12659 case OPC_CMP_NGT_PS:
8153667c 12660 if (ctx->opcode & (1 << 6)) {
71375b59 12661 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 12662 } else {
71375b59 12663 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12664 }
6ea83fed 12665 break;
5a5012ec 12666 default:
9d68ac14 12667 MIPS_INVAL("farith");
9c708c7f 12668 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12669 return;
12670 }
6ea83fed 12671}
6af0bf9c 12672
5a5012ec 12673/* Coprocessor 3 (FPU) */
235785e8
AM
12674static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12675 int fd, int fs, int base, int index)
7a387fff 12676{
4e2474d6 12677 TCGv t0 = tcg_temp_new();
7a387fff 12678
93b12ccc 12679 if (base == 0) {
6c5c1e20 12680 gen_load_gpr(t0, index);
93b12ccc 12681 } else if (index == 0) {
6c5c1e20 12682 gen_load_gpr(t0, base);
93b12ccc 12683 } else {
05168674 12684 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12685 }
7480515f
AM
12686 /*
12687 * Don't do NOP if destination is zero: we must perform the actual
12688 * memory access.
12689 */
5a5012ec
TS
12690 switch (opc) {
12691 case OPC_LWXC1:
8c0ab41f 12692 check_cop1x(ctx);
b6d96bed 12693 {
a7812ae4 12694 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12695
5f68f5ae 12696 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12697 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12698 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12699 tcg_temp_free_i32(fp0);
b6d96bed 12700 }
5a5012ec
TS
12701 break;
12702 case OPC_LDXC1:
8c0ab41f
AJ
12703 check_cop1x(ctx);
12704 check_cp1_registers(ctx, fd);
b6d96bed 12705 {
a7812ae4 12706 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12707 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12708 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12709 tcg_temp_free_i64(fp0);
b6d96bed 12710 }
5a5012ec
TS
12711 break;
12712 case OPC_LUXC1:
8c0ab41f 12713 check_cp1_64bitmode(ctx);
6c5c1e20 12714 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12715 {
a7812ae4 12716 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12717
5f68f5ae 12718 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12719 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12720 tcg_temp_free_i64(fp0);
b6d96bed 12721 }
5a5012ec
TS
12722 break;
12723 case OPC_SWXC1:
8c0ab41f 12724 check_cop1x(ctx);
b6d96bed 12725 {
a7812ae4 12726 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12727 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12728 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12729 tcg_temp_free_i32(fp0);
b6d96bed 12730 }
5a5012ec
TS
12731 break;
12732 case OPC_SDXC1:
8c0ab41f
AJ
12733 check_cop1x(ctx);
12734 check_cp1_registers(ctx, fs);
b6d96bed 12735 {
a7812ae4 12736 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12737 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12738 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12739 tcg_temp_free_i64(fp0);
b6d96bed 12740 }
5a5012ec
TS
12741 break;
12742 case OPC_SUXC1:
8c0ab41f 12743 check_cp1_64bitmode(ctx);
6c5c1e20 12744 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12745 {
a7812ae4 12746 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12747 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12748 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12749 tcg_temp_free_i64(fp0);
b6d96bed 12750 }
5a5012ec 12751 break;
5a5012ec 12752 }
6c5c1e20 12753 tcg_temp_free(t0);
5a5012ec
TS
12754}
12755
235785e8
AM
12756static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12757 int fd, int fr, int fs, int ft)
5a5012ec 12758{
5a5012ec
TS
12759 switch (opc) {
12760 case OPC_ALNV_PS:
e29c9628 12761 check_ps(ctx);
a16336e4 12762 {
a7812ae4 12763 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12764 TCGv_i32 fp = tcg_temp_new_i32();
12765 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12766 TCGLabel *l1 = gen_new_label();
12767 TCGLabel *l2 = gen_new_label();
a16336e4 12768
6c5c1e20
TS
12769 gen_load_gpr(t0, fr);
12770 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12771
12772 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12773 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12774 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12775 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12776 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12777 tcg_gen_br(l2);
12778 gen_set_label(l1);
6c5c1e20
TS
12779 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12780 tcg_temp_free(t0);
a16336e4 12781#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12782 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12783 gen_load_fpr32h(ctx, fph, ft);
12784 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12785 gen_store_fpr32(ctx, fph, fd);
a16336e4 12786#else
7f6613ce 12787 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12788 gen_load_fpr32(ctx, fp, ft);
12789 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12790 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12791#endif
12792 gen_set_label(l2);
c905fdac
AJ
12793 tcg_temp_free_i32(fp);
12794 tcg_temp_free_i32(fph);
a16336e4 12795 }
5a5012ec
TS
12796 break;
12797 case OPC_MADD_S:
b8aa4598 12798 check_cop1x(ctx);
b6d96bed 12799 {
a7812ae4
PB
12800 TCGv_i32 fp0 = tcg_temp_new_i32();
12801 TCGv_i32 fp1 = tcg_temp_new_i32();
12802 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12803
7c979afd
LA
12804 gen_load_fpr32(ctx, fp0, fs);
12805 gen_load_fpr32(ctx, fp1, ft);
12806 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12807 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12808 tcg_temp_free_i32(fp0);
12809 tcg_temp_free_i32(fp1);
7c979afd 12810 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12811 tcg_temp_free_i32(fp2);
b6d96bed 12812 }
5a5012ec
TS
12813 break;
12814 case OPC_MADD_D:
b8aa4598
TS
12815 check_cop1x(ctx);
12816 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12817 {
a7812ae4
PB
12818 TCGv_i64 fp0 = tcg_temp_new_i64();
12819 TCGv_i64 fp1 = tcg_temp_new_i64();
12820 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12821
12822 gen_load_fpr64(ctx, fp0, fs);
12823 gen_load_fpr64(ctx, fp1, ft);
12824 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12825 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12826 tcg_temp_free_i64(fp0);
12827 tcg_temp_free_i64(fp1);
b6d96bed 12828 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12829 tcg_temp_free_i64(fp2);
b6d96bed 12830 }
5a5012ec
TS
12831 break;
12832 case OPC_MADD_PS:
e29c9628 12833 check_ps(ctx);
b6d96bed 12834 {
a7812ae4
PB
12835 TCGv_i64 fp0 = tcg_temp_new_i64();
12836 TCGv_i64 fp1 = tcg_temp_new_i64();
12837 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12838
12839 gen_load_fpr64(ctx, fp0, fs);
12840 gen_load_fpr64(ctx, fp1, ft);
12841 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12842 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12843 tcg_temp_free_i64(fp0);
12844 tcg_temp_free_i64(fp1);
b6d96bed 12845 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12846 tcg_temp_free_i64(fp2);
b6d96bed 12847 }
5a5012ec
TS
12848 break;
12849 case OPC_MSUB_S:
b8aa4598 12850 check_cop1x(ctx);
b6d96bed 12851 {
a7812ae4
PB
12852 TCGv_i32 fp0 = tcg_temp_new_i32();
12853 TCGv_i32 fp1 = tcg_temp_new_i32();
12854 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12855
7c979afd
LA
12856 gen_load_fpr32(ctx, fp0, fs);
12857 gen_load_fpr32(ctx, fp1, ft);
12858 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12859 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12860 tcg_temp_free_i32(fp0);
12861 tcg_temp_free_i32(fp1);
7c979afd 12862 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12863 tcg_temp_free_i32(fp2);
b6d96bed 12864 }
5a5012ec
TS
12865 break;
12866 case OPC_MSUB_D:
b8aa4598
TS
12867 check_cop1x(ctx);
12868 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12869 {
a7812ae4
PB
12870 TCGv_i64 fp0 = tcg_temp_new_i64();
12871 TCGv_i64 fp1 = tcg_temp_new_i64();
12872 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12873
12874 gen_load_fpr64(ctx, fp0, fs);
12875 gen_load_fpr64(ctx, fp1, ft);
12876 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12877 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12878 tcg_temp_free_i64(fp0);
12879 tcg_temp_free_i64(fp1);
b6d96bed 12880 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12881 tcg_temp_free_i64(fp2);
b6d96bed 12882 }
5a5012ec
TS
12883 break;
12884 case OPC_MSUB_PS:
e29c9628 12885 check_ps(ctx);
b6d96bed 12886 {
a7812ae4
PB
12887 TCGv_i64 fp0 = tcg_temp_new_i64();
12888 TCGv_i64 fp1 = tcg_temp_new_i64();
12889 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12890
12891 gen_load_fpr64(ctx, fp0, fs);
12892 gen_load_fpr64(ctx, fp1, ft);
12893 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12894 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12895 tcg_temp_free_i64(fp0);
12896 tcg_temp_free_i64(fp1);
b6d96bed 12897 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12898 tcg_temp_free_i64(fp2);
b6d96bed 12899 }
5a5012ec
TS
12900 break;
12901 case OPC_NMADD_S:
b8aa4598 12902 check_cop1x(ctx);
b6d96bed 12903 {
a7812ae4
PB
12904 TCGv_i32 fp0 = tcg_temp_new_i32();
12905 TCGv_i32 fp1 = tcg_temp_new_i32();
12906 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12907
7c979afd
LA
12908 gen_load_fpr32(ctx, fp0, fs);
12909 gen_load_fpr32(ctx, fp1, ft);
12910 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12911 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12912 tcg_temp_free_i32(fp0);
12913 tcg_temp_free_i32(fp1);
7c979afd 12914 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12915 tcg_temp_free_i32(fp2);
b6d96bed 12916 }
5a5012ec
TS
12917 break;
12918 case OPC_NMADD_D:
b8aa4598
TS
12919 check_cop1x(ctx);
12920 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12921 {
a7812ae4
PB
12922 TCGv_i64 fp0 = tcg_temp_new_i64();
12923 TCGv_i64 fp1 = tcg_temp_new_i64();
12924 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12925
12926 gen_load_fpr64(ctx, fp0, fs);
12927 gen_load_fpr64(ctx, fp1, ft);
12928 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12929 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12930 tcg_temp_free_i64(fp0);
12931 tcg_temp_free_i64(fp1);
b6d96bed 12932 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12933 tcg_temp_free_i64(fp2);
b6d96bed 12934 }
5a5012ec
TS
12935 break;
12936 case OPC_NMADD_PS:
e29c9628 12937 check_ps(ctx);
b6d96bed 12938 {
a7812ae4
PB
12939 TCGv_i64 fp0 = tcg_temp_new_i64();
12940 TCGv_i64 fp1 = tcg_temp_new_i64();
12941 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12942
12943 gen_load_fpr64(ctx, fp0, fs);
12944 gen_load_fpr64(ctx, fp1, ft);
12945 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12946 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12947 tcg_temp_free_i64(fp0);
12948 tcg_temp_free_i64(fp1);
b6d96bed 12949 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12950 tcg_temp_free_i64(fp2);
b6d96bed 12951 }
5a5012ec
TS
12952 break;
12953 case OPC_NMSUB_S:
b8aa4598 12954 check_cop1x(ctx);
b6d96bed 12955 {
a7812ae4
PB
12956 TCGv_i32 fp0 = tcg_temp_new_i32();
12957 TCGv_i32 fp1 = tcg_temp_new_i32();
12958 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12959
7c979afd
LA
12960 gen_load_fpr32(ctx, fp0, fs);
12961 gen_load_fpr32(ctx, fp1, ft);
12962 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12963 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12964 tcg_temp_free_i32(fp0);
12965 tcg_temp_free_i32(fp1);
7c979afd 12966 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12967 tcg_temp_free_i32(fp2);
b6d96bed 12968 }
5a5012ec
TS
12969 break;
12970 case OPC_NMSUB_D:
b8aa4598
TS
12971 check_cop1x(ctx);
12972 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12973 {
a7812ae4
PB
12974 TCGv_i64 fp0 = tcg_temp_new_i64();
12975 TCGv_i64 fp1 = tcg_temp_new_i64();
12976 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12977
12978 gen_load_fpr64(ctx, fp0, fs);
12979 gen_load_fpr64(ctx, fp1, ft);
12980 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12981 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12982 tcg_temp_free_i64(fp0);
12983 tcg_temp_free_i64(fp1);
b6d96bed 12984 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12985 tcg_temp_free_i64(fp2);
b6d96bed 12986 }
5a5012ec
TS
12987 break;
12988 case OPC_NMSUB_PS:
e29c9628 12989 check_ps(ctx);
b6d96bed 12990 {
a7812ae4
PB
12991 TCGv_i64 fp0 = tcg_temp_new_i64();
12992 TCGv_i64 fp1 = tcg_temp_new_i64();
12993 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12994
12995 gen_load_fpr64(ctx, fp0, fs);
12996 gen_load_fpr64(ctx, fp1, ft);
12997 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12998 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12999 tcg_temp_free_i64(fp0);
13000 tcg_temp_free_i64(fp1);
b6d96bed 13001 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13002 tcg_temp_free_i64(fp2);
b6d96bed 13003 }
5a5012ec 13004 break;
923617a3 13005 default:
9d68ac14 13006 MIPS_INVAL("flt3_arith");
9c708c7f 13007 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
13008 return;
13009 }
7a387fff
TS
13010}
13011
b00c7218 13012static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
13013{
13014 TCGv t0;
13015
b3167288 13016#if !defined(CONFIG_USER_ONLY)
7480515f
AM
13017 /*
13018 * The Linux kernel will emulate rdhwr if it's not supported natively.
13019 * Therefore only check the ISA in system mode.
13020 */
d75c135e 13021 check_insn(ctx, ISA_MIPS32R2);
b3167288 13022#endif
26ebe468
NF
13023 t0 = tcg_temp_new();
13024
13025 switch (rd) {
13026 case 0:
895c2d04 13027 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
13028 gen_store_gpr(t0, rt);
13029 break;
13030 case 1:
895c2d04 13031 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
13032 gen_store_gpr(t0, rt);
13033 break;
13034 case 2:
eeb3bba8 13035 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
13036 gen_io_start();
13037 }
895c2d04 13038 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 13039 gen_store_gpr(t0, rt);
7480515f
AM
13040 /*
13041 * Break the TB to be able to take timer interrupts immediately
13042 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13043 * we break completely out of translated code.
13044 */
eeb3bba8
EC
13045 gen_save_pc(ctx->base.pc_next + 4);
13046 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
13047 break;
13048 case 3:
895c2d04 13049 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
13050 gen_store_gpr(t0, rt);
13051 break;
b00c7218
YK
13052 case 4:
13053 check_insn(ctx, ISA_MIPS32R6);
13054 if (sel != 0) {
7480515f
AM
13055 /*
13056 * Performance counter registers are not implemented other than
b00c7218
YK
13057 * control register 0.
13058 */
13059 generate_exception(ctx, EXCP_RI);
13060 }
13061 gen_helper_rdhwr_performance(t0, cpu_env);
13062 gen_store_gpr(t0, rt);
13063 break;
13064 case 5:
13065 check_insn(ctx, ISA_MIPS32R6);
13066 gen_helper_rdhwr_xnp(t0, cpu_env);
13067 gen_store_gpr(t0, rt);
13068 break;
26ebe468
NF
13069 case 29:
13070#if defined(CONFIG_USER_ONLY)
d279279e
PJ
13071 tcg_gen_ld_tl(t0, cpu_env,
13072 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
13073 gen_store_gpr(t0, rt);
13074 break;
13075#else
d279279e
PJ
13076 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13077 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13078 tcg_gen_ld_tl(t0, cpu_env,
13079 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13080 gen_store_gpr(t0, rt);
13081 } else {
9c708c7f 13082 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
13083 }
13084 break;
26ebe468
NF
13085#endif
13086 default: /* Invalid */
13087 MIPS_INVAL("rdhwr");
9c708c7f 13088 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
13089 break;
13090 }
13091 tcg_temp_free(t0);
13092}
13093
a5f53390
LA
13094static inline void clear_branch_hflags(DisasContext *ctx)
13095{
13096 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 13097 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
13098 save_cpu_state(ctx, 0);
13099 } else {
7480515f
AM
13100 /*
13101 * It is not safe to save ctx->hflags as hflags may be changed
13102 * in execution time by the instruction in delay / forbidden slot.
13103 */
a5f53390
LA
13104 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13105 }
13106}
13107
31837be3 13108static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
13109{
13110 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 13111 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 13112 /* Branches completion */
a5f53390 13113 clear_branch_hflags(ctx);
eeb3bba8 13114 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 13115 /* FIXME: Need to clear can_do_io. */
364d4831 13116 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 13117 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 13118 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 13119 break;
c9602061
NF
13120 case MIPS_HFLAG_B:
13121 /* unconditional branch */
364d4831
NF
13122 if (proc_hflags & MIPS_HFLAG_BX) {
13123 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13124 }
c9602061
NF
13125 gen_goto_tb(ctx, 0, ctx->btarget);
13126 break;
13127 case MIPS_HFLAG_BL:
13128 /* blikely taken case */
c9602061
NF
13129 gen_goto_tb(ctx, 0, ctx->btarget);
13130 break;
13131 case MIPS_HFLAG_BC:
13132 /* Conditional branch */
c9602061 13133 {
42a268c2 13134 TCGLabel *l1 = gen_new_label();
c9602061
NF
13135
13136 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 13137 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
13138 gen_set_label(l1);
13139 gen_goto_tb(ctx, 0, ctx->btarget);
13140 }
13141 break;
13142 case MIPS_HFLAG_BR:
13143 /* unconditional branch to register */
d75c135e 13144 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
13145 TCGv t0 = tcg_temp_new();
13146 TCGv_i32 t1 = tcg_temp_new_i32();
13147
13148 tcg_gen_andi_tl(t0, btarget, 0x1);
13149 tcg_gen_trunc_tl_i32(t1, t0);
13150 tcg_temp_free(t0);
13151 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13152 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13153 tcg_gen_or_i32(hflags, hflags, t1);
13154 tcg_temp_free_i32(t1);
13155
13156 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13157 } else {
13158 tcg_gen_mov_tl(cpu_PC, btarget);
13159 }
eeb3bba8 13160 if (ctx->base.singlestep_enabled) {
c9602061 13161 save_cpu_state(ctx, 0);
9c708c7f 13162 gen_helper_raise_exception_debug(cpu_env);
c9602061 13163 }
7f11636d 13164 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
13165 break;
13166 default:
a5f53390
LA
13167 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13168 abort();
c9602061
NF
13169 }
13170 }
13171}
13172
6893f074
YK
13173/* Compact Branches */
13174static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13175 int rs, int rt, int32_t offset)
13176{
13177 int bcond_compute = 0;
13178 TCGv t0 = tcg_temp_new();
13179 TCGv t1 = tcg_temp_new();
65935f07 13180 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
13181
13182 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13183#ifdef MIPS_DEBUG_DISAS
13184 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 13185 "\n", ctx->base.pc_next);
6893f074 13186#endif
9c708c7f 13187 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13188 goto out;
13189 }
13190
13191 /* Load needed operands and calculate btarget */
13192 switch (opc) {
13193 /* compact branch */
13194 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13195 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13196 gen_load_gpr(t0, rs);
13197 gen_load_gpr(t1, rt);
13198 bcond_compute = 1;
eeb3bba8 13199 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13200 if (rs <= rt && rs == 0) {
13201 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 13202 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13203 }
13204 break;
13205 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13206 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13207 gen_load_gpr(t0, rs);
13208 gen_load_gpr(t1, rt);
13209 bcond_compute = 1;
eeb3bba8 13210 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13211 break;
13212 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13213 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13214 if (rs == 0 || rs == rt) {
13215 /* OPC_BLEZALC, OPC_BGEZALC */
13216 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 13217 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13218 }
13219 gen_load_gpr(t0, rs);
13220 gen_load_gpr(t1, rt);
13221 bcond_compute = 1;
eeb3bba8 13222 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13223 break;
13224 case OPC_BC:
13225 case OPC_BALC:
eeb3bba8 13226 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13227 break;
13228 case OPC_BEQZC:
13229 case OPC_BNEZC:
13230 if (rs != 0) {
13231 /* OPC_BEQZC, OPC_BNEZC */
13232 gen_load_gpr(t0, rs);
13233 bcond_compute = 1;
eeb3bba8 13234 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13235 } else {
13236 /* OPC_JIC, OPC_JIALC */
13237 TCGv tbase = tcg_temp_new();
13238 TCGv toffset = tcg_temp_new();
13239
13240 gen_load_gpr(tbase, rt);
13241 tcg_gen_movi_tl(toffset, offset);
13242 gen_op_addr_add(ctx, btarget, tbase, toffset);
13243 tcg_temp_free(tbase);
13244 tcg_temp_free(toffset);
13245 }
13246 break;
13247 default:
13248 MIPS_INVAL("Compact branch/jump");
9c708c7f 13249 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13250 goto out;
13251 }
13252
13253 if (bcond_compute == 0) {
13254 /* Uncoditional compact branch */
13255 switch (opc) {
13256 case OPC_JIALC:
eeb3bba8 13257 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13258 /* Fallthrough */
13259 case OPC_JIC:
13260 ctx->hflags |= MIPS_HFLAG_BR;
13261 break;
13262 case OPC_BALC:
eeb3bba8 13263 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13264 /* Fallthrough */
13265 case OPC_BC:
13266 ctx->hflags |= MIPS_HFLAG_B;
13267 break;
13268 default:
13269 MIPS_INVAL("Compact branch/jump");
9c708c7f 13270 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13271 goto out;
13272 }
13273
13274 /* Generating branch here as compact branches don't have delay slot */
13275 gen_branch(ctx, 4);
13276 } else {
13277 /* Conditional compact branch */
13278 TCGLabel *fs = gen_new_label();
13279 save_cpu_state(ctx, 0);
13280
13281 switch (opc) {
13282 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13283 if (rs == 0 && rt != 0) {
13284 /* OPC_BLEZALC */
13285 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13286 } else if (rs != 0 && rt != 0 && rs == rt) {
13287 /* OPC_BGEZALC */
13288 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13289 } else {
13290 /* OPC_BGEUC */
13291 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13292 }
13293 break;
13294 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13295 if (rs == 0 && rt != 0) {
13296 /* OPC_BGTZALC */
13297 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13298 } else if (rs != 0 && rt != 0 && rs == rt) {
13299 /* OPC_BLTZALC */
13300 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13301 } else {
13302 /* OPC_BLTUC */
13303 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13304 }
13305 break;
13306 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13307 if (rs == 0 && rt != 0) {
13308 /* OPC_BLEZC */
13309 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13310 } else if (rs != 0 && rt != 0 && rs == rt) {
13311 /* OPC_BGEZC */
13312 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13313 } else {
13314 /* OPC_BGEC */
13315 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13316 }
13317 break;
13318 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13319 if (rs == 0 && rt != 0) {
13320 /* OPC_BGTZC */
13321 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13322 } else if (rs != 0 && rt != 0 && rs == rt) {
13323 /* OPC_BLTZC */
13324 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13325 } else {
13326 /* OPC_BLTC */
13327 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13328 }
13329 break;
13330 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13331 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13332 if (rs >= rt) {
13333 /* OPC_BOVC, OPC_BNVC */
13334 TCGv t2 = tcg_temp_new();
13335 TCGv t3 = tcg_temp_new();
13336 TCGv t4 = tcg_temp_new();
13337 TCGv input_overflow = tcg_temp_new();
13338
13339 gen_load_gpr(t0, rs);
13340 gen_load_gpr(t1, rt);
13341 tcg_gen_ext32s_tl(t2, t0);
13342 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13343 tcg_gen_ext32s_tl(t3, t1);
13344 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13345 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13346
13347 tcg_gen_add_tl(t4, t2, t3);
13348 tcg_gen_ext32s_tl(t4, t4);
13349 tcg_gen_xor_tl(t2, t2, t3);
13350 tcg_gen_xor_tl(t3, t4, t3);
13351 tcg_gen_andc_tl(t2, t3, t2);
13352 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13353 tcg_gen_or_tl(t4, t4, input_overflow);
13354 if (opc == OPC_BOVC) {
13355 /* OPC_BOVC */
13356 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13357 } else {
13358 /* OPC_BNVC */
13359 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13360 }
13361 tcg_temp_free(input_overflow);
13362 tcg_temp_free(t4);
13363 tcg_temp_free(t3);
13364 tcg_temp_free(t2);
13365 } else if (rs < rt && rs == 0) {
13366 /* OPC_BEQZALC, OPC_BNEZALC */
13367 if (opc == OPC_BEQZALC) {
13368 /* OPC_BEQZALC */
13369 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13370 } else {
13371 /* OPC_BNEZALC */
13372 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13373 }
13374 } else {
13375 /* OPC_BEQC, OPC_BNEC */
13376 if (opc == OPC_BEQC) {
13377 /* OPC_BEQC */
13378 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13379 } else {
13380 /* OPC_BNEC */
13381 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13382 }
13383 }
13384 break;
13385 case OPC_BEQZC:
13386 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13387 break;
13388 case OPC_BNEZC:
13389 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13390 break;
13391 default:
13392 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13393 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13394 goto out;
13395 }
13396
13397 /* Generating branch here as compact branches don't have delay slot */
13398 gen_goto_tb(ctx, 1, ctx->btarget);
13399 gen_set_label(fs);
13400
13401 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13402 }
13403
13404out:
13405 tcg_temp_free(t0);
13406 tcg_temp_free(t1);
13407}
13408
7a387fff 13409/* ISA extensions (ASEs) */
6af0bf9c 13410/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13411
13412/* MIPS16 major opcodes */
13413enum {
13414 M16_OPC_ADDIUSP = 0x00,
13415 M16_OPC_ADDIUPC = 0x01,
13416 M16_OPC_B = 0x02,
13417 M16_OPC_JAL = 0x03,
13418 M16_OPC_BEQZ = 0x04,
13419 M16_OPC_BNEQZ = 0x05,
13420 M16_OPC_SHIFT = 0x06,
13421 M16_OPC_LD = 0x07,
13422 M16_OPC_RRIA = 0x08,
13423 M16_OPC_ADDIU8 = 0x09,
13424 M16_OPC_SLTI = 0x0a,
13425 M16_OPC_SLTIU = 0x0b,
13426 M16_OPC_I8 = 0x0c,
13427 M16_OPC_LI = 0x0d,
13428 M16_OPC_CMPI = 0x0e,
13429 M16_OPC_SD = 0x0f,
13430 M16_OPC_LB = 0x10,
13431 M16_OPC_LH = 0x11,
13432 M16_OPC_LWSP = 0x12,
13433 M16_OPC_LW = 0x13,
13434 M16_OPC_LBU = 0x14,
13435 M16_OPC_LHU = 0x15,
13436 M16_OPC_LWPC = 0x16,
13437 M16_OPC_LWU = 0x17,
13438 M16_OPC_SB = 0x18,
13439 M16_OPC_SH = 0x19,
13440 M16_OPC_SWSP = 0x1a,
13441 M16_OPC_SW = 0x1b,
13442 M16_OPC_RRR = 0x1c,
13443 M16_OPC_RR = 0x1d,
13444 M16_OPC_EXTEND = 0x1e,
13445 M16_OPC_I64 = 0x1f
13446};
13447
13448/* I8 funct field */
13449enum {
13450 I8_BTEQZ = 0x0,
13451 I8_BTNEZ = 0x1,
13452 I8_SWRASP = 0x2,
13453 I8_ADJSP = 0x3,
13454 I8_SVRS = 0x4,
13455 I8_MOV32R = 0x5,
13456 I8_MOVR32 = 0x7
13457};
13458
13459/* RRR f field */
13460enum {
13461 RRR_DADDU = 0x0,
13462 RRR_ADDU = 0x1,
13463 RRR_DSUBU = 0x2,
13464 RRR_SUBU = 0x3
13465};
13466
13467/* RR funct field */
13468enum {
13469 RR_JR = 0x00,
13470 RR_SDBBP = 0x01,
13471 RR_SLT = 0x02,
13472 RR_SLTU = 0x03,
13473 RR_SLLV = 0x04,
13474 RR_BREAK = 0x05,
13475 RR_SRLV = 0x06,
13476 RR_SRAV = 0x07,
13477 RR_DSRL = 0x08,
13478 RR_CMP = 0x0a,
13479 RR_NEG = 0x0b,
13480 RR_AND = 0x0c,
13481 RR_OR = 0x0d,
13482 RR_XOR = 0x0e,
13483 RR_NOT = 0x0f,
13484 RR_MFHI = 0x10,
13485 RR_CNVT = 0x11,
13486 RR_MFLO = 0x12,
13487 RR_DSRA = 0x13,
13488 RR_DSLLV = 0x14,
13489 RR_DSRLV = 0x16,
13490 RR_DSRAV = 0x17,
13491 RR_MULT = 0x18,
13492 RR_MULTU = 0x19,
13493 RR_DIV = 0x1a,
13494 RR_DIVU = 0x1b,
13495 RR_DMULT = 0x1c,
13496 RR_DMULTU = 0x1d,
13497 RR_DDIV = 0x1e,
13498 RR_DDIVU = 0x1f
13499};
13500
13501/* I64 funct field */
13502enum {
13503 I64_LDSP = 0x0,
13504 I64_SDSP = 0x1,
13505 I64_SDRASP = 0x2,
13506 I64_DADJSP = 0x3,
13507 I64_LDPC = 0x4,
364d4831 13508 I64_DADDIU5 = 0x5,
6ea219d0
NF
13509 I64_DADDIUPC = 0x6,
13510 I64_DADDIUSP = 0x7
13511};
13512
13513/* RR ry field for CNVT */
13514enum {
13515 RR_RY_CNVT_ZEB = 0x0,
13516 RR_RY_CNVT_ZEH = 0x1,
13517 RR_RY_CNVT_ZEW = 0x2,
13518 RR_RY_CNVT_SEB = 0x4,
13519 RR_RY_CNVT_SEH = 0x5,
13520 RR_RY_CNVT_SEW = 0x6,
13521};
13522
235785e8 13523static int xlat(int r)
364d4831
NF
13524{
13525 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13526
13527 return map[r];
13528}
13529
235785e8
AM
13530static void gen_mips16_save(DisasContext *ctx,
13531 int xsregs, int aregs,
13532 int do_ra, int do_s0, int do_s1,
13533 int framesize)
364d4831
NF
13534{
13535 TCGv t0 = tcg_temp_new();
13536 TCGv t1 = tcg_temp_new();
c48245f0 13537 TCGv t2 = tcg_temp_new();
364d4831
NF
13538 int args, astatic;
13539
13540 switch (aregs) {
13541 case 0:
13542 case 1:
13543 case 2:
13544 case 3:
13545 case 11:
13546 args = 0;
13547 break;
13548 case 4:
13549 case 5:
13550 case 6:
13551 case 7:
13552 args = 1;
13553 break;
13554 case 8:
13555 case 9:
13556 case 10:
13557 args = 2;
13558 break;
13559 case 12:
13560 case 13:
13561 args = 3;
13562 break;
13563 case 14:
13564 args = 4;
13565 break;
13566 default:
9c708c7f 13567 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13568 return;
13569 }
13570
13571 switch (args) {
13572 case 4:
13573 gen_base_offset_addr(ctx, t0, 29, 12);
13574 gen_load_gpr(t1, 7);
5f68f5ae 13575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13576 /* Fall through */
13577 case 3:
13578 gen_base_offset_addr(ctx, t0, 29, 8);
13579 gen_load_gpr(t1, 6);
5f68f5ae 13580 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13581 /* Fall through */
13582 case 2:
13583 gen_base_offset_addr(ctx, t0, 29, 4);
13584 gen_load_gpr(t1, 5);
5f68f5ae 13585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13586 /* Fall through */
13587 case 1:
13588 gen_base_offset_addr(ctx, t0, 29, 0);
13589 gen_load_gpr(t1, 4);
5f68f5ae 13590 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13591 }
13592
13593 gen_load_gpr(t0, 29);
13594
5f68f5ae 13595#define DECR_AND_STORE(reg) do { \
c48245f0
MR
13596 tcg_gen_movi_tl(t2, -4); \
13597 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13598 gen_load_gpr(t1, reg); \
13599 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
13600 } while (0)
13601
13602 if (do_ra) {
13603 DECR_AND_STORE(31);
13604 }
13605
13606 switch (xsregs) {
13607 case 7:
13608 DECR_AND_STORE(30);
13609 /* Fall through */
13610 case 6:
13611 DECR_AND_STORE(23);
13612 /* Fall through */
13613 case 5:
13614 DECR_AND_STORE(22);
13615 /* Fall through */
13616 case 4:
13617 DECR_AND_STORE(21);
13618 /* Fall through */
13619 case 3:
13620 DECR_AND_STORE(20);
13621 /* Fall through */
13622 case 2:
13623 DECR_AND_STORE(19);
13624 /* Fall through */
13625 case 1:
13626 DECR_AND_STORE(18);
13627 }
13628
13629 if (do_s1) {
13630 DECR_AND_STORE(17);
13631 }
13632 if (do_s0) {
13633 DECR_AND_STORE(16);
13634 }
13635
13636 switch (aregs) {
13637 case 0:
13638 case 4:
13639 case 8:
13640 case 12:
13641 case 14:
13642 astatic = 0;
13643 break;
13644 case 1:
13645 case 5:
13646 case 9:
13647 case 13:
13648 astatic = 1;
13649 break;
13650 case 2:
13651 case 6:
13652 case 10:
13653 astatic = 2;
13654 break;
13655 case 3:
13656 case 7:
13657 astatic = 3;
13658 break;
13659 case 11:
13660 astatic = 4;
13661 break;
13662 default:
9c708c7f 13663 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13664 return;
13665 }
13666
13667 if (astatic > 0) {
13668 DECR_AND_STORE(7);
13669 if (astatic > 1) {
13670 DECR_AND_STORE(6);
13671 if (astatic > 2) {
13672 DECR_AND_STORE(5);
13673 if (astatic > 3) {
13674 DECR_AND_STORE(4);
13675 }
13676 }
13677 }
13678 }
13679#undef DECR_AND_STORE
13680
c48245f0
MR
13681 tcg_gen_movi_tl(t2, -framesize);
13682 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13683 tcg_temp_free(t0);
13684 tcg_temp_free(t1);
c48245f0 13685 tcg_temp_free(t2);
364d4831
NF
13686}
13687
235785e8
AM
13688static void gen_mips16_restore(DisasContext *ctx,
13689 int xsregs, int aregs,
13690 int do_ra, int do_s0, int do_s1,
13691 int framesize)
364d4831
NF
13692{
13693 int astatic;
13694 TCGv t0 = tcg_temp_new();
13695 TCGv t1 = tcg_temp_new();
c48245f0 13696 TCGv t2 = tcg_temp_new();
364d4831 13697
c48245f0
MR
13698 tcg_gen_movi_tl(t2, framesize);
13699 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13700
5f68f5ae 13701#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13702 tcg_gen_movi_tl(t2, -4); \
13703 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13704 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13705 gen_store_gpr(t1, reg); \
364d4831
NF
13706 } while (0)
13707
13708 if (do_ra) {
13709 DECR_AND_LOAD(31);
13710 }
13711
13712 switch (xsregs) {
13713 case 7:
13714 DECR_AND_LOAD(30);
13715 /* Fall through */
13716 case 6:
13717 DECR_AND_LOAD(23);
13718 /* Fall through */
13719 case 5:
13720 DECR_AND_LOAD(22);
13721 /* Fall through */
13722 case 4:
13723 DECR_AND_LOAD(21);
13724 /* Fall through */
13725 case 3:
13726 DECR_AND_LOAD(20);
13727 /* Fall through */
13728 case 2:
13729 DECR_AND_LOAD(19);
13730 /* Fall through */
13731 case 1:
13732 DECR_AND_LOAD(18);
13733 }
13734
13735 if (do_s1) {
13736 DECR_AND_LOAD(17);
13737 }
13738 if (do_s0) {
13739 DECR_AND_LOAD(16);
13740 }
13741
13742 switch (aregs) {
13743 case 0:
13744 case 4:
13745 case 8:
13746 case 12:
13747 case 14:
13748 astatic = 0;
13749 break;
13750 case 1:
13751 case 5:
13752 case 9:
13753 case 13:
13754 astatic = 1;
13755 break;
13756 case 2:
13757 case 6:
13758 case 10:
13759 astatic = 2;
13760 break;
13761 case 3:
13762 case 7:
13763 astatic = 3;
13764 break;
13765 case 11:
13766 astatic = 4;
13767 break;
13768 default:
9c708c7f 13769 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13770 return;
13771 }
13772
13773 if (astatic > 0) {
13774 DECR_AND_LOAD(7);
13775 if (astatic > 1) {
13776 DECR_AND_LOAD(6);
13777 if (astatic > 2) {
13778 DECR_AND_LOAD(5);
13779 if (astatic > 3) {
13780 DECR_AND_LOAD(4);
13781 }
13782 }
13783 }
13784 }
13785#undef DECR_AND_LOAD
13786
c48245f0
MR
13787 tcg_gen_movi_tl(t2, framesize);
13788 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13789 tcg_temp_free(t0);
13790 tcg_temp_free(t1);
c48245f0 13791 tcg_temp_free(t2);
364d4831
NF
13792}
13793
235785e8
AM
13794static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13795 int is_64_bit, int extended)
364d4831
NF
13796{
13797 TCGv t0;
13798
13799 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13800 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13801 return;
13802 }
13803
13804 t0 = tcg_temp_new();
13805
13806 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13807 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13808 if (!is_64_bit) {
13809 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13810 }
13811
13812 tcg_temp_free(t0);
13813}
13814
0d74a222
LA
13815static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13816 int16_t offset)
13817{
13818 TCGv_i32 t0 = tcg_const_i32(op);
13819 TCGv t1 = tcg_temp_new();
13820 gen_base_offset_addr(ctx, t1, base, offset);
13821 gen_helper_cache(cpu_env, t1, t0);
13822}
13823
364d4831 13824#if defined(TARGET_MIPS64)
235785e8
AM
13825static void decode_i64_mips16(DisasContext *ctx,
13826 int ry, int funct, int16_t offset,
13827 int extended)
364d4831
NF
13828{
13829 switch (funct) {
13830 case I64_LDSP:
d9224450 13831 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13832 check_mips_64(ctx);
13833 offset = extended ? offset : offset << 3;
d75c135e 13834 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13835 break;
13836 case I64_SDSP:
d9224450 13837 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13838 check_mips_64(ctx);
13839 offset = extended ? offset : offset << 3;
5c13fdfd 13840 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13841 break;
13842 case I64_SDRASP:
d9224450 13843 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13844 check_mips_64(ctx);
13845 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13846 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13847 break;
13848 case I64_DADJSP:
d9224450 13849 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13850 check_mips_64(ctx);
13851 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13852 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13853 break;
13854 case I64_LDPC:
d9224450
MR
13855 check_insn(ctx, ISA_MIPS3);
13856 check_mips_64(ctx);
364d4831 13857 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13858 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13859 } else {
13860 offset = extended ? offset : offset << 3;
d75c135e 13861 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13862 }
13863 break;
13864 case I64_DADDIU5:
d9224450 13865 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13866 check_mips_64(ctx);
13867 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13868 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13869 break;
13870 case I64_DADDIUPC:
d9224450 13871 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13872 check_mips_64(ctx);
13873 offset = extended ? offset : offset << 2;
13874 gen_addiupc(ctx, ry, offset, 1, extended);
13875 break;
13876 case I64_DADDIUSP:
d9224450 13877 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13878 check_mips_64(ctx);
13879 offset = extended ? offset : offset << 2;
d75c135e 13880 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13881 break;
13882 }
13883}
13884#endif
13885
235785e8 13886static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 13887{
eeb3bba8 13888 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13889 int op, rx, ry, funct, sa;
13890 int16_t imm, offset;
13891
13892 ctx->opcode = (ctx->opcode << 16) | extend;
13893 op = (ctx->opcode >> 11) & 0x1f;
13894 sa = (ctx->opcode >> 22) & 0x1f;
13895 funct = (ctx->opcode >> 8) & 0x7;
13896 rx = xlat((ctx->opcode >> 8) & 0x7);
13897 ry = xlat((ctx->opcode >> 5) & 0x7);
13898 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13899 | ((ctx->opcode >> 21) & 0x3f) << 5
13900 | (ctx->opcode & 0x1f));
13901
7480515f
AM
13902 /*
13903 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13904 * counterparts.
13905 */
364d4831
NF
13906 switch (op) {
13907 case M16_OPC_ADDIUSP:
d75c135e 13908 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13909 break;
13910 case M16_OPC_ADDIUPC:
13911 gen_addiupc(ctx, rx, imm, 0, 1);
13912 break;
13913 case M16_OPC_B:
b231c103 13914 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13915 /* No delay slot, so just process as a normal instruction */
13916 break;
13917 case M16_OPC_BEQZ:
b231c103 13918 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13919 /* No delay slot, so just process as a normal instruction */
13920 break;
13921 case M16_OPC_BNEQZ:
b231c103 13922 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13923 /* No delay slot, so just process as a normal instruction */
13924 break;
13925 case M16_OPC_SHIFT:
13926 switch (ctx->opcode & 0x3) {
13927 case 0x0:
d75c135e 13928 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13929 break;
13930 case 0x1:
13931#if defined(TARGET_MIPS64)
13932 check_mips_64(ctx);
d75c135e 13933 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13934#else
9c708c7f 13935 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13936#endif
13937 break;
13938 case 0x2:
d75c135e 13939 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13940 break;
13941 case 0x3:
d75c135e 13942 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13943 break;
13944 }
13945 break;
13946#if defined(TARGET_MIPS64)
13947 case M16_OPC_LD:
d9224450 13948 check_insn(ctx, ISA_MIPS3);
d75de749 13949 check_mips_64(ctx);
d75c135e 13950 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13951 break;
13952#endif
13953 case M16_OPC_RRIA:
13954 imm = ctx->opcode & 0xf;
13955 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13956 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13957 imm = (int16_t) (imm << 1) >> 1;
13958 if ((ctx->opcode >> 4) & 0x1) {
13959#if defined(TARGET_MIPS64)
13960 check_mips_64(ctx);
d75c135e 13961 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13962#else
9c708c7f 13963 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13964#endif
13965 } else {
d75c135e 13966 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13967 }
13968 break;
13969 case M16_OPC_ADDIU8:
d75c135e 13970 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13971 break;
13972 case M16_OPC_SLTI:
d75c135e 13973 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13974 break;
13975 case M16_OPC_SLTIU:
d75c135e 13976 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13977 break;
13978 case M16_OPC_I8:
13979 switch (funct) {
13980 case I8_BTEQZ:
b231c103 13981 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13982 break;
13983 case I8_BTNEZ:
b231c103 13984 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13985 break;
13986 case I8_SWRASP:
5c13fdfd 13987 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13988 break;
13989 case I8_ADJSP:
d75c135e 13990 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13991 break;
13992 case I8_SVRS:
d9224450 13993 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13994 {
13995 int xsregs = (ctx->opcode >> 24) & 0x7;
13996 int aregs = (ctx->opcode >> 16) & 0xf;
13997 int do_ra = (ctx->opcode >> 6) & 0x1;
13998 int do_s0 = (ctx->opcode >> 5) & 0x1;
13999 int do_s1 = (ctx->opcode >> 4) & 0x1;
14000 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14001 | (ctx->opcode & 0xf)) << 3;
14002
14003 if (ctx->opcode & (1 << 7)) {
14004 gen_mips16_save(ctx, xsregs, aregs,
14005 do_ra, do_s0, do_s1,
14006 framesize);
14007 } else {
14008 gen_mips16_restore(ctx, xsregs, aregs,
14009 do_ra, do_s0, do_s1,
14010 framesize);
14011 }
14012 }
14013 break;
14014 default:
9c708c7f 14015 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14016 break;
14017 }
14018 break;
14019 case M16_OPC_LI:
14020 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14021 break;
14022 case M16_OPC_CMPI:
14023 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14024 break;
14025#if defined(TARGET_MIPS64)
14026 case M16_OPC_SD:
d9224450
MR
14027 check_insn(ctx, ISA_MIPS3);
14028 check_mips_64(ctx);
5c13fdfd 14029 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
14030 break;
14031#endif
14032 case M16_OPC_LB:
d75c135e 14033 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14034 break;
14035 case M16_OPC_LH:
d75c135e 14036 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
14037 break;
14038 case M16_OPC_LWSP:
d75c135e 14039 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
14040 break;
14041 case M16_OPC_LW:
d75c135e 14042 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
14043 break;
14044 case M16_OPC_LBU:
d75c135e 14045 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14046 break;
14047 case M16_OPC_LHU:
d75c135e 14048 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
14049 break;
14050 case M16_OPC_LWPC:
d75c135e 14051 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
14052 break;
14053#if defined(TARGET_MIPS64)
14054 case M16_OPC_LWU:
d9224450
MR
14055 check_insn(ctx, ISA_MIPS3);
14056 check_mips_64(ctx);
d75c135e 14057 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
14058 break;
14059#endif
14060 case M16_OPC_SB:
5c13fdfd 14061 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14062 break;
14063 case M16_OPC_SH:
5c13fdfd 14064 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
14065 break;
14066 case M16_OPC_SWSP:
5c13fdfd 14067 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
14068 break;
14069 case M16_OPC_SW:
5c13fdfd 14070 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
14071 break;
14072#if defined(TARGET_MIPS64)
14073 case M16_OPC_I64:
d75c135e 14074 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
14075 break;
14076#endif
14077 default:
9c708c7f 14078 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14079 break;
14080 }
14081
14082 return 4;
14083}
14084
3b3c1694
LA
14085static inline bool is_uhi(int sdbbp_code)
14086{
14087#ifdef CONFIG_USER_ONLY
14088 return false;
14089#else
14090 return semihosting_enabled() && sdbbp_code == 1;
14091#endif
14092}
14093
82ba4266
AB
14094#ifdef CONFIG_USER_ONLY
14095/* The above should dead-code away any calls to this..*/
14096static inline void gen_helper_do_semihosting(void *env)
14097{
14098 g_assert_not_reached();
14099}
14100#endif
14101
235785e8 14102static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
14103{
14104 int rx, ry;
14105 int sa;
14106 int op, cnvt_op, op1, offset;
14107 int funct;
14108 int n_bytes;
14109
14110 op = (ctx->opcode >> 11) & 0x1f;
14111 sa = (ctx->opcode >> 2) & 0x7;
14112 sa = sa == 0 ? 8 : sa;
14113 rx = xlat((ctx->opcode >> 8) & 0x7);
14114 cnvt_op = (ctx->opcode >> 5) & 0x7;
14115 ry = xlat((ctx->opcode >> 5) & 0x7);
14116 op1 = offset = ctx->opcode & 0x1f;
14117
14118 n_bytes = 2;
14119
14120 switch (op) {
14121 case M16_OPC_ADDIUSP:
14122 {
14123 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14124
d75c135e 14125 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
14126 }
14127 break;
14128 case M16_OPC_ADDIUPC:
14129 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14130 break;
14131 case M16_OPC_B:
14132 offset = (ctx->opcode & 0x7ff) << 1;
14133 offset = (int16_t)(offset << 4) >> 4;
b231c103 14134 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
14135 /* No delay slot, so just process as a normal instruction */
14136 break;
14137 case M16_OPC_JAL:
eeb3bba8 14138 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
14139 offset = (((ctx->opcode & 0x1f) << 21)
14140 | ((ctx->opcode >> 5) & 0x1f) << 16
14141 | offset) << 2;
b231c103
YK
14142 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14143 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 14144 n_bytes = 4;
364d4831
NF
14145 break;
14146 case M16_OPC_BEQZ:
b231c103
YK
14147 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14148 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14149 /* No delay slot, so just process as a normal instruction */
14150 break;
14151 case M16_OPC_BNEQZ:
b231c103
YK
14152 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14153 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14154 /* No delay slot, so just process as a normal instruction */
14155 break;
14156 case M16_OPC_SHIFT:
14157 switch (ctx->opcode & 0x3) {
14158 case 0x0:
d75c135e 14159 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
14160 break;
14161 case 0x1:
14162#if defined(TARGET_MIPS64)
d9224450 14163 check_insn(ctx, ISA_MIPS3);
364d4831 14164 check_mips_64(ctx);
d75c135e 14165 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 14166#else
9c708c7f 14167 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14168#endif
14169 break;
14170 case 0x2:
d75c135e 14171 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
14172 break;
14173 case 0x3:
d75c135e 14174 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
14175 break;
14176 }
14177 break;
14178#if defined(TARGET_MIPS64)
14179 case M16_OPC_LD:
d9224450 14180 check_insn(ctx, ISA_MIPS3);
364d4831 14181 check_mips_64(ctx);
d75c135e 14182 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
14183 break;
14184#endif
14185 case M16_OPC_RRIA:
14186 {
14187 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14188
14189 if ((ctx->opcode >> 4) & 1) {
14190#if defined(TARGET_MIPS64)
d9224450 14191 check_insn(ctx, ISA_MIPS3);
364d4831 14192 check_mips_64(ctx);
d75c135e 14193 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 14194#else
9c708c7f 14195 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14196#endif
14197 } else {
d75c135e 14198 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14199 }
14200 }
14201 break;
14202 case M16_OPC_ADDIU8:
14203 {
14204 int16_t imm = (int8_t) ctx->opcode;
14205
d75c135e 14206 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14207 }
14208 break;
14209 case M16_OPC_SLTI:
14210 {
14211 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14212 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14213 }
14214 break;
14215 case M16_OPC_SLTIU:
14216 {
14217 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14218 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14219 }
14220 break;
14221 case M16_OPC_I8:
14222 {
14223 int reg32;
14224
14225 funct = (ctx->opcode >> 8) & 0x7;
14226 switch (funct) {
14227 case I8_BTEQZ:
14228 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 14229 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14230 break;
14231 case I8_BTNEZ:
14232 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 14233 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14234 break;
14235 case I8_SWRASP:
5c13fdfd 14236 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
14237 break;
14238 case I8_ADJSP:
d75c135e 14239 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
14240 ((int8_t)ctx->opcode) << 3);
14241 break;
14242 case I8_SVRS:
d9224450 14243 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14244 {
14245 int do_ra = ctx->opcode & (1 << 6);
14246 int do_s0 = ctx->opcode & (1 << 5);
14247 int do_s1 = ctx->opcode & (1 << 4);
14248 int framesize = ctx->opcode & 0xf;
14249
14250 if (framesize == 0) {
14251 framesize = 128;
14252 } else {
14253 framesize = framesize << 3;
14254 }
14255
14256 if (ctx->opcode & (1 << 7)) {
14257 gen_mips16_save(ctx, 0, 0,
14258 do_ra, do_s0, do_s1, framesize);
14259 } else {
14260 gen_mips16_restore(ctx, 0, 0,
14261 do_ra, do_s0, do_s1, framesize);
14262 }
14263 }
14264 break;
14265 case I8_MOV32R:
14266 {
14267 int rz = xlat(ctx->opcode & 0x7);
14268
14269 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14270 ((ctx->opcode >> 5) & 0x7);
d75c135e 14271 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
14272 }
14273 break;
14274 case I8_MOVR32:
14275 reg32 = ctx->opcode & 0x1f;
d75c135e 14276 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
14277 break;
14278 default:
9c708c7f 14279 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14280 break;
14281 }
14282 }
14283 break;
14284 case M16_OPC_LI:
14285 {
14286 int16_t imm = (uint8_t) ctx->opcode;
14287
d75c135e 14288 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
14289 }
14290 break;
14291 case M16_OPC_CMPI:
14292 {
14293 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14294 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
14295 }
14296 break;
14297#if defined(TARGET_MIPS64)
14298 case M16_OPC_SD:
d9224450 14299 check_insn(ctx, ISA_MIPS3);
364d4831 14300 check_mips_64(ctx);
5c13fdfd 14301 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
14302 break;
14303#endif
14304 case M16_OPC_LB:
d75c135e 14305 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14306 break;
14307 case M16_OPC_LH:
d75c135e 14308 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
14309 break;
14310 case M16_OPC_LWSP:
d75c135e 14311 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14312 break;
14313 case M16_OPC_LW:
d75c135e 14314 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
14315 break;
14316 case M16_OPC_LBU:
d75c135e 14317 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14318 break;
14319 case M16_OPC_LHU:
d75c135e 14320 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
14321 break;
14322 case M16_OPC_LWPC:
d75c135e 14323 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 14324 break;
235785e8 14325#if defined(TARGET_MIPS64)
364d4831 14326 case M16_OPC_LWU:
d9224450 14327 check_insn(ctx, ISA_MIPS3);
364d4831 14328 check_mips_64(ctx);
d75c135e 14329 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
14330 break;
14331#endif
14332 case M16_OPC_SB:
5c13fdfd 14333 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14334 break;
14335 case M16_OPC_SH:
5c13fdfd 14336 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14337 break;
14338 case M16_OPC_SWSP:
5c13fdfd 14339 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14340 break;
14341 case M16_OPC_SW:
5c13fdfd 14342 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14343 break;
14344 case M16_OPC_RRR:
14345 {
14346 int rz = xlat((ctx->opcode >> 2) & 0x7);
14347 int mips32_op;
14348
14349 switch (ctx->opcode & 0x3) {
14350 case RRR_ADDU:
14351 mips32_op = OPC_ADDU;
14352 break;
14353 case RRR_SUBU:
14354 mips32_op = OPC_SUBU;
14355 break;
14356#if defined(TARGET_MIPS64)
14357 case RRR_DADDU:
14358 mips32_op = OPC_DADDU;
d9224450 14359 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14360 check_mips_64(ctx);
14361 break;
14362 case RRR_DSUBU:
14363 mips32_op = OPC_DSUBU;
d9224450 14364 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14365 check_mips_64(ctx);
14366 break;
14367#endif
14368 default:
9c708c7f 14369 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14370 goto done;
14371 }
14372
d75c135e 14373 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14374 done:
14375 ;
14376 }
14377 break;
14378 case M16_OPC_RR:
14379 switch (op1) {
14380 case RR_JR:
14381 {
14382 int nd = (ctx->opcode >> 7) & 0x1;
14383 int link = (ctx->opcode >> 6) & 0x1;
14384 int ra = (ctx->opcode >> 5) & 0x1;
14385
d9224450
MR
14386 if (nd) {
14387 check_insn(ctx, ISA_MIPS32);
14388 }
14389
364d4831 14390 if (link) {
b231c103 14391 op = OPC_JALR;
364d4831
NF
14392 } else {
14393 op = OPC_JR;
14394 }
14395
b231c103
YK
14396 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14397 (nd ? 0 : 2));
364d4831
NF
14398 }
14399 break;
14400 case RR_SDBBP:
3b3c1694
LA
14401 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14402 gen_helper_do_semihosting(cpu_env);
14403 } else {
7480515f
AM
14404 /*
14405 * XXX: not clear which exception should be raised
3b3c1694
LA
14406 * when in debug mode...
14407 */
14408 check_insn(ctx, ISA_MIPS32);
9c708c7f 14409 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14410 }
364d4831
NF
14411 break;
14412 case RR_SLT:
d75c135e 14413 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14414 break;
14415 case RR_SLTU:
d75c135e 14416 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14417 break;
14418 case RR_BREAK:
9c708c7f 14419 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14420 break;
14421 case RR_SLLV:
d75c135e 14422 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14423 break;
14424 case RR_SRLV:
d75c135e 14425 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14426 break;
14427 case RR_SRAV:
d75c135e 14428 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 14429 break;
235785e8 14430#if defined(TARGET_MIPS64)
364d4831 14431 case RR_DSRL:
d9224450 14432 check_insn(ctx, ISA_MIPS3);
364d4831 14433 check_mips_64(ctx);
d75c135e 14434 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14435 break;
14436#endif
14437 case RR_CMP:
d75c135e 14438 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14439 break;
14440 case RR_NEG:
d75c135e 14441 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14442 break;
14443 case RR_AND:
d75c135e 14444 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14445 break;
14446 case RR_OR:
d75c135e 14447 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14448 break;
14449 case RR_XOR:
d75c135e 14450 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14451 break;
14452 case RR_NOT:
d75c135e 14453 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14454 break;
14455 case RR_MFHI:
26135ead 14456 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14457 break;
14458 case RR_CNVT:
d9224450 14459 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14460 switch (cnvt_op) {
14461 case RR_RY_CNVT_ZEB:
14462 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14463 break;
14464 case RR_RY_CNVT_ZEH:
14465 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14466 break;
14467 case RR_RY_CNVT_SEB:
14468 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14469 break;
14470 case RR_RY_CNVT_SEH:
14471 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14472 break;
71375b59 14473#if defined(TARGET_MIPS64)
364d4831 14474 case RR_RY_CNVT_ZEW:
d9224450 14475 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14476 check_mips_64(ctx);
14477 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14478 break;
14479 case RR_RY_CNVT_SEW:
d9224450 14480 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14481 check_mips_64(ctx);
14482 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14483 break;
14484#endif
14485 default:
9c708c7f 14486 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14487 break;
14488 }
14489 break;
14490 case RR_MFLO:
26135ead 14491 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 14492 break;
235785e8 14493#if defined(TARGET_MIPS64)
364d4831 14494 case RR_DSRA:
d9224450 14495 check_insn(ctx, ISA_MIPS3);
364d4831 14496 check_mips_64(ctx);
d75c135e 14497 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14498 break;
14499 case RR_DSLLV:
d9224450 14500 check_insn(ctx, ISA_MIPS3);
364d4831 14501 check_mips_64(ctx);
d75c135e 14502 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14503 break;
14504 case RR_DSRLV:
d9224450 14505 check_insn(ctx, ISA_MIPS3);
364d4831 14506 check_mips_64(ctx);
d75c135e 14507 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14508 break;
14509 case RR_DSRAV:
d9224450 14510 check_insn(ctx, ISA_MIPS3);
364d4831 14511 check_mips_64(ctx);
d75c135e 14512 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14513 break;
14514#endif
14515 case RR_MULT:
26135ead 14516 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14517 break;
14518 case RR_MULTU:
26135ead 14519 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14520 break;
14521 case RR_DIV:
26135ead 14522 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14523 break;
14524 case RR_DIVU:
26135ead 14525 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 14526 break;
235785e8 14527#if defined(TARGET_MIPS64)
364d4831 14528 case RR_DMULT:
d9224450 14529 check_insn(ctx, ISA_MIPS3);
364d4831 14530 check_mips_64(ctx);
26135ead 14531 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14532 break;
14533 case RR_DMULTU:
d9224450 14534 check_insn(ctx, ISA_MIPS3);
364d4831 14535 check_mips_64(ctx);
26135ead 14536 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14537 break;
14538 case RR_DDIV:
d9224450 14539 check_insn(ctx, ISA_MIPS3);
364d4831 14540 check_mips_64(ctx);
26135ead 14541 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14542 break;
14543 case RR_DDIVU:
d9224450 14544 check_insn(ctx, ISA_MIPS3);
364d4831 14545 check_mips_64(ctx);
26135ead 14546 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14547 break;
14548#endif
14549 default:
9c708c7f 14550 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14551 break;
14552 }
14553 break;
14554 case M16_OPC_EXTEND:
240ce26a 14555 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14556 n_bytes = 4;
14557 break;
14558#if defined(TARGET_MIPS64)
14559 case M16_OPC_I64:
14560 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14561 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14562 break;
14563#endif
14564 default:
9c708c7f 14565 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14566 break;
14567 }
14568
14569 return n_bytes;
14570}
14571
211da992 14572/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 14573
211da992
CWR
14574/*
14575 * microMIPS32/microMIPS64 major opcodes
14576 *
14577 * 1. MIPS Architecture for Programmers Volume II-B:
14578 * The microMIPS32 Instruction Set (Revision 3.05)
14579 *
14580 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14581 *
14582 * 2. MIPS Architecture For Programmers Volume II-A:
14583 * The MIPS64 Instruction Set (Revision 3.51)
14584 */
6af0bf9c 14585
3c824109
NF
14586enum {
14587 POOL32A = 0x00,
14588 POOL16A = 0x01,
14589 LBU16 = 0x02,
14590 MOVE16 = 0x03,
14591 ADDI32 = 0x04,
3a1f4268
YK
14592 R6_LUI = 0x04,
14593 AUI = 0x04,
3c824109
NF
14594 LBU32 = 0x05,
14595 SB32 = 0x06,
14596 LB32 = 0x07,
14597
14598 POOL32B = 0x08,
14599 POOL16B = 0x09,
14600 LHU16 = 0x0a,
14601 ANDI16 = 0x0b,
14602 ADDIU32 = 0x0c,
14603 LHU32 = 0x0d,
14604 SH32 = 0x0e,
14605 LH32 = 0x0f,
14606
14607 POOL32I = 0x10,
14608 POOL16C = 0x11,
14609 LWSP16 = 0x12,
14610 POOL16D = 0x13,
14611 ORI32 = 0x14,
14612 POOL32F = 0x15,
211da992
CWR
14613 POOL32S = 0x16, /* MIPS64 */
14614 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
14615
14616 POOL32C = 0x18,
14617 LWGP16 = 0x19,
14618 LW16 = 0x1a,
14619 POOL16E = 0x1b,
14620 XORI32 = 0x1c,
14621 JALS32 = 0x1d,
3a1f4268
YK
14622 BOVC = 0x1d,
14623 BEQC = 0x1d,
14624 BEQZALC = 0x1d,
3c824109 14625 ADDIUPC = 0x1e,
3a1f4268
YK
14626 PCREL = 0x1e,
14627 BNVC = 0x1f,
14628 BNEC = 0x1f,
14629 BNEZALC = 0x1f,
3c824109 14630
3a1f4268
YK
14631 R6_BEQZC = 0x20,
14632 JIC = 0x20,
3c824109
NF
14633 POOL16F = 0x21,
14634 SB16 = 0x22,
14635 BEQZ16 = 0x23,
3a1f4268 14636 BEQZC16 = 0x23,
3c824109
NF
14637 SLTI32 = 0x24,
14638 BEQ32 = 0x25,
3a1f4268 14639 BC = 0x25,
3c824109
NF
14640 SWC132 = 0x26,
14641 LWC132 = 0x27,
14642
3a1f4268 14643 /* 0x29 is reserved */
3c824109 14644 RES_29 = 0x29,
3a1f4268
YK
14645 R6_BNEZC = 0x28,
14646 JIALC = 0x28,
3c824109
NF
14647 SH16 = 0x2a,
14648 BNEZ16 = 0x2b,
3a1f4268 14649 BNEZC16 = 0x2b,
3c824109
NF
14650 SLTIU32 = 0x2c,
14651 BNE32 = 0x2d,
3a1f4268 14652 BALC = 0x2d,
3c824109
NF
14653 SDC132 = 0x2e,
14654 LDC132 = 0x2f,
14655
3a1f4268 14656 /* 0x31 is reserved */
3c824109 14657 RES_31 = 0x31,
3a1f4268
YK
14658 BLEZALC = 0x30,
14659 BGEZALC = 0x30,
14660 BGEUC = 0x30,
3c824109
NF
14661 SWSP16 = 0x32,
14662 B16 = 0x33,
3a1f4268 14663 BC16 = 0x33,
3c824109
NF
14664 ANDI32 = 0x34,
14665 J32 = 0x35,
3a1f4268
YK
14666 BGTZC = 0x35,
14667 BLTZC = 0x35,
14668 BLTC = 0x35,
211da992
CWR
14669 SD32 = 0x36, /* MIPS64 */
14670 LD32 = 0x37, /* MIPS64 */
3c824109 14671
3a1f4268 14672 /* 0x39 is reserved */
3c824109 14673 RES_39 = 0x39,
3a1f4268
YK
14674 BGTZALC = 0x38,
14675 BLTZALC = 0x38,
14676 BLTUC = 0x38,
3c824109
NF
14677 SW16 = 0x3a,
14678 LI16 = 0x3b,
14679 JALX32 = 0x3c,
14680 JAL32 = 0x3d,
3a1f4268
YK
14681 BLEZC = 0x3d,
14682 BGEZC = 0x3d,
14683 BGEC = 0x3d,
3c824109
NF
14684 SW32 = 0x3e,
14685 LW32 = 0x3f
14686};
14687
3a1f4268
YK
14688/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14689enum {
14690 ADDIUPC_00 = 0x00,
c38a1d52
AR
14691 ADDIUPC_01 = 0x01,
14692 ADDIUPC_02 = 0x02,
14693 ADDIUPC_03 = 0x03,
14694 ADDIUPC_04 = 0x04,
14695 ADDIUPC_05 = 0x05,
14696 ADDIUPC_06 = 0x06,
3a1f4268
YK
14697 ADDIUPC_07 = 0x07,
14698 AUIPC = 0x1e,
14699 ALUIPC = 0x1f,
14700 LWPC_08 = 0x08,
c38a1d52
AR
14701 LWPC_09 = 0x09,
14702 LWPC_0A = 0x0A,
14703 LWPC_0B = 0x0B,
14704 LWPC_0C = 0x0C,
14705 LWPC_0D = 0x0D,
14706 LWPC_0E = 0x0E,
3a1f4268
YK
14707 LWPC_0F = 0x0F,
14708};
14709
3c824109
NF
14710/* POOL32A encoding of minor opcode field */
14711
14712enum {
7480515f
AM
14713 /*
14714 * These opcodes are distinguished only by bits 9..6; those bits are
14715 * what are recorded below.
14716 */
3c824109
NF
14717 SLL32 = 0x0,
14718 SRL32 = 0x1,
14719 SRA = 0x2,
14720 ROTR = 0x3,
3a1f4268
YK
14721 SELEQZ = 0x5,
14722 SELNEZ = 0x6,
b00c7218 14723 R6_RDHWR = 0x7,
3c824109
NF
14724
14725 SLLV = 0x0,
14726 SRLV = 0x1,
14727 SRAV = 0x2,
14728 ROTRV = 0x3,
14729 ADD = 0x4,
14730 ADDU32 = 0x5,
14731 SUB = 0x6,
14732 SUBU32 = 0x7,
14733 MUL = 0x8,
14734 AND = 0x9,
14735 OR32 = 0xa,
14736 NOR = 0xb,
14737 XOR32 = 0xc,
14738 SLT = 0xd,
14739 SLTU = 0xe,
14740
14741 MOVN = 0x0,
3a1f4268 14742 R6_MUL = 0x0,
3c824109 14743 MOVZ = 0x1,
3a1f4268
YK
14744 MUH = 0x1,
14745 MULU = 0x2,
14746 MUHU = 0x3,
3c824109 14747 LWXS = 0x4,
3a1f4268
YK
14748 R6_DIV = 0x4,
14749 MOD = 0x5,
14750 R6_DIVU = 0x6,
14751 MODU = 0x7,
3c824109
NF
14752
14753 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14754 BREAK32 = 0x07,
3c824109 14755 INS = 0x0c,
3a1f4268
YK
14756 LSA = 0x0f,
14757 ALIGN = 0x1f,
3c824109 14758 EXT = 0x2c,
bb238210
YK
14759 POOL32AXF = 0x3c,
14760 SIGRIE = 0x3f
3c824109
NF
14761};
14762
14763/* POOL32AXF encoding of minor opcode field extension */
14764
d132c79f
CWR
14765/*
14766 * 1. MIPS Architecture for Programmers Volume II-B:
14767 * The microMIPS32 Instruction Set (Revision 3.05)
14768 *
14769 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14770 *
14771 * 2. MIPS Architecture for Programmers VolumeIV-e:
14772 * The MIPS DSP Application-Specific Extension
14773 * to the microMIPS32 Architecture (Revision 2.34)
14774 *
14775 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14776 */
14777
3c824109
NF
14778enum {
14779 /* bits 11..6 */
14780 TEQ = 0x00,
14781 TGE = 0x08,
14782 TGEU = 0x10,
14783 TLT = 0x20,
14784 TLTU = 0x28,
14785 TNE = 0x30,
14786
14787 MFC0 = 0x03,
14788 MTC0 = 0x0b,
14789
d132c79f
CWR
14790 /* begin of microMIPS32 DSP */
14791
3c824109
NF
14792 /* bits 13..12 for 0x01 */
14793 MFHI_ACC = 0x0,
14794 MFLO_ACC = 0x1,
14795 MTHI_ACC = 0x2,
14796 MTLO_ACC = 0x3,
14797
14798 /* bits 13..12 for 0x2a */
14799 MADD_ACC = 0x0,
14800 MADDU_ACC = 0x1,
14801 MSUB_ACC = 0x2,
14802 MSUBU_ACC = 0x3,
14803
14804 /* bits 13..12 for 0x32 */
14805 MULT_ACC = 0x0,
6801038b 14806 MULTU_ACC = 0x1,
3c824109 14807
d132c79f
CWR
14808 /* end of microMIPS32 DSP */
14809
3c824109 14810 /* bits 15..12 for 0x2c */
3a1f4268 14811 BITSWAP = 0x0,
3c824109
NF
14812 SEB = 0x2,
14813 SEH = 0x3,
14814 CLO = 0x4,
14815 CLZ = 0x5,
14816 RDHWR = 0x6,
14817 WSBH = 0x7,
14818 MULT = 0x8,
14819 MULTU = 0x9,
14820 DIV = 0xa,
14821 DIVU = 0xb,
14822 MADD = 0xc,
14823 MADDU = 0xd,
14824 MSUB = 0xe,
14825 MSUBU = 0xf,
14826
14827 /* bits 15..12 for 0x34 */
14828 MFC2 = 0x4,
14829 MTC2 = 0x5,
14830 MFHC2 = 0x8,
14831 MTHC2 = 0x9,
14832 CFC2 = 0xc,
14833 CTC2 = 0xd,
14834
14835 /* bits 15..12 for 0x3c */
14836 JALR = 0x0,
14837 JR = 0x0, /* alias */
3a1f4268
YK
14838 JALRC = 0x0,
14839 JRC = 0x0,
3c824109 14840 JALR_HB = 0x1,
3a1f4268 14841 JALRC_HB = 0x1,
3c824109
NF
14842 JALRS = 0x4,
14843 JALRS_HB = 0x5,
14844
14845 /* bits 15..12 for 0x05 */
14846 RDPGPR = 0xe,
14847 WRPGPR = 0xf,
14848
14849 /* bits 15..12 for 0x0d */
14850 TLBP = 0x0,
14851 TLBR = 0x1,
14852 TLBWI = 0x2,
14853 TLBWR = 0x3,
e60ec063
YK
14854 TLBINV = 0x4,
14855 TLBINVF = 0x5,
3c824109
NF
14856 WAIT = 0x9,
14857 IRET = 0xd,
14858 DERET = 0xe,
14859 ERET = 0xf,
14860
14861 /* bits 15..12 for 0x15 */
14862 DMT = 0x0,
14863 DVPE = 0x1,
14864 EMT = 0x2,
14865 EVPE = 0x3,
14866
14867 /* bits 15..12 for 0x1d */
14868 DI = 0x4,
14869 EI = 0x5,
14870
14871 /* bits 15..12 for 0x2d */
14872 SYNC = 0x6,
14873 SYSCALL = 0x8,
14874 SDBBP = 0xd,
14875
14876 /* bits 15..12 for 0x35 */
14877 MFHI32 = 0x0,
14878 MFLO32 = 0x1,
14879 MTHI32 = 0x2,
14880 MTLO32 = 0x3,
14881};
14882
14883/* POOL32B encoding of minor opcode field (bits 15..12) */
14884
14885enum {
14886 LWC2 = 0x0,
14887 LWP = 0x1,
14888 LDP = 0x4,
14889 LWM32 = 0x5,
14890 CACHE = 0x6,
14891 LDM = 0x7,
14892 SWC2 = 0x8,
14893 SWP = 0x9,
14894 SDP = 0xc,
14895 SWM32 = 0xd,
14896 SDM = 0xf
14897};
14898
14899/* POOL32C encoding of minor opcode field (bits 15..12) */
14900
14901enum {
14902 LWL = 0x0,
14903 SWL = 0x8,
14904 LWR = 0x1,
14905 SWR = 0x9,
14906 PREF = 0x2,
8fffc646 14907 ST_EVA = 0xa,
3c824109
NF
14908 LL = 0x3,
14909 SC = 0xb,
14910 LDL = 0x4,
14911 SDL = 0xc,
14912 LDR = 0x5,
14913 SDR = 0xd,
8fffc646 14914 LD_EVA = 0x6,
3c824109
NF
14915 LWU = 0xe,
14916 LLD = 0x7,
14917 SCD = 0xf
14918};
14919
8fffc646
JH
14920/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14921
14922enum {
14923 LBUE = 0x0,
14924 LHUE = 0x1,
14925 LWLE = 0x2,
14926 LWRE = 0x3,
14927 LBE = 0x4,
14928 LHE = 0x5,
14929 LLE = 0x6,
14930 LWE = 0x7,
14931};
14932
14933/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14934
14935enum {
14936 SWLE = 0x0,
14937 SWRE = 0x1,
14938 PREFE = 0x2,
14939 CACHEE = 0x3,
14940 SBE = 0x4,
14941 SHE = 0x5,
14942 SCE = 0x6,
14943 SWE = 0x7,
14944};
14945
3c824109
NF
14946/* POOL32F encoding of minor opcode field (bits 5..0) */
14947
14948enum {
14949 /* These are the bit 7..6 values */
14950 ADD_FMT = 0x0,
3c824109
NF
14951
14952 SUB_FMT = 0x1,
3c824109
NF
14953
14954 MUL_FMT = 0x2,
14955
14956 DIV_FMT = 0x3,
14957
14958 /* These are the bit 8..6 values */
3a1f4268 14959 MOVN_FMT = 0x0,
3c824109
NF
14960 RSQRT2_FMT = 0x0,
14961 MOVF_FMT = 0x0,
3a1f4268
YK
14962 RINT_FMT = 0x0,
14963 SELNEZ_FMT = 0x0,
3c824109 14964
3a1f4268 14965 MOVZ_FMT = 0x1,
3c824109
NF
14966 LWXC1 = 0x1,
14967 MOVT_FMT = 0x1,
3a1f4268
YK
14968 CLASS_FMT = 0x1,
14969 SELEQZ_FMT = 0x1,
3c824109
NF
14970
14971 PLL_PS = 0x2,
14972 SWXC1 = 0x2,
3a1f4268 14973 SEL_FMT = 0x2,
3c824109
NF
14974
14975 PLU_PS = 0x3,
14976 LDXC1 = 0x3,
14977
3a1f4268 14978 MOVN_FMT_04 = 0x4,
3c824109
NF
14979 PUL_PS = 0x4,
14980 SDXC1 = 0x4,
14981 RECIP2_FMT = 0x4,
14982
3a1f4268 14983 MOVZ_FMT_05 = 0x05,
3c824109
NF
14984 PUU_PS = 0x5,
14985 LUXC1 = 0x5,
14986
14987 CVT_PS_S = 0x6,
14988 SUXC1 = 0x6,
14989 ADDR_PS = 0x6,
14990 PREFX = 0x6,
3a1f4268 14991 MADDF_FMT = 0x6,
3c824109
NF
14992
14993 MULR_PS = 0x7,
3a1f4268 14994 MSUBF_FMT = 0x7,
3c824109
NF
14995
14996 MADD_S = 0x01,
14997 MADD_D = 0x09,
14998 MADD_PS = 0x11,
14999 ALNV_PS = 0x19,
15000 MSUB_S = 0x21,
15001 MSUB_D = 0x29,
15002 MSUB_PS = 0x31,
15003
15004 NMADD_S = 0x02,
15005 NMADD_D = 0x0a,
15006 NMADD_PS = 0x12,
15007 NMSUB_S = 0x22,
15008 NMSUB_D = 0x2a,
15009 NMSUB_PS = 0x32,
15010
3a1f4268
YK
15011 MIN_FMT = 0x3,
15012 MAX_FMT = 0xb,
15013 MINA_FMT = 0x23,
15014 MAXA_FMT = 0x2b,
3c824109
NF
15015 POOL32FXF = 0x3b,
15016
15017 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
15018 C_COND_FMT = 0x3c,
15019
15020 CMP_CONDN_S = 0x5,
15021 CMP_CONDN_D = 0x15
3c824109
NF
15022};
15023
15024/* POOL32Fxf encoding of minor opcode extension field */
15025
15026enum {
15027 CVT_L = 0x04,
15028 RSQRT_FMT = 0x08,
15029 FLOOR_L = 0x0c,
15030 CVT_PW_PS = 0x1c,
15031 CVT_W = 0x24,
15032 SQRT_FMT = 0x28,
15033 FLOOR_W = 0x2c,
15034 CVT_PS_PW = 0x3c,
15035 CFC1 = 0x40,
15036 RECIP_FMT = 0x48,
15037 CEIL_L = 0x4c,
15038 CTC1 = 0x60,
15039 CEIL_W = 0x6c,
15040 MFC1 = 0x80,
15041 CVT_S_PL = 0x84,
15042 TRUNC_L = 0x8c,
15043 MTC1 = 0xa0,
15044 CVT_S_PU = 0xa4,
15045 TRUNC_W = 0xac,
15046 MFHC1 = 0xc0,
15047 ROUND_L = 0xcc,
15048 MTHC1 = 0xe0,
15049 ROUND_W = 0xec,
15050
15051 MOV_FMT = 0x01,
15052 MOVF = 0x05,
15053 ABS_FMT = 0x0d,
15054 RSQRT1_FMT = 0x1d,
15055 MOVT = 0x25,
15056 NEG_FMT = 0x2d,
15057 CVT_D = 0x4d,
15058 RECIP1_FMT = 0x5d,
15059 CVT_S = 0x6d
15060};
15061
15062/* POOL32I encoding of minor opcode field (bits 25..21) */
15063
15064enum {
15065 BLTZ = 0x00,
15066 BLTZAL = 0x01,
15067 BGEZ = 0x02,
15068 BGEZAL = 0x03,
15069 BLEZ = 0x04,
15070 BNEZC = 0x05,
15071 BGTZ = 0x06,
15072 BEQZC = 0x07,
15073 TLTI = 0x08,
3a1f4268 15074 BC1EQZC = 0x08,
3c824109 15075 TGEI = 0x09,
3a1f4268 15076 BC1NEZC = 0x09,
3c824109 15077 TLTIU = 0x0a,
3a1f4268 15078 BC2EQZC = 0x0a,
3c824109 15079 TGEIU = 0x0b,
3a1f4268 15080 BC2NEZC = 0x0a,
3c824109 15081 TNEI = 0x0c,
3a1f4268 15082 R6_SYNCI = 0x0c,
3c824109
NF
15083 LUI = 0x0d,
15084 TEQI = 0x0e,
15085 SYNCI = 0x10,
15086 BLTZALS = 0x11,
15087 BGEZALS = 0x13,
15088 BC2F = 0x14,
15089 BC2T = 0x15,
15090 BPOSGE64 = 0x1a,
15091 BPOSGE32 = 0x1b,
15092 /* These overlap and are distinguished by bit16 of the instruction */
15093 BC1F = 0x1c,
15094 BC1T = 0x1d,
15095 BC1ANY2F = 0x1c,
15096 BC1ANY2T = 0x1d,
15097 BC1ANY4F = 0x1e,
15098 BC1ANY4T = 0x1f
15099};
15100
15101/* POOL16A encoding of minor opcode field */
15102
15103enum {
15104 ADDU16 = 0x0,
15105 SUBU16 = 0x1
15106};
15107
15108/* POOL16B encoding of minor opcode field */
15109
15110enum {
15111 SLL16 = 0x0,
15112 SRL16 = 0x1
15113};
15114
15115/* POOL16C encoding of minor opcode field */
15116
15117enum {
15118 NOT16 = 0x00,
15119 XOR16 = 0x04,
15120 AND16 = 0x08,
15121 OR16 = 0x0c,
15122 LWM16 = 0x10,
15123 SWM16 = 0x14,
15124 JR16 = 0x18,
15125 JRC16 = 0x1a,
15126 JALR16 = 0x1c,
15127 JALR16S = 0x1e,
15128 MFHI16 = 0x20,
15129 MFLO16 = 0x24,
15130 BREAK16 = 0x28,
15131 SDBBP16 = 0x2c,
15132 JRADDIUSP = 0x30
15133};
15134
3a1f4268
YK
15135/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15136
15137enum {
15138 R6_NOT16 = 0x00,
15139 R6_AND16 = 0x01,
15140 R6_LWM16 = 0x02,
15141 R6_JRC16 = 0x03,
15142 MOVEP = 0x04,
c38a1d52
AR
15143 MOVEP_05 = 0x05,
15144 MOVEP_06 = 0x06,
3a1f4268
YK
15145 MOVEP_07 = 0x07,
15146 R6_XOR16 = 0x08,
15147 R6_OR16 = 0x09,
15148 R6_SWM16 = 0x0a,
15149 JALRC16 = 0x0b,
15150 MOVEP_0C = 0x0c,
c38a1d52
AR
15151 MOVEP_0D = 0x0d,
15152 MOVEP_0E = 0x0e,
3a1f4268
YK
15153 MOVEP_0F = 0x0f,
15154 JRCADDIUSP = 0x13,
15155 R6_BREAK16 = 0x1b,
15156 R6_SDBBP16 = 0x3b
15157};
15158
3c824109
NF
15159/* POOL16D encoding of minor opcode field */
15160
15161enum {
15162 ADDIUS5 = 0x0,
15163 ADDIUSP = 0x1
15164};
15165
15166/* POOL16E encoding of minor opcode field */
15167
15168enum {
15169 ADDIUR2 = 0x0,
15170 ADDIUR1SP = 0x1
15171};
15172
235785e8 15173static int mmreg(int r)
3c824109
NF
15174{
15175 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15176
15177 return map[r];
15178}
15179
15180/* Used for 16-bit store instructions. */
235785e8 15181static int mmreg2(int r)
3c824109
NF
15182{
15183 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15184
15185 return map[r];
15186}
15187
15188#define uMIPS_RD(op) ((op >> 7) & 0x7)
15189#define uMIPS_RS(op) ((op >> 4) & 0x7)
15190#define uMIPS_RS2(op) uMIPS_RS(op)
15191#define uMIPS_RS1(op) ((op >> 1) & 0x7)
15192#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15193#define uMIPS_RS5(op) (op & 0x1f)
15194
15195/* Signed immediate */
15196#define SIMM(op, start, width) \
71375b59
AM
15197 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15198 << (32 - width)) \
15199 >> (32 - width))
3c824109 15200/* Zero-extended immediate */
71375b59 15201#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 15202
d75c135e 15203static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
15204{
15205 int rd = mmreg(uMIPS_RD(ctx->opcode));
15206
d75c135e 15207 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
15208}
15209
d75c135e 15210static void gen_addiur2(DisasContext *ctx)
3c824109
NF
15211{
15212 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15213 int rd = mmreg(uMIPS_RD(ctx->opcode));
15214 int rs = mmreg(uMIPS_RS(ctx->opcode));
15215
d75c135e 15216 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
15217}
15218
d75c135e 15219static void gen_addiusp(DisasContext *ctx)
3c824109
NF
15220{
15221 int encoded = ZIMM(ctx->opcode, 1, 9);
15222 int decoded;
15223
15224 if (encoded <= 1) {
15225 decoded = 256 + encoded;
15226 } else if (encoded <= 255) {
15227 decoded = encoded;
15228 } else if (encoded <= 509) {
15229 decoded = encoded - 512;
15230 } else {
15231 decoded = encoded - 768;
15232 }
15233
d75c135e 15234 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
15235}
15236
d75c135e 15237static void gen_addius5(DisasContext *ctx)
3c824109
NF
15238{
15239 int imm = SIMM(ctx->opcode, 1, 4);
15240 int rd = (ctx->opcode >> 5) & 0x1f;
15241
d75c135e 15242 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
15243}
15244
d75c135e 15245static void gen_andi16(DisasContext *ctx)
3c824109
NF
15246{
15247 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15248 31, 32, 63, 64, 255, 32768, 65535 };
15249 int rd = mmreg(uMIPS_RD(ctx->opcode));
15250 int rs = mmreg(uMIPS_RS(ctx->opcode));
15251 int encoded = ZIMM(ctx->opcode, 0, 4);
15252
d75c135e 15253 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
15254}
15255
235785e8
AM
15256static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15257 int base, int16_t offset)
3c824109
NF
15258{
15259 TCGv t0, t1;
15260 TCGv_i32 t2;
15261
15262 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 15263 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15264 return;
15265 }
15266
15267 t0 = tcg_temp_new();
15268
15269 gen_base_offset_addr(ctx, t0, base, offset);
15270
15271 t1 = tcg_const_tl(reglist);
15272 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 15273
3c824109
NF
15274 save_cpu_state(ctx, 1);
15275 switch (opc) {
15276 case LWM32:
895c2d04 15277 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
15278 break;
15279 case SWM32:
895c2d04 15280 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
15281 break;
15282#ifdef TARGET_MIPS64
15283 case LDM:
895c2d04 15284 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
15285 break;
15286 case SDM:
895c2d04 15287 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 15288 break;
6af0bf9c 15289#endif
3c824109 15290 }
3c824109 15291 tcg_temp_free(t0);
33087598 15292 tcg_temp_free(t1);
3c824109
NF
15293 tcg_temp_free_i32(t2);
15294}
6af0bf9c 15295
3c824109 15296
240ce26a 15297static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 15298{
3c824109
NF
15299 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15300 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 15301
3c824109
NF
15302 switch (((ctx->opcode) >> 4) & 0x3f) {
15303 case NOT16 + 0:
15304 case NOT16 + 1:
15305 case NOT16 + 2:
15306 case NOT16 + 3:
d75c135e 15307 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
15308 break;
15309 case XOR16 + 0:
15310 case XOR16 + 1:
15311 case XOR16 + 2:
15312 case XOR16 + 3:
d75c135e 15313 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
15314 break;
15315 case AND16 + 0:
15316 case AND16 + 1:
15317 case AND16 + 2:
15318 case AND16 + 3:
d75c135e 15319 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
15320 break;
15321 case OR16 + 0:
15322 case OR16 + 1:
15323 case OR16 + 2:
15324 case OR16 + 3:
d75c135e 15325 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
15326 break;
15327 case LWM16 + 0:
15328 case LWM16 + 1:
15329 case LWM16 + 2:
15330 case LWM16 + 3:
15331 {
15332 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15333 int offset = ZIMM(ctx->opcode, 0, 4);
15334
15335 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15336 29, offset << 2);
15337 }
15338 break;
15339 case SWM16 + 0:
15340 case SWM16 + 1:
15341 case SWM16 + 2:
15342 case SWM16 + 3:
15343 {
15344 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15345 int offset = ZIMM(ctx->opcode, 0, 4);
15346
15347 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15348 29, offset << 2);
15349 }
15350 break;
15351 case JR16 + 0:
15352 case JR16 + 1:
15353 {
15354 int reg = ctx->opcode & 0x1f;
15355
b231c103 15356 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15357 }
3c824109
NF
15358 break;
15359 case JRC16 + 0:
15360 case JRC16 + 1:
15361 {
15362 int reg = ctx->opcode & 0x1f;
b231c103 15363 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
15364 /*
15365 * Let normal delay slot handling in our caller take us
15366 * to the branch target.
15367 */
3c824109
NF
15368 }
15369 break;
15370 case JALR16 + 0:
15371 case JALR16 + 1:
b231c103
YK
15372 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15373 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15374 break;
3c824109
NF
15375 case JALR16S + 0:
15376 case JALR16S + 1:
b231c103
YK
15377 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15378 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15379 break;
15380 case MFHI16 + 0:
15381 case MFHI16 + 1:
26135ead 15382 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15383 break;
15384 case MFLO16 + 0:
15385 case MFLO16 + 1:
26135ead 15386 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15387 break;
15388 case BREAK16:
9c708c7f 15389 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15390 break;
15391 case SDBBP16:
3b3c1694
LA
15392 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15393 gen_helper_do_semihosting(cpu_env);
15394 } else {
7480515f
AM
15395 /*
15396 * XXX: not clear which exception should be raised
3b3c1694
LA
15397 * when in debug mode...
15398 */
15399 check_insn(ctx, ISA_MIPS32);
9c708c7f 15400 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15401 }
3c824109
NF
15402 break;
15403 case JRADDIUSP + 0:
15404 case JRADDIUSP + 1:
15405 {
15406 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15407 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15408 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
15409 /*
15410 * Let normal delay slot handling in our caller take us
15411 * to the branch target.
15412 */
3c824109
NF
15413 }
15414 break;
15415 default:
9c708c7f 15416 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15417 break;
15418 }
15419}
15420
ed7ce6c0
YK
15421static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15422 int enc_rs)
15423{
15424 int rd, rs, re, rt;
15425 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15426 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15427 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15428 rd = rd_enc[enc_dest];
15429 re = re_enc[enc_dest];
15430 rs = rs_rt_enc[enc_rs];
15431 rt = rs_rt_enc[enc_rt];
15432 if (rs) {
15433 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15434 } else {
15435 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15436 }
15437 if (rt) {
15438 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15439 } else {
15440 tcg_gen_movi_tl(cpu_gpr[re], 0);
15441 }
15442}
15443
15444static void gen_pool16c_r6_insn(DisasContext *ctx)
15445{
15446 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15447 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15448
15449 switch (ctx->opcode & 0xf) {
15450 case R6_NOT16:
15451 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15452 break;
15453 case R6_AND16:
15454 gen_logic(ctx, OPC_AND, rt, rt, rs);
15455 break;
15456 case R6_LWM16:
15457 {
15458 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15459 int offset = extract32(ctx->opcode, 4, 4);
15460 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15461 }
15462 break;
15463 case R6_JRC16: /* JRCADDIUSP */
15464 if ((ctx->opcode >> 4) & 1) {
15465 /* JRCADDIUSP */
15466 int imm = extract32(ctx->opcode, 5, 5);
15467 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15468 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15469 } else {
15470 /* JRC16 */
e1555d7d 15471 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15472 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15473 }
15474 break;
c38a1d52
AR
15475 case MOVEP:
15476 case MOVEP_05:
15477 case MOVEP_06:
15478 case MOVEP_07:
15479 case MOVEP_0C:
15480 case MOVEP_0D:
15481 case MOVEP_0E:
15482 case MOVEP_0F:
ed7ce6c0
YK
15483 {
15484 int enc_dest = uMIPS_RD(ctx->opcode);
15485 int enc_rt = uMIPS_RS2(ctx->opcode);
15486 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15487 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15488 }
15489 break;
15490 case R6_XOR16:
15491 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15492 break;
15493 case R6_OR16:
15494 gen_logic(ctx, OPC_OR, rt, rt, rs);
15495 break;
15496 case R6_SWM16:
15497 {
15498 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15499 int offset = extract32(ctx->opcode, 4, 4);
15500 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15501 }
15502 break;
15503 case JALRC16: /* BREAK16, SDBBP16 */
15504 switch (ctx->opcode & 0x3f) {
15505 case JALRC16:
15506 case JALRC16 + 0x20:
15507 /* JALRC16 */
15508 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15509 31, 0, 0);
15510 break;
15511 case R6_BREAK16:
15512 /* BREAK16 */
15513 generate_exception(ctx, EXCP_BREAK);
15514 break;
15515 case R6_SDBBP16:
15516 /* SDBBP16 */
060ebfef
LA
15517 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15518 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15519 } else {
060ebfef
LA
15520 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15521 generate_exception(ctx, EXCP_RI);
15522 } else {
15523 generate_exception(ctx, EXCP_DBp);
15524 }
ed7ce6c0
YK
15525 }
15526 break;
15527 }
15528 break;
15529 default:
15530 generate_exception(ctx, EXCP_RI);
15531 break;
15532 }
15533}
15534
235785e8 15535static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
15536{
15537 TCGv t0 = tcg_temp_new();
15538 TCGv t1 = tcg_temp_new();
15539
15540 gen_load_gpr(t0, base);
15541
15542 if (index != 0) {
15543 gen_load_gpr(t1, index);
15544 tcg_gen_shli_tl(t1, t1, 2);
15545 gen_op_addr_add(ctx, t0, t1, t0);
15546 }
15547
5f68f5ae 15548 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15549 gen_store_gpr(t1, rd);
15550
15551 tcg_temp_free(t0);
15552 tcg_temp_free(t1);
15553}
15554
235785e8
AM
15555static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15556 int base, int16_t offset)
3c824109 15557{
3c824109
NF
15558 TCGv t0, t1;
15559
36c6711b 15560 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15561 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15562 return;
15563 }
15564
3c824109
NF
15565 t0 = tcg_temp_new();
15566 t1 = tcg_temp_new();
8e9ade68 15567
3c824109
NF
15568 gen_base_offset_addr(ctx, t0, base, offset);
15569
15570 switch (opc) {
15571 case LWP:
36c6711b 15572 if (rd == base) {
9c708c7f 15573 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15574 return;
15575 }
5f68f5ae 15576 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15577 gen_store_gpr(t1, rd);
15578 tcg_gen_movi_tl(t1, 4);
15579 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15580 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 15581 gen_store_gpr(t1, rd + 1);
3c824109
NF
15582 break;
15583 case SWP:
3c824109 15584 gen_load_gpr(t1, rd);
5f68f5ae 15585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15586 tcg_gen_movi_tl(t1, 4);
15587 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15588 gen_load_gpr(t1, rd + 1);
5f68f5ae 15589 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15590 break;
15591#ifdef TARGET_MIPS64
15592 case LDP:
36c6711b 15593 if (rd == base) {
9c708c7f 15594 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15595 return;
15596 }
5f68f5ae 15597 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15598 gen_store_gpr(t1, rd);
15599 tcg_gen_movi_tl(t1, 8);
15600 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15601 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 15602 gen_store_gpr(t1, rd + 1);
3c824109
NF
15603 break;
15604 case SDP:
3c824109 15605 gen_load_gpr(t1, rd);
5f68f5ae 15606 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15607 tcg_gen_movi_tl(t1, 8);
15608 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15609 gen_load_gpr(t1, rd + 1);
5f68f5ae 15610 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15611 break;
15612#endif
6af0bf9c 15613 }
3c824109
NF
15614 tcg_temp_free(t0);
15615 tcg_temp_free(t1);
15616}
618b0fe9 15617
d208ac0c
LA
15618static void gen_sync(int stype)
15619{
15620 TCGBar tcg_mo = TCG_BAR_SC;
15621
15622 switch (stype) {
15623 case 0x4: /* SYNC_WMB */
15624 tcg_mo |= TCG_MO_ST_ST;
15625 break;
15626 case 0x10: /* SYNC_MB */
15627 tcg_mo |= TCG_MO_ALL;
15628 break;
15629 case 0x11: /* SYNC_ACQUIRE */
15630 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15631 break;
15632 case 0x12: /* SYNC_RELEASE */
15633 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15634 break;
15635 case 0x13: /* SYNC_RMB */
15636 tcg_mo |= TCG_MO_LD_LD;
15637 break;
15638 default:
15639 tcg_mo |= TCG_MO_ALL;
15640 break;
15641 }
15642
15643 tcg_gen_mb(tcg_mo);
15644}
15645
235785e8 15646static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
15647{
15648 int extension = (ctx->opcode >> 6) & 0x3f;
15649 int minor = (ctx->opcode >> 12) & 0xf;
15650 uint32_t mips32_op;
15651
15652 switch (extension) {
15653 case TEQ:
15654 mips32_op = OPC_TEQ;
15655 goto do_trap;
15656 case TGE:
15657 mips32_op = OPC_TGE;
15658 goto do_trap;
15659 case TGEU:
15660 mips32_op = OPC_TGEU;
15661 goto do_trap;
15662 case TLT:
15663 mips32_op = OPC_TLT;
15664 goto do_trap;
15665 case TLTU:
15666 mips32_op = OPC_TLTU;
15667 goto do_trap;
15668 case TNE:
15669 mips32_op = OPC_TNE;
15670 do_trap:
15671 gen_trap(ctx, mips32_op, rs, rt, -1);
15672 break;
15673#ifndef CONFIG_USER_ONLY
15674 case MFC0:
15675 case MFC0 + 32:
2e15497c 15676 check_cp0_enabled(ctx);
3c824109
NF
15677 if (rt == 0) {
15678 /* Treat as NOP. */
15679 break;
15680 }
d75c135e 15681 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15682 break;
15683 case MTC0:
15684 case MTC0 + 32:
2e15497c 15685 check_cp0_enabled(ctx);
3c824109
NF
15686 {
15687 TCGv t0 = tcg_temp_new();
618b0fe9 15688
3c824109 15689 gen_load_gpr(t0, rt);
d75c135e 15690 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15691 tcg_temp_free(t0);
15692 }
15693 break;
15694#endif
a1fc6246
LA
15695 case 0x2a:
15696 switch (minor & 3) {
15697 case MADD_ACC:
15698 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15699 break;
15700 case MADDU_ACC:
15701 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15702 break;
15703 case MSUB_ACC:
15704 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15705 break;
15706 case MSUBU_ACC:
15707 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15708 break;
15709 default:
15710 goto pool32axf_invalid;
15711 }
15712 break;
15713 case 0x32:
15714 switch (minor & 3) {
15715 case MULT_ACC:
15716 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15717 break;
15718 case MULTU_ACC:
15719 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15720 break;
15721 default:
15722 goto pool32axf_invalid;
15723 }
15724 break;
3c824109
NF
15725 case 0x2c:
15726 switch (minor) {
e0332095
YK
15727 case BITSWAP:
15728 check_insn(ctx, ISA_MIPS32R6);
15729 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15730 break;
3c824109
NF
15731 case SEB:
15732 gen_bshfl(ctx, OPC_SEB, rs, rt);
15733 break;
15734 case SEH:
15735 gen_bshfl(ctx, OPC_SEH, rs, rt);
15736 break;
15737 case CLO:
15738 mips32_op = OPC_CLO;
15739 goto do_cl;
15740 case CLZ:
15741 mips32_op = OPC_CLZ;
15742 do_cl:
d75c135e 15743 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15744 gen_cl(ctx, mips32_op, rt, rs);
15745 break;
15746 case RDHWR:
b00c7218
YK
15747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15748 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15749 break;
15750 case WSBH:
15751 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15752 break;
15753 case MULT:
9e8f441a 15754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15755 mips32_op = OPC_MULT;
26135ead 15756 goto do_mul;
3c824109 15757 case MULTU:
9e8f441a 15758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15759 mips32_op = OPC_MULTU;
26135ead 15760 goto do_mul;
3c824109 15761 case DIV:
9e8f441a 15762 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15763 mips32_op = OPC_DIV;
26135ead 15764 goto do_div;
3c824109 15765 case DIVU:
9e8f441a 15766 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15767 mips32_op = OPC_DIVU;
26135ead
RS
15768 goto do_div;
15769 do_div:
15770 check_insn(ctx, ISA_MIPS32);
15771 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15772 break;
3c824109 15773 case MADD:
9e8f441a 15774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15775 mips32_op = OPC_MADD;
26135ead 15776 goto do_mul;
3c824109 15777 case MADDU:
9e8f441a 15778 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15779 mips32_op = OPC_MADDU;
26135ead 15780 goto do_mul;
3c824109 15781 case MSUB:
9e8f441a 15782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15783 mips32_op = OPC_MSUB;
26135ead 15784 goto do_mul;
3c824109 15785 case MSUBU:
9e8f441a 15786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15787 mips32_op = OPC_MSUBU;
26135ead 15788 do_mul:
d75c135e 15789 check_insn(ctx, ISA_MIPS32);
a1fc6246 15790 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15791 break;
15792 default:
15793 goto pool32axf_invalid;
15794 }
15795 break;
15796 case 0x34:
15797 switch (minor) {
15798 case MFC2:
15799 case MTC2:
15800 case MFHC2:
15801 case MTHC2:
15802 case CFC2:
15803 case CTC2:
15804 generate_exception_err(ctx, EXCP_CpU, 2);
15805 break;
15806 default:
15807 goto pool32axf_invalid;
15808 }
15809 break;
15810 case 0x3c:
15811 switch (minor) {
65935f07
YK
15812 case JALR: /* JALRC */
15813 case JALR_HB: /* JALRC_HB */
15814 if (ctx->insn_flags & ISA_MIPS32R6) {
15815 /* JALRC, JALRC_HB */
15816 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15817 } else {
15818 /* JALR, JALR_HB */
15819 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15820 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15821 }
3c824109
NF
15822 break;
15823 case JALRS:
15824 case JALRS_HB:
9e8f441a 15825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15826 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15827 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15828 break;
15829 default:
15830 goto pool32axf_invalid;
15831 }
15832 break;
15833 case 0x05:
15834 switch (minor) {
15835 case RDPGPR:
2e15497c 15836 check_cp0_enabled(ctx);
d75c135e 15837 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15838 gen_load_srsgpr(rs, rt);
3c824109
NF
15839 break;
15840 case WRPGPR:
2e15497c 15841 check_cp0_enabled(ctx);
d75c135e 15842 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15843 gen_store_srsgpr(rs, rt);
3c824109
NF
15844 break;
15845 default:
15846 goto pool32axf_invalid;
15847 }
15848 break;
15849#ifndef CONFIG_USER_ONLY
15850 case 0x0d:
15851 switch (minor) {
15852 case TLBP:
15853 mips32_op = OPC_TLBP;
15854 goto do_cp0;
15855 case TLBR:
15856 mips32_op = OPC_TLBR;
15857 goto do_cp0;
15858 case TLBWI:
15859 mips32_op = OPC_TLBWI;
15860 goto do_cp0;
15861 case TLBWR:
15862 mips32_op = OPC_TLBWR;
15863 goto do_cp0;
e60ec063
YK
15864 case TLBINV:
15865 mips32_op = OPC_TLBINV;
15866 goto do_cp0;
15867 case TLBINVF:
15868 mips32_op = OPC_TLBINVF;
15869 goto do_cp0;
3c824109
NF
15870 case WAIT:
15871 mips32_op = OPC_WAIT;
15872 goto do_cp0;
15873 case DERET:
15874 mips32_op = OPC_DERET;
15875 goto do_cp0;
15876 case ERET:
15877 mips32_op = OPC_ERET;
15878 do_cp0:
15879 gen_cp0(env, ctx, mips32_op, rt, rs);
15880 break;
15881 default:
15882 goto pool32axf_invalid;
15883 }
15884 break;
15885 case 0x1d:
15886 switch (minor) {
15887 case DI:
2e15497c 15888 check_cp0_enabled(ctx);
3c824109
NF
15889 {
15890 TCGv t0 = tcg_temp_new();
15891
15892 save_cpu_state(ctx, 1);
895c2d04 15893 gen_helper_di(t0, cpu_env);
3c824109 15894 gen_store_gpr(t0, rs);
71375b59
AM
15895 /*
15896 * Stop translation as we may have switched the execution
15897 * mode.
15898 */
eeb3bba8 15899 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15900 tcg_temp_free(t0);
15901 }
15902 break;
15903 case EI:
2e15497c 15904 check_cp0_enabled(ctx);
3c824109
NF
15905 {
15906 TCGv t0 = tcg_temp_new();
15907
15908 save_cpu_state(ctx, 1);
895c2d04 15909 gen_helper_ei(t0, cpu_env);
3c824109 15910 gen_store_gpr(t0, rs);
7480515f
AM
15911 /*
15912 * DISAS_STOP isn't sufficient, we need to ensure we break out
15913 * of translated code to check for pending interrupts.
15914 */
eeb3bba8
EC
15915 gen_save_pc(ctx->base.pc_next + 4);
15916 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15917 tcg_temp_free(t0);
15918 }
15919 break;
15920 default:
15921 goto pool32axf_invalid;
15922 }
15923 break;
15924#endif
15925 case 0x2d:
15926 switch (minor) {
15927 case SYNC:
d208ac0c 15928 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15929 break;
15930 case SYSCALL:
9c708c7f 15931 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15932 break;
15933 case SDBBP:
3b3c1694
LA
15934 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15935 gen_helper_do_semihosting(cpu_env);
15936 } else {
15937 check_insn(ctx, ISA_MIPS32);
e0332095 15938 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15939 generate_exception_end(ctx, EXCP_RI);
e0332095 15940 } else {
9c708c7f 15941 generate_exception_end(ctx, EXCP_DBp);
e0332095 15942 }
3b3c1694 15943 }
3c824109
NF
15944 break;
15945 default:
15946 goto pool32axf_invalid;
15947 }
15948 break;
a1fc6246 15949 case 0x01:
26135ead 15950 switch (minor & 3) {
a1fc6246 15951 case MFHI_ACC:
26135ead 15952 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15953 break;
a1fc6246 15954 case MFLO_ACC:
26135ead 15955 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15956 break;
a1fc6246 15957 case MTHI_ACC:
26135ead 15958 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15959 break;
a1fc6246 15960 case MTLO_ACC:
26135ead 15961 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15962 break;
15963 default:
15964 goto pool32axf_invalid;
15965 }
15966 break;
a1fc6246 15967 case 0x35:
9e8f441a 15968 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15969 switch (minor) {
15970 case MFHI32:
15971 gen_HILO(ctx, OPC_MFHI, 0, rs);
15972 break;
15973 case MFLO32:
15974 gen_HILO(ctx, OPC_MFLO, 0, rs);
15975 break;
15976 case MTHI32:
15977 gen_HILO(ctx, OPC_MTHI, 0, rs);
15978 break;
15979 case MTLO32:
15980 gen_HILO(ctx, OPC_MTLO, 0, rs);
15981 break;
15982 default:
15983 goto pool32axf_invalid;
15984 }
15985 break;
3c824109
NF
15986 default:
15987 pool32axf_invalid:
15988 MIPS_INVAL("pool32axf");
9c708c7f 15989 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15990 break;
15991 }
15992}
15993
7480515f
AM
15994/*
15995 * Values for microMIPS fmt field. Variable-width, depending on which
15996 * formats the instruction supports.
15997 */
3c824109
NF
15998enum {
15999 FMT_SD_S = 0,
16000 FMT_SD_D = 1,
16001
16002 FMT_SDPS_S = 0,
16003 FMT_SDPS_D = 1,
16004 FMT_SDPS_PS = 2,
16005
16006 FMT_SWL_S = 0,
16007 FMT_SWL_W = 1,
16008 FMT_SWL_L = 2,
16009
16010 FMT_DWL_D = 0,
16011 FMT_DWL_W = 1,
16012 FMT_DWL_L = 2
16013};
16014
d75c135e 16015static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
16016{
16017 int extension = (ctx->opcode >> 6) & 0x3ff;
16018 uint32_t mips32_op;
16019
71375b59
AM
16020#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16021#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16022#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
16023
16024 switch (extension) {
16025 case FLOAT_1BIT_FMT(CFC1, 0):
16026 mips32_op = OPC_CFC1;
16027 goto do_cp1;
16028 case FLOAT_1BIT_FMT(CTC1, 0):
16029 mips32_op = OPC_CTC1;
16030 goto do_cp1;
16031 case FLOAT_1BIT_FMT(MFC1, 0):
16032 mips32_op = OPC_MFC1;
16033 goto do_cp1;
16034 case FLOAT_1BIT_FMT(MTC1, 0):
16035 mips32_op = OPC_MTC1;
16036 goto do_cp1;
16037 case FLOAT_1BIT_FMT(MFHC1, 0):
16038 mips32_op = OPC_MFHC1;
16039 goto do_cp1;
16040 case FLOAT_1BIT_FMT(MTHC1, 0):
16041 mips32_op = OPC_MTHC1;
16042 do_cp1:
16043 gen_cp1(ctx, mips32_op, rt, rs);
16044 break;
16045
16046 /* Reciprocal square root */
16047 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16048 mips32_op = OPC_RSQRT_S;
16049 goto do_unaryfp;
16050 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16051 mips32_op = OPC_RSQRT_D;
16052 goto do_unaryfp;
16053
16054 /* Square root */
16055 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16056 mips32_op = OPC_SQRT_S;
16057 goto do_unaryfp;
16058 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16059 mips32_op = OPC_SQRT_D;
16060 goto do_unaryfp;
16061
16062 /* Reciprocal */
16063 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16064 mips32_op = OPC_RECIP_S;
16065 goto do_unaryfp;
16066 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16067 mips32_op = OPC_RECIP_D;
16068 goto do_unaryfp;
16069
16070 /* Floor */
16071 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16072 mips32_op = OPC_FLOOR_L_S;
16073 goto do_unaryfp;
16074 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16075 mips32_op = OPC_FLOOR_L_D;
16076 goto do_unaryfp;
16077 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16078 mips32_op = OPC_FLOOR_W_S;
16079 goto do_unaryfp;
16080 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16081 mips32_op = OPC_FLOOR_W_D;
16082 goto do_unaryfp;
16083
16084 /* Ceiling */
16085 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16086 mips32_op = OPC_CEIL_L_S;
16087 goto do_unaryfp;
16088 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16089 mips32_op = OPC_CEIL_L_D;
16090 goto do_unaryfp;
16091 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16092 mips32_op = OPC_CEIL_W_S;
16093 goto do_unaryfp;
16094 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16095 mips32_op = OPC_CEIL_W_D;
16096 goto do_unaryfp;
16097
16098 /* Truncation */
16099 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16100 mips32_op = OPC_TRUNC_L_S;
16101 goto do_unaryfp;
16102 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16103 mips32_op = OPC_TRUNC_L_D;
16104 goto do_unaryfp;
16105 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16106 mips32_op = OPC_TRUNC_W_S;
16107 goto do_unaryfp;
16108 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16109 mips32_op = OPC_TRUNC_W_D;
16110 goto do_unaryfp;
16111
16112 /* Round */
16113 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16114 mips32_op = OPC_ROUND_L_S;
16115 goto do_unaryfp;
16116 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16117 mips32_op = OPC_ROUND_L_D;
16118 goto do_unaryfp;
16119 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16120 mips32_op = OPC_ROUND_W_S;
16121 goto do_unaryfp;
16122 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16123 mips32_op = OPC_ROUND_W_D;
16124 goto do_unaryfp;
16125
16126 /* Integer to floating-point conversion */
16127 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16128 mips32_op = OPC_CVT_L_S;
16129 goto do_unaryfp;
16130 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16131 mips32_op = OPC_CVT_L_D;
16132 goto do_unaryfp;
16133 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16134 mips32_op = OPC_CVT_W_S;
16135 goto do_unaryfp;
16136 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16137 mips32_op = OPC_CVT_W_D;
16138 goto do_unaryfp;
16139
16140 /* Paired-foo conversions */
16141 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16142 mips32_op = OPC_CVT_S_PL;
16143 goto do_unaryfp;
16144 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16145 mips32_op = OPC_CVT_S_PU;
16146 goto do_unaryfp;
16147 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16148 mips32_op = OPC_CVT_PW_PS;
16149 goto do_unaryfp;
16150 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16151 mips32_op = OPC_CVT_PS_PW;
16152 goto do_unaryfp;
16153
16154 /* Floating-point moves */
16155 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16156 mips32_op = OPC_MOV_S;
16157 goto do_unaryfp;
16158 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16159 mips32_op = OPC_MOV_D;
16160 goto do_unaryfp;
16161 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16162 mips32_op = OPC_MOV_PS;
16163 goto do_unaryfp;
16164
16165 /* Absolute value */
16166 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16167 mips32_op = OPC_ABS_S;
16168 goto do_unaryfp;
16169 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16170 mips32_op = OPC_ABS_D;
16171 goto do_unaryfp;
16172 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16173 mips32_op = OPC_ABS_PS;
16174 goto do_unaryfp;
16175
16176 /* Negation */
16177 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16178 mips32_op = OPC_NEG_S;
16179 goto do_unaryfp;
16180 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16181 mips32_op = OPC_NEG_D;
16182 goto do_unaryfp;
16183 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16184 mips32_op = OPC_NEG_PS;
16185 goto do_unaryfp;
16186
16187 /* Reciprocal square root step */
16188 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16189 mips32_op = OPC_RSQRT1_S;
16190 goto do_unaryfp;
16191 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16192 mips32_op = OPC_RSQRT1_D;
16193 goto do_unaryfp;
16194 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16195 mips32_op = OPC_RSQRT1_PS;
16196 goto do_unaryfp;
16197
16198 /* Reciprocal step */
16199 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16200 mips32_op = OPC_RECIP1_S;
16201 goto do_unaryfp;
16202 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16203 mips32_op = OPC_RECIP1_S;
16204 goto do_unaryfp;
16205 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16206 mips32_op = OPC_RECIP1_PS;
16207 goto do_unaryfp;
16208
16209 /* Conversions from double */
16210 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16211 mips32_op = OPC_CVT_D_S;
16212 goto do_unaryfp;
16213 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16214 mips32_op = OPC_CVT_D_W;
16215 goto do_unaryfp;
16216 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16217 mips32_op = OPC_CVT_D_L;
16218 goto do_unaryfp;
16219
16220 /* Conversions from single */
16221 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16222 mips32_op = OPC_CVT_S_D;
16223 goto do_unaryfp;
16224 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16225 mips32_op = OPC_CVT_S_W;
16226 goto do_unaryfp;
16227 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16228 mips32_op = OPC_CVT_S_L;
16229 do_unaryfp:
16230 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16231 break;
16232
16233 /* Conditional moves on floating-point codes */
16234 case COND_FLOAT_MOV(MOVT, 0):
16235 case COND_FLOAT_MOV(MOVT, 1):
16236 case COND_FLOAT_MOV(MOVT, 2):
16237 case COND_FLOAT_MOV(MOVT, 3):
16238 case COND_FLOAT_MOV(MOVT, 4):
16239 case COND_FLOAT_MOV(MOVT, 5):
16240 case COND_FLOAT_MOV(MOVT, 6):
16241 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 16242 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16243 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16244 break;
16245 case COND_FLOAT_MOV(MOVF, 0):
16246 case COND_FLOAT_MOV(MOVF, 1):
16247 case COND_FLOAT_MOV(MOVF, 2):
16248 case COND_FLOAT_MOV(MOVF, 3):
16249 case COND_FLOAT_MOV(MOVF, 4):
16250 case COND_FLOAT_MOV(MOVF, 5):
16251 case COND_FLOAT_MOV(MOVF, 6):
16252 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 16253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16254 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16255 break;
16256 default:
16257 MIPS_INVAL("pool32fxf");
9c708c7f 16258 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16259 break;
16260 }
16261}
16262
f60eeb0c 16263static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16264{
16265 int32_t offset;
16266 uint16_t insn;
16267 int rt, rs, rd, rr;
16268 int16_t imm;
8fffc646 16269 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
16270 uint32_t cond, fmt, cc;
16271
eeb3bba8 16272 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
16273 ctx->opcode = (ctx->opcode << 16) | insn;
16274
16275 rt = (ctx->opcode >> 21) & 0x1f;
16276 rs = (ctx->opcode >> 16) & 0x1f;
16277 rd = (ctx->opcode >> 11) & 0x1f;
16278 rr = (ctx->opcode >> 6) & 0x1f;
16279 imm = (int16_t) ctx->opcode;
16280
16281 op = (ctx->opcode >> 26) & 0x3f;
16282 switch (op) {
16283 case POOL32A:
16284 minor = ctx->opcode & 0x3f;
16285 switch (minor) {
16286 case 0x00:
16287 minor = (ctx->opcode >> 6) & 0xf;
16288 switch (minor) {
16289 case SLL32:
16290 mips32_op = OPC_SLL;
16291 goto do_shifti;
16292 case SRA:
16293 mips32_op = OPC_SRA;
16294 goto do_shifti;
16295 case SRL32:
16296 mips32_op = OPC_SRL;
16297 goto do_shifti;
16298 case ROTR:
16299 mips32_op = OPC_ROTR;
16300 do_shifti:
d75c135e 16301 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 16302 break;
e0332095
YK
16303 case SELEQZ:
16304 check_insn(ctx, ISA_MIPS32R6);
16305 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16306 break;
16307 case SELNEZ:
16308 check_insn(ctx, ISA_MIPS32R6);
16309 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16310 break;
b00c7218
YK
16311 case R6_RDHWR:
16312 check_insn(ctx, ISA_MIPS32R6);
16313 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16314 break;
3c824109
NF
16315 default:
16316 goto pool32a_invalid;
16317 }
16318 break;
16319 case 0x10:
16320 minor = (ctx->opcode >> 6) & 0xf;
16321 switch (minor) {
16322 /* Arithmetic */
16323 case ADD:
16324 mips32_op = OPC_ADD;
16325 goto do_arith;
16326 case ADDU32:
16327 mips32_op = OPC_ADDU;
16328 goto do_arith;
16329 case SUB:
16330 mips32_op = OPC_SUB;
16331 goto do_arith;
16332 case SUBU32:
16333 mips32_op = OPC_SUBU;
16334 goto do_arith;
16335 case MUL:
9e8f441a 16336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16337 mips32_op = OPC_MUL;
16338 do_arith:
d75c135e 16339 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16340 break;
16341 /* Shifts */
16342 case SLLV:
16343 mips32_op = OPC_SLLV;
16344 goto do_shift;
16345 case SRLV:
16346 mips32_op = OPC_SRLV;
16347 goto do_shift;
16348 case SRAV:
16349 mips32_op = OPC_SRAV;
16350 goto do_shift;
16351 case ROTRV:
16352 mips32_op = OPC_ROTRV;
16353 do_shift:
d75c135e 16354 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16355 break;
16356 /* Logical operations */
16357 case AND:
16358 mips32_op = OPC_AND;
16359 goto do_logic;
16360 case OR32:
16361 mips32_op = OPC_OR;
16362 goto do_logic;
16363 case NOR:
16364 mips32_op = OPC_NOR;
16365 goto do_logic;
16366 case XOR32:
16367 mips32_op = OPC_XOR;
16368 do_logic:
d75c135e 16369 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16370 break;
16371 /* Set less than */
16372 case SLT:
16373 mips32_op = OPC_SLT;
16374 goto do_slt;
16375 case SLTU:
16376 mips32_op = OPC_SLTU;
16377 do_slt:
d75c135e 16378 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16379 break;
16380 default:
16381 goto pool32a_invalid;
16382 }
16383 break;
16384 case 0x18:
16385 minor = (ctx->opcode >> 6) & 0xf;
16386 switch (minor) {
16387 /* Conditional moves */
e0332095
YK
16388 case MOVN: /* MUL */
16389 if (ctx->insn_flags & ISA_MIPS32R6) {
16390 /* MUL */
16391 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16392 } else {
16393 /* MOVN */
16394 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16395 }
16396 break;
16397 case MOVZ: /* MUH */
16398 if (ctx->insn_flags & ISA_MIPS32R6) {
16399 /* MUH */
16400 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16401 } else {
16402 /* MOVZ */
16403 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16404 }
16405 break;
16406 case MULU:
16407 check_insn(ctx, ISA_MIPS32R6);
16408 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16409 break;
16410 case MUHU:
16411 check_insn(ctx, ISA_MIPS32R6);
16412 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16413 break;
16414 case LWXS: /* DIV */
16415 if (ctx->insn_flags & ISA_MIPS32R6) {
16416 /* DIV */
16417 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16418 } else {
16419 /* LWXS */
16420 gen_ldxs(ctx, rs, rt, rd);
16421 }
16422 break;
16423 case MOD:
16424 check_insn(ctx, ISA_MIPS32R6);
16425 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16426 break;
16427 case R6_DIVU:
16428 check_insn(ctx, ISA_MIPS32R6);
16429 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16430 break;
e0332095
YK
16431 case MODU:
16432 check_insn(ctx, ISA_MIPS32R6);
16433 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16434 break;
16435 default:
16436 goto pool32a_invalid;
16437 }
16438 break;
16439 case INS:
16440 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16441 return;
e0332095
YK
16442 case LSA:
16443 check_insn(ctx, ISA_MIPS32R6);
16444 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16445 extract32(ctx->opcode, 9, 2));
16446 break;
16447 case ALIGN:
16448 check_insn(ctx, ISA_MIPS32R6);
821f2008 16449 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16450 break;
3c824109
NF
16451 case EXT:
16452 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16453 return;
16454 case POOL32AXF:
240ce26a 16455 gen_pool32axf(env, ctx, rt, rs);
3c824109 16456 break;
dbd8af98 16457 case BREAK32:
9c708c7f 16458 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16459 break;
bb238210
YK
16460 case SIGRIE:
16461 check_insn(ctx, ISA_MIPS32R6);
16462 generate_exception_end(ctx, EXCP_RI);
16463 break;
3c824109
NF
16464 default:
16465 pool32a_invalid:
16466 MIPS_INVAL("pool32a");
9c708c7f 16467 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16468 break;
16469 }
16470 break;
16471 case POOL32B:
16472 minor = (ctx->opcode >> 12) & 0xf;
16473 switch (minor) {
16474 case CACHE:
2e15497c 16475 check_cp0_enabled(ctx);
0d74a222
LA
16476 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16477 gen_cache_operation(ctx, rt, rs, imm);
16478 }
3c824109
NF
16479 break;
16480 case LWC2:
16481 case SWC2:
16482 /* COP2: Not implemented. */
16483 generate_exception_err(ctx, EXCP_CpU, 2);
16484 break;
3c824109
NF
16485#ifdef TARGET_MIPS64
16486 case LDP:
16487 case SDP:
d9224450
MR
16488 check_insn(ctx, ISA_MIPS3);
16489 check_mips_64(ctx);
3c824109 16490#endif
146dd620 16491 /* fall through */
d9224450
MR
16492 case LWP:
16493 case SWP:
3c824109
NF
16494 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16495 break;
3c824109
NF
16496#ifdef TARGET_MIPS64
16497 case LDM:
16498 case SDM:
d9224450
MR
16499 check_insn(ctx, ISA_MIPS3);
16500 check_mips_64(ctx);
3c824109 16501#endif
146dd620 16502 /* fall through */
d9224450
MR
16503 case LWM32:
16504 case SWM32:
3c824109
NF
16505 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16506 break;
16507 default:
16508 MIPS_INVAL("pool32b");
9c708c7f 16509 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16510 break;
16511 }
16512 break;
16513 case POOL32F:
5ab5c041 16514 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16515 minor = ctx->opcode & 0x3f;
16516 check_cp1_enabled(ctx);
16517 switch (minor) {
16518 case ALNV_PS:
9e8f441a 16519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16520 mips32_op = OPC_ALNV_PS;
16521 goto do_madd;
16522 case MADD_S:
9e8f441a 16523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16524 mips32_op = OPC_MADD_S;
16525 goto do_madd;
16526 case MADD_D:
9e8f441a 16527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16528 mips32_op = OPC_MADD_D;
16529 goto do_madd;
16530 case MADD_PS:
9e8f441a 16531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16532 mips32_op = OPC_MADD_PS;
16533 goto do_madd;
16534 case MSUB_S:
9e8f441a 16535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16536 mips32_op = OPC_MSUB_S;
16537 goto do_madd;
16538 case MSUB_D:
9e8f441a 16539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16540 mips32_op = OPC_MSUB_D;
16541 goto do_madd;
16542 case MSUB_PS:
9e8f441a 16543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16544 mips32_op = OPC_MSUB_PS;
16545 goto do_madd;
16546 case NMADD_S:
9e8f441a 16547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16548 mips32_op = OPC_NMADD_S;
16549 goto do_madd;
16550 case NMADD_D:
9e8f441a 16551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16552 mips32_op = OPC_NMADD_D;
16553 goto do_madd;
16554 case NMADD_PS:
9e8f441a 16555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16556 mips32_op = OPC_NMADD_PS;
16557 goto do_madd;
16558 case NMSUB_S:
9e8f441a 16559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16560 mips32_op = OPC_NMSUB_S;
16561 goto do_madd;
16562 case NMSUB_D:
9e8f441a 16563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16564 mips32_op = OPC_NMSUB_D;
16565 goto do_madd;
16566 case NMSUB_PS:
9e8f441a 16567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16568 mips32_op = OPC_NMSUB_PS;
16569 do_madd:
16570 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16571 break;
16572 case CABS_COND_FMT:
9e8f441a 16573 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16574 cond = (ctx->opcode >> 6) & 0xf;
16575 cc = (ctx->opcode >> 13) & 0x7;
16576 fmt = (ctx->opcode >> 10) & 0x3;
16577 switch (fmt) {
16578 case 0x0:
16579 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16580 break;
16581 case 0x1:
16582 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16583 break;
16584 case 0x2:
16585 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16586 break;
16587 default:
16588 goto pool32f_invalid;
16589 }
16590 break;
16591 case C_COND_FMT:
9e8f441a 16592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16593 cond = (ctx->opcode >> 6) & 0xf;
16594 cc = (ctx->opcode >> 13) & 0x7;
16595 fmt = (ctx->opcode >> 10) & 0x3;
16596 switch (fmt) {
16597 case 0x0:
16598 gen_cmp_s(ctx, cond, rt, rs, cc);
16599 break;
16600 case 0x1:
16601 gen_cmp_d(ctx, cond, rt, rs, cc);
16602 break;
16603 case 0x2:
16604 gen_cmp_ps(ctx, cond, rt, rs, cc);
16605 break;
16606 default:
16607 goto pool32f_invalid;
16608 }
16609 break;
2a24a7ba
YK
16610 case CMP_CONDN_S:
16611 check_insn(ctx, ISA_MIPS32R6);
16612 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16613 break;
16614 case CMP_CONDN_D:
16615 check_insn(ctx, ISA_MIPS32R6);
16616 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16617 break;
3c824109 16618 case POOL32FXF:
d75c135e 16619 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
16620 break;
16621 case 0x00:
16622 /* PLL foo */
16623 switch ((ctx->opcode >> 6) & 0x7) {
16624 case PLL_PS:
16625 mips32_op = OPC_PLL_PS;
16626 goto do_ps;
16627 case PLU_PS:
16628 mips32_op = OPC_PLU_PS;
16629 goto do_ps;
16630 case PUL_PS:
16631 mips32_op = OPC_PUL_PS;
16632 goto do_ps;
16633 case PUU_PS:
16634 mips32_op = OPC_PUU_PS;
16635 goto do_ps;
16636 case CVT_PS_S:
9e8f441a 16637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16638 mips32_op = OPC_CVT_PS_S;
16639 do_ps:
16640 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16641 break;
16642 default:
16643 goto pool32f_invalid;
16644 }
16645 break;
2a24a7ba
YK
16646 case MIN_FMT:
16647 check_insn(ctx, ISA_MIPS32R6);
16648 switch ((ctx->opcode >> 9) & 0x3) {
16649 case FMT_SDPS_S:
16650 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16651 break;
16652 case FMT_SDPS_D:
16653 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16654 break;
16655 default:
16656 goto pool32f_invalid;
16657 }
16658 break;
3c824109
NF
16659 case 0x08:
16660 /* [LS][WDU]XC1 */
16661 switch ((ctx->opcode >> 6) & 0x7) {
16662 case LWXC1:
9e8f441a 16663 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16664 mips32_op = OPC_LWXC1;
16665 goto do_ldst_cp1;
16666 case SWXC1:
9e8f441a 16667 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16668 mips32_op = OPC_SWXC1;
16669 goto do_ldst_cp1;
16670 case LDXC1:
9e8f441a 16671 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16672 mips32_op = OPC_LDXC1;
16673 goto do_ldst_cp1;
16674 case SDXC1:
9e8f441a 16675 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16676 mips32_op = OPC_SDXC1;
16677 goto do_ldst_cp1;
16678 case LUXC1:
9e8f441a 16679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16680 mips32_op = OPC_LUXC1;
16681 goto do_ldst_cp1;
16682 case SUXC1:
9e8f441a 16683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16684 mips32_op = OPC_SUXC1;
16685 do_ldst_cp1:
16686 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16687 break;
16688 default:
16689 goto pool32f_invalid;
16690 }
16691 break;
2a24a7ba
YK
16692 case MAX_FMT:
16693 check_insn(ctx, ISA_MIPS32R6);
16694 switch ((ctx->opcode >> 9) & 0x3) {
16695 case FMT_SDPS_S:
16696 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16697 break;
16698 case FMT_SDPS_D:
16699 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16700 break;
16701 default:
16702 goto pool32f_invalid;
16703 }
16704 break;
3c824109
NF
16705 case 0x18:
16706 /* 3D insns */
9e8f441a 16707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16708 fmt = (ctx->opcode >> 9) & 0x3;
16709 switch ((ctx->opcode >> 6) & 0x7) {
16710 case RSQRT2_FMT:
16711 switch (fmt) {
16712 case FMT_SDPS_S:
16713 mips32_op = OPC_RSQRT2_S;
16714 goto do_3d;
16715 case FMT_SDPS_D:
16716 mips32_op = OPC_RSQRT2_D;
16717 goto do_3d;
16718 case FMT_SDPS_PS:
16719 mips32_op = OPC_RSQRT2_PS;
16720 goto do_3d;
16721 default:
16722 goto pool32f_invalid;
16723 }
16724 break;
16725 case RECIP2_FMT:
16726 switch (fmt) {
16727 case FMT_SDPS_S:
16728 mips32_op = OPC_RECIP2_S;
16729 goto do_3d;
16730 case FMT_SDPS_D:
16731 mips32_op = OPC_RECIP2_D;
16732 goto do_3d;
16733 case FMT_SDPS_PS:
16734 mips32_op = OPC_RECIP2_PS;
16735 goto do_3d;
16736 default:
16737 goto pool32f_invalid;
16738 }
16739 break;
16740 case ADDR_PS:
16741 mips32_op = OPC_ADDR_PS;
16742 goto do_3d;
16743 case MULR_PS:
16744 mips32_op = OPC_MULR_PS;
16745 do_3d:
16746 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16747 break;
16748 default:
16749 goto pool32f_invalid;
16750 }
16751 break;
16752 case 0x20:
2a24a7ba 16753 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16754 cc = (ctx->opcode >> 13) & 0x7;
16755 fmt = (ctx->opcode >> 9) & 0x3;
16756 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16757 case MOVF_FMT: /* RINT_FMT */
16758 if (ctx->insn_flags & ISA_MIPS32R6) {
16759 /* RINT_FMT */
16760 switch (fmt) {
16761 case FMT_SDPS_S:
16762 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16763 break;
16764 case FMT_SDPS_D:
16765 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16766 break;
16767 default:
16768 goto pool32f_invalid;
16769 }
16770 } else {
16771 /* MOVF_FMT */
16772 switch (fmt) {
16773 case FMT_SDPS_S:
16774 gen_movcf_s(ctx, rs, rt, cc, 0);
16775 break;
16776 case FMT_SDPS_D:
16777 gen_movcf_d(ctx, rs, rt, cc, 0);
16778 break;
16779 case FMT_SDPS_PS:
16780 check_ps(ctx);
16781 gen_movcf_ps(ctx, rs, rt, cc, 0);
16782 break;
16783 default:
16784 goto pool32f_invalid;
16785 }
3c824109
NF
16786 }
16787 break;
2a24a7ba
YK
16788 case MOVT_FMT: /* CLASS_FMT */
16789 if (ctx->insn_flags & ISA_MIPS32R6) {
16790 /* CLASS_FMT */
16791 switch (fmt) {
16792 case FMT_SDPS_S:
16793 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16794 break;
16795 case FMT_SDPS_D:
16796 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16797 break;
16798 default:
16799 goto pool32f_invalid;
16800 }
16801 } else {
16802 /* MOVT_FMT */
16803 switch (fmt) {
16804 case FMT_SDPS_S:
16805 gen_movcf_s(ctx, rs, rt, cc, 1);
16806 break;
16807 case FMT_SDPS_D:
16808 gen_movcf_d(ctx, rs, rt, cc, 1);
16809 break;
16810 case FMT_SDPS_PS:
16811 check_ps(ctx);
16812 gen_movcf_ps(ctx, rs, rt, cc, 1);
16813 break;
16814 default:
16815 goto pool32f_invalid;
16816 }
3c824109
NF
16817 }
16818 break;
16819 case PREFX:
9e8f441a 16820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16821 break;
16822 default:
16823 goto pool32f_invalid;
16824 }
16825 break;
16826#define FINSN_3ARG_SDPS(prfx) \
16827 switch ((ctx->opcode >> 8) & 0x3) { \
16828 case FMT_SDPS_S: \
16829 mips32_op = OPC_##prfx##_S; \
16830 goto do_fpop; \
16831 case FMT_SDPS_D: \
16832 mips32_op = OPC_##prfx##_D; \
16833 goto do_fpop; \
16834 case FMT_SDPS_PS: \
e29c9628 16835 check_ps(ctx); \
3c824109
NF
16836 mips32_op = OPC_##prfx##_PS; \
16837 goto do_fpop; \
16838 default: \
16839 goto pool32f_invalid; \
16840 }
2a24a7ba
YK
16841 case MINA_FMT:
16842 check_insn(ctx, ISA_MIPS32R6);
16843 switch ((ctx->opcode >> 9) & 0x3) {
16844 case FMT_SDPS_S:
16845 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16846 break;
16847 case FMT_SDPS_D:
16848 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16849 break;
16850 default:
16851 goto pool32f_invalid;
16852 }
16853 break;
16854 case MAXA_FMT:
16855 check_insn(ctx, ISA_MIPS32R6);
16856 switch ((ctx->opcode >> 9) & 0x3) {
16857 case FMT_SDPS_S:
16858 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16859 break;
16860 case FMT_SDPS_D:
16861 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16862 break;
16863 default:
16864 goto pool32f_invalid;
16865 }
16866 break;
3c824109
NF
16867 case 0x30:
16868 /* regular FP ops */
16869 switch ((ctx->opcode >> 6) & 0x3) {
16870 case ADD_FMT:
16871 FINSN_3ARG_SDPS(ADD);
16872 break;
16873 case SUB_FMT:
16874 FINSN_3ARG_SDPS(SUB);
16875 break;
16876 case MUL_FMT:
16877 FINSN_3ARG_SDPS(MUL);
16878 break;
16879 case DIV_FMT:
16880 fmt = (ctx->opcode >> 8) & 0x3;
16881 if (fmt == 1) {
16882 mips32_op = OPC_DIV_D;
16883 } else if (fmt == 0) {
16884 mips32_op = OPC_DIV_S;
16885 } else {
16886 goto pool32f_invalid;
16887 }
16888 goto do_fpop;
16889 default:
16890 goto pool32f_invalid;
16891 }
16892 break;
16893 case 0x38:
16894 /* cmovs */
2a24a7ba 16895 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16896 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16897 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16898 /* SELEQZ_FMT */
2a24a7ba
YK
16899 switch ((ctx->opcode >> 9) & 0x3) {
16900 case FMT_SDPS_S:
fdac60cd 16901 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16902 break;
16903 case FMT_SDPS_D:
fdac60cd 16904 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16905 break;
16906 default:
16907 goto pool32f_invalid;
16908 }
16909 } else {
16910 /* MOVN_FMT */
16911 FINSN_3ARG_SDPS(MOVN);
16912 }
16913 break;
16914 case MOVN_FMT_04:
16915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16916 FINSN_3ARG_SDPS(MOVN);
16917 break;
fdac60cd 16918 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16919 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16920 /* SELNEZ_FMT */
2a24a7ba
YK
16921 switch ((ctx->opcode >> 9) & 0x3) {
16922 case FMT_SDPS_S:
fdac60cd 16923 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16924 break;
16925 case FMT_SDPS_D:
fdac60cd 16926 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16927 break;
16928 default:
16929 goto pool32f_invalid;
16930 }
16931 } else {
16932 /* MOVZ_FMT */
16933 FINSN_3ARG_SDPS(MOVZ);
16934 }
16935 break;
16936 case MOVZ_FMT_05:
16937 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16938 FINSN_3ARG_SDPS(MOVZ);
16939 break;
2a24a7ba
YK
16940 case SEL_FMT:
16941 check_insn(ctx, ISA_MIPS32R6);
16942 switch ((ctx->opcode >> 9) & 0x3) {
16943 case FMT_SDPS_S:
16944 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16945 break;
16946 case FMT_SDPS_D:
16947 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16948 break;
16949 default:
16950 goto pool32f_invalid;
16951 }
16952 break;
16953 case MADDF_FMT:
16954 check_insn(ctx, ISA_MIPS32R6);
16955 switch ((ctx->opcode >> 9) & 0x3) {
16956 case FMT_SDPS_S:
16957 mips32_op = OPC_MADDF_S;
16958 goto do_fpop;
16959 case FMT_SDPS_D:
16960 mips32_op = OPC_MADDF_D;
16961 goto do_fpop;
16962 default:
16963 goto pool32f_invalid;
16964 }
16965 break;
16966 case MSUBF_FMT:
16967 check_insn(ctx, ISA_MIPS32R6);
16968 switch ((ctx->opcode >> 9) & 0x3) {
16969 case FMT_SDPS_S:
16970 mips32_op = OPC_MSUBF_S;
16971 goto do_fpop;
16972 case FMT_SDPS_D:
16973 mips32_op = OPC_MSUBF_D;
16974 goto do_fpop;
16975 default:
16976 goto pool32f_invalid;
16977 }
16978 break;
3c824109
NF
16979 default:
16980 goto pool32f_invalid;
16981 }
16982 break;
16983 do_fpop:
16984 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16985 break;
16986 default:
16987 pool32f_invalid:
16988 MIPS_INVAL("pool32f");
9c708c7f 16989 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16990 break;
16991 }
16992 } else {
16993 generate_exception_err(ctx, EXCP_CpU, 1);
16994 }
16995 break;
16996 case POOL32I:
16997 minor = (ctx->opcode >> 21) & 0x1f;
16998 switch (minor) {
16999 case BLTZ:
9e8f441a 17000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17001 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17002 break;
3c824109 17003 case BLTZAL:
9e8f441a 17004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17005 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17006 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17007 break;
3c824109 17008 case BLTZALS:
9e8f441a 17009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17010 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17011 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17012 break;
3c824109 17013 case BGEZ:
9e8f441a 17014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17015 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17016 break;
3c824109 17017 case BGEZAL:
9e8f441a 17018 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17019 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17020 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17021 break;
3c824109 17022 case BGEZALS:
9e8f441a 17023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17024 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17025 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17026 break;
3c824109 17027 case BLEZ:
9e8f441a 17028 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
17029 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17030 break;
3c824109 17031 case BGTZ:
9e8f441a 17032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 17033 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
17034 break;
17035
17036 /* Traps */
65935f07
YK
17037 case TLTI: /* BC1EQZC */
17038 if (ctx->insn_flags & ISA_MIPS32R6) {
17039 /* BC1EQZC */
17040 check_cp1_enabled(ctx);
17041 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17042 } else {
17043 /* TLTI */
17044 mips32_op = OPC_TLTI;
17045 goto do_trapi;
17046 }
17047 break;
17048 case TGEI: /* BC1NEZC */
17049 if (ctx->insn_flags & ISA_MIPS32R6) {
17050 /* BC1NEZC */
17051 check_cp1_enabled(ctx);
17052 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17053 } else {
17054 /* TGEI */
17055 mips32_op = OPC_TGEI;
17056 goto do_trapi;
17057 }
17058 break;
3c824109 17059 case TLTIU:
9e8f441a 17060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17061 mips32_op = OPC_TLTIU;
17062 goto do_trapi;
17063 case TGEIU:
9e8f441a 17064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17065 mips32_op = OPC_TGEIU;
17066 goto do_trapi;
3b4a5489
YK
17067 case TNEI: /* SYNCI */
17068 if (ctx->insn_flags & ISA_MIPS32R6) {
17069 /* SYNCI */
7480515f
AM
17070 /*
17071 * Break the TB to be able to sync copied instructions
17072 * immediately.
17073 */
eeb3bba8 17074 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
17075 } else {
17076 /* TNEI */
17077 mips32_op = OPC_TNEI;
17078 goto do_trapi;
17079 }
17080 break;
3c824109 17081 case TEQI:
9e8f441a 17082 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17083 mips32_op = OPC_TEQI;
17084 do_trapi:
17085 gen_trap(ctx, mips32_op, rs, -1, imm);
17086 break;
17087
17088 case BNEZC:
17089 case BEQZC:
9e8f441a 17090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17091 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 17092 4, rs, 0, imm << 1, 0);
7480515f
AM
17093 /*
17094 * Compact branches don't have a delay slot, so just let
17095 * the normal delay slot handling take us to the branch
17096 * target.
17097 */
3c824109
NF
17098 break;
17099 case LUI:
9e8f441a 17100 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 17101 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
17102 break;
17103 case SYNCI:
9e8f441a 17104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7480515f
AM
17105 /*
17106 * Break the TB to be able to sync copied instructions
17107 * immediately.
17108 */
eeb3bba8 17109 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
17110 break;
17111 case BC2F:
17112 case BC2T:
9e8f441a 17113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17114 /* COP2: Not implemented. */
17115 generate_exception_err(ctx, EXCP_CpU, 2);
17116 break;
17117 case BC1F:
9e8f441a 17118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17119 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17120 goto do_cp1branch;
17121 case BC1T:
9e8f441a 17122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17123 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17124 goto do_cp1branch;
17125 case BC1ANY4F:
9e8f441a 17126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17127 mips32_op = OPC_BC1FANY4;
17128 goto do_cp1mips3d;
17129 case BC1ANY4T:
9e8f441a 17130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17131 mips32_op = OPC_BC1TANY4;
17132 do_cp1mips3d:
17133 check_cop1x(ctx);
d75c135e 17134 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
17135 /* Fall through */
17136 do_cp1branch:
272f458d
MR
17137 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17138 check_cp1_enabled(ctx);
17139 gen_compute_branch1(ctx, mips32_op,
17140 (ctx->opcode >> 18) & 0x7, imm << 1);
17141 } else {
17142 generate_exception_err(ctx, EXCP_CpU, 1);
17143 }
3c824109
NF
17144 break;
17145 case BPOSGE64:
17146 case BPOSGE32:
17147 /* MIPS DSP: not implemented */
17148 /* Fall through */
17149 default:
17150 MIPS_INVAL("pool32i");
9c708c7f 17151 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17152 break;
17153 }
17154 break;
17155 case POOL32C:
17156 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
17157 offset = sextract32(ctx->opcode, 0,
17158 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
17159 switch (minor) {
17160 case LWL:
9e8f441a 17161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17162 mips32_op = OPC_LWL;
5c13fdfd 17163 goto do_ld_lr;
3c824109 17164 case SWL:
9e8f441a 17165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17166 mips32_op = OPC_SWL;
5c13fdfd 17167 goto do_st_lr;
3c824109 17168 case LWR:
9e8f441a 17169 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17170 mips32_op = OPC_LWR;
5c13fdfd 17171 goto do_ld_lr;
3c824109 17172 case SWR:
9e8f441a 17173 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17174 mips32_op = OPC_SWR;
5c13fdfd 17175 goto do_st_lr;
3c824109
NF
17176#if defined(TARGET_MIPS64)
17177 case LDL:
d9224450
MR
17178 check_insn(ctx, ISA_MIPS3);
17179 check_mips_64(ctx);
9e8f441a 17180 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17181 mips32_op = OPC_LDL;
5c13fdfd 17182 goto do_ld_lr;
3c824109 17183 case SDL:
d9224450
MR
17184 check_insn(ctx, ISA_MIPS3);
17185 check_mips_64(ctx);
9e8f441a 17186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17187 mips32_op = OPC_SDL;
5c13fdfd 17188 goto do_st_lr;
3c824109 17189 case LDR:
d9224450
MR
17190 check_insn(ctx, ISA_MIPS3);
17191 check_mips_64(ctx);
9e8f441a 17192 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17193 mips32_op = OPC_LDR;
5c13fdfd 17194 goto do_ld_lr;
3c824109 17195 case SDR:
d9224450
MR
17196 check_insn(ctx, ISA_MIPS3);
17197 check_mips_64(ctx);
9e8f441a 17198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17199 mips32_op = OPC_SDR;
5c13fdfd 17200 goto do_st_lr;
3c824109 17201 case LWU:
d9224450
MR
17202 check_insn(ctx, ISA_MIPS3);
17203 check_mips_64(ctx);
3c824109 17204 mips32_op = OPC_LWU;
5c13fdfd 17205 goto do_ld_lr;
3c824109 17206 case LLD:
d9224450
MR
17207 check_insn(ctx, ISA_MIPS3);
17208 check_mips_64(ctx);
3c824109 17209 mips32_op = OPC_LLD;
5c13fdfd 17210 goto do_ld_lr;
3c824109
NF
17211#endif
17212 case LL:
17213 mips32_op = OPC_LL;
5c13fdfd
AJ
17214 goto do_ld_lr;
17215 do_ld_lr:
3b4a5489 17216 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
17217 break;
17218 do_st_lr:
8fffc646 17219 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
17220 break;
17221 case SC:
33a07fa2 17222 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
17223 break;
17224#if defined(TARGET_MIPS64)
17225 case SCD:
d9224450
MR
17226 check_insn(ctx, ISA_MIPS3);
17227 check_mips_64(ctx);
33a07fa2 17228 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
17229 break;
17230#endif
8fffc646
JH
17231 case LD_EVA:
17232 if (!ctx->eva) {
17233 MIPS_INVAL("pool32c ld-eva");
17234 generate_exception_end(ctx, EXCP_RI);
17235 break;
17236 }
17237 check_cp0_enabled(ctx);
17238
17239 minor2 = (ctx->opcode >> 9) & 0x7;
17240 offset = sextract32(ctx->opcode, 0, 9);
17241 switch (minor2) {
17242 case LBUE:
17243 mips32_op = OPC_LBUE;
17244 goto do_ld_lr;
17245 case LHUE:
17246 mips32_op = OPC_LHUE;
17247 goto do_ld_lr;
17248 case LWLE:
17249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17250 mips32_op = OPC_LWLE;
17251 goto do_ld_lr;
17252 case LWRE:
17253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17254 mips32_op = OPC_LWRE;
17255 goto do_ld_lr;
17256 case LBE:
17257 mips32_op = OPC_LBE;
17258 goto do_ld_lr;
17259 case LHE:
17260 mips32_op = OPC_LHE;
17261 goto do_ld_lr;
17262 case LLE:
17263 mips32_op = OPC_LLE;
17264 goto do_ld_lr;
17265 case LWE:
17266 mips32_op = OPC_LWE;
17267 goto do_ld_lr;
17268 };
17269 break;
17270 case ST_EVA:
17271 if (!ctx->eva) {
17272 MIPS_INVAL("pool32c st-eva");
17273 generate_exception_end(ctx, EXCP_RI);
17274 break;
17275 }
17276 check_cp0_enabled(ctx);
17277
17278 minor2 = (ctx->opcode >> 9) & 0x7;
17279 offset = sextract32(ctx->opcode, 0, 9);
17280 switch (minor2) {
17281 case SWLE:
17282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17283 mips32_op = OPC_SWLE;
17284 goto do_st_lr;
17285 case SWRE:
17286 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17287 mips32_op = OPC_SWRE;
17288 goto do_st_lr;
17289 case PREFE:
17290 /* Treat as no-op */
17291 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17292 /* hint codes 24-31 are reserved and signal RI */
17293 generate_exception(ctx, EXCP_RI);
17294 }
17295 break;
17296 case CACHEE:
17297 /* Treat as no-op */
17298 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17299 gen_cache_operation(ctx, rt, rs, offset);
17300 }
17301 break;
17302 case SBE:
17303 mips32_op = OPC_SBE;
17304 goto do_st_lr;
17305 case SHE:
17306 mips32_op = OPC_SHE;
17307 goto do_st_lr;
17308 case SCE:
33a07fa2 17309 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
17310 break;
17311 case SWE:
17312 mips32_op = OPC_SWE;
17313 goto do_st_lr;
17314 };
17315 break;
3c824109
NF
17316 case PREF:
17317 /* Treat as no-op */
3b4a5489
YK
17318 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17319 /* hint codes 24-31 are reserved and signal RI */
17320 generate_exception(ctx, EXCP_RI);
17321 }
3c824109
NF
17322 break;
17323 default:
17324 MIPS_INVAL("pool32c");
9c708c7f 17325 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17326 break;
17327 }
17328 break;
ab39ee45
YK
17329 case ADDI32: /* AUI, LUI */
17330 if (ctx->insn_flags & ISA_MIPS32R6) {
17331 /* AUI, LUI */
17332 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17333 } else {
17334 /* ADDI32 */
17335 mips32_op = OPC_ADDI;
17336 goto do_addi;
17337 }
17338 break;
3c824109
NF
17339 case ADDIU32:
17340 mips32_op = OPC_ADDIU;
17341 do_addi:
d75c135e 17342 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17343 break;
17344
17345 /* Logical operations */
17346 case ORI32:
17347 mips32_op = OPC_ORI;
17348 goto do_logici;
17349 case XORI32:
17350 mips32_op = OPC_XORI;
17351 goto do_logici;
17352 case ANDI32:
17353 mips32_op = OPC_ANDI;
17354 do_logici:
d75c135e 17355 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17356 break;
17357
17358 /* Set less than immediate */
17359 case SLTI32:
17360 mips32_op = OPC_SLTI;
17361 goto do_slti;
17362 case SLTIU32:
17363 mips32_op = OPC_SLTIU;
17364 do_slti:
d75c135e 17365 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17366 break;
17367 case JALX32:
9e8f441a 17368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17369 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17370 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17371 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17372 break;
65935f07
YK
17373 case JALS32: /* BOVC, BEQC, BEQZALC */
17374 if (ctx->insn_flags & ISA_MIPS32R6) {
17375 if (rs >= rt) {
17376 /* BOVC */
17377 mips32_op = OPC_BOVC;
17378 } else if (rs < rt && rs == 0) {
17379 /* BEQZALC */
17380 mips32_op = OPC_BEQZALC;
17381 } else {
17382 /* BEQC */
17383 mips32_op = OPC_BEQC;
17384 }
17385 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17386 } else {
17387 /* JALS32 */
17388 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17389 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17390 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17391 }
3c824109 17392 break;
65935f07
YK
17393 case BEQ32: /* BC */
17394 if (ctx->insn_flags & ISA_MIPS32R6) {
17395 /* BC */
17396 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17397 sextract32(ctx->opcode << 1, 0, 27));
17398 } else {
17399 /* BEQ32 */
17400 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17401 }
3c824109 17402 break;
65935f07
YK
17403 case BNE32: /* BALC */
17404 if (ctx->insn_flags & ISA_MIPS32R6) {
17405 /* BALC */
17406 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17407 sextract32(ctx->opcode << 1, 0, 27));
17408 } else {
17409 /* BNE32 */
17410 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17411 }
3c824109 17412 break;
65935f07
YK
17413 case J32: /* BGTZC, BLTZC, BLTC */
17414 if (ctx->insn_flags & ISA_MIPS32R6) {
17415 if (rs == 0 && rt != 0) {
17416 /* BGTZC */
17417 mips32_op = OPC_BGTZC;
17418 } else if (rs != 0 && rt != 0 && rs == rt) {
17419 /* BLTZC */
17420 mips32_op = OPC_BLTZC;
17421 } else {
17422 /* BLTC */
17423 mips32_op = OPC_BLTC;
17424 }
17425 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17426 } else {
17427 /* J32 */
17428 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17429 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17430 }
3c824109 17431 break;
65935f07
YK
17432 case JAL32: /* BLEZC, BGEZC, BGEC */
17433 if (ctx->insn_flags & ISA_MIPS32R6) {
17434 if (rs == 0 && rt != 0) {
17435 /* BLEZC */
17436 mips32_op = OPC_BLEZC;
17437 } else if (rs != 0 && rt != 0 && rs == rt) {
17438 /* BGEZC */
17439 mips32_op = OPC_BGEZC;
17440 } else {
17441 /* BGEC */
17442 mips32_op = OPC_BGEC;
17443 }
17444 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17445 } else {
17446 /* JAL32 */
17447 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17448 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17449 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17450 }
3c824109
NF
17451 break;
17452 /* Floating point (COP1) */
17453 case LWC132:
17454 mips32_op = OPC_LWC1;
17455 goto do_cop1;
17456 case LDC132:
17457 mips32_op = OPC_LDC1;
17458 goto do_cop1;
17459 case SWC132:
17460 mips32_op = OPC_SWC1;
17461 goto do_cop1;
17462 case SDC132:
17463 mips32_op = OPC_SDC1;
17464 do_cop1:
5ab5c041 17465 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17466 break;
ab39ee45
YK
17467 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17468 if (ctx->insn_flags & ISA_MIPS32R6) {
17469 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17470 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17471 case ADDIUPC_00:
17472 case ADDIUPC_01:
17473 case ADDIUPC_02:
17474 case ADDIUPC_03:
17475 case ADDIUPC_04:
17476 case ADDIUPC_05:
17477 case ADDIUPC_06:
17478 case ADDIUPC_07:
eeb3bba8 17479 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17480 break;
17481 case AUIPC:
eeb3bba8 17482 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17483 break;
17484 case ALUIPC:
eeb3bba8 17485 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17486 break;
c38a1d52
AR
17487 case LWPC_08:
17488 case LWPC_09:
17489 case LWPC_0A:
17490 case LWPC_0B:
17491 case LWPC_0C:
17492 case LWPC_0D:
17493 case LWPC_0E:
17494 case LWPC_0F:
eeb3bba8 17495 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17496 break;
17497 default:
17498 generate_exception(ctx, EXCP_RI);
17499 break;
17500 }
17501 } else {
17502 /* ADDIUPC */
3c824109 17503 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17504 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17505
17506 gen_addiupc(ctx, reg, offset, 0, 0);
17507 }
17508 break;
65935f07
YK
17509 case BNVC: /* BNEC, BNEZALC */
17510 check_insn(ctx, ISA_MIPS32R6);
17511 if (rs >= rt) {
17512 /* BNVC */
17513 mips32_op = OPC_BNVC;
17514 } else if (rs < rt && rs == 0) {
17515 /* BNEZALC */
17516 mips32_op = OPC_BNEZALC;
17517 } else {
17518 /* BNEC */
17519 mips32_op = OPC_BNEC;
17520 }
17521 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17522 break;
17523 case R6_BNEZC: /* JIALC */
17524 check_insn(ctx, ISA_MIPS32R6);
17525 if (rt != 0) {
17526 /* BNEZC */
17527 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17528 sextract32(ctx->opcode << 1, 0, 22));
17529 } else {
17530 /* JIALC */
17531 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17532 }
17533 break;
17534 case R6_BEQZC: /* JIC */
17535 check_insn(ctx, ISA_MIPS32R6);
17536 if (rt != 0) {
17537 /* BEQZC */
17538 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17539 sextract32(ctx->opcode << 1, 0, 22));
17540 } else {
17541 /* JIC */
17542 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17543 }
17544 break;
17545 case BLEZALC: /* BGEZALC, BGEUC */
17546 check_insn(ctx, ISA_MIPS32R6);
17547 if (rs == 0 && rt != 0) {
17548 /* BLEZALC */
17549 mips32_op = OPC_BLEZALC;
17550 } else if (rs != 0 && rt != 0 && rs == rt) {
17551 /* BGEZALC */
17552 mips32_op = OPC_BGEZALC;
17553 } else {
17554 /* BGEUC */
17555 mips32_op = OPC_BGEUC;
17556 }
17557 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17558 break;
17559 case BGTZALC: /* BLTZALC, BLTUC */
17560 check_insn(ctx, ISA_MIPS32R6);
17561 if (rs == 0 && rt != 0) {
17562 /* BGTZALC */
17563 mips32_op = OPC_BGTZALC;
17564 } else if (rs != 0 && rt != 0 && rs == rt) {
17565 /* BLTZALC */
17566 mips32_op = OPC_BLTZALC;
17567 } else {
17568 /* BLTUC */
17569 mips32_op = OPC_BLTUC;
17570 }
17571 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17572 break;
3c824109
NF
17573 /* Loads and stores */
17574 case LB32:
17575 mips32_op = OPC_LB;
5c13fdfd 17576 goto do_ld;
3c824109
NF
17577 case LBU32:
17578 mips32_op = OPC_LBU;
5c13fdfd 17579 goto do_ld;
3c824109
NF
17580 case LH32:
17581 mips32_op = OPC_LH;
5c13fdfd 17582 goto do_ld;
3c824109
NF
17583 case LHU32:
17584 mips32_op = OPC_LHU;
5c13fdfd 17585 goto do_ld;
3c824109
NF
17586 case LW32:
17587 mips32_op = OPC_LW;
5c13fdfd 17588 goto do_ld;
3c824109
NF
17589#ifdef TARGET_MIPS64
17590 case LD32:
d9224450
MR
17591 check_insn(ctx, ISA_MIPS3);
17592 check_mips_64(ctx);
3c824109 17593 mips32_op = OPC_LD;
5c13fdfd 17594 goto do_ld;
3c824109 17595 case SD32:
d9224450
MR
17596 check_insn(ctx, ISA_MIPS3);
17597 check_mips_64(ctx);
3c824109 17598 mips32_op = OPC_SD;
5c13fdfd 17599 goto do_st;
3c824109
NF
17600#endif
17601 case SB32:
17602 mips32_op = OPC_SB;
5c13fdfd 17603 goto do_st;
3c824109
NF
17604 case SH32:
17605 mips32_op = OPC_SH;
5c13fdfd 17606 goto do_st;
3c824109
NF
17607 case SW32:
17608 mips32_op = OPC_SW;
5c13fdfd
AJ
17609 goto do_st;
17610 do_ld:
d75c135e 17611 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
17612 break;
17613 do_st:
17614 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17615 break;
17616 default:
9c708c7f 17617 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17618 break;
17619 }
17620}
17621
235785e8 17622static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
17623{
17624 uint32_t op;
17625
17626 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
17627 if (ctx->base.pc_next & 0x1) {
17628 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 17629 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
17630 return 2;
17631 }
17632
17633 op = (ctx->opcode >> 10) & 0x3f;
17634 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
17635 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17636 switch (op & 0x7) { /* MSB-3..MSB-5 */
17637 case 0:
17638 /* POOL32A, POOL32B, POOL32I, POOL32C */
17639 case 4:
17640 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17641 case 5:
17642 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17643 case 6:
17644 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17645 case 7:
17646 /* LB32, LH32, LWC132, LDC132, LW32 */
17647 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 17648 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17649 return 2;
17650 }
17651 break;
b231c103
YK
17652 case 1:
17653 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17654 case 2:
17655 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17656 case 3:
17657 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17658 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 17659 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17660 return 2;
17661 }
17662 break;
3c824109
NF
17663 }
17664 }
b231c103 17665
3c824109
NF
17666 switch (op) {
17667 case POOL16A:
17668 {
17669 int rd = mmreg(uMIPS_RD(ctx->opcode));
17670 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17671 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17672 uint32_t opc = 0;
17673
17674 switch (ctx->opcode & 0x1) {
17675 case ADDU16:
17676 opc = OPC_ADDU;
17677 break;
17678 case SUBU16:
17679 opc = OPC_SUBU;
17680 break;
17681 }
ed7ce6c0 17682 if (ctx->insn_flags & ISA_MIPS32R6) {
7480515f
AM
17683 /*
17684 * In the Release 6, the register number location in
ed7ce6c0
YK
17685 * the instruction encoding has changed.
17686 */
17687 gen_arith(ctx, opc, rs1, rd, rs2);
17688 } else {
17689 gen_arith(ctx, opc, rd, rs1, rs2);
17690 }
3c824109
NF
17691 }
17692 break;
17693 case POOL16B:
17694 {
17695 int rd = mmreg(uMIPS_RD(ctx->opcode));
17696 int rs = mmreg(uMIPS_RS(ctx->opcode));
17697 int amount = (ctx->opcode >> 1) & 0x7;
17698 uint32_t opc = 0;
17699 amount = amount == 0 ? 8 : amount;
17700
17701 switch (ctx->opcode & 0x1) {
17702 case SLL16:
17703 opc = OPC_SLL;
17704 break;
17705 case SRL16:
17706 opc = OPC_SRL;
17707 break;
17708 }
17709
d75c135e 17710 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17711 }
17712 break;
17713 case POOL16C:
ed7ce6c0
YK
17714 if (ctx->insn_flags & ISA_MIPS32R6) {
17715 gen_pool16c_r6_insn(ctx);
17716 } else {
17717 gen_pool16c_insn(ctx);
17718 }
3c824109
NF
17719 break;
17720 case LWGP16:
17721 {
17722 int rd = mmreg(uMIPS_RD(ctx->opcode));
17723 int rb = 28; /* GP */
17724 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17725
d75c135e 17726 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17727 }
17728 break;
17729 case POOL16F:
9e8f441a 17730 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17731 if (ctx->opcode & 1) {
9c708c7f 17732 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17733 } else {
17734 /* MOVEP */
17735 int enc_dest = uMIPS_RD(ctx->opcode);
17736 int enc_rt = uMIPS_RS2(ctx->opcode);
17737 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17738 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17739 }
17740 break;
17741 case LBU16:
17742 {
17743 int rd = mmreg(uMIPS_RD(ctx->opcode));
17744 int rb = mmreg(uMIPS_RS(ctx->opcode));
17745 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17746 offset = (offset == 0xf ? -1 : offset);
17747
d75c135e 17748 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17749 }
17750 break;
17751 case LHU16:
17752 {
17753 int rd = mmreg(uMIPS_RD(ctx->opcode));
17754 int rb = mmreg(uMIPS_RS(ctx->opcode));
17755 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17756
d75c135e 17757 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17758 }
17759 break;
17760 case LWSP16:
17761 {
17762 int rd = (ctx->opcode >> 5) & 0x1f;
17763 int rb = 29; /* SP */
17764 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17765
d75c135e 17766 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17767 }
17768 break;
17769 case LW16:
17770 {
17771 int rd = mmreg(uMIPS_RD(ctx->opcode));
17772 int rb = mmreg(uMIPS_RS(ctx->opcode));
17773 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17774
d75c135e 17775 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17776 }
17777 break;
17778 case SB16:
17779 {
17780 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17781 int rb = mmreg(uMIPS_RS(ctx->opcode));
17782 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17783
5c13fdfd 17784 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17785 }
17786 break;
17787 case SH16:
17788 {
17789 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17790 int rb = mmreg(uMIPS_RS(ctx->opcode));
17791 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17792
5c13fdfd 17793 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17794 }
17795 break;
17796 case SWSP16:
17797 {
17798 int rd = (ctx->opcode >> 5) & 0x1f;
17799 int rb = 29; /* SP */
17800 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17801
5c13fdfd 17802 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17803 }
17804 break;
17805 case SW16:
17806 {
17807 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17808 int rb = mmreg(uMIPS_RS(ctx->opcode));
17809 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17810
5c13fdfd 17811 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17812 }
17813 break;
17814 case MOVE16:
17815 {
17816 int rd = uMIPS_RD5(ctx->opcode);
17817 int rs = uMIPS_RS5(ctx->opcode);
17818
7215d7e7 17819 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17820 }
17821 break;
17822 case ANDI16:
d75c135e 17823 gen_andi16(ctx);
3c824109
NF
17824 break;
17825 case POOL16D:
17826 switch (ctx->opcode & 0x1) {
17827 case ADDIUS5:
d75c135e 17828 gen_addius5(ctx);
3c824109
NF
17829 break;
17830 case ADDIUSP:
d75c135e 17831 gen_addiusp(ctx);
3c824109
NF
17832 break;
17833 }
17834 break;
17835 case POOL16E:
17836 switch (ctx->opcode & 0x1) {
17837 case ADDIUR2:
d75c135e 17838 gen_addiur2(ctx);
3c824109
NF
17839 break;
17840 case ADDIUR1SP:
d75c135e 17841 gen_addiur1sp(ctx);
3c824109
NF
17842 break;
17843 }
17844 break;
65935f07 17845 case B16: /* BC16 */
3c824109 17846 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17847 sextract32(ctx->opcode, 0, 10) << 1,
17848 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17849 break;
65935f07
YK
17850 case BNEZ16: /* BNEZC16 */
17851 case BEQZ16: /* BEQZC16 */
3c824109
NF
17852 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17853 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17854 0, sextract32(ctx->opcode, 0, 7) << 1,
17855 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17856
3c824109
NF
17857 break;
17858 case LI16:
17859 {
17860 int reg = mmreg(uMIPS_RD(ctx->opcode));
17861 int imm = ZIMM(ctx->opcode, 0, 7);
17862
17863 imm = (imm == 0x7f ? -1 : imm);
17864 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17865 }
17866 break;
3c824109 17867 case RES_29:
3c824109 17868 case RES_31:
3c824109 17869 case RES_39:
9c708c7f 17870 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17871 break;
17872 default:
f60eeb0c 17873 decode_micromips32_opc(env, ctx);
3c824109
NF
17874 return 4;
17875 }
17876
17877 return 2;
17878}
17879
261c95a0
YK
17880/*
17881 *
17882 * nanoMIPS opcodes
17883 *
17884 */
17885
17886/* MAJOR, P16, and P32 pools opcodes */
17887enum {
17888 NM_P_ADDIU = 0x00,
17889 NM_ADDIUPC = 0x01,
17890 NM_MOVE_BALC = 0x02,
17891 NM_P16_MV = 0x04,
17892 NM_LW16 = 0x05,
17893 NM_BC16 = 0x06,
17894 NM_P16_SR = 0x07,
17895
17896 NM_POOL32A = 0x08,
17897 NM_P_BAL = 0x0a,
17898 NM_P16_SHIFT = 0x0c,
17899 NM_LWSP16 = 0x0d,
17900 NM_BALC16 = 0x0e,
17901 NM_P16_4X4 = 0x0f,
17902
17903 NM_P_GP_W = 0x10,
17904 NM_P_GP_BH = 0x11,
17905 NM_P_J = 0x12,
17906 NM_P16C = 0x14,
17907 NM_LWGP16 = 0x15,
17908 NM_P16_LB = 0x17,
17909
17910 NM_P48I = 0x18,
17911 NM_P16_A1 = 0x1c,
17912 NM_LW4X4 = 0x1d,
17913 NM_P16_LH = 0x1f,
17914
17915 NM_P_U12 = 0x20,
17916 NM_P_LS_U12 = 0x21,
17917 NM_P_BR1 = 0x22,
17918 NM_P16_A2 = 0x24,
17919 NM_SW16 = 0x25,
17920 NM_BEQZC16 = 0x26,
17921
17922 NM_POOL32F = 0x28,
17923 NM_P_LS_S9 = 0x29,
17924 NM_P_BR2 = 0x2a,
17925
17926 NM_P16_ADDU = 0x2c,
17927 NM_SWSP16 = 0x2d,
17928 NM_BNEZC16 = 0x2e,
17929 NM_MOVEP = 0x2f,
17930
17931 NM_POOL32S = 0x30,
17932 NM_P_BRI = 0x32,
17933 NM_LI16 = 0x34,
17934 NM_SWGP16 = 0x35,
17935 NM_P16_BR = 0x36,
17936
17937 NM_P_LUI = 0x38,
17938 NM_ANDI16 = 0x3c,
17939 NM_SW4X4 = 0x3d,
17940 NM_MOVEPREV = 0x3f,
17941};
17942
17943/* POOL32A instruction pool */
17944enum {
17945 NM_POOL32A0 = 0x00,
17946 NM_SPECIAL2 = 0x01,
17947 NM_COP2_1 = 0x02,
17948 NM_UDI = 0x03,
17949 NM_POOL32A5 = 0x05,
17950 NM_POOL32A7 = 0x07,
17951};
17952
17953/* P.GP.W instruction pool */
17954enum {
17955 NM_ADDIUGP_W = 0x00,
17956 NM_LWGP = 0x02,
17957 NM_SWGP = 0x03,
17958};
17959
17960/* P48I instruction pool */
17961enum {
17962 NM_LI48 = 0x00,
17963 NM_ADDIU48 = 0x01,
17964 NM_ADDIUGP48 = 0x02,
17965 NM_ADDIUPC48 = 0x03,
17966 NM_LWPC48 = 0x0b,
17967 NM_SWPC48 = 0x0f,
17968};
17969
17970/* P.U12 instruction pool */
17971enum {
17972 NM_ORI = 0x00,
17973 NM_XORI = 0x01,
17974 NM_ANDI = 0x02,
17975 NM_P_SR = 0x03,
17976 NM_SLTI = 0x04,
17977 NM_SLTIU = 0x05,
17978 NM_SEQI = 0x06,
17979 NM_ADDIUNEG = 0x08,
17980 NM_P_SHIFT = 0x0c,
17981 NM_P_ROTX = 0x0d,
17982 NM_P_INS = 0x0e,
17983 NM_P_EXT = 0x0f,
17984};
17985
17986/* POOL32F instruction pool */
17987enum {
17988 NM_POOL32F_0 = 0x00,
17989 NM_POOL32F_3 = 0x03,
17990 NM_POOL32F_5 = 0x05,
17991};
17992
17993/* POOL32S instruction pool */
17994enum {
17995 NM_POOL32S_0 = 0x00,
17996 NM_POOL32S_4 = 0x04,
17997};
17998
17999/* P.LUI instruction pool */
18000enum {
18001 NM_LUI = 0x00,
18002 NM_ALUIPC = 0x01,
18003};
18004
18005/* P.GP.BH instruction pool */
18006enum {
18007 NM_LBGP = 0x00,
18008 NM_SBGP = 0x01,
18009 NM_LBUGP = 0x02,
18010 NM_ADDIUGP_B = 0x03,
18011 NM_P_GP_LH = 0x04,
18012 NM_P_GP_SH = 0x05,
18013 NM_P_GP_CP1 = 0x06,
18014};
18015
18016/* P.LS.U12 instruction pool */
18017enum {
18018 NM_LB = 0x00,
18019 NM_SB = 0x01,
18020 NM_LBU = 0x02,
18021 NM_P_PREFU12 = 0x03,
18022 NM_LH = 0x04,
18023 NM_SH = 0x05,
18024 NM_LHU = 0x06,
18025 NM_LWU = 0x07,
18026 NM_LW = 0x08,
18027 NM_SW = 0x09,
18028 NM_LWC1 = 0x0a,
18029 NM_SWC1 = 0x0b,
18030 NM_LDC1 = 0x0e,
18031 NM_SDC1 = 0x0f,
18032};
18033
18034/* P.LS.S9 instruction pool */
18035enum {
18036 NM_P_LS_S0 = 0x00,
18037 NM_P_LS_S1 = 0x01,
18038 NM_P_LS_E0 = 0x02,
18039 NM_P_LS_WM = 0x04,
18040 NM_P_LS_UAWM = 0x05,
18041};
18042
18043/* P.BAL instruction pool */
18044enum {
18045 NM_BC = 0x00,
18046 NM_BALC = 0x01,
18047};
18048
18049/* P.J instruction pool */
18050enum {
18051 NM_JALRC = 0x00,
18052 NM_JALRC_HB = 0x01,
18053 NM_P_BALRSC = 0x08,
18054};
18055
18056/* P.BR1 instruction pool */
18057enum {
18058 NM_BEQC = 0x00,
18059 NM_P_BR3A = 0x01,
18060 NM_BGEC = 0x02,
18061 NM_BGEUC = 0x03,
18062};
18063
18064/* P.BR2 instruction pool */
18065enum {
18066 NM_BNEC = 0x00,
18067 NM_BLTC = 0x02,
18068 NM_BLTUC = 0x03,
18069};
18070
18071/* P.BRI instruction pool */
18072enum {
18073 NM_BEQIC = 0x00,
18074 NM_BBEQZC = 0x01,
18075 NM_BGEIC = 0x02,
18076 NM_BGEIUC = 0x03,
18077 NM_BNEIC = 0x04,
18078 NM_BBNEZC = 0x05,
18079 NM_BLTIC = 0x06,
18080 NM_BLTIUC = 0x07,
18081};
18082
18083/* P16.SHIFT instruction pool */
18084enum {
18085 NM_SLL16 = 0x00,
18086 NM_SRL16 = 0x01,
18087};
18088
18089/* POOL16C instruction pool */
18090enum {
18091 NM_POOL16C_0 = 0x00,
18092 NM_LWXS16 = 0x01,
18093};
18094
18095/* P16.A1 instruction pool */
18096enum {
18097 NM_ADDIUR1SP = 0x01,
18098};
18099
18100/* P16.A2 instruction pool */
18101enum {
18102 NM_ADDIUR2 = 0x00,
18103 NM_P_ADDIURS5 = 0x01,
18104};
18105
18106/* P16.ADDU instruction pool */
18107enum {
18108 NM_ADDU16 = 0x00,
18109 NM_SUBU16 = 0x01,
18110};
18111
18112/* P16.SR instruction pool */
18113enum {
18114 NM_SAVE16 = 0x00,
18115 NM_RESTORE_JRC16 = 0x01,
18116};
18117
18118/* P16.4X4 instruction pool */
18119enum {
18120 NM_ADDU4X4 = 0x00,
18121 NM_MUL4X4 = 0x01,
18122};
18123
18124/* P16.LB instruction pool */
18125enum {
18126 NM_LB16 = 0x00,
18127 NM_SB16 = 0x01,
18128 NM_LBU16 = 0x02,
18129};
18130
18131/* P16.LH instruction pool */
18132enum {
18133 NM_LH16 = 0x00,
18134 NM_SH16 = 0x01,
18135 NM_LHU16 = 0x02,
18136};
18137
18138/* P.RI instruction pool */
18139enum {
18140 NM_SIGRIE = 0x00,
18141 NM_P_SYSCALL = 0x01,
18142 NM_BREAK = 0x02,
18143 NM_SDBBP = 0x03,
18144};
18145
18146/* POOL32A0 instruction pool */
18147enum {
18148 NM_P_TRAP = 0x00,
18149 NM_SEB = 0x01,
18150 NM_SLLV = 0x02,
18151 NM_MUL = 0x03,
18152 NM_MFC0 = 0x06,
18153 NM_MFHC0 = 0x07,
18154 NM_SEH = 0x09,
18155 NM_SRLV = 0x0a,
18156 NM_MUH = 0x0b,
18157 NM_MTC0 = 0x0e,
18158 NM_MTHC0 = 0x0f,
18159 NM_SRAV = 0x12,
18160 NM_MULU = 0x13,
18161 NM_ROTRV = 0x1a,
18162 NM_MUHU = 0x1b,
18163 NM_ADD = 0x22,
18164 NM_DIV = 0x23,
18165 NM_ADDU = 0x2a,
18166 NM_MOD = 0x2b,
18167 NM_SUB = 0x32,
18168 NM_DIVU = 0x33,
18169 NM_RDHWR = 0x38,
18170 NM_SUBU = 0x3a,
18171 NM_MODU = 0x3b,
18172 NM_P_CMOVE = 0x42,
18173 NM_FORK = 0x45,
18174 NM_MFTR = 0x46,
18175 NM_MFHTR = 0x47,
18176 NM_AND = 0x4a,
18177 NM_YIELD = 0x4d,
18178 NM_MTTR = 0x4e,
18179 NM_MTHTR = 0x4f,
18180 NM_OR = 0x52,
18181 NM_D_E_MT_VPE = 0x56,
18182 NM_NOR = 0x5a,
18183 NM_XOR = 0x62,
18184 NM_SLT = 0x6a,
18185 NM_P_SLTU = 0x72,
18186 NM_SOV = 0x7a,
18187};
18188
ba1e8117
AM
18189/* CRC32 instruction pool */
18190enum {
18191 NM_CRC32B = 0x00,
18192 NM_CRC32H = 0x01,
18193 NM_CRC32W = 0x02,
18194 NM_CRC32CB = 0x04,
18195 NM_CRC32CH = 0x05,
18196 NM_CRC32CW = 0x06,
18197};
18198
b3979b6f
SM
18199/* POOL32A5 instruction pool */
18200enum {
18201 NM_CMP_EQ_PH = 0x00,
18202 NM_CMP_LT_PH = 0x08,
18203 NM_CMP_LE_PH = 0x10,
18204 NM_CMPGU_EQ_QB = 0x18,
18205 NM_CMPGU_LT_QB = 0x20,
18206 NM_CMPGU_LE_QB = 0x28,
18207 NM_CMPGDU_EQ_QB = 0x30,
18208 NM_CMPGDU_LT_QB = 0x38,
18209 NM_CMPGDU_LE_QB = 0x40,
18210 NM_CMPU_EQ_QB = 0x48,
18211 NM_CMPU_LT_QB = 0x50,
18212 NM_CMPU_LE_QB = 0x58,
18213 NM_ADDQ_S_W = 0x60,
18214 NM_SUBQ_S_W = 0x68,
18215 NM_ADDSC = 0x70,
18216 NM_ADDWC = 0x78,
18217
18218 NM_ADDQ_S_PH = 0x01,
18219 NM_ADDQH_R_PH = 0x09,
18220 NM_ADDQH_R_W = 0x11,
18221 NM_ADDU_S_QB = 0x19,
18222 NM_ADDU_S_PH = 0x21,
18223 NM_ADDUH_R_QB = 0x29,
18224 NM_SHRAV_R_PH = 0x31,
18225 NM_SHRAV_R_QB = 0x39,
18226 NM_SUBQ_S_PH = 0x41,
18227 NM_SUBQH_R_PH = 0x49,
18228 NM_SUBQH_R_W = 0x51,
18229 NM_SUBU_S_QB = 0x59,
18230 NM_SUBU_S_PH = 0x61,
18231 NM_SUBUH_R_QB = 0x69,
18232 NM_SHLLV_S_PH = 0x71,
18233 NM_PRECR_SRA_R_PH_W = 0x79,
18234
18235 NM_MULEU_S_PH_QBL = 0x12,
18236 NM_MULEU_S_PH_QBR = 0x1a,
18237 NM_MULQ_RS_PH = 0x22,
18238 NM_MULQ_S_PH = 0x2a,
18239 NM_MULQ_RS_W = 0x32,
18240 NM_MULQ_S_W = 0x3a,
18241 NM_APPEND = 0x42,
18242 NM_MODSUB = 0x52,
18243 NM_SHRAV_R_W = 0x5a,
18244 NM_SHRLV_PH = 0x62,
18245 NM_SHRLV_QB = 0x6a,
18246 NM_SHLLV_QB = 0x72,
18247 NM_SHLLV_S_W = 0x7a,
18248
18249 NM_SHILO = 0x03,
18250
18251 NM_MULEQ_S_W_PHL = 0x04,
18252 NM_MULEQ_S_W_PHR = 0x0c,
18253
18254 NM_MUL_S_PH = 0x05,
18255 NM_PRECR_QB_PH = 0x0d,
18256 NM_PRECRQ_QB_PH = 0x15,
18257 NM_PRECRQ_PH_W = 0x1d,
18258 NM_PRECRQ_RS_PH_W = 0x25,
18259 NM_PRECRQU_S_QB_PH = 0x2d,
18260 NM_PACKRL_PH = 0x35,
18261 NM_PICK_QB = 0x3d,
18262 NM_PICK_PH = 0x45,
18263
18264 NM_SHRA_R_W = 0x5e,
18265 NM_SHRA_R_PH = 0x66,
18266 NM_SHLL_S_PH = 0x76,
18267 NM_SHLL_S_W = 0x7e,
18268
18269 NM_REPL_PH = 0x07
18270};
18271
261c95a0
YK
18272/* POOL32A7 instruction pool */
18273enum {
18274 NM_P_LSX = 0x00,
18275 NM_LSA = 0x01,
18276 NM_EXTW = 0x03,
18277 NM_POOL32AXF = 0x07,
18278};
18279
18280/* P.SR instruction pool */
18281enum {
18282 NM_PP_SR = 0x00,
18283 NM_P_SR_F = 0x01,
18284};
18285
18286/* P.SHIFT instruction pool */
18287enum {
18288 NM_P_SLL = 0x00,
18289 NM_SRL = 0x02,
18290 NM_SRA = 0x04,
18291 NM_ROTR = 0x06,
18292};
18293
18294/* P.ROTX instruction pool */
18295enum {
18296 NM_ROTX = 0x00,
18297};
18298
18299/* P.INS instruction pool */
18300enum {
18301 NM_INS = 0x00,
18302};
18303
18304/* P.EXT instruction pool */
18305enum {
18306 NM_EXT = 0x00,
18307};
18308
18309/* POOL32F_0 (fmt) instruction pool */
18310enum {
18311 NM_RINT_S = 0x04,
18312 NM_RINT_D = 0x44,
18313 NM_ADD_S = 0x06,
18314 NM_SELEQZ_S = 0x07,
18315 NM_SELEQZ_D = 0x47,
18316 NM_CLASS_S = 0x0c,
18317 NM_CLASS_D = 0x4c,
18318 NM_SUB_S = 0x0e,
18319 NM_SELNEZ_S = 0x0f,
18320 NM_SELNEZ_D = 0x4f,
18321 NM_MUL_S = 0x16,
18322 NM_SEL_S = 0x17,
18323 NM_SEL_D = 0x57,
18324 NM_DIV_S = 0x1e,
18325 NM_ADD_D = 0x26,
18326 NM_SUB_D = 0x2e,
18327 NM_MUL_D = 0x36,
18328 NM_MADDF_S = 0x37,
18329 NM_MADDF_D = 0x77,
18330 NM_DIV_D = 0x3e,
18331 NM_MSUBF_S = 0x3f,
18332 NM_MSUBF_D = 0x7f,
18333};
18334
18335/* POOL32F_3 instruction pool */
18336enum {
18337 NM_MIN_FMT = 0x00,
18338 NM_MAX_FMT = 0x01,
18339 NM_MINA_FMT = 0x04,
18340 NM_MAXA_FMT = 0x05,
18341 NM_POOL32FXF = 0x07,
18342};
18343
18344/* POOL32F_5 instruction pool */
18345enum {
18346 NM_CMP_CONDN_S = 0x00,
18347 NM_CMP_CONDN_D = 0x02,
18348};
18349
18350/* P.GP.LH instruction pool */
18351enum {
18352 NM_LHGP = 0x00,
18353 NM_LHUGP = 0x01,
18354};
18355
18356/* P.GP.SH instruction pool */
18357enum {
18358 NM_SHGP = 0x00,
18359};
18360
18361/* P.GP.CP1 instruction pool */
18362enum {
18363 NM_LWC1GP = 0x00,
18364 NM_SWC1GP = 0x01,
18365 NM_LDC1GP = 0x02,
18366 NM_SDC1GP = 0x03,
18367};
18368
18369/* P.LS.S0 instruction pool */
18370enum {
18371 NM_LBS9 = 0x00,
18372 NM_LHS9 = 0x04,
18373 NM_LWS9 = 0x08,
18374 NM_LDS9 = 0x0c,
18375
18376 NM_SBS9 = 0x01,
18377 NM_SHS9 = 0x05,
18378 NM_SWS9 = 0x09,
18379 NM_SDS9 = 0x0d,
18380
18381 NM_LBUS9 = 0x02,
18382 NM_LHUS9 = 0x06,
18383 NM_LWC1S9 = 0x0a,
18384 NM_LDC1S9 = 0x0e,
18385
18386 NM_P_PREFS9 = 0x03,
18387 NM_LWUS9 = 0x07,
18388 NM_SWC1S9 = 0x0b,
18389 NM_SDC1S9 = 0x0f,
18390};
18391
18392/* P.LS.S1 instruction pool */
18393enum {
18394 NM_ASET_ACLR = 0x02,
18395 NM_UALH = 0x04,
18396 NM_UASH = 0x05,
18397 NM_CACHE = 0x07,
18398 NM_P_LL = 0x0a,
18399 NM_P_SC = 0x0b,
18400};
18401
0d30b3bb
DN
18402/* P.LS.E0 instruction pool */
18403enum {
18404 NM_LBE = 0x00,
18405 NM_SBE = 0x01,
18406 NM_LBUE = 0x02,
18407 NM_P_PREFE = 0x03,
18408 NM_LHE = 0x04,
18409 NM_SHE = 0x05,
18410 NM_LHUE = 0x06,
18411 NM_CACHEE = 0x07,
18412 NM_LWE = 0x08,
18413 NM_SWE = 0x09,
18414 NM_P_LLE = 0x0a,
18415 NM_P_SCE = 0x0b,
18416};
18417
18418/* P.PREFE instruction pool */
18419enum {
18420 NM_SYNCIE = 0x00,
18421 NM_PREFE = 0x01,
18422};
18423
18424/* P.LLE instruction pool */
18425enum {
18426 NM_LLE = 0x00,
18427 NM_LLWPE = 0x01,
18428};
18429
18430/* P.SCE instruction pool */
18431enum {
18432 NM_SCE = 0x00,
18433 NM_SCWPE = 0x01,
18434};
18435
261c95a0
YK
18436/* P.LS.WM instruction pool */
18437enum {
18438 NM_LWM = 0x00,
18439 NM_SWM = 0x01,
18440};
18441
18442/* P.LS.UAWM instruction pool */
18443enum {
18444 NM_UALWM = 0x00,
18445 NM_UASWM = 0x01,
18446};
18447
18448/* P.BR3A instruction pool */
18449enum {
18450 NM_BC1EQZC = 0x00,
18451 NM_BC1NEZC = 0x01,
18452 NM_BC2EQZC = 0x02,
18453 NM_BC2NEZC = 0x03,
18454 NM_BPOSGE32C = 0x04,
18455};
18456
18457/* P16.RI instruction pool */
18458enum {
18459 NM_P16_SYSCALL = 0x01,
18460 NM_BREAK16 = 0x02,
18461 NM_SDBBP16 = 0x03,
18462};
18463
18464/* POOL16C_0 instruction pool */
18465enum {
18466 NM_POOL16C_00 = 0x00,
18467};
18468
18469/* P16.JRC instruction pool */
18470enum {
18471 NM_JRC = 0x00,
18472 NM_JALRC16 = 0x01,
18473};
18474
18475/* P.SYSCALL instruction pool */
18476enum {
18477 NM_SYSCALL = 0x00,
18478 NM_HYPCALL = 0x01,
18479};
18480
18481/* P.TRAP instruction pool */
18482enum {
18483 NM_TEQ = 0x00,
18484 NM_TNE = 0x01,
18485};
18486
18487/* P.CMOVE instruction pool */
18488enum {
18489 NM_MOVZ = 0x00,
18490 NM_MOVN = 0x01,
18491};
18492
18493/* POOL32Axf instruction pool */
18494enum {
b3979b6f
SM
18495 NM_POOL32AXF_1 = 0x01,
18496 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18497 NM_POOL32AXF_4 = 0x04,
18498 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18499 NM_POOL32AXF_7 = 0x07,
18500};
18501
18502/* POOL32Axf_1 instruction pool */
18503enum {
18504 NM_POOL32AXF_1_0 = 0x00,
18505 NM_POOL32AXF_1_1 = 0x01,
18506 NM_POOL32AXF_1_3 = 0x03,
18507 NM_POOL32AXF_1_4 = 0x04,
18508 NM_POOL32AXF_1_5 = 0x05,
18509 NM_POOL32AXF_1_7 = 0x07,
18510};
18511
18512/* POOL32Axf_2 instruction pool */
18513enum {
18514 NM_POOL32AXF_2_0_7 = 0x00,
18515 NM_POOL32AXF_2_8_15 = 0x01,
18516 NM_POOL32AXF_2_16_23 = 0x02,
18517 NM_POOL32AXF_2_24_31 = 0x03,
18518};
18519
18520/* POOL32Axf_7 instruction pool */
18521enum {
18522 NM_SHRA_R_QB = 0x0,
18523 NM_SHRL_PH = 0x1,
18524 NM_REPL_QB = 0x2,
18525};
18526
18527/* POOL32Axf_1_0 instruction pool */
18528enum {
18529 NM_MFHI = 0x0,
18530 NM_MFLO = 0x1,
18531 NM_MTHI = 0x2,
18532 NM_MTLO = 0x3,
18533};
18534
18535/* POOL32Axf_1_1 instruction pool */
18536enum {
18537 NM_MTHLIP = 0x0,
18538 NM_SHILOV = 0x1,
18539};
18540
18541/* POOL32Axf_1_3 instruction pool */
18542enum {
18543 NM_RDDSP = 0x0,
18544 NM_WRDSP = 0x1,
18545 NM_EXTP = 0x2,
18546 NM_EXTPDP = 0x3,
18547};
18548
18549/* POOL32Axf_1_4 instruction pool */
18550enum {
18551 NM_SHLL_QB = 0x0,
18552 NM_SHRL_QB = 0x1,
18553};
18554
18555/* POOL32Axf_1_5 instruction pool */
18556enum {
18557 NM_MAQ_S_W_PHR = 0x0,
18558 NM_MAQ_S_W_PHL = 0x1,
18559 NM_MAQ_SA_W_PHR = 0x2,
18560 NM_MAQ_SA_W_PHL = 0x3,
18561};
18562
18563/* POOL32Axf_1_7 instruction pool */
18564enum {
18565 NM_EXTR_W = 0x0,
18566 NM_EXTR_R_W = 0x1,
18567 NM_EXTR_RS_W = 0x2,
18568 NM_EXTR_S_H = 0x3,
18569};
18570
18571/* POOL32Axf_2_0_7 instruction pool */
18572enum {
18573 NM_DPA_W_PH = 0x0,
18574 NM_DPAQ_S_W_PH = 0x1,
18575 NM_DPS_W_PH = 0x2,
18576 NM_DPSQ_S_W_PH = 0x3,
18577 NM_BALIGN = 0x4,
18578 NM_MADD = 0x5,
18579 NM_MULT = 0x6,
18580 NM_EXTRV_W = 0x7,
18581};
18582
18583/* POOL32Axf_2_8_15 instruction pool */
18584enum {
18585 NM_DPAX_W_PH = 0x0,
18586 NM_DPAQ_SA_L_W = 0x1,
18587 NM_DPSX_W_PH = 0x2,
18588 NM_DPSQ_SA_L_W = 0x3,
18589 NM_MADDU = 0x5,
18590 NM_MULTU = 0x6,
18591 NM_EXTRV_R_W = 0x7,
18592};
18593
18594/* POOL32Axf_2_16_23 instruction pool */
18595enum {
18596 NM_DPAU_H_QBL = 0x0,
18597 NM_DPAQX_S_W_PH = 0x1,
18598 NM_DPSU_H_QBL = 0x2,
18599 NM_DPSQX_S_W_PH = 0x3,
18600 NM_EXTPV = 0x4,
18601 NM_MSUB = 0x5,
18602 NM_MULSA_W_PH = 0x6,
18603 NM_EXTRV_RS_W = 0x7,
18604};
18605
18606/* POOL32Axf_2_24_31 instruction pool */
18607enum {
18608 NM_DPAU_H_QBR = 0x0,
18609 NM_DPAQX_SA_W_PH = 0x1,
18610 NM_DPSU_H_QBR = 0x2,
18611 NM_DPSQX_SA_W_PH = 0x3,
18612 NM_EXTPDPV = 0x4,
18613 NM_MSUBU = 0x5,
18614 NM_MULSAQ_S_W_PH = 0x6,
18615 NM_EXTRV_S_H = 0x7,
261c95a0
YK
18616};
18617
18618/* POOL32Axf_{4, 5} instruction pool */
18619enum {
18620 NM_CLO = 0x25,
18621 NM_CLZ = 0x2d,
18622
18623 NM_TLBP = 0x01,
18624 NM_TLBR = 0x09,
18625 NM_TLBWI = 0x11,
18626 NM_TLBWR = 0x19,
18627 NM_TLBINV = 0x03,
18628 NM_TLBINVF = 0x0b,
18629 NM_DI = 0x23,
18630 NM_EI = 0x2b,
18631 NM_RDPGPR = 0x70,
18632 NM_WRPGPR = 0x78,
18633 NM_WAIT = 0x61,
18634 NM_DERET = 0x71,
18635 NM_ERETX = 0x79,
b3979b6f
SM
18636
18637 /* nanoMIPS DSP instructions */
18638 NM_ABSQ_S_QB = 0x00,
18639 NM_ABSQ_S_PH = 0x08,
18640 NM_ABSQ_S_W = 0x10,
18641 NM_PRECEQ_W_PHL = 0x28,
18642 NM_PRECEQ_W_PHR = 0x30,
18643 NM_PRECEQU_PH_QBL = 0x38,
18644 NM_PRECEQU_PH_QBR = 0x48,
18645 NM_PRECEU_PH_QBL = 0x58,
18646 NM_PRECEU_PH_QBR = 0x68,
18647 NM_PRECEQU_PH_QBLA = 0x39,
18648 NM_PRECEQU_PH_QBRA = 0x49,
18649 NM_PRECEU_PH_QBLA = 0x59,
18650 NM_PRECEU_PH_QBRA = 0x69,
18651 NM_REPLV_PH = 0x01,
18652 NM_REPLV_QB = 0x09,
18653 NM_BITREV = 0x18,
18654 NM_INSV = 0x20,
18655 NM_RADDU_W_QB = 0x78,
18656
18657 NM_BITSWAP = 0x05,
18658 NM_WSBH = 0x3d,
261c95a0
YK
18659};
18660
18661/* PP.SR instruction pool */
18662enum {
18663 NM_SAVE = 0x00,
18664 NM_RESTORE = 0x02,
18665 NM_RESTORE_JRC = 0x03,
18666};
18667
18668/* P.SR.F instruction pool */
18669enum {
18670 NM_SAVEF = 0x00,
18671 NM_RESTOREF = 0x01,
18672};
18673
18674/* P16.SYSCALL instruction pool */
18675enum {
18676 NM_SYSCALL16 = 0x00,
18677 NM_HYPCALL16 = 0x01,
18678};
18679
18680/* POOL16C_00 instruction pool */
18681enum {
18682 NM_NOT16 = 0x00,
18683 NM_XOR16 = 0x01,
18684 NM_AND16 = 0x02,
18685 NM_OR16 = 0x03,
18686};
18687
18688/* PP.LSX and PP.LSXS instruction pool */
18689enum {
18690 NM_LBX = 0x00,
18691 NM_LHX = 0x04,
18692 NM_LWX = 0x08,
18693 NM_LDX = 0x0c,
18694
18695 NM_SBX = 0x01,
18696 NM_SHX = 0x05,
18697 NM_SWX = 0x09,
18698 NM_SDX = 0x0d,
18699
18700 NM_LBUX = 0x02,
18701 NM_LHUX = 0x06,
18702 NM_LWC1X = 0x0a,
18703 NM_LDC1X = 0x0e,
18704
18705 NM_LWUX = 0x07,
18706 NM_SWC1X = 0x0b,
18707 NM_SDC1X = 0x0f,
18708
18709 NM_LHXS = 0x04,
18710 NM_LWXS = 0x08,
18711 NM_LDXS = 0x0c,
18712
18713 NM_SHXS = 0x05,
18714 NM_SWXS = 0x09,
18715 NM_SDXS = 0x0d,
18716
18717 NM_LHUXS = 0x06,
18718 NM_LWC1XS = 0x0a,
18719 NM_LDC1XS = 0x0e,
18720
18721 NM_LWUXS = 0x07,
18722 NM_SWC1XS = 0x0b,
18723 NM_SDC1XS = 0x0f,
18724};
18725
18726/* ERETx instruction pool */
18727enum {
18728 NM_ERET = 0x00,
18729 NM_ERETNC = 0x01,
18730};
18731
18732/* POOL32FxF_{0, 1} insturction pool */
18733enum {
18734 NM_CFC1 = 0x40,
18735 NM_CTC1 = 0x60,
18736 NM_MFC1 = 0x80,
18737 NM_MTC1 = 0xa0,
18738 NM_MFHC1 = 0xc0,
18739 NM_MTHC1 = 0xe0,
18740
18741 NM_CVT_S_PL = 0x84,
18742 NM_CVT_S_PU = 0xa4,
18743
18744 NM_CVT_L_S = 0x004,
18745 NM_CVT_L_D = 0x104,
18746 NM_CVT_W_S = 0x024,
18747 NM_CVT_W_D = 0x124,
18748
18749 NM_RSQRT_S = 0x008,
18750 NM_RSQRT_D = 0x108,
18751
18752 NM_SQRT_S = 0x028,
18753 NM_SQRT_D = 0x128,
18754
18755 NM_RECIP_S = 0x048,
18756 NM_RECIP_D = 0x148,
18757
18758 NM_FLOOR_L_S = 0x00c,
18759 NM_FLOOR_L_D = 0x10c,
18760
18761 NM_FLOOR_W_S = 0x02c,
18762 NM_FLOOR_W_D = 0x12c,
18763
18764 NM_CEIL_L_S = 0x04c,
18765 NM_CEIL_L_D = 0x14c,
18766 NM_CEIL_W_S = 0x06c,
18767 NM_CEIL_W_D = 0x16c,
18768 NM_TRUNC_L_S = 0x08c,
18769 NM_TRUNC_L_D = 0x18c,
18770 NM_TRUNC_W_S = 0x0ac,
18771 NM_TRUNC_W_D = 0x1ac,
18772 NM_ROUND_L_S = 0x0cc,
18773 NM_ROUND_L_D = 0x1cc,
18774 NM_ROUND_W_S = 0x0ec,
18775 NM_ROUND_W_D = 0x1ec,
18776
18777 NM_MOV_S = 0x01,
18778 NM_MOV_D = 0x81,
18779 NM_ABS_S = 0x0d,
18780 NM_ABS_D = 0x8d,
18781 NM_NEG_S = 0x2d,
18782 NM_NEG_D = 0xad,
18783 NM_CVT_D_S = 0x04d,
18784 NM_CVT_D_W = 0x0cd,
18785 NM_CVT_D_L = 0x14d,
18786 NM_CVT_S_D = 0x06d,
18787 NM_CVT_S_W = 0x0ed,
18788 NM_CVT_S_L = 0x16d,
18789};
18790
18791/* P.LL instruction pool */
18792enum {
18793 NM_LL = 0x00,
18794 NM_LLWP = 0x01,
18795};
18796
18797/* P.SC instruction pool */
18798enum {
18799 NM_SC = 0x00,
18800 NM_SCWP = 0x01,
18801};
18802
18803/* P.DVP instruction pool */
18804enum {
18805 NM_DVP = 0x00,
18806 NM_EVP = 0x01,
18807};
18808
c533c0f4
AM
18809
18810/*
18811 *
18812 * nanoMIPS decoding engine
18813 *
18814 */
18815
6bfa9f4c
AM
18816
18817/* extraction utilities */
18818
99e49abf
AM
18819#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18820#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18821#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
18822#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18823#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18824
ea4ca3c2
YK
18825/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18826static inline int decode_gpr_gpr3(int r)
18827{
18828 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18829
18830 return map[r & 0x7];
18831}
18832
8bdb7029
YK
18833/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18834static inline int decode_gpr_gpr3_src_store(int r)
18835{
18836 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18837
18838 return map[r & 0x7];
18839}
18840
ea4ca3c2
YK
18841/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18842static inline int decode_gpr_gpr4(int r)
18843{
18844 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18845 16, 17, 18, 19, 20, 21, 22, 23 };
18846
18847 return map[r & 0xf];
18848}
18849
8bdb7029
YK
18850/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18851static inline int decode_gpr_gpr4_zero(int r)
18852{
18853 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18854 16, 17, 18, 19, 20, 21, 22, 23 };
18855
18856 return map[r & 0xf];
18857}
18858
6bfa9f4c 18859
bf0718c5
SM
18860static void gen_adjust_sp(DisasContext *ctx, int u)
18861{
18862 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18863}
18864
18865static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18866 uint8_t gp, uint16_t u)
18867{
18868 int counter = 0;
18869 TCGv va = tcg_temp_new();
18870 TCGv t0 = tcg_temp_new();
18871
18872 while (counter != count) {
18873 bool use_gp = gp && (counter == count - 1);
18874 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18875 int this_offset = -((counter + 1) << 2);
18876 gen_base_offset_addr(ctx, va, 29, this_offset);
18877 gen_load_gpr(t0, this_rt);
18878 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18879 (MO_TEUL | ctx->default_tcg_memop_mask));
18880 counter++;
18881 }
18882
18883 /* adjust stack pointer */
18884 gen_adjust_sp(ctx, -u);
18885
18886 tcg_temp_free(t0);
18887 tcg_temp_free(va);
18888}
18889
18890static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18891 uint8_t gp, uint16_t u)
18892{
18893 int counter = 0;
18894 TCGv va = tcg_temp_new();
18895 TCGv t0 = tcg_temp_new();
18896
18897 while (counter != count) {
18898 bool use_gp = gp && (counter == count - 1);
18899 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18900 int this_offset = u - ((counter + 1) << 2);
18901 gen_base_offset_addr(ctx, va, 29, this_offset);
18902 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18903 ctx->default_tcg_memop_mask);
18904 tcg_gen_ext32s_tl(t0, t0);
18905 gen_store_gpr(t0, this_rt);
18906 counter++;
18907 }
18908
18909 /* adjust stack pointer */
18910 gen_adjust_sp(ctx, u);
18911
18912 tcg_temp_free(t0);
18913 tcg_temp_free(va);
18914}
18915
80845edf
YK
18916static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18917{
99e49abf
AM
18918 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18919 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
18920
18921 switch (extract32(ctx->opcode, 2, 2)) {
18922 case NM_NOT16:
18923 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18924 break;
18925 case NM_AND16:
18926 gen_logic(ctx, OPC_AND, rt, rt, rs);
18927 break;
18928 case NM_XOR16:
18929 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18930 break;
18931 case NM_OR16:
18932 gen_logic(ctx, OPC_OR, rt, rt, rs);
18933 break;
18934 }
18935}
18936
0a1a6ed7 18937static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18938{
18939 int rt = extract32(ctx->opcode, 21, 5);
18940 int rs = extract32(ctx->opcode, 16, 5);
18941 int rd = extract32(ctx->opcode, 11, 5);
18942
18943 switch (extract32(ctx->opcode, 3, 7)) {
18944 case NM_P_TRAP:
18945 switch (extract32(ctx->opcode, 10, 1)) {
18946 case NM_TEQ:
fb32f8c8 18947 check_nms(ctx);
e0cf0e65
YK
18948 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18949 break;
18950 case NM_TNE:
fb32f8c8 18951 check_nms(ctx);
e0cf0e65
YK
18952 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18953 break;
18954 }
18955 break;
18956 case NM_RDHWR:
fb32f8c8 18957 check_nms(ctx);
e0cf0e65
YK
18958 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18959 break;
18960 case NM_SEB:
fb32f8c8 18961 check_nms(ctx);
e0cf0e65
YK
18962 gen_bshfl(ctx, OPC_SEB, rs, rt);
18963 break;
18964 case NM_SEH:
18965 gen_bshfl(ctx, OPC_SEH, rs, rt);
18966 break;
18967 case NM_SLLV:
18968 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18969 break;
18970 case NM_SRLV:
18971 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18972 break;
18973 case NM_SRAV:
18974 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18975 break;
18976 case NM_ROTRV:
18977 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18978 break;
18979 case NM_ADD:
18980 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18981 break;
18982 case NM_ADDU:
18983 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18984 break;
18985 case NM_SUB:
fb32f8c8 18986 check_nms(ctx);
e0cf0e65
YK
18987 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18988 break;
18989 case NM_SUBU:
18990 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18991 break;
18992 case NM_P_CMOVE:
18993 switch (extract32(ctx->opcode, 10, 1)) {
18994 case NM_MOVZ:
18995 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18996 break;
18997 case NM_MOVN:
18998 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18999 break;
19000 }
19001 break;
19002 case NM_AND:
19003 gen_logic(ctx, OPC_AND, rd, rs, rt);
19004 break;
19005 case NM_OR:
19006 gen_logic(ctx, OPC_OR, rd, rs, rt);
19007 break;
19008 case NM_NOR:
19009 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19010 break;
19011 case NM_XOR:
19012 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19013 break;
19014 case NM_SLT:
19015 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19016 break;
19017 case NM_P_SLTU:
19018 if (rd == 0) {
19019 /* P_DVP */
19020#ifndef CONFIG_USER_ONLY
19021 TCGv t0 = tcg_temp_new();
19022 switch (extract32(ctx->opcode, 10, 1)) {
19023 case NM_DVP:
19024 if (ctx->vp) {
19025 check_cp0_enabled(ctx);
19026 gen_helper_dvp(t0, cpu_env);
19027 gen_store_gpr(t0, rt);
19028 }
19029 break;
19030 case NM_EVP:
19031 if (ctx->vp) {
19032 check_cp0_enabled(ctx);
19033 gen_helper_evp(t0, cpu_env);
19034 gen_store_gpr(t0, rt);
19035 }
19036 break;
19037 }
19038 tcg_temp_free(t0);
19039#endif
19040 } else {
19041 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19042 }
19043 break;
19044 case NM_SOV:
19045 {
19046 TCGv t0 = tcg_temp_new();
19047 TCGv t1 = tcg_temp_new();
19048 TCGv t2 = tcg_temp_new();
19049
19050 gen_load_gpr(t1, rs);
19051 gen_load_gpr(t2, rt);
19052 tcg_gen_add_tl(t0, t1, t2);
19053 tcg_gen_ext32s_tl(t0, t0);
19054 tcg_gen_xor_tl(t1, t1, t2);
19055 tcg_gen_xor_tl(t2, t0, t2);
19056 tcg_gen_andc_tl(t1, t2, t1);
19057
19058 /* operands of same sign, result different sign */
19059 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19060 gen_store_gpr(t0, rd);
19061
19062 tcg_temp_free(t0);
19063 tcg_temp_free(t1);
19064 tcg_temp_free(t2);
19065 }
19066 break;
19067 case NM_MUL:
19068 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19069 break;
19070 case NM_MUH:
19071 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19072 break;
19073 case NM_MULU:
19074 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19075 break;
19076 case NM_MUHU:
19077 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19078 break;
19079 case NM_DIV:
19080 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19081 break;
19082 case NM_MOD:
19083 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19084 break;
19085 case NM_DIVU:
19086 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19087 break;
19088 case NM_MODU:
19089 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19090 break;
19091#ifndef CONFIG_USER_ONLY
19092 case NM_MFC0:
19093 check_cp0_enabled(ctx);
19094 if (rt == 0) {
19095 /* Treat as NOP. */
19096 break;
19097 }
19098 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19099 break;
19100 case NM_MTC0:
19101 check_cp0_enabled(ctx);
19102 {
19103 TCGv t0 = tcg_temp_new();
19104
19105 gen_load_gpr(t0, rt);
19106 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19107 tcg_temp_free(t0);
19108 }
19109 break;
0a1a6ed7
SM
19110 case NM_D_E_MT_VPE:
19111 {
19112 uint8_t sc = extract32(ctx->opcode, 10, 1);
19113 TCGv t0 = tcg_temp_new();
19114
19115 switch (sc) {
19116 case 0:
19117 if (rs == 1) {
19118 /* DMT */
19119 check_cp0_mt(ctx);
19120 gen_helper_dmt(t0);
19121 gen_store_gpr(t0, rt);
19122 } else if (rs == 0) {
19123 /* DVPE */
19124 check_cp0_mt(ctx);
19125 gen_helper_dvpe(t0, cpu_env);
19126 gen_store_gpr(t0, rt);
19127 } else {
19128 generate_exception_end(ctx, EXCP_RI);
19129 }
19130 break;
19131 case 1:
19132 if (rs == 1) {
19133 /* EMT */
19134 check_cp0_mt(ctx);
19135 gen_helper_emt(t0);
19136 gen_store_gpr(t0, rt);
19137 } else if (rs == 0) {
19138 /* EVPE */
19139 check_cp0_mt(ctx);
19140 gen_helper_evpe(t0, cpu_env);
19141 gen_store_gpr(t0, rt);
19142 } else {
19143 generate_exception_end(ctx, EXCP_RI);
19144 }
19145 break;
19146 }
19147
19148 tcg_temp_free(t0);
19149 }
19150 break;
19151 case NM_FORK:
19152 check_mt(ctx);
19153 {
19154 TCGv t0 = tcg_temp_new();
19155 TCGv t1 = tcg_temp_new();
19156
19157 gen_load_gpr(t0, rt);
19158 gen_load_gpr(t1, rs);
19159 gen_helper_fork(t0, t1);
19160 tcg_temp_free(t0);
19161 tcg_temp_free(t1);
19162 }
19163 break;
19164 case NM_MFTR:
19165 case NM_MFHTR:
19166 check_cp0_enabled(ctx);
19167 if (rd == 0) {
19168 /* Treat as NOP. */
19169 return;
19170 }
19171 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19172 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19173 break;
19174 case NM_MTTR:
19175 case NM_MTHTR:
19176 check_cp0_enabled(ctx);
19177 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19178 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19179 break;
19180 case NM_YIELD:
19181 check_mt(ctx);
19182 {
19183 TCGv t0 = tcg_temp_new();
19184
19185 gen_load_gpr(t0, rs);
19186 gen_helper_yield(t0, cpu_env, t0);
19187 gen_store_gpr(t0, rt);
19188 tcg_temp_free(t0);
19189 }
19190 break;
e0cf0e65
YK
19191#endif
19192 default:
19193 generate_exception_end(ctx, EXCP_RI);
19194 break;
19195 }
19196}
19197
2ed42efa
SM
19198/* dsp */
19199static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19200 int ret, int v1, int v2)
19201{
19202 TCGv_i32 t0;
19203 TCGv v0_t;
19204 TCGv v1_t;
19205
19206 t0 = tcg_temp_new_i32();
19207
19208 v0_t = tcg_temp_new();
19209 v1_t = tcg_temp_new();
19210
19211 tcg_gen_movi_i32(t0, v2 >> 3);
19212
19213 gen_load_gpr(v0_t, ret);
19214 gen_load_gpr(v1_t, v1);
19215
19216 switch (opc) {
19217 case NM_MAQ_S_W_PHR:
19218 check_dsp(ctx);
19219 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19220 break;
19221 case NM_MAQ_S_W_PHL:
19222 check_dsp(ctx);
19223 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19224 break;
19225 case NM_MAQ_SA_W_PHR:
19226 check_dsp(ctx);
19227 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19228 break;
19229 case NM_MAQ_SA_W_PHL:
19230 check_dsp(ctx);
19231 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19232 break;
19233 default:
19234 generate_exception_end(ctx, EXCP_RI);
19235 break;
19236 }
19237
19238 tcg_temp_free_i32(t0);
19239
19240 tcg_temp_free(v0_t);
19241 tcg_temp_free(v1_t);
19242}
19243
19244
19245static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19246 int ret, int v1, int v2)
19247{
19248 int16_t imm;
19249 TCGv t0 = tcg_temp_new();
19250 TCGv t1 = tcg_temp_new();
19251 TCGv v0_t = tcg_temp_new();
19252
19253 gen_load_gpr(v0_t, v1);
19254
19255 switch (opc) {
19256 case NM_POOL32AXF_1_0:
19257 check_dsp(ctx);
19258 switch (extract32(ctx->opcode, 12, 2)) {
19259 case NM_MFHI:
19260 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19261 break;
19262 case NM_MFLO:
19263 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19264 break;
19265 case NM_MTHI:
19266 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19267 break;
19268 case NM_MTLO:
19269 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19270 break;
19271 }
19272 break;
19273 case NM_POOL32AXF_1_1:
19274 check_dsp(ctx);
19275 switch (extract32(ctx->opcode, 12, 2)) {
19276 case NM_MTHLIP:
19277 tcg_gen_movi_tl(t0, v2);
19278 gen_helper_mthlip(t0, v0_t, cpu_env);
19279 break;
19280 case NM_SHILOV:
19281 tcg_gen_movi_tl(t0, v2 >> 3);
19282 gen_helper_shilo(t0, v0_t, cpu_env);
19283 break;
19284 default:
19285 generate_exception_end(ctx, EXCP_RI);
19286 break;
19287 }
19288 break;
19289 case NM_POOL32AXF_1_3:
19290 check_dsp(ctx);
19291 imm = extract32(ctx->opcode, 14, 7);
19292 switch (extract32(ctx->opcode, 12, 2)) {
19293 case NM_RDDSP:
19294 tcg_gen_movi_tl(t0, imm);
19295 gen_helper_rddsp(t0, t0, cpu_env);
19296 gen_store_gpr(t0, ret);
19297 break;
19298 case NM_WRDSP:
19299 gen_load_gpr(t0, ret);
19300 tcg_gen_movi_tl(t1, imm);
19301 gen_helper_wrdsp(t0, t1, cpu_env);
19302 break;
19303 case NM_EXTP:
19304 tcg_gen_movi_tl(t0, v2 >> 3);
19305 tcg_gen_movi_tl(t1, v1);
19306 gen_helper_extp(t0, t0, t1, cpu_env);
19307 gen_store_gpr(t0, ret);
19308 break;
19309 case NM_EXTPDP:
19310 tcg_gen_movi_tl(t0, v2 >> 3);
19311 tcg_gen_movi_tl(t1, v1);
19312 gen_helper_extpdp(t0, t0, t1, cpu_env);
19313 gen_store_gpr(t0, ret);
19314 break;
19315 }
19316 break;
19317 case NM_POOL32AXF_1_4:
19318 check_dsp(ctx);
19319 tcg_gen_movi_tl(t0, v2 >> 2);
19320 switch (extract32(ctx->opcode, 12, 1)) {
19321 case NM_SHLL_QB:
19322 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19323 gen_store_gpr(t0, ret);
19324 break;
19325 case NM_SHRL_QB:
19326 gen_helper_shrl_qb(t0, t0, v0_t);
19327 gen_store_gpr(t0, ret);
19328 break;
19329 }
19330 break;
19331 case NM_POOL32AXF_1_5:
19332 opc = extract32(ctx->opcode, 12, 2);
19333 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19334 break;
19335 case NM_POOL32AXF_1_7:
19336 check_dsp(ctx);
19337 tcg_gen_movi_tl(t0, v2 >> 3);
19338 tcg_gen_movi_tl(t1, v1);
19339 switch (extract32(ctx->opcode, 12, 2)) {
19340 case NM_EXTR_W:
19341 gen_helper_extr_w(t0, t0, t1, cpu_env);
19342 gen_store_gpr(t0, ret);
19343 break;
19344 case NM_EXTR_R_W:
19345 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19346 gen_store_gpr(t0, ret);
19347 break;
19348 case NM_EXTR_RS_W:
19349 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19350 gen_store_gpr(t0, ret);
19351 break;
19352 case NM_EXTR_S_H:
19353 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19354 gen_store_gpr(t0, ret);
19355 break;
19356 }
19357 break;
19358 default:
19359 generate_exception_end(ctx, EXCP_RI);
19360 break;
19361 }
19362
19363 tcg_temp_free(t0);
19364 tcg_temp_free(t1);
19365 tcg_temp_free(v0_t);
19366}
19367
8b3698b2
SM
19368static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19369 TCGv v0, TCGv v1, int rd)
19370{
19371 TCGv_i32 t0;
19372
19373 t0 = tcg_temp_new_i32();
19374
19375 tcg_gen_movi_i32(t0, rd >> 3);
19376
19377 switch (opc) {
19378 case NM_POOL32AXF_2_0_7:
19379 switch (extract32(ctx->opcode, 9, 3)) {
19380 case NM_DPA_W_PH:
908f6be1 19381 check_dsp_r2(ctx);
8b3698b2
SM
19382 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19383 break;
19384 case NM_DPAQ_S_W_PH:
19385 check_dsp(ctx);
19386 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19387 break;
19388 case NM_DPS_W_PH:
908f6be1 19389 check_dsp_r2(ctx);
8b3698b2
SM
19390 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19391 break;
19392 case NM_DPSQ_S_W_PH:
19393 check_dsp(ctx);
19394 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19395 break;
19396 default:
19397 generate_exception_end(ctx, EXCP_RI);
19398 break;
19399 }
19400 break;
19401 case NM_POOL32AXF_2_8_15:
19402 switch (extract32(ctx->opcode, 9, 3)) {
19403 case NM_DPAX_W_PH:
908f6be1 19404 check_dsp_r2(ctx);
8b3698b2
SM
19405 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19406 break;
19407 case NM_DPAQ_SA_L_W:
19408 check_dsp(ctx);
19409 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19410 break;
19411 case NM_DPSX_W_PH:
908f6be1 19412 check_dsp_r2(ctx);
8b3698b2
SM
19413 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19414 break;
19415 case NM_DPSQ_SA_L_W:
19416 check_dsp(ctx);
19417 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19418 break;
19419 default:
19420 generate_exception_end(ctx, EXCP_RI);
19421 break;
19422 }
19423 break;
19424 case NM_POOL32AXF_2_16_23:
19425 switch (extract32(ctx->opcode, 9, 3)) {
19426 case NM_DPAU_H_QBL:
19427 check_dsp(ctx);
19428 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19429 break;
19430 case NM_DPAQX_S_W_PH:
908f6be1 19431 check_dsp_r2(ctx);
8b3698b2
SM
19432 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19433 break;
19434 case NM_DPSU_H_QBL:
19435 check_dsp(ctx);
19436 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19437 break;
19438 case NM_DPSQX_S_W_PH:
908f6be1 19439 check_dsp_r2(ctx);
8b3698b2
SM
19440 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19441 break;
19442 case NM_MULSA_W_PH:
908f6be1 19443 check_dsp_r2(ctx);
8b3698b2
SM
19444 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19445 break;
19446 default:
19447 generate_exception_end(ctx, EXCP_RI);
19448 break;
19449 }
19450 break;
19451 case NM_POOL32AXF_2_24_31:
19452 switch (extract32(ctx->opcode, 9, 3)) {
19453 case NM_DPAU_H_QBR:
19454 check_dsp(ctx);
19455 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19456 break;
19457 case NM_DPAQX_SA_W_PH:
908f6be1 19458 check_dsp_r2(ctx);
8b3698b2
SM
19459 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19460 break;
19461 case NM_DPSU_H_QBR:
19462 check_dsp(ctx);
19463 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19464 break;
19465 case NM_DPSQX_SA_W_PH:
908f6be1 19466 check_dsp_r2(ctx);
8b3698b2
SM
19467 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19468 break;
19469 case NM_MULSAQ_S_W_PH:
19470 check_dsp(ctx);
19471 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19472 break;
19473 default:
19474 generate_exception_end(ctx, EXCP_RI);
19475 break;
19476 }
19477 break;
19478 default:
19479 generate_exception_end(ctx, EXCP_RI);
19480 break;
19481 }
19482
19483 tcg_temp_free_i32(t0);
19484}
19485
19486static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19487 int rt, int rs, int rd)
19488{
19489 int ret = rt;
19490 TCGv t0 = tcg_temp_new();
19491 TCGv t1 = tcg_temp_new();
19492 TCGv v0_t = tcg_temp_new();
19493 TCGv v1_t = tcg_temp_new();
19494
19495 gen_load_gpr(v0_t, rt);
19496 gen_load_gpr(v1_t, rs);
19497
19498 switch (opc) {
19499 case NM_POOL32AXF_2_0_7:
19500 switch (extract32(ctx->opcode, 9, 3)) {
19501 case NM_DPA_W_PH:
19502 case NM_DPAQ_S_W_PH:
19503 case NM_DPS_W_PH:
19504 case NM_DPSQ_S_W_PH:
19505 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19506 break;
19507 case NM_BALIGN:
908f6be1 19508 check_dsp_r2(ctx);
8b3698b2
SM
19509 if (rt != 0) {
19510 gen_load_gpr(t0, rs);
19511 rd &= 3;
19512 if (rd != 0 && rd != 2) {
19513 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19514 tcg_gen_ext32u_tl(t0, t0);
19515 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19516 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19517 }
19518 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19519 }
19520 break;
19521 case NM_MADD:
19522 check_dsp(ctx);
19523 {
19524 int acc = extract32(ctx->opcode, 14, 2);
19525 TCGv_i64 t2 = tcg_temp_new_i64();
19526 TCGv_i64 t3 = tcg_temp_new_i64();
19527
19528 gen_load_gpr(t0, rt);
19529 gen_load_gpr(t1, rs);
19530 tcg_gen_ext_tl_i64(t2, t0);
19531 tcg_gen_ext_tl_i64(t3, t1);
19532 tcg_gen_mul_i64(t2, t2, t3);
19533 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19534 tcg_gen_add_i64(t2, t2, t3);
19535 tcg_temp_free_i64(t3);
19536 gen_move_low32(cpu_LO[acc], t2);
19537 gen_move_high32(cpu_HI[acc], t2);
19538 tcg_temp_free_i64(t2);
19539 }
19540 break;
19541 case NM_MULT:
19542 check_dsp(ctx);
19543 {
19544 int acc = extract32(ctx->opcode, 14, 2);
19545 TCGv_i32 t2 = tcg_temp_new_i32();
19546 TCGv_i32 t3 = tcg_temp_new_i32();
19547
19548 gen_load_gpr(t0, rs);
19549 gen_load_gpr(t1, rt);
19550 tcg_gen_trunc_tl_i32(t2, t0);
19551 tcg_gen_trunc_tl_i32(t3, t1);
19552 tcg_gen_muls2_i32(t2, t3, t2, t3);
19553 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19554 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19555 tcg_temp_free_i32(t2);
19556 tcg_temp_free_i32(t3);
19557 }
19558 break;
19559 case NM_EXTRV_W:
19560 check_dsp(ctx);
19561 gen_load_gpr(v1_t, rs);
19562 tcg_gen_movi_tl(t0, rd >> 3);
19563 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19564 gen_store_gpr(t0, ret);
19565 break;
19566 }
19567 break;
19568 case NM_POOL32AXF_2_8_15:
19569 switch (extract32(ctx->opcode, 9, 3)) {
19570 case NM_DPAX_W_PH:
19571 case NM_DPAQ_SA_L_W:
19572 case NM_DPSX_W_PH:
19573 case NM_DPSQ_SA_L_W:
19574 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19575 break;
19576 case NM_MADDU:
19577 check_dsp(ctx);
19578 {
19579 int acc = extract32(ctx->opcode, 14, 2);
19580 TCGv_i64 t2 = tcg_temp_new_i64();
19581 TCGv_i64 t3 = tcg_temp_new_i64();
19582
19583 gen_load_gpr(t0, rs);
19584 gen_load_gpr(t1, rt);
19585 tcg_gen_ext32u_tl(t0, t0);
19586 tcg_gen_ext32u_tl(t1, t1);
19587 tcg_gen_extu_tl_i64(t2, t0);
19588 tcg_gen_extu_tl_i64(t3, t1);
19589 tcg_gen_mul_i64(t2, t2, t3);
19590 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19591 tcg_gen_add_i64(t2, t2, t3);
19592 tcg_temp_free_i64(t3);
19593 gen_move_low32(cpu_LO[acc], t2);
19594 gen_move_high32(cpu_HI[acc], t2);
19595 tcg_temp_free_i64(t2);
19596 }
19597 break;
19598 case NM_MULTU:
19599 check_dsp(ctx);
19600 {
19601 int acc = extract32(ctx->opcode, 14, 2);
19602 TCGv_i32 t2 = tcg_temp_new_i32();
19603 TCGv_i32 t3 = tcg_temp_new_i32();
19604
19605 gen_load_gpr(t0, rs);
19606 gen_load_gpr(t1, rt);
19607 tcg_gen_trunc_tl_i32(t2, t0);
19608 tcg_gen_trunc_tl_i32(t3, t1);
19609 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19610 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19611 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19612 tcg_temp_free_i32(t2);
19613 tcg_temp_free_i32(t3);
19614 }
19615 break;
19616 case NM_EXTRV_R_W:
19617 check_dsp(ctx);
19618 tcg_gen_movi_tl(t0, rd >> 3);
19619 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19620 gen_store_gpr(t0, ret);
19621 break;
19622 default:
19623 generate_exception_end(ctx, EXCP_RI);
19624 break;
19625 }
19626 break;
19627 case NM_POOL32AXF_2_16_23:
19628 switch (extract32(ctx->opcode, 9, 3)) {
19629 case NM_DPAU_H_QBL:
19630 case NM_DPAQX_S_W_PH:
19631 case NM_DPSU_H_QBL:
19632 case NM_DPSQX_S_W_PH:
19633 case NM_MULSA_W_PH:
19634 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19635 break;
19636 case NM_EXTPV:
19637 check_dsp(ctx);
19638 tcg_gen_movi_tl(t0, rd >> 3);
19639 gen_helper_extp(t0, t0, v1_t, cpu_env);
19640 gen_store_gpr(t0, ret);
19641 break;
19642 case NM_MSUB:
19643 check_dsp(ctx);
19644 {
19645 int acc = extract32(ctx->opcode, 14, 2);
19646 TCGv_i64 t2 = tcg_temp_new_i64();
19647 TCGv_i64 t3 = tcg_temp_new_i64();
19648
19649 gen_load_gpr(t0, rs);
19650 gen_load_gpr(t1, rt);
19651 tcg_gen_ext_tl_i64(t2, t0);
19652 tcg_gen_ext_tl_i64(t3, t1);
19653 tcg_gen_mul_i64(t2, t2, t3);
19654 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19655 tcg_gen_sub_i64(t2, t3, t2);
19656 tcg_temp_free_i64(t3);
19657 gen_move_low32(cpu_LO[acc], t2);
19658 gen_move_high32(cpu_HI[acc], t2);
19659 tcg_temp_free_i64(t2);
19660 }
19661 break;
19662 case NM_EXTRV_RS_W:
19663 check_dsp(ctx);
19664 tcg_gen_movi_tl(t0, rd >> 3);
19665 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19666 gen_store_gpr(t0, ret);
19667 break;
19668 }
19669 break;
19670 case NM_POOL32AXF_2_24_31:
19671 switch (extract32(ctx->opcode, 9, 3)) {
19672 case NM_DPAU_H_QBR:
19673 case NM_DPAQX_SA_W_PH:
19674 case NM_DPSU_H_QBR:
19675 case NM_DPSQX_SA_W_PH:
19676 case NM_MULSAQ_S_W_PH:
19677 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19678 break;
19679 case NM_EXTPDPV:
19680 check_dsp(ctx);
19681 tcg_gen_movi_tl(t0, rd >> 3);
19682 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19683 gen_store_gpr(t0, ret);
19684 break;
19685 case NM_MSUBU:
19686 check_dsp(ctx);
19687 {
19688 int acc = extract32(ctx->opcode, 14, 2);
19689 TCGv_i64 t2 = tcg_temp_new_i64();
19690 TCGv_i64 t3 = tcg_temp_new_i64();
19691
19692 gen_load_gpr(t0, rs);
19693 gen_load_gpr(t1, rt);
19694 tcg_gen_ext32u_tl(t0, t0);
19695 tcg_gen_ext32u_tl(t1, t1);
19696 tcg_gen_extu_tl_i64(t2, t0);
19697 tcg_gen_extu_tl_i64(t3, t1);
19698 tcg_gen_mul_i64(t2, t2, t3);
19699 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19700 tcg_gen_sub_i64(t2, t3, t2);
19701 tcg_temp_free_i64(t3);
19702 gen_move_low32(cpu_LO[acc], t2);
19703 gen_move_high32(cpu_HI[acc], t2);
19704 tcg_temp_free_i64(t2);
19705 }
19706 break;
19707 case NM_EXTRV_S_H:
19708 check_dsp(ctx);
19709 tcg_gen_movi_tl(t0, rd >> 3);
19710 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19711 gen_store_gpr(t0, ret);
19712 break;
19713 }
19714 break;
19715 default:
19716 generate_exception_end(ctx, EXCP_RI);
19717 break;
19718 }
19719
19720 tcg_temp_free(t0);
19721 tcg_temp_free(t1);
19722
19723 tcg_temp_free(v0_t);
19724 tcg_temp_free(v1_t);
19725}
19726
4c75c985
SM
19727static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19728 int rt, int rs)
19729{
19730 int ret = rt;
19731 TCGv t0 = tcg_temp_new();
19732 TCGv v0_t = tcg_temp_new();
19733
19734 gen_load_gpr(v0_t, rs);
19735
19736 switch (opc) {
19737 case NM_ABSQ_S_QB:
908f6be1 19738 check_dsp_r2(ctx);
4c75c985
SM
19739 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19740 gen_store_gpr(v0_t, ret);
19741 break;
19742 case NM_ABSQ_S_PH:
19743 check_dsp(ctx);
19744 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19745 gen_store_gpr(v0_t, ret);
19746 break;
19747 case NM_ABSQ_S_W:
19748 check_dsp(ctx);
19749 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19750 gen_store_gpr(v0_t, ret);
19751 break;
19752 case NM_PRECEQ_W_PHL:
19753 check_dsp(ctx);
19754 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19755 tcg_gen_ext32s_tl(v0_t, v0_t);
19756 gen_store_gpr(v0_t, ret);
19757 break;
19758 case NM_PRECEQ_W_PHR:
19759 check_dsp(ctx);
19760 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19761 tcg_gen_shli_tl(v0_t, v0_t, 16);
19762 tcg_gen_ext32s_tl(v0_t, v0_t);
19763 gen_store_gpr(v0_t, ret);
19764 break;
19765 case NM_PRECEQU_PH_QBL:
19766 check_dsp(ctx);
19767 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19768 gen_store_gpr(v0_t, ret);
19769 break;
19770 case NM_PRECEQU_PH_QBR:
19771 check_dsp(ctx);
19772 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19773 gen_store_gpr(v0_t, ret);
19774 break;
19775 case NM_PRECEQU_PH_QBLA:
19776 check_dsp(ctx);
19777 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19778 gen_store_gpr(v0_t, ret);
19779 break;
19780 case NM_PRECEQU_PH_QBRA:
19781 check_dsp(ctx);
19782 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19783 gen_store_gpr(v0_t, ret);
19784 break;
19785 case NM_PRECEU_PH_QBL:
19786 check_dsp(ctx);
19787 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19788 gen_store_gpr(v0_t, ret);
19789 break;
19790 case NM_PRECEU_PH_QBR:
19791 check_dsp(ctx);
19792 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19793 gen_store_gpr(v0_t, ret);
19794 break;
19795 case NM_PRECEU_PH_QBLA:
19796 check_dsp(ctx);
19797 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19798 gen_store_gpr(v0_t, ret);
19799 break;
19800 case NM_PRECEU_PH_QBRA:
19801 check_dsp(ctx);
19802 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19803 gen_store_gpr(v0_t, ret);
19804 break;
19805 case NM_REPLV_PH:
19806 check_dsp(ctx);
19807 tcg_gen_ext16u_tl(v0_t, v0_t);
19808 tcg_gen_shli_tl(t0, v0_t, 16);
19809 tcg_gen_or_tl(v0_t, v0_t, t0);
19810 tcg_gen_ext32s_tl(v0_t, v0_t);
19811 gen_store_gpr(v0_t, ret);
19812 break;
19813 case NM_REPLV_QB:
19814 check_dsp(ctx);
19815 tcg_gen_ext8u_tl(v0_t, v0_t);
19816 tcg_gen_shli_tl(t0, v0_t, 8);
19817 tcg_gen_or_tl(v0_t, v0_t, t0);
19818 tcg_gen_shli_tl(t0, v0_t, 16);
19819 tcg_gen_or_tl(v0_t, v0_t, t0);
19820 tcg_gen_ext32s_tl(v0_t, v0_t);
19821 gen_store_gpr(v0_t, ret);
19822 break;
19823 case NM_BITREV:
19824 check_dsp(ctx);
19825 gen_helper_bitrev(v0_t, v0_t);
19826 gen_store_gpr(v0_t, ret);
19827 break;
19828 case NM_INSV:
19829 check_dsp(ctx);
19830 {
19831 TCGv tv0 = tcg_temp_new();
19832
19833 gen_load_gpr(tv0, rt);
19834 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19835 gen_store_gpr(v0_t, ret);
19836 tcg_temp_free(tv0);
19837 }
19838 break;
19839 case NM_RADDU_W_QB:
19840 check_dsp(ctx);
19841 gen_helper_raddu_w_qb(v0_t, v0_t);
19842 gen_store_gpr(v0_t, ret);
19843 break;
19844 case NM_BITSWAP:
19845 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19846 break;
19847 case NM_CLO:
fb32f8c8 19848 check_nms(ctx);
4c75c985
SM
19849 gen_cl(ctx, OPC_CLO, ret, rs);
19850 break;
19851 case NM_CLZ:
fb32f8c8 19852 check_nms(ctx);
4c75c985
SM
19853 gen_cl(ctx, OPC_CLZ, ret, rs);
19854 break;
19855 case NM_WSBH:
19856 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19857 break;
19858 default:
19859 generate_exception_end(ctx, EXCP_RI);
19860 break;
19861 }
19862
19863 tcg_temp_free(v0_t);
19864 tcg_temp_free(t0);
19865}
19866
0b591184
SM
19867static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19868 int rt, int rs, int rd)
19869{
19870 TCGv t0 = tcg_temp_new();
19871 TCGv rs_t = tcg_temp_new();
19872
19873 gen_load_gpr(rs_t, rs);
19874
19875 switch (opc) {
19876 case NM_SHRA_R_QB:
908f6be1 19877 check_dsp_r2(ctx);
0b591184
SM
19878 tcg_gen_movi_tl(t0, rd >> 2);
19879 switch (extract32(ctx->opcode, 12, 1)) {
19880 case 0:
19881 /* NM_SHRA_QB */
19882 gen_helper_shra_qb(t0, t0, rs_t);
19883 gen_store_gpr(t0, rt);
19884 break;
19885 case 1:
19886 /* NM_SHRA_R_QB */
19887 gen_helper_shra_r_qb(t0, t0, rs_t);
19888 gen_store_gpr(t0, rt);
19889 break;
19890 }
19891 break;
19892 case NM_SHRL_PH:
908f6be1 19893 check_dsp_r2(ctx);
0b591184
SM
19894 tcg_gen_movi_tl(t0, rd >> 1);
19895 gen_helper_shrl_ph(t0, t0, rs_t);
19896 gen_store_gpr(t0, rt);
19897 break;
19898 case NM_REPL_QB:
19899 check_dsp(ctx);
19900 {
19901 int16_t imm;
19902 target_long result;
19903 imm = extract32(ctx->opcode, 13, 8);
19904 result = (uint32_t)imm << 24 |
19905 (uint32_t)imm << 16 |
19906 (uint32_t)imm << 8 |
19907 (uint32_t)imm;
19908 result = (int32_t)result;
19909 tcg_gen_movi_tl(t0, result);
19910 gen_store_gpr(t0, rt);
19911 }
19912 break;
19913 default:
19914 generate_exception_end(ctx, EXCP_RI);
19915 break;
19916 }
19917 tcg_temp_free(t0);
19918 tcg_temp_free(rs_t);
19919}
19920
2ed42efa 19921
64224187
YK
19922static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19923{
64224187
YK
19924 int rt = extract32(ctx->opcode, 21, 5);
19925 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19926 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19927
19928 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19929 case NM_POOL32AXF_1:
19930 {
19931 int32_t op1 = extract32(ctx->opcode, 9, 3);
19932 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19933 }
19934 break;
19935 case NM_POOL32AXF_2:
8b3698b2
SM
19936 {
19937 int32_t op1 = extract32(ctx->opcode, 12, 2);
19938 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19939 }
2ed42efa 19940 break;
64224187 19941 case NM_POOL32AXF_4:
4c75c985
SM
19942 {
19943 int32_t op1 = extract32(ctx->opcode, 9, 7);
19944 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19945 }
2ed42efa 19946 break;
64224187
YK
19947 case NM_POOL32AXF_5:
19948 switch (extract32(ctx->opcode, 9, 7)) {
19949#ifndef CONFIG_USER_ONLY
19950 case NM_TLBP:
19951 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19952 break;
19953 case NM_TLBR:
19954 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19955 break;
19956 case NM_TLBWI:
19957 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19958 break;
19959 case NM_TLBWR:
19960 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19961 break;
19962 case NM_TLBINV:
19963 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19964 break;
19965 case NM_TLBINVF:
19966 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19967 break;
19968 case NM_DI:
19969 check_cp0_enabled(ctx);
19970 {
19971 TCGv t0 = tcg_temp_new();
19972
19973 save_cpu_state(ctx, 1);
19974 gen_helper_di(t0, cpu_env);
19975 gen_store_gpr(t0, rt);
19976 /* Stop translation as we may have switched the execution mode */
19977 ctx->base.is_jmp = DISAS_STOP;
19978 tcg_temp_free(t0);
19979 }
19980 break;
19981 case NM_EI:
19982 check_cp0_enabled(ctx);
19983 {
19984 TCGv t0 = tcg_temp_new();
19985
19986 save_cpu_state(ctx, 1);
19987 gen_helper_ei(t0, cpu_env);
19988 gen_store_gpr(t0, rt);
19989 /* Stop translation as we may have switched the execution mode */
19990 ctx->base.is_jmp = DISAS_STOP;
19991 tcg_temp_free(t0);
19992 }
19993 break;
19994 case NM_RDPGPR:
19995 gen_load_srsgpr(rs, rt);
19996 break;
19997 case NM_WRPGPR:
19998 gen_store_srsgpr(rs, rt);
19999 break;
20000 case NM_WAIT:
20001 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20002 break;
20003 case NM_DERET:
20004 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20005 break;
20006 case NM_ERETX:
20007 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20008 break;
20009#endif
20010 default:
20011 generate_exception_end(ctx, EXCP_RI);
20012 break;
20013 }
20014 break;
2ed42efa 20015 case NM_POOL32AXF_7:
0b591184
SM
20016 {
20017 int32_t op1 = extract32(ctx->opcode, 9, 3);
20018 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20019 }
2ed42efa 20020 break;
64224187
YK
20021 default:
20022 generate_exception_end(ctx, EXCP_RI);
20023 break;
20024 }
20025}
20026
11d0fc10
SM
20027/* Immediate Value Compact Branches */
20028static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20029 int rt, int32_t imm, int32_t offset)
20030{
20031 TCGCond cond;
20032 int bcond_compute = 0;
20033 TCGv t0 = tcg_temp_new();
20034 TCGv t1 = tcg_temp_new();
20035
20036 gen_load_gpr(t0, rt);
20037 tcg_gen_movi_tl(t1, imm);
20038 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20039
20040 /* Load needed operands and calculate btarget */
20041 switch (opc) {
20042 case NM_BEQIC:
20043 if (rt == 0 && imm == 0) {
20044 /* Unconditional branch */
20045 } else if (rt == 0 && imm != 0) {
20046 /* Treat as NOP */
20047 goto out;
20048 } else {
20049 bcond_compute = 1;
20050 cond = TCG_COND_EQ;
20051 }
20052 break;
20053 case NM_BBEQZC:
20054 case NM_BBNEZC:
fb32f8c8 20055 check_nms(ctx);
11d0fc10
SM
20056 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20057 generate_exception_end(ctx, EXCP_RI);
20058 goto out;
20059 } else if (rt == 0 && opc == NM_BBEQZC) {
20060 /* Unconditional branch */
20061 } else if (rt == 0 && opc == NM_BBNEZC) {
20062 /* Treat as NOP */
20063 goto out;
20064 } else {
20065 tcg_gen_shri_tl(t0, t0, imm);
20066 tcg_gen_andi_tl(t0, t0, 1);
20067 tcg_gen_movi_tl(t1, 0);
20068 bcond_compute = 1;
20069 if (opc == NM_BBEQZC) {
20070 cond = TCG_COND_EQ;
20071 } else {
20072 cond = TCG_COND_NE;
20073 }
20074 }
20075 break;
20076 case NM_BNEIC:
20077 if (rt == 0 && imm == 0) {
20078 /* Treat as NOP */
20079 goto out;
20080 } else if (rt == 0 && imm != 0) {
20081 /* Unconditional branch */
20082 } else {
20083 bcond_compute = 1;
20084 cond = TCG_COND_NE;
20085 }
20086 break;
20087 case NM_BGEIC:
20088 if (rt == 0 && imm == 0) {
20089 /* Unconditional branch */
20090 } else {
20091 bcond_compute = 1;
20092 cond = TCG_COND_GE;
20093 }
20094 break;
20095 case NM_BLTIC:
20096 bcond_compute = 1;
20097 cond = TCG_COND_LT;
20098 break;
20099 case NM_BGEIUC:
20100 if (rt == 0 && imm == 0) {
20101 /* Unconditional branch */
20102 } else {
20103 bcond_compute = 1;
20104 cond = TCG_COND_GEU;
20105 }
20106 break;
20107 case NM_BLTIUC:
20108 bcond_compute = 1;
20109 cond = TCG_COND_LTU;
20110 break;
20111 default:
20112 MIPS_INVAL("Immediate Value Compact branch");
20113 generate_exception_end(ctx, EXCP_RI);
20114 goto out;
20115 }
20116
697b7b6b
SM
20117 /* branch completion */
20118 clear_branch_hflags(ctx);
20119 ctx->base.is_jmp = DISAS_NORETURN;
20120
11d0fc10
SM
20121 if (bcond_compute == 0) {
20122 /* Uncoditional compact branch */
20123 gen_goto_tb(ctx, 0, ctx->btarget);
20124 } else {
20125 /* Conditional compact branch */
20126 TCGLabel *fs = gen_new_label();
20127
20128 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20129
20130 gen_goto_tb(ctx, 1, ctx->btarget);
20131 gen_set_label(fs);
20132
20133 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20134 }
20135
20136out:
20137 tcg_temp_free(t0);
20138 tcg_temp_free(t1);
20139}
20140
20141/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20142static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20143 int rt)
20144{
20145 TCGv t0 = tcg_temp_new();
20146 TCGv t1 = tcg_temp_new();
20147
20148 /* load rs */
20149 gen_load_gpr(t0, rs);
20150
20151 /* link */
20152 if (rt != 0) {
20153 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20154 }
20155
20156 /* calculate btarget */
20157 tcg_gen_shli_tl(t0, t0, 1);
20158 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20159 gen_op_addr_add(ctx, btarget, t1, t0);
20160
697b7b6b
SM
20161 /* branch completion */
20162 clear_branch_hflags(ctx);
20163 ctx->base.is_jmp = DISAS_NORETURN;
20164
11d0fc10
SM
20165 /* unconditional branch to register */
20166 tcg_gen_mov_tl(cpu_PC, btarget);
20167 tcg_gen_lookup_and_goto_ptr();
20168
20169 tcg_temp_free(t0);
20170 tcg_temp_free(t1);
20171}
20172
20173/* nanoMIPS Branches */
20174static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20175 int rs, int rt, int32_t offset)
20176{
20177 int bcond_compute = 0;
20178 TCGv t0 = tcg_temp_new();
20179 TCGv t1 = tcg_temp_new();
20180
20181 /* Load needed operands and calculate btarget */
20182 switch (opc) {
20183 /* compact branch */
20184 case OPC_BGEC:
20185 case OPC_BLTC:
20186 gen_load_gpr(t0, rs);
20187 gen_load_gpr(t1, rt);
20188 bcond_compute = 1;
20189 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20190 break;
20191 case OPC_BGEUC:
20192 case OPC_BLTUC:
20193 if (rs == 0 || rs == rt) {
20194 /* OPC_BLEZALC, OPC_BGEZALC */
20195 /* OPC_BGTZALC, OPC_BLTZALC */
20196 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20197 }
20198 gen_load_gpr(t0, rs);
20199 gen_load_gpr(t1, rt);
20200 bcond_compute = 1;
20201 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20202 break;
20203 case OPC_BC:
20204 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20205 break;
20206 case OPC_BEQZC:
20207 if (rs != 0) {
20208 /* OPC_BEQZC, OPC_BNEZC */
20209 gen_load_gpr(t0, rs);
20210 bcond_compute = 1;
20211 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20212 } else {
20213 /* OPC_JIC, OPC_JIALC */
20214 TCGv tbase = tcg_temp_new();
20215 TCGv toffset = tcg_temp_new();
20216
20217 gen_load_gpr(tbase, rt);
20218 tcg_gen_movi_tl(toffset, offset);
20219 gen_op_addr_add(ctx, btarget, tbase, toffset);
20220 tcg_temp_free(tbase);
20221 tcg_temp_free(toffset);
20222 }
20223 break;
20224 default:
20225 MIPS_INVAL("Compact branch/jump");
20226 generate_exception_end(ctx, EXCP_RI);
20227 goto out;
20228 }
20229
20230 if (bcond_compute == 0) {
20231 /* Uncoditional compact branch */
20232 switch (opc) {
20233 case OPC_BC:
20234 gen_goto_tb(ctx, 0, ctx->btarget);
20235 break;
20236 default:
20237 MIPS_INVAL("Compact branch/jump");
20238 generate_exception_end(ctx, EXCP_RI);
20239 goto out;
20240 }
20241 } else {
20242 /* Conditional compact branch */
20243 TCGLabel *fs = gen_new_label();
20244
20245 switch (opc) {
20246 case OPC_BGEUC:
20247 if (rs == 0 && rt != 0) {
20248 /* OPC_BLEZALC */
20249 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20250 } else if (rs != 0 && rt != 0 && rs == rt) {
20251 /* OPC_BGEZALC */
20252 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20253 } else {
20254 /* OPC_BGEUC */
20255 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20256 }
20257 break;
20258 case OPC_BLTUC:
20259 if (rs == 0 && rt != 0) {
20260 /* OPC_BGTZALC */
20261 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20262 } else if (rs != 0 && rt != 0 && rs == rt) {
20263 /* OPC_BLTZALC */
20264 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20265 } else {
20266 /* OPC_BLTUC */
20267 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20268 }
20269 break;
20270 case OPC_BGEC:
20271 if (rs == 0 && rt != 0) {
20272 /* OPC_BLEZC */
20273 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20274 } else if (rs != 0 && rt != 0 && rs == rt) {
20275 /* OPC_BGEZC */
20276 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20277 } else {
20278 /* OPC_BGEC */
20279 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20280 }
20281 break;
20282 case OPC_BLTC:
20283 if (rs == 0 && rt != 0) {
20284 /* OPC_BGTZC */
20285 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20286 } else if (rs != 0 && rt != 0 && rs == rt) {
20287 /* OPC_BLTZC */
20288 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20289 } else {
20290 /* OPC_BLTC */
20291 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20292 }
20293 break;
20294 case OPC_BEQZC:
20295 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20296 break;
20297 default:
20298 MIPS_INVAL("Compact conditional branch/jump");
20299 generate_exception_end(ctx, EXCP_RI);
20300 goto out;
20301 }
20302
697b7b6b
SM
20303 /* branch completion */
20304 clear_branch_hflags(ctx);
20305 ctx->base.is_jmp = DISAS_NORETURN;
20306
11d0fc10
SM
20307 /* Generating branch here as compact branches don't have delay slot */
20308 gen_goto_tb(ctx, 1, ctx->btarget);
20309 gen_set_label(fs);
20310
20311 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20312 }
20313
20314out:
20315 tcg_temp_free(t0);
20316 tcg_temp_free(t1);
20317}
20318
20319
20320/* nanoMIPS CP1 Branches */
20321static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20322 int32_t ft, int32_t offset)
20323{
20324 target_ulong btarget;
20325 TCGv_i64 t0 = tcg_temp_new_i64();
20326
20327 gen_load_fpr64(ctx, t0, ft);
20328 tcg_gen_andi_i64(t0, t0, 1);
20329
20330 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20331
20332 switch (op) {
20333 case NM_BC1EQZC:
20334 tcg_gen_xori_i64(t0, t0, 1);
20335 ctx->hflags |= MIPS_HFLAG_BC;
20336 break;
20337 case NM_BC1NEZC:
20338 /* t0 already set */
20339 ctx->hflags |= MIPS_HFLAG_BC;
20340 break;
20341 default:
20342 MIPS_INVAL("cp1 cond branch");
20343 generate_exception_end(ctx, EXCP_RI);
20344 goto out;
20345 }
20346
20347 tcg_gen_trunc_i64_tl(bcond, t0);
20348
20349 ctx->btarget = btarget;
20350
20351out:
20352 tcg_temp_free_i64(t0);
20353}
20354
eac52664
YK
20355
20356static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20357{
20358 TCGv t0, t1;
20359 t0 = tcg_temp_new();
20360 t1 = tcg_temp_new();
20361
20362 gen_load_gpr(t0, rs);
20363 gen_load_gpr(t1, rt);
20364
20365 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20366 /* PP.LSXS instructions require shifting */
20367 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20368 case NM_SHXS:
fb32f8c8 20369 check_nms(ctx);
45152d05 20370 /* fall through */
fb32f8c8 20371 case NM_LHXS:
eac52664
YK
20372 case NM_LHUXS:
20373 tcg_gen_shli_tl(t0, t0, 1);
20374 break;
eac52664 20375 case NM_SWXS:
fb32f8c8 20376 check_nms(ctx);
45152d05 20377 /* fall through */
fb32f8c8 20378 case NM_LWXS:
eac52664
YK
20379 case NM_LWC1XS:
20380 case NM_SWC1XS:
20381 tcg_gen_shli_tl(t0, t0, 2);
20382 break;
20383 case NM_LDC1XS:
20384 case NM_SDC1XS:
20385 tcg_gen_shli_tl(t0, t0, 3);
20386 break;
20387 }
20388 }
20389 gen_op_addr_add(ctx, t0, t0, t1);
20390
20391 switch (extract32(ctx->opcode, 7, 4)) {
20392 case NM_LBX:
20393 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20394 MO_SB);
20395 gen_store_gpr(t0, rd);
20396 break;
20397 case NM_LHX:
20398 /*case NM_LHXS:*/
20399 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20400 MO_TESW);
20401 gen_store_gpr(t0, rd);
20402 break;
20403 case NM_LWX:
20404 /*case NM_LWXS:*/
20405 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20406 MO_TESL);
20407 gen_store_gpr(t0, rd);
20408 break;
20409 case NM_LBUX:
20410 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20411 MO_UB);
20412 gen_store_gpr(t0, rd);
20413 break;
20414 case NM_LHUX:
20415 /*case NM_LHUXS:*/
20416 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20417 MO_TEUW);
20418 gen_store_gpr(t0, rd);
20419 break;
20420 case NM_SBX:
fb32f8c8 20421 check_nms(ctx);
eac52664
YK
20422 gen_load_gpr(t1, rd);
20423 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20424 MO_8);
20425 break;
20426 case NM_SHX:
20427 /*case NM_SHXS:*/
fb32f8c8 20428 check_nms(ctx);
eac52664
YK
20429 gen_load_gpr(t1, rd);
20430 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20431 MO_TEUW);
20432 break;
20433 case NM_SWX:
20434 /*case NM_SWXS:*/
fb32f8c8 20435 check_nms(ctx);
eac52664
YK
20436 gen_load_gpr(t1, rd);
20437 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20438 MO_TEUL);
20439 break;
20440 case NM_LWC1X:
20441 /*case NM_LWC1XS:*/
20442 case NM_LDC1X:
20443 /*case NM_LDC1XS:*/
20444 case NM_SWC1X:
20445 /*case NM_SWC1XS:*/
20446 case NM_SDC1X:
20447 /*case NM_SDC1XS:*/
20448 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20449 check_cp1_enabled(ctx);
20450 switch (extract32(ctx->opcode, 7, 4)) {
20451 case NM_LWC1X:
20452 /*case NM_LWC1XS:*/
20453 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20454 break;
20455 case NM_LDC1X:
20456 /*case NM_LDC1XS:*/
20457 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20458 break;
20459 case NM_SWC1X:
20460 /*case NM_SWC1XS:*/
20461 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20462 break;
20463 case NM_SDC1X:
20464 /*case NM_SDC1XS:*/
20465 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20466 break;
20467 }
20468 } else {
20469 generate_exception_err(ctx, EXCP_CpU, 1);
20470 }
20471 break;
20472 default:
20473 generate_exception_end(ctx, EXCP_RI);
20474 break;
20475 }
20476
20477 tcg_temp_free(t0);
20478 tcg_temp_free(t1);
20479}
20480
579b8ea9
YK
20481static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20482{
20483 int rt, rs, rd;
20484
20485 rt = extract32(ctx->opcode, 21, 5);
20486 rs = extract32(ctx->opcode, 16, 5);
20487 rd = extract32(ctx->opcode, 11, 5);
20488
20489 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20490 generate_exception_end(ctx, EXCP_RI);
20491 return;
20492 }
20493 check_cp1_enabled(ctx);
20494 switch (extract32(ctx->opcode, 0, 3)) {
20495 case NM_POOL32F_0:
20496 switch (extract32(ctx->opcode, 3, 7)) {
20497 case NM_RINT_S:
20498 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20499 break;
20500 case NM_RINT_D:
20501 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20502 break;
20503 case NM_CLASS_S:
20504 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20505 break;
20506 case NM_CLASS_D:
20507 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20508 break;
20509 case NM_ADD_S:
20510 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20511 break;
20512 case NM_ADD_D:
20513 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20514 break;
20515 case NM_SUB_S:
20516 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20517 break;
20518 case NM_SUB_D:
20519 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20520 break;
20521 case NM_MUL_S:
20522 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20523 break;
20524 case NM_MUL_D:
20525 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20526 break;
20527 case NM_DIV_S:
20528 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20529 break;
20530 case NM_DIV_D:
20531 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20532 break;
20533 case NM_SELEQZ_S:
20534 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20535 break;
20536 case NM_SELEQZ_D:
20537 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20538 break;
20539 case NM_SELNEZ_S:
20540 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20541 break;
20542 case NM_SELNEZ_D:
20543 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20544 break;
20545 case NM_SEL_S:
20546 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20547 break;
20548 case NM_SEL_D:
20549 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20550 break;
20551 case NM_MADDF_S:
20552 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20553 break;
20554 case NM_MADDF_D:
20555 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20556 break;
20557 case NM_MSUBF_S:
20558 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20559 break;
20560 case NM_MSUBF_D:
20561 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20562 break;
20563 default:
20564 generate_exception_end(ctx, EXCP_RI);
20565 break;
20566 }
20567 break;
20568 case NM_POOL32F_3:
20569 switch (extract32(ctx->opcode, 3, 3)) {
20570 case NM_MIN_FMT:
20571 switch (extract32(ctx->opcode, 9, 1)) {
20572 case FMT_SDPS_S:
20573 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20574 break;
20575 case FMT_SDPS_D:
20576 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20577 break;
20578 }
20579 break;
20580 case NM_MAX_FMT:
20581 switch (extract32(ctx->opcode, 9, 1)) {
20582 case FMT_SDPS_S:
20583 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20584 break;
20585 case FMT_SDPS_D:
20586 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20587 break;
20588 }
20589 break;
20590 case NM_MINA_FMT:
20591 switch (extract32(ctx->opcode, 9, 1)) {
20592 case FMT_SDPS_S:
20593 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20594 break;
20595 case FMT_SDPS_D:
20596 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20597 break;
20598 }
20599 break;
20600 case NM_MAXA_FMT:
20601 switch (extract32(ctx->opcode, 9, 1)) {
20602 case FMT_SDPS_S:
20603 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20604 break;
20605 case FMT_SDPS_D:
20606 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20607 break;
20608 }
20609 break;
20610 case NM_POOL32FXF:
20611 switch (extract32(ctx->opcode, 6, 8)) {
20612 case NM_CFC1:
20613 gen_cp1(ctx, OPC_CFC1, rt, rs);
20614 break;
20615 case NM_CTC1:
20616 gen_cp1(ctx, OPC_CTC1, rt, rs);
20617 break;
20618 case NM_MFC1:
20619 gen_cp1(ctx, OPC_MFC1, rt, rs);
20620 break;
20621 case NM_MTC1:
20622 gen_cp1(ctx, OPC_MTC1, rt, rs);
20623 break;
20624 case NM_MFHC1:
20625 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20626 break;
20627 case NM_MTHC1:
20628 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20629 break;
20630 case NM_CVT_S_PL:
20631 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20632 break;
20633 case NM_CVT_S_PU:
20634 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20635 break;
20636 default:
20637 switch (extract32(ctx->opcode, 6, 9)) {
20638 case NM_CVT_L_S:
20639 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20640 break;
20641 case NM_CVT_L_D:
20642 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20643 break;
20644 case NM_CVT_W_S:
20645 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20646 break;
20647 case NM_CVT_W_D:
20648 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20649 break;
20650 case NM_RSQRT_S:
20651 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20652 break;
20653 case NM_RSQRT_D:
20654 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20655 break;
20656 case NM_SQRT_S:
20657 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20658 break;
20659 case NM_SQRT_D:
20660 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20661 break;
20662 case NM_RECIP_S:
20663 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20664 break;
20665 case NM_RECIP_D:
20666 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20667 break;
20668 case NM_FLOOR_L_S:
20669 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20670 break;
20671 case NM_FLOOR_L_D:
20672 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20673 break;
20674 case NM_FLOOR_W_S:
20675 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20676 break;
20677 case NM_FLOOR_W_D:
20678 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20679 break;
20680 case NM_CEIL_L_S:
20681 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20682 break;
20683 case NM_CEIL_L_D:
20684 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20685 break;
20686 case NM_CEIL_W_S:
20687 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20688 break;
20689 case NM_CEIL_W_D:
20690 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20691 break;
20692 case NM_TRUNC_L_S:
20693 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20694 break;
20695 case NM_TRUNC_L_D:
20696 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20697 break;
20698 case NM_TRUNC_W_S:
20699 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20700 break;
20701 case NM_TRUNC_W_D:
20702 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20703 break;
20704 case NM_ROUND_L_S:
20705 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20706 break;
20707 case NM_ROUND_L_D:
20708 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20709 break;
20710 case NM_ROUND_W_S:
20711 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20712 break;
20713 case NM_ROUND_W_D:
20714 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20715 break;
20716 case NM_MOV_S:
20717 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20718 break;
20719 case NM_MOV_D:
20720 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20721 break;
20722 case NM_ABS_S:
20723 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20724 break;
20725 case NM_ABS_D:
20726 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20727 break;
20728 case NM_NEG_S:
20729 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20730 break;
20731 case NM_NEG_D:
20732 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20733 break;
20734 case NM_CVT_D_S:
20735 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20736 break;
20737 case NM_CVT_D_W:
20738 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20739 break;
20740 case NM_CVT_D_L:
20741 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20742 break;
20743 case NM_CVT_S_D:
20744 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20745 break;
20746 case NM_CVT_S_W:
20747 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20748 break;
20749 case NM_CVT_S_L:
20750 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20751 break;
20752 default:
20753 generate_exception_end(ctx, EXCP_RI);
20754 break;
20755 }
20756 break;
20757 }
20758 break;
20759 }
20760 break;
20761 case NM_POOL32F_5:
20762 switch (extract32(ctx->opcode, 3, 3)) {
20763 case NM_CMP_CONDN_S:
20764 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20765 break;
20766 case NM_CMP_CONDN_D:
20767 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20768 break;
20769 default:
20770 generate_exception_end(ctx, EXCP_RI);
20771 break;
20772 }
20773 break;
20774 default:
20775 generate_exception_end(ctx, EXCP_RI);
20776 break;
20777 }
20778}
20779
3285a3e4
SM
20780static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20781 int rd, int rs, int rt)
20782{
20783 int ret = rd;
20784 TCGv t0 = tcg_temp_new();
20785 TCGv v1_t = tcg_temp_new();
20786 TCGv v2_t = tcg_temp_new();
20787
20788 gen_load_gpr(v1_t, rs);
20789 gen_load_gpr(v2_t, rt);
20790
20791 switch (opc) {
20792 case NM_CMP_EQ_PH:
20793 check_dsp(ctx);
20794 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20795 break;
20796 case NM_CMP_LT_PH:
20797 check_dsp(ctx);
20798 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20799 break;
20800 case NM_CMP_LE_PH:
20801 check_dsp(ctx);
20802 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20803 break;
20804 case NM_CMPU_EQ_QB:
20805 check_dsp(ctx);
20806 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20807 break;
20808 case NM_CMPU_LT_QB:
20809 check_dsp(ctx);
20810 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20811 break;
20812 case NM_CMPU_LE_QB:
20813 check_dsp(ctx);
20814 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20815 break;
20816 case NM_CMPGU_EQ_QB:
20817 check_dsp(ctx);
20818 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20819 gen_store_gpr(v1_t, ret);
20820 break;
20821 case NM_CMPGU_LT_QB:
20822 check_dsp(ctx);
20823 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20824 gen_store_gpr(v1_t, ret);
20825 break;
20826 case NM_CMPGU_LE_QB:
20827 check_dsp(ctx);
20828 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20829 gen_store_gpr(v1_t, ret);
20830 break;
20831 case NM_CMPGDU_EQ_QB:
908f6be1 20832 check_dsp_r2(ctx);
3285a3e4
SM
20833 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20834 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20835 gen_store_gpr(v1_t, ret);
20836 break;
20837 case NM_CMPGDU_LT_QB:
908f6be1 20838 check_dsp_r2(ctx);
3285a3e4
SM
20839 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20840 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20841 gen_store_gpr(v1_t, ret);
20842 break;
20843 case NM_CMPGDU_LE_QB:
908f6be1 20844 check_dsp_r2(ctx);
3285a3e4
SM
20845 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20846 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20847 gen_store_gpr(v1_t, ret);
20848 break;
20849 case NM_PACKRL_PH:
20850 check_dsp(ctx);
20851 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20852 gen_store_gpr(v1_t, ret);
20853 break;
20854 case NM_PICK_QB:
20855 check_dsp(ctx);
20856 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20857 gen_store_gpr(v1_t, ret);
20858 break;
20859 case NM_PICK_PH:
20860 check_dsp(ctx);
20861 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20862 gen_store_gpr(v1_t, ret);
20863 break;
20864 case NM_ADDQ_S_W:
20865 check_dsp(ctx);
20866 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20867 gen_store_gpr(v1_t, ret);
20868 break;
20869 case NM_SUBQ_S_W:
20870 check_dsp(ctx);
20871 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20872 gen_store_gpr(v1_t, ret);
20873 break;
20874 case NM_ADDSC:
20875 check_dsp(ctx);
20876 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20877 gen_store_gpr(v1_t, ret);
20878 break;
20879 case NM_ADDWC:
20880 check_dsp(ctx);
20881 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20882 gen_store_gpr(v1_t, ret);
20883 break;
20884 case NM_ADDQ_S_PH:
20885 check_dsp(ctx);
20886 switch (extract32(ctx->opcode, 10, 1)) {
20887 case 0:
20888 /* ADDQ_PH */
20889 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20890 gen_store_gpr(v1_t, ret);
20891 break;
20892 case 1:
20893 /* ADDQ_S_PH */
20894 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20895 gen_store_gpr(v1_t, ret);
20896 break;
20897 }
20898 break;
20899 case NM_ADDQH_R_PH:
908f6be1 20900 check_dsp_r2(ctx);
3285a3e4
SM
20901 switch (extract32(ctx->opcode, 10, 1)) {
20902 case 0:
20903 /* ADDQH_PH */
20904 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20905 gen_store_gpr(v1_t, ret);
20906 break;
20907 case 1:
20908 /* ADDQH_R_PH */
20909 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20910 gen_store_gpr(v1_t, ret);
20911 break;
20912 }
20913 break;
20914 case NM_ADDQH_R_W:
908f6be1 20915 check_dsp_r2(ctx);
3285a3e4
SM
20916 switch (extract32(ctx->opcode, 10, 1)) {
20917 case 0:
20918 /* ADDQH_W */
20919 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20920 gen_store_gpr(v1_t, ret);
20921 break;
20922 case 1:
20923 /* ADDQH_R_W */
20924 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20925 gen_store_gpr(v1_t, ret);
20926 break;
20927 }
20928 break;
20929 case NM_ADDU_S_QB:
20930 check_dsp(ctx);
20931 switch (extract32(ctx->opcode, 10, 1)) {
20932 case 0:
20933 /* ADDU_QB */
20934 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20935 gen_store_gpr(v1_t, ret);
20936 break;
20937 case 1:
20938 /* ADDU_S_QB */
20939 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20940 gen_store_gpr(v1_t, ret);
20941 break;
20942 }
20943 break;
20944 case NM_ADDU_S_PH:
908f6be1 20945 check_dsp_r2(ctx);
3285a3e4
SM
20946 switch (extract32(ctx->opcode, 10, 1)) {
20947 case 0:
20948 /* ADDU_PH */
20949 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20950 gen_store_gpr(v1_t, ret);
20951 break;
20952 case 1:
20953 /* ADDU_S_PH */
20954 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20955 gen_store_gpr(v1_t, ret);
20956 break;
20957 }
20958 break;
20959 case NM_ADDUH_R_QB:
908f6be1 20960 check_dsp_r2(ctx);
3285a3e4
SM
20961 switch (extract32(ctx->opcode, 10, 1)) {
20962 case 0:
20963 /* ADDUH_QB */
20964 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20965 gen_store_gpr(v1_t, ret);
20966 break;
20967 case 1:
20968 /* ADDUH_R_QB */
20969 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20970 gen_store_gpr(v1_t, ret);
20971 break;
20972 }
20973 break;
20974 case NM_SHRAV_R_PH:
20975 check_dsp(ctx);
20976 switch (extract32(ctx->opcode, 10, 1)) {
20977 case 0:
20978 /* SHRAV_PH */
20979 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20980 gen_store_gpr(v1_t, ret);
20981 break;
20982 case 1:
20983 /* SHRAV_R_PH */
20984 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20985 gen_store_gpr(v1_t, ret);
20986 break;
20987 }
20988 break;
20989 case NM_SHRAV_R_QB:
908f6be1 20990 check_dsp_r2(ctx);
3285a3e4
SM
20991 switch (extract32(ctx->opcode, 10, 1)) {
20992 case 0:
20993 /* SHRAV_QB */
20994 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20995 gen_store_gpr(v1_t, ret);
20996 break;
20997 case 1:
20998 /* SHRAV_R_QB */
20999 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21000 gen_store_gpr(v1_t, ret);
21001 break;
21002 }
21003 break;
21004 case NM_SUBQ_S_PH:
21005 check_dsp(ctx);
21006 switch (extract32(ctx->opcode, 10, 1)) {
21007 case 0:
21008 /* SUBQ_PH */
21009 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21010 gen_store_gpr(v1_t, ret);
21011 break;
21012 case 1:
21013 /* SUBQ_S_PH */
21014 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21015 gen_store_gpr(v1_t, ret);
21016 break;
21017 }
21018 break;
21019 case NM_SUBQH_R_PH:
908f6be1 21020 check_dsp_r2(ctx);
3285a3e4
SM
21021 switch (extract32(ctx->opcode, 10, 1)) {
21022 case 0:
21023 /* SUBQH_PH */
21024 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21025 gen_store_gpr(v1_t, ret);
21026 break;
21027 case 1:
21028 /* SUBQH_R_PH */
21029 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21030 gen_store_gpr(v1_t, ret);
21031 break;
21032 }
21033 break;
21034 case NM_SUBQH_R_W:
908f6be1 21035 check_dsp_r2(ctx);
3285a3e4
SM
21036 switch (extract32(ctx->opcode, 10, 1)) {
21037 case 0:
21038 /* SUBQH_W */
21039 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21040 gen_store_gpr(v1_t, ret);
21041 break;
21042 case 1:
21043 /* SUBQH_R_W */
21044 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21045 gen_store_gpr(v1_t, ret);
21046 break;
21047 }
21048 break;
21049 case NM_SUBU_S_QB:
21050 check_dsp(ctx);
21051 switch (extract32(ctx->opcode, 10, 1)) {
21052 case 0:
21053 /* SUBU_QB */
21054 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21055 gen_store_gpr(v1_t, ret);
21056 break;
21057 case 1:
21058 /* SUBU_S_QB */
21059 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21060 gen_store_gpr(v1_t, ret);
21061 break;
21062 }
21063 break;
21064 case NM_SUBU_S_PH:
908f6be1 21065 check_dsp_r2(ctx);
3285a3e4
SM
21066 switch (extract32(ctx->opcode, 10, 1)) {
21067 case 0:
21068 /* SUBU_PH */
21069 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21070 gen_store_gpr(v1_t, ret);
21071 break;
21072 case 1:
21073 /* SUBU_S_PH */
21074 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21075 gen_store_gpr(v1_t, ret);
21076 break;
21077 }
21078 break;
21079 case NM_SUBUH_R_QB:
908f6be1 21080 check_dsp_r2(ctx);
3285a3e4
SM
21081 switch (extract32(ctx->opcode, 10, 1)) {
21082 case 0:
21083 /* SUBUH_QB */
21084 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21085 gen_store_gpr(v1_t, ret);
21086 break;
21087 case 1:
21088 /* SUBUH_R_QB */
21089 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21090 gen_store_gpr(v1_t, ret);
21091 break;
21092 }
21093 break;
21094 case NM_SHLLV_S_PH:
21095 check_dsp(ctx);
21096 switch (extract32(ctx->opcode, 10, 1)) {
21097 case 0:
21098 /* SHLLV_PH */
21099 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21100 gen_store_gpr(v1_t, ret);
21101 break;
21102 case 1:
21103 /* SHLLV_S_PH */
21104 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21105 gen_store_gpr(v1_t, ret);
21106 break;
21107 }
21108 break;
21109 case NM_PRECR_SRA_R_PH_W:
908f6be1 21110 check_dsp_r2(ctx);
3285a3e4
SM
21111 switch (extract32(ctx->opcode, 10, 1)) {
21112 case 0:
21113 /* PRECR_SRA_PH_W */
21114 {
21115 TCGv_i32 sa_t = tcg_const_i32(rd);
21116 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21117 cpu_gpr[rt]);
21118 gen_store_gpr(v1_t, rt);
21119 tcg_temp_free_i32(sa_t);
21120 }
21121 break;
21122 case 1:
21123 /* PRECR_SRA_R_PH_W */
21124 {
21125 TCGv_i32 sa_t = tcg_const_i32(rd);
21126 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21127 cpu_gpr[rt]);
21128 gen_store_gpr(v1_t, rt);
21129 tcg_temp_free_i32(sa_t);
21130 }
21131 break;
21132 }
21133 break;
21134 case NM_MULEU_S_PH_QBL:
21135 check_dsp(ctx);
21136 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21137 gen_store_gpr(v1_t, ret);
21138 break;
21139 case NM_MULEU_S_PH_QBR:
21140 check_dsp(ctx);
21141 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21142 gen_store_gpr(v1_t, ret);
21143 break;
21144 case NM_MULQ_RS_PH:
21145 check_dsp(ctx);
21146 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21147 gen_store_gpr(v1_t, ret);
21148 break;
21149 case NM_MULQ_S_PH:
908f6be1 21150 check_dsp_r2(ctx);
3285a3e4
SM
21151 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21152 gen_store_gpr(v1_t, ret);
21153 break;
21154 case NM_MULQ_RS_W:
908f6be1 21155 check_dsp_r2(ctx);
3285a3e4
SM
21156 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21157 gen_store_gpr(v1_t, ret);
21158 break;
21159 case NM_MULQ_S_W:
908f6be1 21160 check_dsp_r2(ctx);
3285a3e4
SM
21161 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21162 gen_store_gpr(v1_t, ret);
21163 break;
21164 case NM_APPEND:
908f6be1 21165 check_dsp_r2(ctx);
3285a3e4
SM
21166 gen_load_gpr(t0, rs);
21167 if (rd != 0) {
21168 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21169 }
21170 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21171 break;
21172 case NM_MODSUB:
21173 check_dsp(ctx);
21174 gen_helper_modsub(v1_t, v1_t, v2_t);
21175 gen_store_gpr(v1_t, ret);
21176 break;
21177 case NM_SHRAV_R_W:
21178 check_dsp(ctx);
21179 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21180 gen_store_gpr(v1_t, ret);
21181 break;
21182 case NM_SHRLV_PH:
908f6be1 21183 check_dsp_r2(ctx);
3285a3e4
SM
21184 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21185 gen_store_gpr(v1_t, ret);
21186 break;
21187 case NM_SHRLV_QB:
21188 check_dsp(ctx);
21189 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21190 gen_store_gpr(v1_t, ret);
21191 break;
21192 case NM_SHLLV_QB:
21193 check_dsp(ctx);
21194 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21195 gen_store_gpr(v1_t, ret);
21196 break;
21197 case NM_SHLLV_S_W:
21198 check_dsp(ctx);
21199 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21200 gen_store_gpr(v1_t, ret);
21201 break;
21202 case NM_SHILO:
21203 check_dsp(ctx);
21204 {
21205 TCGv tv0 = tcg_temp_new();
21206 TCGv tv1 = tcg_temp_new();
21207 int16_t imm = extract32(ctx->opcode, 16, 7);
21208
21209 tcg_gen_movi_tl(tv0, rd >> 3);
21210 tcg_gen_movi_tl(tv1, imm);
21211 gen_helper_shilo(tv0, tv1, cpu_env);
21212 }
21213 break;
21214 case NM_MULEQ_S_W_PHL:
21215 check_dsp(ctx);
21216 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21217 gen_store_gpr(v1_t, ret);
21218 break;
21219 case NM_MULEQ_S_W_PHR:
21220 check_dsp(ctx);
21221 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21222 gen_store_gpr(v1_t, ret);
21223 break;
21224 case NM_MUL_S_PH:
908f6be1 21225 check_dsp_r2(ctx);
3285a3e4
SM
21226 switch (extract32(ctx->opcode, 10, 1)) {
21227 case 0:
21228 /* MUL_PH */
21229 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21230 gen_store_gpr(v1_t, ret);
21231 break;
21232 case 1:
21233 /* MUL_S_PH */
21234 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21235 gen_store_gpr(v1_t, ret);
21236 break;
21237 }
21238 break;
21239 case NM_PRECR_QB_PH:
908f6be1 21240 check_dsp_r2(ctx);
3285a3e4
SM
21241 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21242 gen_store_gpr(v1_t, ret);
21243 break;
21244 case NM_PRECRQ_QB_PH:
21245 check_dsp(ctx);
21246 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21247 gen_store_gpr(v1_t, ret);
21248 break;
21249 case NM_PRECRQ_PH_W:
21250 check_dsp(ctx);
21251 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21252 gen_store_gpr(v1_t, ret);
21253 break;
21254 case NM_PRECRQ_RS_PH_W:
21255 check_dsp(ctx);
21256 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21257 gen_store_gpr(v1_t, ret);
21258 break;
21259 case NM_PRECRQU_S_QB_PH:
21260 check_dsp(ctx);
21261 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21262 gen_store_gpr(v1_t, ret);
21263 break;
21264 case NM_SHRA_R_W:
21265 check_dsp(ctx);
21266 tcg_gen_movi_tl(t0, rd);
21267 gen_helper_shra_r_w(v1_t, t0, v1_t);
21268 gen_store_gpr(v1_t, rt);
21269 break;
21270 case NM_SHRA_R_PH:
21271 check_dsp(ctx);
21272 tcg_gen_movi_tl(t0, rd >> 1);
21273 switch (extract32(ctx->opcode, 10, 1)) {
21274 case 0:
21275 /* SHRA_PH */
21276 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 21277 gen_store_gpr(v1_t, rt);
d5ebcbaf 21278 break;
3285a3e4
SM
21279 case 1:
21280 /* SHRA_R_PH */
21281 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21282 gen_store_gpr(v1_t, rt);
21283 break;
21284 }
21285 break;
21286 case NM_SHLL_S_PH:
21287 check_dsp(ctx);
21288 tcg_gen_movi_tl(t0, rd >> 1);
21289 switch (extract32(ctx->opcode, 10, 2)) {
21290 case 0:
21291 /* SHLL_PH */
21292 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21293 gen_store_gpr(v1_t, rt);
21294 break;
21295 case 2:
21296 /* SHLL_S_PH */
21297 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21298 gen_store_gpr(v1_t, rt);
21299 break;
21300 default:
21301 generate_exception_end(ctx, EXCP_RI);
21302 break;
21303 }
21304 break;
21305 case NM_SHLL_S_W:
21306 check_dsp(ctx);
21307 tcg_gen_movi_tl(t0, rd);
21308 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21309 gen_store_gpr(v1_t, rt);
21310 break;
21311 case NM_REPL_PH:
21312 check_dsp(ctx);
21313 {
21314 int16_t imm;
21315 imm = sextract32(ctx->opcode, 11, 11);
21316 imm = (int16_t)(imm << 6) >> 6;
21317 if (rt != 0) {
21318 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21319 }
21320 }
21321 break;
21322 default:
21323 generate_exception_end(ctx, EXCP_RI);
21324 break;
21325 }
21326}
21327
c0280983
YK
21328static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21329{
21330 uint16_t insn;
21331 uint32_t op;
eac52664 21332 int rt, rs, rd;
c0280983
YK
21333 int offset;
21334 int imm;
21335
21336 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21337 ctx->opcode = (ctx->opcode << 16) | insn;
21338
21339 rt = extract32(ctx->opcode, 21, 5);
21340 rs = extract32(ctx->opcode, 16, 5);
eac52664 21341 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
21342
21343 op = extract32(ctx->opcode, 26, 6);
21344 switch (op) {
21345 case NM_P_ADDIU:
21346 if (rt == 0) {
21347 /* P.RI */
21348 switch (extract32(ctx->opcode, 19, 2)) {
21349 case NM_SIGRIE:
21350 default:
21351 generate_exception_end(ctx, EXCP_RI);
21352 break;
21353 case NM_P_SYSCALL:
21354 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21355 generate_exception_end(ctx, EXCP_SYSCALL);
21356 } else {
21357 generate_exception_end(ctx, EXCP_RI);
21358 }
21359 break;
21360 case NM_BREAK:
21361 generate_exception_end(ctx, EXCP_BREAK);
21362 break;
21363 case NM_SDBBP:
21364 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21365 gen_helper_do_semihosting(cpu_env);
21366 } else {
21367 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21368 generate_exception_end(ctx, EXCP_RI);
21369 } else {
21370 generate_exception_end(ctx, EXCP_DBp);
21371 }
21372 }
21373 break;
21374 }
21375 } else {
21376 /* NM_ADDIU */
21377 imm = extract32(ctx->opcode, 0, 16);
21378 if (rs != 0) {
21379 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21380 } else {
21381 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21382 }
21383 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21384 }
21385 break;
21386 case NM_ADDIUPC:
21387 if (rt != 0) {
21388 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21389 extract32(ctx->opcode, 1, 20) << 1;
21390 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21391 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21392 }
21393 break;
21394 case NM_POOL32A:
e0cf0e65
YK
21395 switch (ctx->opcode & 0x07) {
21396 case NM_POOL32A0:
0a1a6ed7 21397 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21398 break;
3285a3e4
SM
21399 case NM_POOL32A5:
21400 {
21401 int32_t op1 = extract32(ctx->opcode, 3, 7);
21402 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21403 }
21404 break;
e0cf0e65 21405 case NM_POOL32A7:
64224187 21406 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21407 case NM_P_LSX:
21408 gen_p_lsx(ctx, rd, rs, rt);
21409 break;
21410 case NM_LSA:
7480515f
AM
21411 /*
21412 * In nanoMIPS, the shift field directly encodes the shift
eac52664 21413 * amount, meaning that the supported shift values are in
7480515f
AM
21414 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21415 */
eac52664
YK
21416 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21417 extract32(ctx->opcode, 9, 2) - 1);
21418 break;
821f2008
JH
21419 case NM_EXTW:
21420 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21421 break;
64224187
YK
21422 case NM_POOL32AXF:
21423 gen_pool32axf_nanomips_insn(env, ctx);
21424 break;
21425 default:
21426 generate_exception_end(ctx, EXCP_RI);
21427 break;
21428 }
e0cf0e65
YK
21429 break;
21430 default:
21431 generate_exception_end(ctx, EXCP_RI);
21432 break;
21433 }
c0280983
YK
21434 break;
21435 case NM_P_GP_W:
21436 switch (ctx->opcode & 0x03) {
21437 case NM_ADDIUGP_W:
21438 if (rt != 0) {
21439 offset = extract32(ctx->opcode, 0, 21);
21440 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21441 }
21442 break;
21443 case NM_LWGP:
21444 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21445 break;
21446 case NM_SWGP:
21447 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21448 break;
21449 default:
21450 generate_exception_end(ctx, EXCP_RI);
21451 break;
21452 }
21453 break;
21454 case NM_P48I:
7ef009b2
YK
21455 {
21456 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21457 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21458 switch (extract32(ctx->opcode, 16, 5)) {
21459 case NM_LI48:
fb32f8c8 21460 check_nms(ctx);
7ef009b2
YK
21461 if (rt != 0) {
21462 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21463 }
21464 break;
21465 case NM_ADDIU48:
fb32f8c8 21466 check_nms(ctx);
7ef009b2
YK
21467 if (rt != 0) {
21468 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21469 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21470 }
21471 break;
21472 case NM_ADDIUGP48:
fb32f8c8 21473 check_nms(ctx);
7ef009b2
YK
21474 if (rt != 0) {
21475 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21476 }
21477 break;
21478 case NM_ADDIUPC48:
fb32f8c8 21479 check_nms(ctx);
7ef009b2
YK
21480 if (rt != 0) {
21481 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21482 addr_off);
21483
21484 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21485 }
21486 break;
21487 case NM_LWPC48:
fb32f8c8 21488 check_nms(ctx);
7ef009b2
YK
21489 if (rt != 0) {
21490 TCGv t0;
21491 t0 = tcg_temp_new();
21492
21493 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21494 addr_off);
21495
21496 tcg_gen_movi_tl(t0, addr);
21497 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21498 tcg_temp_free(t0);
21499 }
21500 break;
21501 case NM_SWPC48:
fb32f8c8 21502 check_nms(ctx);
7ef009b2
YK
21503 {
21504 TCGv t0, t1;
21505 t0 = tcg_temp_new();
21506 t1 = tcg_temp_new();
21507
21508 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21509 addr_off);
21510
21511 tcg_gen_movi_tl(t0, addr);
21512 gen_load_gpr(t1, rt);
21513
21514 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21515
21516 tcg_temp_free(t0);
21517 tcg_temp_free(t1);
21518 }
21519 break;
21520 default:
21521 generate_exception_end(ctx, EXCP_RI);
21522 break;
21523 }
21524 return 6;
21525 }
c0280983
YK
21526 case NM_P_U12:
21527 switch (extract32(ctx->opcode, 12, 4)) {
21528 case NM_ORI:
21529 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21530 break;
21531 case NM_XORI:
21532 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21533 break;
21534 case NM_ANDI:
21535 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21536 break;
21537 case NM_P_SR:
21538 switch (extract32(ctx->opcode, 20, 1)) {
21539 case NM_PP_SR:
21540 switch (ctx->opcode & 3) {
21541 case NM_SAVE:
21542 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21543 extract32(ctx->opcode, 2, 1),
21544 extract32(ctx->opcode, 3, 9) << 3);
21545 break;
21546 case NM_RESTORE:
21547 case NM_RESTORE_JRC:
21548 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21549 extract32(ctx->opcode, 2, 1),
21550 extract32(ctx->opcode, 3, 9) << 3);
21551 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21552 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21553 }
21554 break;
21555 default:
21556 generate_exception_end(ctx, EXCP_RI);
21557 break;
21558 }
21559 break;
21560 case NM_P_SR_F:
21561 generate_exception_end(ctx, EXCP_RI);
21562 break;
21563 }
21564 break;
21565 case NM_SLTI:
21566 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21567 break;
21568 case NM_SLTIU:
21569 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21570 break;
21571 case NM_SEQI:
21572 {
21573 TCGv t0 = tcg_temp_new();
21574
21575 imm = extract32(ctx->opcode, 0, 12);
21576 gen_load_gpr(t0, rs);
21577 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21578 gen_store_gpr(t0, rt);
21579
21580 tcg_temp_free(t0);
21581 }
21582 break;
21583 case NM_ADDIUNEG:
21584 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21585 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21586 break;
21587 case NM_P_SHIFT:
21588 {
21589 int shift = extract32(ctx->opcode, 0, 5);
21590 switch (extract32(ctx->opcode, 5, 4)) {
21591 case NM_P_SLL:
21592 if (rt == 0 && shift == 0) {
21593 /* NOP */
21594 } else if (rt == 0 && shift == 3) {
21595 /* EHB - treat as NOP */
21596 } else if (rt == 0 && shift == 5) {
21597 /* PAUSE - treat as NOP */
21598 } else if (rt == 0 && shift == 6) {
21599 /* SYNC */
21600 gen_sync(extract32(ctx->opcode, 16, 5));
21601 } else {
21602 /* SLL */
21603 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21604 extract32(ctx->opcode, 0, 5));
21605 }
21606 break;
21607 case NM_SRL:
21608 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21609 extract32(ctx->opcode, 0, 5));
21610 break;
21611 case NM_SRA:
21612 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21613 extract32(ctx->opcode, 0, 5));
21614 break;
21615 case NM_ROTR:
21616 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21617 extract32(ctx->opcode, 0, 5));
21618 break;
21619 }
21620 }
21621 break;
21622 case NM_P_ROTX:
fb32f8c8 21623 check_nms(ctx);
e222f506
MF
21624 if (rt != 0) {
21625 TCGv t0 = tcg_temp_new();
21626 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21627 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21628 << 1);
21629 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21630
21631 gen_load_gpr(t0, rs);
21632 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21633 tcg_temp_free(t0);
21634
21635 tcg_temp_free_i32(shift);
21636 tcg_temp_free_i32(shiftx);
21637 tcg_temp_free_i32(stripe);
21638 }
c0280983
YK
21639 break;
21640 case NM_P_INS:
21641 switch (((ctx->opcode >> 10) & 2) |
21642 (extract32(ctx->opcode, 5, 1))) {
21643 case NM_INS:
fb32f8c8 21644 check_nms(ctx);
c0280983
YK
21645 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21646 extract32(ctx->opcode, 6, 5));
21647 break;
21648 default:
21649 generate_exception_end(ctx, EXCP_RI);
21650 break;
21651 }
21652 break;
21653 case NM_P_EXT:
21654 switch (((ctx->opcode >> 10) & 2) |
21655 (extract32(ctx->opcode, 5, 1))) {
21656 case NM_EXT:
fb32f8c8 21657 check_nms(ctx);
c0280983
YK
21658 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21659 extract32(ctx->opcode, 6, 5));
21660 break;
21661 default:
21662 generate_exception_end(ctx, EXCP_RI);
21663 break;
21664 }
21665 break;
21666 default:
21667 generate_exception_end(ctx, EXCP_RI);
21668 break;
21669 }
21670 break;
21671 case NM_POOL32F:
579b8ea9 21672 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
21673 break;
21674 case NM_POOL32S:
21675 break;
21676 case NM_P_LUI:
21677 switch (extract32(ctx->opcode, 1, 1)) {
21678 case NM_LUI:
21679 if (rt != 0) {
21680 tcg_gen_movi_tl(cpu_gpr[rt],
21681 sextract32(ctx->opcode, 0, 1) << 31 |
21682 extract32(ctx->opcode, 2, 10) << 21 |
21683 extract32(ctx->opcode, 12, 9) << 12);
21684 }
21685 break;
21686 case NM_ALUIPC:
21687 if (rt != 0) {
21688 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21689 extract32(ctx->opcode, 2, 10) << 21 |
21690 extract32(ctx->opcode, 12, 9) << 12;
21691 target_long addr;
21692 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21693 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21694 }
21695 break;
21696 }
21697 break;
21698 case NM_P_GP_BH:
8f1d9b6d
YK
21699 {
21700 uint32_t u = extract32(ctx->opcode, 0, 18);
21701
21702 switch (extract32(ctx->opcode, 18, 3)) {
21703 case NM_LBGP:
21704 gen_ld(ctx, OPC_LB, rt, 28, u);
21705 break;
21706 case NM_SBGP:
21707 gen_st(ctx, OPC_SB, rt, 28, u);
21708 break;
21709 case NM_LBUGP:
21710 gen_ld(ctx, OPC_LBU, rt, 28, u);
21711 break;
21712 case NM_ADDIUGP_B:
21713 if (rt != 0) {
21714 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21715 }
21716 break;
21717 case NM_P_GP_LH:
21718 u &= ~1;
21719 switch (ctx->opcode & 1) {
21720 case NM_LHGP:
21721 gen_ld(ctx, OPC_LH, rt, 28, u);
21722 break;
21723 case NM_LHUGP:
21724 gen_ld(ctx, OPC_LHU, rt, 28, u);
21725 break;
21726 }
21727 break;
21728 case NM_P_GP_SH:
21729 u &= ~1;
21730 switch (ctx->opcode & 1) {
21731 case NM_SHGP:
21732 gen_st(ctx, OPC_SH, rt, 28, u);
21733 break;
21734 default:
21735 generate_exception_end(ctx, EXCP_RI);
21736 break;
21737 }
21738 break;
21739 case NM_P_GP_CP1:
21740 u &= ~0x3;
21741 switch (ctx->opcode & 0x3) {
21742 case NM_LWC1GP:
21743 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21744 break;
21745 case NM_LDC1GP:
21746 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21747 break;
21748 case NM_SWC1GP:
21749 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21750 break;
21751 case NM_SDC1GP:
21752 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21753 break;
21754 }
21755 break;
21756 default:
21757 generate_exception_end(ctx, EXCP_RI);
21758 break;
21759 }
21760 }
c0280983
YK
21761 break;
21762 case NM_P_LS_U12:
8f1d9b6d
YK
21763 {
21764 uint32_t u = extract32(ctx->opcode, 0, 12);
21765
21766 switch (extract32(ctx->opcode, 12, 4)) {
21767 case NM_P_PREFU12:
21768 if (rt == 31) {
21769 /* SYNCI */
7480515f
AM
21770 /*
21771 * Break the TB to be able to sync copied instructions
21772 * immediately.
21773 */
8f1d9b6d
YK
21774 ctx->base.is_jmp = DISAS_STOP;
21775 } else {
21776 /* PREF */
21777 /* Treat as NOP. */
21778 }
21779 break;
21780 case NM_LB:
21781 gen_ld(ctx, OPC_LB, rt, rs, u);
21782 break;
21783 case NM_LH:
21784 gen_ld(ctx, OPC_LH, rt, rs, u);
21785 break;
21786 case NM_LW:
21787 gen_ld(ctx, OPC_LW, rt, rs, u);
21788 break;
21789 case NM_LBU:
21790 gen_ld(ctx, OPC_LBU, rt, rs, u);
21791 break;
21792 case NM_LHU:
21793 gen_ld(ctx, OPC_LHU, rt, rs, u);
21794 break;
21795 case NM_SB:
21796 gen_st(ctx, OPC_SB, rt, rs, u);
21797 break;
21798 case NM_SH:
21799 gen_st(ctx, OPC_SH, rt, rs, u);
21800 break;
21801 case NM_SW:
21802 gen_st(ctx, OPC_SW, rt, rs, u);
21803 break;
21804 case NM_LWC1:
21805 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21806 break;
21807 case NM_LDC1:
21808 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21809 break;
21810 case NM_SWC1:
21811 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21812 break;
21813 case NM_SDC1:
21814 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21815 break;
21816 default:
21817 generate_exception_end(ctx, EXCP_RI);
21818 break;
21819 }
21820 }
c0280983
YK
21821 break;
21822 case NM_P_LS_S9:
8f1d9b6d
YK
21823 {
21824 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21825 extract32(ctx->opcode, 0, 8);
21826
21827 switch (extract32(ctx->opcode, 8, 3)) {
21828 case NM_P_LS_S0:
21829 switch (extract32(ctx->opcode, 11, 4)) {
21830 case NM_LBS9:
21831 gen_ld(ctx, OPC_LB, rt, rs, s);
21832 break;
21833 case NM_LHS9:
21834 gen_ld(ctx, OPC_LH, rt, rs, s);
21835 break;
21836 case NM_LWS9:
21837 gen_ld(ctx, OPC_LW, rt, rs, s);
21838 break;
21839 case NM_LBUS9:
21840 gen_ld(ctx, OPC_LBU, rt, rs, s);
21841 break;
21842 case NM_LHUS9:
21843 gen_ld(ctx, OPC_LHU, rt, rs, s);
21844 break;
21845 case NM_SBS9:
21846 gen_st(ctx, OPC_SB, rt, rs, s);
21847 break;
21848 case NM_SHS9:
21849 gen_st(ctx, OPC_SH, rt, rs, s);
21850 break;
21851 case NM_SWS9:
21852 gen_st(ctx, OPC_SW, rt, rs, s);
21853 break;
21854 case NM_LWC1S9:
21855 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21856 break;
21857 case NM_LDC1S9:
21858 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21859 break;
21860 case NM_SWC1S9:
21861 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21862 break;
21863 case NM_SDC1S9:
21864 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21865 break;
21866 case NM_P_PREFS9:
21867 if (rt == 31) {
21868 /* SYNCI */
7480515f
AM
21869 /*
21870 * Break the TB to be able to sync copied instructions
21871 * immediately.
21872 */
8f1d9b6d
YK
21873 ctx->base.is_jmp = DISAS_STOP;
21874 } else {
21875 /* PREF */
21876 /* Treat as NOP. */
21877 }
21878 break;
21879 default:
21880 generate_exception_end(ctx, EXCP_RI);
21881 break;
21882 }
21883 break;
21884 case NM_P_LS_S1:
21885 switch (extract32(ctx->opcode, 11, 4)) {
21886 case NM_UALH:
21887 case NM_UASH:
fb32f8c8 21888 check_nms(ctx);
8f1d9b6d
YK
21889 {
21890 TCGv t0 = tcg_temp_new();
21891 TCGv t1 = tcg_temp_new();
21892
21893 gen_base_offset_addr(ctx, t0, rs, s);
21894
21895 switch (extract32(ctx->opcode, 11, 4)) {
21896 case NM_UALH:
21897 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21898 MO_UNALN);
21899 gen_store_gpr(t0, rt);
21900 break;
21901 case NM_UASH:
21902 gen_load_gpr(t1, rt);
21903 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21904 MO_UNALN);
21905 break;
21906 }
21907 tcg_temp_free(t0);
21908 tcg_temp_free(t1);
21909 }
21910 break;
21911 case NM_P_LL:
21912 switch (ctx->opcode & 0x03) {
21913 case NM_LL:
21914 gen_ld(ctx, OPC_LL, rt, rs, s);
21915 break;
21916 case NM_LLWP:
0b16dcd1
AR
21917 check_xnp(ctx);
21918 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21919 break;
21920 }
21921 break;
21922 case NM_P_SC:
21923 switch (ctx->opcode & 0x03) {
21924 case NM_SC:
33a07fa2 21925 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
21926 break;
21927 case NM_SCWP:
0b16dcd1 21928 check_xnp(ctx);
8d5388c1
AM
21929 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21930 false);
8f1d9b6d
YK
21931 break;
21932 }
21933 break;
21934 case NM_CACHE:
21935 check_cp0_enabled(ctx);
21936 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21937 gen_cache_operation(ctx, rt, rs, s);
21938 }
21939 break;
21940 }
21941 break;
d046a9ea
DN
21942 case NM_P_LS_E0:
21943 switch (extract32(ctx->opcode, 11, 4)) {
21944 case NM_LBE:
21945 check_eva(ctx);
21946 check_cp0_enabled(ctx);
21947 gen_ld(ctx, OPC_LBE, rt, rs, s);
21948 break;
21949 case NM_SBE:
21950 check_eva(ctx);
21951 check_cp0_enabled(ctx);
21952 gen_st(ctx, OPC_SBE, rt, rs, s);
21953 break;
21954 case NM_LBUE:
21955 check_eva(ctx);
21956 check_cp0_enabled(ctx);
21957 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21958 break;
21959 case NM_P_PREFE:
21960 if (rt == 31) {
21961 /* case NM_SYNCIE */
21962 check_eva(ctx);
21963 check_cp0_enabled(ctx);
7480515f
AM
21964 /*
21965 * Break the TB to be able to sync copied instructions
21966 * immediately.
21967 */
d046a9ea
DN
21968 ctx->base.is_jmp = DISAS_STOP;
21969 } else {
21970 /* case NM_PREFE */
21971 check_eva(ctx);
21972 check_cp0_enabled(ctx);
21973 /* Treat as NOP. */
21974 }
21975 break;
21976 case NM_LHE:
21977 check_eva(ctx);
21978 check_cp0_enabled(ctx);
21979 gen_ld(ctx, OPC_LHE, rt, rs, s);
21980 break;
21981 case NM_SHE:
21982 check_eva(ctx);
21983 check_cp0_enabled(ctx);
21984 gen_st(ctx, OPC_SHE, rt, rs, s);
21985 break;
21986 case NM_LHUE:
21987 check_eva(ctx);
21988 check_cp0_enabled(ctx);
21989 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21990 break;
21991 case NM_CACHEE:
21992 check_nms_dl_il_sl_tl_l2c(ctx);
21993 gen_cache_operation(ctx, rt, rs, s);
21994 break;
21995 case NM_LWE:
21996 check_eva(ctx);
21997 check_cp0_enabled(ctx);
21998 gen_ld(ctx, OPC_LWE, rt, rs, s);
21999 break;
22000 case NM_SWE:
22001 check_eva(ctx);
22002 check_cp0_enabled(ctx);
22003 gen_st(ctx, OPC_SWE, rt, rs, s);
22004 break;
22005 case NM_P_LLE:
22006 switch (extract32(ctx->opcode, 2, 2)) {
22007 case NM_LLE:
22008 check_xnp(ctx);
22009 check_eva(ctx);
22010 check_cp0_enabled(ctx);
22011 gen_ld(ctx, OPC_LLE, rt, rs, s);
22012 break;
22013 case NM_LLWPE:
22014 check_xnp(ctx);
22015 check_eva(ctx);
22016 check_cp0_enabled(ctx);
22017 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 22018 break;
d046a9ea
DN
22019 default:
22020 generate_exception_end(ctx, EXCP_RI);
22021 break;
22022 }
22023 break;
22024 case NM_P_SCE:
22025 switch (extract32(ctx->opcode, 2, 2)) {
22026 case NM_SCE:
22027 check_xnp(ctx);
22028 check_eva(ctx);
22029 check_cp0_enabled(ctx);
33a07fa2 22030 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
22031 break;
22032 case NM_SCWPE:
22033 check_xnp(ctx);
22034 check_eva(ctx);
22035 check_cp0_enabled(ctx);
8d5388c1
AM
22036 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22037 true);
2431a422 22038 break;
d046a9ea
DN
22039 default:
22040 generate_exception_end(ctx, EXCP_RI);
22041 break;
22042 }
22043 break;
22044 }
22045 break;
8f1d9b6d
YK
22046 case NM_P_LS_WM:
22047 case NM_P_LS_UAWM:
fb32f8c8 22048 check_nms(ctx);
8f1d9b6d
YK
22049 {
22050 int count = extract32(ctx->opcode, 12, 3);
22051 int counter = 0;
22052
22053 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22054 extract32(ctx->opcode, 0, 8);
22055 TCGv va = tcg_temp_new();
22056 TCGv t1 = tcg_temp_new();
14776ab5 22057 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
22058 NM_P_LS_UAWM ? MO_UNALN : 0;
22059
22060 count = (count == 0) ? 8 : count;
22061 while (counter != count) {
22062 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22063 int this_offset = offset + (counter << 2);
22064
22065 gen_base_offset_addr(ctx, va, rs, this_offset);
22066
22067 switch (extract32(ctx->opcode, 11, 1)) {
22068 case NM_LWM:
22069 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22070 memop | MO_TESL);
22071 gen_store_gpr(t1, this_rt);
22072 if ((this_rt == rs) &&
22073 (counter != (count - 1))) {
22074 /* UNPREDICTABLE */
22075 }
22076 break;
22077 case NM_SWM:
22078 this_rt = (rt == 0) ? 0 : this_rt;
22079 gen_load_gpr(t1, this_rt);
22080 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22081 memop | MO_TEUL);
22082 break;
22083 }
22084 counter++;
22085 }
22086 tcg_temp_free(va);
22087 tcg_temp_free(t1);
22088 }
22089 break;
22090 default:
22091 generate_exception_end(ctx, EXCP_RI);
22092 break;
22093 }
22094 }
c0280983
YK
22095 break;
22096 case NM_MOVE_BALC:
fb32f8c8 22097 check_nms(ctx);
11d0fc10
SM
22098 {
22099 TCGv t0 = tcg_temp_new();
22100 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22101 extract32(ctx->opcode, 1, 20) << 1;
22102 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22103 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22104 extract32(ctx->opcode, 21, 3));
22105 gen_load_gpr(t0, rt);
22106 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22107 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22108 tcg_temp_free(t0);
22109 }
c0280983
YK
22110 break;
22111 case NM_P_BAL:
11d0fc10
SM
22112 {
22113 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22114 extract32(ctx->opcode, 1, 24) << 1;
22115
22116 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22117 /* BC */
22118 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22119 } else {
22120 /* BALC */
22121 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22122 }
22123 }
c0280983
YK
22124 break;
22125 case NM_P_J:
11d0fc10
SM
22126 switch (extract32(ctx->opcode, 12, 4)) {
22127 case NM_JALRC:
22128 case NM_JALRC_HB:
22129 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22130 break;
22131 case NM_P_BALRSC:
22132 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22133 break;
22134 default:
22135 generate_exception_end(ctx, EXCP_RI);
22136 break;
22137 }
c0280983
YK
22138 break;
22139 case NM_P_BR1:
11d0fc10
SM
22140 {
22141 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22142 extract32(ctx->opcode, 1, 13) << 1;
22143 switch (extract32(ctx->opcode, 14, 2)) {
22144 case NM_BEQC:
fb32f8c8 22145 check_nms(ctx);
11d0fc10
SM
22146 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22147 break;
22148 case NM_P_BR3A:
22149 s = sextract32(ctx->opcode, 0, 1) << 14 |
22150 extract32(ctx->opcode, 1, 13) << 1;
22151 check_cp1_enabled(ctx);
22152 switch (extract32(ctx->opcode, 16, 5)) {
22153 case NM_BC1EQZC:
22154 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22155 break;
22156 case NM_BC1NEZC:
22157 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22158 break;
6d033ca7 22159 case NM_BPOSGE32C:
908f6be1 22160 check_dsp_r3(ctx);
6d033ca7
SM
22161 {
22162 int32_t imm = extract32(ctx->opcode, 1, 13) |
22163 extract32(ctx->opcode, 0, 1) << 13;
22164
22165 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22166 imm);
22167 }
22168 break;
11d0fc10
SM
22169 default:
22170 generate_exception_end(ctx, EXCP_RI);
22171 break;
22172 }
22173 break;
22174 case NM_BGEC:
22175 if (rs == rt) {
22176 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22177 } else {
22178 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22179 }
22180 break;
22181 case NM_BGEUC:
22182 if (rs == rt || rt == 0) {
22183 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22184 } else if (rs == 0) {
22185 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22186 } else {
22187 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22188 }
22189 break;
22190 }
22191 }
c0280983
YK
22192 break;
22193 case NM_P_BR2:
11d0fc10
SM
22194 {
22195 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22196 extract32(ctx->opcode, 1, 13) << 1;
22197 switch (extract32(ctx->opcode, 14, 2)) {
22198 case NM_BNEC:
fb32f8c8 22199 check_nms(ctx);
11d0fc10
SM
22200 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22201 break;
22202 case NM_BLTC:
22203 if (rs != 0 && rt != 0 && rs == rt) {
22204 /* NOP */
22205 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22206 } else {
22207 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22208 }
22209 break;
22210 case NM_BLTUC:
22211 if (rs == 0 || rs == rt) {
22212 /* NOP */
22213 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22214 } else {
22215 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22216 }
22217 break;
22218 default:
22219 generate_exception_end(ctx, EXCP_RI);
22220 break;
22221 }
22222 }
c0280983
YK
22223 break;
22224 case NM_P_BRI:
11d0fc10
SM
22225 {
22226 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22227 extract32(ctx->opcode, 1, 10) << 1;
22228 uint32_t u = extract32(ctx->opcode, 11, 7);
22229
22230 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22231 rt, u, s);
22232 }
c0280983
YK
22233 break;
22234 default:
22235 generate_exception_end(ctx, EXCP_RI);
22236 break;
22237 }
22238 return 4;
22239}
22240
c533c0f4
AM
22241static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22242{
ea4ca3c2 22243 uint32_t op;
99e49abf
AM
22244 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22245 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22246 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 22247 int offset;
ea4ca3c2
YK
22248 int imm;
22249
22250 /* make sure instructions are on a halfword boundary */
22251 if (ctx->base.pc_next & 0x1) {
22252 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22253 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22254 tcg_temp_free(tmp);
22255 generate_exception_end(ctx, EXCP_AdEL);
22256 return 2;
22257 }
22258
22259 op = extract32(ctx->opcode, 10, 6);
22260 switch (op) {
22261 case NM_P16_MV:
8869ad02
YK
22262 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22263 if (rt != 0) {
22264 /* MOVE */
22265 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22266 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22267 } else {
22268 /* P16.RI */
22269 switch (extract32(ctx->opcode, 3, 2)) {
22270 case NM_P16_SYSCALL:
22271 if (extract32(ctx->opcode, 2, 1) == 0) {
22272 generate_exception_end(ctx, EXCP_SYSCALL);
22273 } else {
22274 generate_exception_end(ctx, EXCP_RI);
22275 }
22276 break;
22277 case NM_BREAK16:
22278 generate_exception_end(ctx, EXCP_BREAK);
22279 break;
22280 case NM_SDBBP16:
22281 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22282 gen_helper_do_semihosting(cpu_env);
22283 } else {
22284 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22285 generate_exception_end(ctx, EXCP_RI);
22286 } else {
22287 generate_exception_end(ctx, EXCP_DBp);
22288 }
22289 }
22290 break;
22291 default:
22292 generate_exception_end(ctx, EXCP_RI);
22293 break;
22294 }
22295 }
ea4ca3c2
YK
22296 break;
22297 case NM_P16_SHIFT:
c46562fb
YK
22298 {
22299 int shift = extract32(ctx->opcode, 0, 3);
22300 uint32_t opc = 0;
22301 shift = (shift == 0) ? 8 : shift;
22302
22303 switch (extract32(ctx->opcode, 3, 1)) {
22304 case NM_SLL16:
22305 opc = OPC_SLL;
22306 break;
22307 case NM_SRL16:
22308 opc = OPC_SRL;
22309 break;
22310 }
22311 gen_shift_imm(ctx, opc, rt, rs, shift);
22312 }
ea4ca3c2
YK
22313 break;
22314 case NM_P16C:
8bdb7029
YK
22315 switch (ctx->opcode & 1) {
22316 case NM_POOL16C_0:
80845edf 22317 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
22318 break;
22319 case NM_LWXS16:
22320 gen_ldxs(ctx, rt, rs, rd);
22321 break;
22322 }
ea4ca3c2
YK
22323 break;
22324 case NM_P16_A1:
22325 switch (extract32(ctx->opcode, 6, 1)) {
22326 case NM_ADDIUR1SP:
22327 imm = extract32(ctx->opcode, 0, 6) << 2;
22328 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22329 break;
22330 default:
22331 generate_exception_end(ctx, EXCP_RI);
22332 break;
22333 }
22334 break;
22335 case NM_P16_A2:
22336 switch (extract32(ctx->opcode, 3, 1)) {
22337 case NM_ADDIUR2:
22338 imm = extract32(ctx->opcode, 0, 3) << 2;
22339 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22340 break;
22341 case NM_P_ADDIURS5:
22342 rt = extract32(ctx->opcode, 5, 5);
22343 if (rt != 0) {
22344 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22345 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22346 (extract32(ctx->opcode, 0, 3));
22347 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22348 }
22349 break;
22350 }
22351 break;
22352 case NM_P16_ADDU:
22353 switch (ctx->opcode & 0x1) {
22354 case NM_ADDU16:
22355 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22356 break;
22357 case NM_SUBU16:
22358 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22359 break;
22360 }
22361 break;
22362 case NM_P16_4X4:
22363 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22364 extract32(ctx->opcode, 5, 3);
22365 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22366 extract32(ctx->opcode, 0, 3);
22367 rt = decode_gpr_gpr4(rt);
22368 rs = decode_gpr_gpr4(rs);
22369 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22370 (extract32(ctx->opcode, 3, 1))) {
22371 case NM_ADDU4X4:
fb32f8c8 22372 check_nms(ctx);
ea4ca3c2
YK
22373 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22374 break;
22375 case NM_MUL4X4:
fb32f8c8 22376 check_nms(ctx);
ea4ca3c2
YK
22377 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22378 break;
22379 default:
22380 generate_exception_end(ctx, EXCP_RI);
22381 break;
22382 }
22383 break;
22384 case NM_LI16:
8869ad02
YK
22385 {
22386 int imm = extract32(ctx->opcode, 0, 7);
22387 imm = (imm == 0x7f ? -1 : imm);
22388 if (rt != 0) {
22389 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22390 }
22391 }
ea4ca3c2
YK
22392 break;
22393 case NM_ANDI16:
80845edf
YK
22394 {
22395 uint32_t u = extract32(ctx->opcode, 0, 4);
22396 u = (u == 12) ? 0xff :
22397 (u == 13) ? 0xffff : u;
22398 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22399 }
ea4ca3c2
YK
22400 break;
22401 case NM_P16_LB:
8bdb7029
YK
22402 offset = extract32(ctx->opcode, 0, 2);
22403 switch (extract32(ctx->opcode, 2, 2)) {
22404 case NM_LB16:
22405 gen_ld(ctx, OPC_LB, rt, rs, offset);
22406 break;
22407 case NM_SB16:
22408 rt = decode_gpr_gpr3_src_store(
99e49abf 22409 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22410 gen_st(ctx, OPC_SB, rt, rs, offset);
22411 break;
22412 case NM_LBU16:
22413 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22414 break;
22415 default:
22416 generate_exception_end(ctx, EXCP_RI);
22417 break;
22418 }
ea4ca3c2
YK
22419 break;
22420 case NM_P16_LH:
8bdb7029
YK
22421 offset = extract32(ctx->opcode, 1, 2) << 1;
22422 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22423 case NM_LH16:
22424 gen_ld(ctx, OPC_LH, rt, rs, offset);
22425 break;
22426 case NM_SH16:
22427 rt = decode_gpr_gpr3_src_store(
99e49abf 22428 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22429 gen_st(ctx, OPC_SH, rt, rs, offset);
22430 break;
22431 case NM_LHU16:
22432 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22433 break;
22434 default:
22435 generate_exception_end(ctx, EXCP_RI);
22436 break;
22437 }
ea4ca3c2
YK
22438 break;
22439 case NM_LW16:
8bdb7029
YK
22440 offset = extract32(ctx->opcode, 0, 4) << 2;
22441 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22442 break;
22443 case NM_LWSP16:
8bdb7029
YK
22444 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22445 offset = extract32(ctx->opcode, 0, 5) << 2;
22446 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22447 break;
22448 case NM_LW4X4:
fb32f8c8 22449 check_nms(ctx);
8bdb7029
YK
22450 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22451 extract32(ctx->opcode, 5, 3);
22452 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22453 extract32(ctx->opcode, 0, 3);
22454 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22455 (extract32(ctx->opcode, 8, 1) << 2);
22456 rt = decode_gpr_gpr4(rt);
22457 rs = decode_gpr_gpr4(rs);
22458 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22459 break;
22460 case NM_SW4X4:
fb32f8c8 22461 check_nms(ctx);
8bdb7029
YK
22462 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22463 extract32(ctx->opcode, 5, 3);
22464 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22465 extract32(ctx->opcode, 0, 3);
22466 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22467 (extract32(ctx->opcode, 8, 1) << 2);
22468 rt = decode_gpr_gpr4_zero(rt);
22469 rs = decode_gpr_gpr4(rs);
22470 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22471 break;
22472 case NM_LWGP16:
8bdb7029
YK
22473 offset = extract32(ctx->opcode, 0, 7) << 2;
22474 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22475 break;
22476 case NM_SWSP16:
8bdb7029
YK
22477 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22478 offset = extract32(ctx->opcode, 0, 5) << 2;
22479 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22480 break;
22481 case NM_SW16:
8bdb7029 22482 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
22483 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22484 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
22485 offset = extract32(ctx->opcode, 0, 4) << 2;
22486 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22487 break;
22488 case NM_SWGP16:
8bdb7029 22489 rt = decode_gpr_gpr3_src_store(
99e49abf 22490 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22491 offset = extract32(ctx->opcode, 0, 7) << 2;
22492 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22493 break;
22494 case NM_BC16:
764371d2
SM
22495 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22496 (sextract32(ctx->opcode, 0, 1) << 10) |
22497 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22498 break;
22499 case NM_BALC16:
764371d2
SM
22500 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22501 (sextract32(ctx->opcode, 0, 1) << 10) |
22502 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22503 break;
22504 case NM_BEQZC16:
764371d2
SM
22505 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22506 (sextract32(ctx->opcode, 0, 1) << 7) |
22507 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22508 break;
22509 case NM_BNEZC16:
764371d2
SM
22510 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22511 (sextract32(ctx->opcode, 0, 1) << 7) |
22512 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22513 break;
22514 case NM_P16_BR:
764371d2
SM
22515 switch (ctx->opcode & 0xf) {
22516 case 0:
22517 /* P16.JRC */
22518 switch (extract32(ctx->opcode, 4, 1)) {
22519 case NM_JRC:
22520 gen_compute_branch_nm(ctx, OPC_JR, 2,
22521 extract32(ctx->opcode, 5, 5), 0, 0);
22522 break;
22523 case NM_JALRC16:
22524 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22525 extract32(ctx->opcode, 5, 5), 31, 0);
22526 break;
22527 }
22528 break;
22529 default:
22530 {
22531 /* P16.BRI */
22532 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22533 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22534 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22535 extract32(ctx->opcode, 0, 4) << 1);
22536 }
22537 break;
22538 }
ea4ca3c2
YK
22539 break;
22540 case NM_P16_SR:
bf0718c5
SM
22541 {
22542 int count = extract32(ctx->opcode, 0, 4);
22543 int u = extract32(ctx->opcode, 4, 4) << 4;
22544
22545 rt = 30 + extract32(ctx->opcode, 9, 1);
22546 switch (extract32(ctx->opcode, 8, 1)) {
22547 case NM_SAVE16:
22548 gen_save(ctx, rt, count, 0, u);
22549 break;
22550 case NM_RESTORE_JRC16:
22551 gen_restore(ctx, rt, count, 0, u);
22552 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22553 break;
22554 }
22555 }
ea4ca3c2
YK
22556 break;
22557 case NM_MOVEP:
ea4ca3c2 22558 case NM_MOVEPREV:
fb32f8c8 22559 check_nms(ctx);
4d18232c
YK
22560 {
22561 static const int gpr2reg1[] = {4, 5, 6, 7};
22562 static const int gpr2reg2[] = {5, 6, 7, 8};
22563 int re;
22564 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22565 extract32(ctx->opcode, 8, 1);
22566 int r1 = gpr2reg1[rd2];
22567 int r2 = gpr2reg2[rd2];
22568 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22569 extract32(ctx->opcode, 0, 3);
22570 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22571 extract32(ctx->opcode, 5, 3);
22572 TCGv t0 = tcg_temp_new();
22573 TCGv t1 = tcg_temp_new();
22574 if (op == NM_MOVEP) {
22575 rd = r1;
22576 re = r2;
22577 rs = decode_gpr_gpr4_zero(r3);
22578 rt = decode_gpr_gpr4_zero(r4);
22579 } else {
22580 rd = decode_gpr_gpr4(r3);
22581 re = decode_gpr_gpr4(r4);
22582 rs = r1;
22583 rt = r2;
22584 }
22585 gen_load_gpr(t0, rs);
22586 gen_load_gpr(t1, rt);
22587 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22588 tcg_gen_mov_tl(cpu_gpr[re], t1);
22589 tcg_temp_free(t0);
22590 tcg_temp_free(t1);
22591 }
ea4ca3c2
YK
22592 break;
22593 default:
c0280983 22594 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
22595 }
22596
c533c0f4
AM
22597 return 2;
22598}
22599
22600
3c824109
NF
22601/* SmartMIPS extension to MIPS32 */
22602
22603#if defined(TARGET_MIPS64)
22604
22605/* MDMX extension to MIPS64 */
22606
22607#endif
22608
9b1a1d68 22609/* MIPSDSP functions. */
d75c135e 22610static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
22611 int rd, int base, int offset)
22612{
9b1a1d68
JL
22613 TCGv t0;
22614
9b1a1d68
JL
22615 check_dsp(ctx);
22616 t0 = tcg_temp_new();
22617
22618 if (base == 0) {
22619 gen_load_gpr(t0, offset);
22620 } else if (offset == 0) {
22621 gen_load_gpr(t0, base);
22622 } else {
22623 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22624 }
22625
9b1a1d68
JL
22626 switch (opc) {
22627 case OPC_LBUX:
5f68f5ae 22628 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 22629 gen_store_gpr(t0, rd);
9b1a1d68
JL
22630 break;
22631 case OPC_LHX:
5f68f5ae 22632 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 22633 gen_store_gpr(t0, rd);
9b1a1d68
JL
22634 break;
22635 case OPC_LWX:
5f68f5ae 22636 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 22637 gen_store_gpr(t0, rd);
9b1a1d68
JL
22638 break;
22639#if defined(TARGET_MIPS64)
22640 case OPC_LDX:
5f68f5ae 22641 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 22642 gen_store_gpr(t0, rd);
9b1a1d68
JL
22643 break;
22644#endif
22645 }
9b1a1d68
JL
22646 tcg_temp_free(t0);
22647}
22648
461c08df
JL
22649static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22650 int ret, int v1, int v2)
22651{
461c08df
JL
22652 TCGv v1_t;
22653 TCGv v2_t;
22654
22655 if (ret == 0) {
22656 /* Treat as NOP. */
461c08df
JL
22657 return;
22658 }
22659
22660 v1_t = tcg_temp_new();
22661 v2_t = tcg_temp_new();
22662
22663 gen_load_gpr(v1_t, v1);
22664 gen_load_gpr(v2_t, v2);
22665
22666 switch (op1) {
22667 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22668 case OPC_MULT_G_2E:
908f6be1 22669 check_dsp_r2(ctx);
461c08df
JL
22670 switch (op2) {
22671 case OPC_ADDUH_QB:
22672 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22673 break;
22674 case OPC_ADDUH_R_QB:
22675 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22676 break;
22677 case OPC_ADDQH_PH:
22678 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22679 break;
22680 case OPC_ADDQH_R_PH:
22681 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22682 break;
22683 case OPC_ADDQH_W:
22684 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22685 break;
22686 case OPC_ADDQH_R_W:
22687 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22688 break;
22689 case OPC_SUBUH_QB:
22690 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22691 break;
22692 case OPC_SUBUH_R_QB:
22693 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22694 break;
22695 case OPC_SUBQH_PH:
22696 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22697 break;
22698 case OPC_SUBQH_R_PH:
22699 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22700 break;
22701 case OPC_SUBQH_W:
22702 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22703 break;
22704 case OPC_SUBQH_R_W:
22705 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22706 break;
22707 }
22708 break;
22709 case OPC_ABSQ_S_PH_DSP:
22710 switch (op2) {
22711 case OPC_ABSQ_S_QB:
908f6be1 22712 check_dsp_r2(ctx);
461c08df
JL
22713 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22714 break;
22715 case OPC_ABSQ_S_PH:
22716 check_dsp(ctx);
22717 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22718 break;
22719 case OPC_ABSQ_S_W:
22720 check_dsp(ctx);
22721 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22722 break;
22723 case OPC_PRECEQ_W_PHL:
22724 check_dsp(ctx);
22725 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22726 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22727 break;
22728 case OPC_PRECEQ_W_PHR:
22729 check_dsp(ctx);
22730 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22731 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22732 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22733 break;
22734 case OPC_PRECEQU_PH_QBL:
22735 check_dsp(ctx);
22736 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22737 break;
22738 case OPC_PRECEQU_PH_QBR:
22739 check_dsp(ctx);
22740 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22741 break;
22742 case OPC_PRECEQU_PH_QBLA:
22743 check_dsp(ctx);
22744 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22745 break;
22746 case OPC_PRECEQU_PH_QBRA:
22747 check_dsp(ctx);
22748 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22749 break;
22750 case OPC_PRECEU_PH_QBL:
22751 check_dsp(ctx);
22752 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22753 break;
22754 case OPC_PRECEU_PH_QBR:
22755 check_dsp(ctx);
22756 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22757 break;
22758 case OPC_PRECEU_PH_QBLA:
22759 check_dsp(ctx);
22760 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22761 break;
22762 case OPC_PRECEU_PH_QBRA:
22763 check_dsp(ctx);
22764 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22765 break;
22766 }
22767 break;
22768 case OPC_ADDU_QB_DSP:
22769 switch (op2) {
22770 case OPC_ADDQ_PH:
22771 check_dsp(ctx);
22772 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_ADDQ_S_PH:
22775 check_dsp(ctx);
22776 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_ADDQ_S_W:
22779 check_dsp(ctx);
22780 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_ADDU_QB:
22783 check_dsp(ctx);
22784 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_ADDU_S_QB:
22787 check_dsp(ctx);
22788 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_ADDU_PH:
908f6be1 22791 check_dsp_r2(ctx);
461c08df
JL
22792 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_ADDU_S_PH:
908f6be1 22795 check_dsp_r2(ctx);
461c08df
JL
22796 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_SUBQ_PH:
22799 check_dsp(ctx);
22800 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_SUBQ_S_PH:
22803 check_dsp(ctx);
22804 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_SUBQ_S_W:
22807 check_dsp(ctx);
22808 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_SUBU_QB:
22811 check_dsp(ctx);
22812 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_SUBU_S_QB:
22815 check_dsp(ctx);
22816 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22817 break;
22818 case OPC_SUBU_PH:
908f6be1 22819 check_dsp_r2(ctx);
461c08df
JL
22820 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22821 break;
22822 case OPC_SUBU_S_PH:
908f6be1 22823 check_dsp_r2(ctx);
461c08df
JL
22824 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22825 break;
22826 case OPC_ADDSC:
22827 check_dsp(ctx);
22828 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22829 break;
22830 case OPC_ADDWC:
22831 check_dsp(ctx);
22832 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22833 break;
22834 case OPC_MODSUB:
22835 check_dsp(ctx);
22836 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22837 break;
22838 case OPC_RADDU_W_QB:
22839 check_dsp(ctx);
22840 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22841 break;
22842 }
22843 break;
22844 case OPC_CMPU_EQ_QB_DSP:
22845 switch (op2) {
22846 case OPC_PRECR_QB_PH:
908f6be1 22847 check_dsp_r2(ctx);
461c08df
JL
22848 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22849 break;
22850 case OPC_PRECRQ_QB_PH:
22851 check_dsp(ctx);
22852 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22853 break;
22854 case OPC_PRECR_SRA_PH_W:
908f6be1 22855 check_dsp_r2(ctx);
461c08df
JL
22856 {
22857 TCGv_i32 sa_t = tcg_const_i32(v2);
22858 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22859 cpu_gpr[ret]);
22860 tcg_temp_free_i32(sa_t);
22861 break;
22862 }
22863 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22864 check_dsp_r2(ctx);
461c08df
JL
22865 {
22866 TCGv_i32 sa_t = tcg_const_i32(v2);
22867 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22868 cpu_gpr[ret]);
22869 tcg_temp_free_i32(sa_t);
22870 break;
22871 }
22872 case OPC_PRECRQ_PH_W:
22873 check_dsp(ctx);
22874 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22875 break;
22876 case OPC_PRECRQ_RS_PH_W:
22877 check_dsp(ctx);
22878 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22879 break;
22880 case OPC_PRECRQU_S_QB_PH:
22881 check_dsp(ctx);
22882 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22883 break;
22884 }
22885 break;
22886#ifdef TARGET_MIPS64
22887 case OPC_ABSQ_S_QH_DSP:
22888 switch (op2) {
22889 case OPC_PRECEQ_L_PWL:
22890 check_dsp(ctx);
22891 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22892 break;
22893 case OPC_PRECEQ_L_PWR:
22894 check_dsp(ctx);
22895 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22896 break;
22897 case OPC_PRECEQ_PW_QHL:
22898 check_dsp(ctx);
22899 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22900 break;
22901 case OPC_PRECEQ_PW_QHR:
22902 check_dsp(ctx);
22903 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22904 break;
22905 case OPC_PRECEQ_PW_QHLA:
22906 check_dsp(ctx);
22907 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22908 break;
22909 case OPC_PRECEQ_PW_QHRA:
22910 check_dsp(ctx);
22911 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22912 break;
22913 case OPC_PRECEQU_QH_OBL:
22914 check_dsp(ctx);
22915 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22916 break;
22917 case OPC_PRECEQU_QH_OBR:
22918 check_dsp(ctx);
22919 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22920 break;
22921 case OPC_PRECEQU_QH_OBLA:
22922 check_dsp(ctx);
22923 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22924 break;
22925 case OPC_PRECEQU_QH_OBRA:
22926 check_dsp(ctx);
22927 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22928 break;
22929 case OPC_PRECEU_QH_OBL:
22930 check_dsp(ctx);
22931 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22932 break;
22933 case OPC_PRECEU_QH_OBR:
22934 check_dsp(ctx);
22935 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22936 break;
22937 case OPC_PRECEU_QH_OBLA:
22938 check_dsp(ctx);
22939 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22940 break;
22941 case OPC_PRECEU_QH_OBRA:
22942 check_dsp(ctx);
22943 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22944 break;
22945 case OPC_ABSQ_S_OB:
908f6be1 22946 check_dsp_r2(ctx);
461c08df
JL
22947 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22948 break;
22949 case OPC_ABSQ_S_PW:
22950 check_dsp(ctx);
22951 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22952 break;
22953 case OPC_ABSQ_S_QH:
22954 check_dsp(ctx);
22955 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22956 break;
22957 }
22958 break;
22959 case OPC_ADDU_OB_DSP:
22960 switch (op2) {
22961 case OPC_RADDU_L_OB:
22962 check_dsp(ctx);
22963 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22964 break;
22965 case OPC_SUBQ_PW:
22966 check_dsp(ctx);
22967 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22968 break;
22969 case OPC_SUBQ_S_PW:
22970 check_dsp(ctx);
22971 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22972 break;
22973 case OPC_SUBQ_QH:
22974 check_dsp(ctx);
22975 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22976 break;
22977 case OPC_SUBQ_S_QH:
22978 check_dsp(ctx);
22979 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22980 break;
22981 case OPC_SUBU_OB:
22982 check_dsp(ctx);
22983 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22984 break;
22985 case OPC_SUBU_S_OB:
22986 check_dsp(ctx);
22987 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22988 break;
22989 case OPC_SUBU_QH:
908f6be1 22990 check_dsp_r2(ctx);
461c08df
JL
22991 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22992 break;
22993 case OPC_SUBU_S_QH:
908f6be1 22994 check_dsp_r2(ctx);
461c08df
JL
22995 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22996 break;
22997 case OPC_SUBUH_OB:
908f6be1 22998 check_dsp_r2(ctx);
461c08df
JL
22999 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23000 break;
23001 case OPC_SUBUH_R_OB:
908f6be1 23002 check_dsp_r2(ctx);
461c08df
JL
23003 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23004 break;
23005 case OPC_ADDQ_PW:
23006 check_dsp(ctx);
23007 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23008 break;
23009 case OPC_ADDQ_S_PW:
23010 check_dsp(ctx);
23011 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23012 break;
23013 case OPC_ADDQ_QH:
23014 check_dsp(ctx);
23015 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23016 break;
23017 case OPC_ADDQ_S_QH:
23018 check_dsp(ctx);
23019 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23020 break;
23021 case OPC_ADDU_OB:
23022 check_dsp(ctx);
23023 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23024 break;
23025 case OPC_ADDU_S_OB:
23026 check_dsp(ctx);
23027 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23028 break;
23029 case OPC_ADDU_QH:
908f6be1 23030 check_dsp_r2(ctx);
461c08df
JL
23031 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23032 break;
23033 case OPC_ADDU_S_QH:
908f6be1 23034 check_dsp_r2(ctx);
461c08df
JL
23035 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_ADDUH_OB:
908f6be1 23038 check_dsp_r2(ctx);
461c08df
JL
23039 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23040 break;
23041 case OPC_ADDUH_R_OB:
908f6be1 23042 check_dsp_r2(ctx);
461c08df
JL
23043 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23044 break;
23045 }
23046 break;
23047 case OPC_CMPU_EQ_OB_DSP:
23048 switch (op2) {
23049 case OPC_PRECR_OB_QH:
908f6be1 23050 check_dsp_r2(ctx);
461c08df
JL
23051 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23052 break;
23053 case OPC_PRECR_SRA_QH_PW:
908f6be1 23054 check_dsp_r2(ctx);
461c08df
JL
23055 {
23056 TCGv_i32 ret_t = tcg_const_i32(ret);
23057 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23058 tcg_temp_free_i32(ret_t);
23059 break;
23060 }
23061 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 23062 check_dsp_r2(ctx);
461c08df
JL
23063 {
23064 TCGv_i32 sa_v = tcg_const_i32(ret);
23065 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23066 tcg_temp_free_i32(sa_v);
23067 break;
23068 }
23069 case OPC_PRECRQ_OB_QH:
23070 check_dsp(ctx);
23071 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23072 break;
23073 case OPC_PRECRQ_PW_L:
23074 check_dsp(ctx);
23075 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23076 break;
23077 case OPC_PRECRQ_QH_PW:
23078 check_dsp(ctx);
23079 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23080 break;
23081 case OPC_PRECRQ_RS_QH_PW:
23082 check_dsp(ctx);
23083 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23084 break;
23085 case OPC_PRECRQU_S_OB_QH:
23086 check_dsp(ctx);
23087 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23088 break;
23089 }
23090 break;
23091#endif
23092 }
23093
23094 tcg_temp_free(v1_t);
23095 tcg_temp_free(v2_t);
461c08df 23096}
9b1a1d68 23097
77c5fa8b
JL
23098static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23099 int ret, int v1, int v2)
23100{
23101 uint32_t op2;
77c5fa8b
JL
23102 TCGv t0;
23103 TCGv v1_t;
23104 TCGv v2_t;
23105
23106 if (ret == 0) {
23107 /* Treat as NOP. */
77c5fa8b
JL
23108 return;
23109 }
23110
23111 t0 = tcg_temp_new();
23112 v1_t = tcg_temp_new();
23113 v2_t = tcg_temp_new();
23114
23115 tcg_gen_movi_tl(t0, v1);
23116 gen_load_gpr(v1_t, v1);
23117 gen_load_gpr(v2_t, v2);
23118
23119 switch (opc) {
23120 case OPC_SHLL_QB_DSP:
23121 {
23122 op2 = MASK_SHLL_QB(ctx->opcode);
23123 switch (op2) {
23124 case OPC_SHLL_QB:
23125 check_dsp(ctx);
23126 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23127 break;
23128 case OPC_SHLLV_QB:
23129 check_dsp(ctx);
23130 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23131 break;
23132 case OPC_SHLL_PH:
23133 check_dsp(ctx);
23134 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23135 break;
23136 case OPC_SHLLV_PH:
23137 check_dsp(ctx);
23138 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23139 break;
23140 case OPC_SHLL_S_PH:
23141 check_dsp(ctx);
23142 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23143 break;
23144 case OPC_SHLLV_S_PH:
23145 check_dsp(ctx);
23146 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23147 break;
23148 case OPC_SHLL_S_W:
23149 check_dsp(ctx);
23150 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23151 break;
23152 case OPC_SHLLV_S_W:
23153 check_dsp(ctx);
23154 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23155 break;
23156 case OPC_SHRL_QB:
23157 check_dsp(ctx);
23158 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23159 break;
23160 case OPC_SHRLV_QB:
23161 check_dsp(ctx);
23162 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23163 break;
23164 case OPC_SHRL_PH:
908f6be1 23165 check_dsp_r2(ctx);
77c5fa8b
JL
23166 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23167 break;
23168 case OPC_SHRLV_PH:
908f6be1 23169 check_dsp_r2(ctx);
77c5fa8b
JL
23170 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23171 break;
23172 case OPC_SHRA_QB:
908f6be1 23173 check_dsp_r2(ctx);
77c5fa8b
JL
23174 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23175 break;
23176 case OPC_SHRA_R_QB:
908f6be1 23177 check_dsp_r2(ctx);
77c5fa8b
JL
23178 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23179 break;
23180 case OPC_SHRAV_QB:
908f6be1 23181 check_dsp_r2(ctx);
77c5fa8b
JL
23182 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23183 break;
23184 case OPC_SHRAV_R_QB:
908f6be1 23185 check_dsp_r2(ctx);
77c5fa8b
JL
23186 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23187 break;
23188 case OPC_SHRA_PH:
23189 check_dsp(ctx);
23190 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23191 break;
23192 case OPC_SHRA_R_PH:
23193 check_dsp(ctx);
23194 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23195 break;
23196 case OPC_SHRAV_PH:
23197 check_dsp(ctx);
23198 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23199 break;
23200 case OPC_SHRAV_R_PH:
23201 check_dsp(ctx);
23202 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23203 break;
23204 case OPC_SHRA_R_W:
23205 check_dsp(ctx);
23206 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23207 break;
23208 case OPC_SHRAV_R_W:
23209 check_dsp(ctx);
23210 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23211 break;
23212 default: /* Invalid */
23213 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 23214 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23215 break;
23216 }
23217 break;
23218 }
23219#ifdef TARGET_MIPS64
23220 case OPC_SHLL_OB_DSP:
23221 op2 = MASK_SHLL_OB(ctx->opcode);
23222 switch (op2) {
23223 case OPC_SHLL_PW:
23224 check_dsp(ctx);
23225 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23226 break;
23227 case OPC_SHLLV_PW:
23228 check_dsp(ctx);
23229 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23230 break;
23231 case OPC_SHLL_S_PW:
23232 check_dsp(ctx);
23233 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23234 break;
23235 case OPC_SHLLV_S_PW:
23236 check_dsp(ctx);
23237 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23238 break;
23239 case OPC_SHLL_OB:
23240 check_dsp(ctx);
23241 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23242 break;
23243 case OPC_SHLLV_OB:
23244 check_dsp(ctx);
23245 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23246 break;
23247 case OPC_SHLL_QH:
23248 check_dsp(ctx);
23249 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23250 break;
23251 case OPC_SHLLV_QH:
23252 check_dsp(ctx);
23253 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23254 break;
23255 case OPC_SHLL_S_QH:
23256 check_dsp(ctx);
23257 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23258 break;
23259 case OPC_SHLLV_S_QH:
23260 check_dsp(ctx);
23261 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23262 break;
23263 case OPC_SHRA_OB:
908f6be1 23264 check_dsp_r2(ctx);
77c5fa8b
JL
23265 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23266 break;
23267 case OPC_SHRAV_OB:
908f6be1 23268 check_dsp_r2(ctx);
77c5fa8b
JL
23269 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23270 break;
23271 case OPC_SHRA_R_OB:
908f6be1 23272 check_dsp_r2(ctx);
77c5fa8b
JL
23273 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23274 break;
23275 case OPC_SHRAV_R_OB:
908f6be1 23276 check_dsp_r2(ctx);
77c5fa8b
JL
23277 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23278 break;
23279 case OPC_SHRA_PW:
23280 check_dsp(ctx);
23281 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23282 break;
23283 case OPC_SHRAV_PW:
23284 check_dsp(ctx);
23285 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23286 break;
23287 case OPC_SHRA_R_PW:
23288 check_dsp(ctx);
23289 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23290 break;
23291 case OPC_SHRAV_R_PW:
23292 check_dsp(ctx);
23293 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23294 break;
23295 case OPC_SHRA_QH:
23296 check_dsp(ctx);
23297 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23298 break;
23299 case OPC_SHRAV_QH:
23300 check_dsp(ctx);
23301 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23302 break;
23303 case OPC_SHRA_R_QH:
23304 check_dsp(ctx);
23305 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23306 break;
23307 case OPC_SHRAV_R_QH:
23308 check_dsp(ctx);
23309 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23310 break;
23311 case OPC_SHRL_OB:
23312 check_dsp(ctx);
23313 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23314 break;
23315 case OPC_SHRLV_OB:
23316 check_dsp(ctx);
23317 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23318 break;
23319 case OPC_SHRL_QH:
908f6be1 23320 check_dsp_r2(ctx);
77c5fa8b
JL
23321 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23322 break;
23323 case OPC_SHRLV_QH:
908f6be1 23324 check_dsp_r2(ctx);
77c5fa8b
JL
23325 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23326 break;
23327 default: /* Invalid */
23328 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 23329 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23330 break;
23331 }
23332 break;
23333#endif
23334 }
23335
23336 tcg_temp_free(t0);
23337 tcg_temp_free(v1_t);
23338 tcg_temp_free(v2_t);
77c5fa8b
JL
23339}
23340
a22260ae
JL
23341static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23342 int ret, int v1, int v2, int check_ret)
23343{
a22260ae
JL
23344 TCGv_i32 t0;
23345 TCGv v1_t;
23346 TCGv v2_t;
23347
23348 if ((ret == 0) && (check_ret == 1)) {
23349 /* Treat as NOP. */
a22260ae
JL
23350 return;
23351 }
23352
23353 t0 = tcg_temp_new_i32();
23354 v1_t = tcg_temp_new();
23355 v2_t = tcg_temp_new();
23356
23357 tcg_gen_movi_i32(t0, ret);
23358 gen_load_gpr(v1_t, v1);
23359 gen_load_gpr(v2_t, v2);
23360
23361 switch (op1) {
7480515f
AM
23362 /*
23363 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23364 * the same mask and op1.
23365 */
a22260ae 23366 case OPC_MULT_G_2E:
908f6be1 23367 check_dsp_r2(ctx);
a22260ae
JL
23368 switch (op2) {
23369 case OPC_MUL_PH:
23370 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23371 break;
23372 case OPC_MUL_S_PH:
23373 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23374 break;
23375 case OPC_MULQ_S_W:
23376 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23377 break;
23378 case OPC_MULQ_RS_W:
23379 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23380 break;
23381 }
23382 break;
23383 case OPC_DPA_W_PH_DSP:
23384 switch (op2) {
23385 case OPC_DPAU_H_QBL:
23386 check_dsp(ctx);
23387 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23388 break;
23389 case OPC_DPAU_H_QBR:
23390 check_dsp(ctx);
23391 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23392 break;
23393 case OPC_DPSU_H_QBL:
23394 check_dsp(ctx);
23395 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23396 break;
23397 case OPC_DPSU_H_QBR:
23398 check_dsp(ctx);
23399 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23400 break;
23401 case OPC_DPA_W_PH:
908f6be1 23402 check_dsp_r2(ctx);
a22260ae
JL
23403 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23404 break;
23405 case OPC_DPAX_W_PH:
908f6be1 23406 check_dsp_r2(ctx);
a22260ae
JL
23407 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_DPAQ_S_W_PH:
23410 check_dsp(ctx);
23411 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_DPAQX_S_W_PH:
908f6be1 23414 check_dsp_r2(ctx);
a22260ae
JL
23415 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_DPAQX_SA_W_PH:
908f6be1 23418 check_dsp_r2(ctx);
a22260ae
JL
23419 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23420 break;
23421 case OPC_DPS_W_PH:
908f6be1 23422 check_dsp_r2(ctx);
a22260ae
JL
23423 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23424 break;
23425 case OPC_DPSX_W_PH:
908f6be1 23426 check_dsp_r2(ctx);
a22260ae
JL
23427 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23428 break;
23429 case OPC_DPSQ_S_W_PH:
23430 check_dsp(ctx);
23431 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23432 break;
23433 case OPC_DPSQX_S_W_PH:
908f6be1 23434 check_dsp_r2(ctx);
a22260ae
JL
23435 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23436 break;
23437 case OPC_DPSQX_SA_W_PH:
908f6be1 23438 check_dsp_r2(ctx);
a22260ae
JL
23439 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23440 break;
23441 case OPC_MULSAQ_S_W_PH:
23442 check_dsp(ctx);
23443 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23444 break;
23445 case OPC_DPAQ_SA_L_W:
23446 check_dsp(ctx);
23447 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23448 break;
23449 case OPC_DPSQ_SA_L_W:
23450 check_dsp(ctx);
23451 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23452 break;
23453 case OPC_MAQ_S_W_PHL:
23454 check_dsp(ctx);
23455 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23456 break;
23457 case OPC_MAQ_S_W_PHR:
23458 check_dsp(ctx);
23459 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23460 break;
23461 case OPC_MAQ_SA_W_PHL:
23462 check_dsp(ctx);
23463 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23464 break;
23465 case OPC_MAQ_SA_W_PHR:
23466 check_dsp(ctx);
23467 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23468 break;
23469 case OPC_MULSA_W_PH:
908f6be1 23470 check_dsp_r2(ctx);
a22260ae
JL
23471 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23472 break;
23473 }
23474 break;
23475#ifdef TARGET_MIPS64
23476 case OPC_DPAQ_W_QH_DSP:
23477 {
23478 int ac = ret & 0x03;
23479 tcg_gen_movi_i32(t0, ac);
23480
23481 switch (op2) {
23482 case OPC_DMADD:
23483 check_dsp(ctx);
23484 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23485 break;
23486 case OPC_DMADDU:
23487 check_dsp(ctx);
23488 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23489 break;
23490 case OPC_DMSUB:
23491 check_dsp(ctx);
23492 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23493 break;
23494 case OPC_DMSUBU:
23495 check_dsp(ctx);
23496 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23497 break;
23498 case OPC_DPA_W_QH:
908f6be1 23499 check_dsp_r2(ctx);
a22260ae
JL
23500 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23501 break;
23502 case OPC_DPAQ_S_W_QH:
23503 check_dsp(ctx);
23504 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23505 break;
23506 case OPC_DPAQ_SA_L_PW:
23507 check_dsp(ctx);
23508 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23509 break;
23510 case OPC_DPAU_H_OBL:
23511 check_dsp(ctx);
23512 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23513 break;
23514 case OPC_DPAU_H_OBR:
23515 check_dsp(ctx);
23516 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23517 break;
23518 case OPC_DPS_W_QH:
908f6be1 23519 check_dsp_r2(ctx);
a22260ae
JL
23520 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23521 break;
23522 case OPC_DPSQ_S_W_QH:
23523 check_dsp(ctx);
23524 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23525 break;
23526 case OPC_DPSQ_SA_L_PW:
23527 check_dsp(ctx);
23528 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23529 break;
23530 case OPC_DPSU_H_OBL:
23531 check_dsp(ctx);
23532 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23533 break;
23534 case OPC_DPSU_H_OBR:
23535 check_dsp(ctx);
23536 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23537 break;
23538 case OPC_MAQ_S_L_PWL:
23539 check_dsp(ctx);
23540 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23541 break;
23542 case OPC_MAQ_S_L_PWR:
23543 check_dsp(ctx);
23544 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23545 break;
23546 case OPC_MAQ_S_W_QHLL:
23547 check_dsp(ctx);
23548 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23549 break;
23550 case OPC_MAQ_SA_W_QHLL:
23551 check_dsp(ctx);
23552 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23553 break;
23554 case OPC_MAQ_S_W_QHLR:
23555 check_dsp(ctx);
23556 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23557 break;
23558 case OPC_MAQ_SA_W_QHLR:
23559 check_dsp(ctx);
23560 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23561 break;
23562 case OPC_MAQ_S_W_QHRL:
23563 check_dsp(ctx);
23564 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23565 break;
23566 case OPC_MAQ_SA_W_QHRL:
23567 check_dsp(ctx);
23568 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23569 break;
23570 case OPC_MAQ_S_W_QHRR:
23571 check_dsp(ctx);
23572 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23573 break;
23574 case OPC_MAQ_SA_W_QHRR:
23575 check_dsp(ctx);
23576 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23577 break;
23578 case OPC_MULSAQ_S_L_PW:
23579 check_dsp(ctx);
23580 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23581 break;
23582 case OPC_MULSAQ_S_W_QH:
23583 check_dsp(ctx);
23584 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23585 break;
23586 }
23587 }
23588 break;
23589#endif
23590 case OPC_ADDU_QB_DSP:
23591 switch (op2) {
23592 case OPC_MULEU_S_PH_QBL:
23593 check_dsp(ctx);
23594 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23595 break;
23596 case OPC_MULEU_S_PH_QBR:
23597 check_dsp(ctx);
23598 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23599 break;
23600 case OPC_MULQ_RS_PH:
23601 check_dsp(ctx);
23602 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23603 break;
23604 case OPC_MULEQ_S_W_PHL:
23605 check_dsp(ctx);
23606 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23607 break;
23608 case OPC_MULEQ_S_W_PHR:
23609 check_dsp(ctx);
23610 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23611 break;
23612 case OPC_MULQ_S_PH:
908f6be1 23613 check_dsp_r2(ctx);
a22260ae
JL
23614 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23615 break;
23616 }
23617 break;
23618#ifdef TARGET_MIPS64
23619 case OPC_ADDU_OB_DSP:
23620 switch (op2) {
23621 case OPC_MULEQ_S_PW_QHL:
23622 check_dsp(ctx);
23623 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23624 break;
23625 case OPC_MULEQ_S_PW_QHR:
23626 check_dsp(ctx);
23627 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23628 break;
23629 case OPC_MULEU_S_QH_OBL:
23630 check_dsp(ctx);
23631 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23632 break;
23633 case OPC_MULEU_S_QH_OBR:
23634 check_dsp(ctx);
23635 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23636 break;
23637 case OPC_MULQ_RS_QH:
23638 check_dsp(ctx);
23639 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23640 break;
23641 }
23642 break;
23643#endif
23644 }
23645
23646 tcg_temp_free_i32(t0);
23647 tcg_temp_free(v1_t);
23648 tcg_temp_free(v2_t);
a22260ae
JL
23649}
23650
d75c135e 23651static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
23652 int ret, int val)
23653{
1cb6686c
JL
23654 int16_t imm;
23655 TCGv t0;
23656 TCGv val_t;
23657
23658 if (ret == 0) {
23659 /* Treat as NOP. */
1cb6686c
JL
23660 return;
23661 }
23662
23663 t0 = tcg_temp_new();
23664 val_t = tcg_temp_new();
23665 gen_load_gpr(val_t, val);
23666
23667 switch (op1) {
23668 case OPC_ABSQ_S_PH_DSP:
23669 switch (op2) {
23670 case OPC_BITREV:
23671 check_dsp(ctx);
23672 gen_helper_bitrev(cpu_gpr[ret], val_t);
23673 break;
23674 case OPC_REPL_QB:
23675 check_dsp(ctx);
23676 {
23677 target_long result;
23678 imm = (ctx->opcode >> 16) & 0xFF;
23679 result = (uint32_t)imm << 24 |
23680 (uint32_t)imm << 16 |
23681 (uint32_t)imm << 8 |
23682 (uint32_t)imm;
23683 result = (int32_t)result;
23684 tcg_gen_movi_tl(cpu_gpr[ret], result);
23685 }
23686 break;
23687 case OPC_REPLV_QB:
23688 check_dsp(ctx);
23689 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23690 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23691 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23692 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23693 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23694 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23695 break;
23696 case OPC_REPL_PH:
23697 check_dsp(ctx);
23698 {
23699 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23700 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23701 tcg_gen_movi_tl(cpu_gpr[ret], \
23702 (target_long)((int32_t)imm << 16 | \
c4aaba92 23703 (uint16_t)imm));
1cb6686c
JL
23704 }
23705 break;
23706 case OPC_REPLV_PH:
23707 check_dsp(ctx);
23708 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23709 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23710 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23711 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23712 break;
23713 }
23714 break;
23715#ifdef TARGET_MIPS64
23716 case OPC_ABSQ_S_QH_DSP:
23717 switch (op2) {
23718 case OPC_REPL_OB:
23719 check_dsp(ctx);
23720 {
23721 target_long temp;
23722
23723 imm = (ctx->opcode >> 16) & 0xFF;
23724 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23725 temp = (temp << 16) | temp;
23726 temp = (temp << 32) | temp;
23727 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23728 break;
23729 }
23730 case OPC_REPL_PW:
23731 check_dsp(ctx);
23732 {
23733 target_long temp;
23734
23735 imm = (ctx->opcode >> 16) & 0x03FF;
23736 imm = (int16_t)(imm << 6) >> 6;
23737 temp = ((target_long)imm << 32) \
23738 | ((target_long)imm & 0xFFFFFFFF);
23739 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23740 break;
23741 }
23742 case OPC_REPL_QH:
23743 check_dsp(ctx);
23744 {
23745 target_long temp;
23746
23747 imm = (ctx->opcode >> 16) & 0x03FF;
23748 imm = (int16_t)(imm << 6) >> 6;
23749
23750 temp = ((uint64_t)(uint16_t)imm << 48) |
23751 ((uint64_t)(uint16_t)imm << 32) |
23752 ((uint64_t)(uint16_t)imm << 16) |
23753 (uint64_t)(uint16_t)imm;
23754 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23755 break;
23756 }
23757 case OPC_REPLV_OB:
23758 check_dsp(ctx);
23759 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23760 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23761 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23762 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23763 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23764 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23765 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23766 break;
23767 case OPC_REPLV_PW:
23768 check_dsp(ctx);
23769 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23770 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23771 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23772 break;
23773 case OPC_REPLV_QH:
23774 check_dsp(ctx);
23775 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23776 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23777 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23778 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23779 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23780 break;
23781 }
23782 break;
23783#endif
23784 }
23785 tcg_temp_free(t0);
23786 tcg_temp_free(val_t);
1cb6686c
JL
23787}
23788
26690560
JL
23789static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23790 uint32_t op1, uint32_t op2,
23791 int ret, int v1, int v2, int check_ret)
23792{
26690560
JL
23793 TCGv t1;
23794 TCGv v1_t;
23795 TCGv v2_t;
23796
23797 if ((ret == 0) && (check_ret == 1)) {
23798 /* Treat as NOP. */
26690560
JL
23799 return;
23800 }
23801
26690560
JL
23802 t1 = tcg_temp_new();
23803 v1_t = tcg_temp_new();
23804 v2_t = tcg_temp_new();
23805
23806 gen_load_gpr(v1_t, v1);
23807 gen_load_gpr(v2_t, v2);
23808
23809 switch (op1) {
26690560
JL
23810 case OPC_CMPU_EQ_QB_DSP:
23811 switch (op2) {
23812 case OPC_CMPU_EQ_QB:
23813 check_dsp(ctx);
23814 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23815 break;
23816 case OPC_CMPU_LT_QB:
23817 check_dsp(ctx);
23818 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23819 break;
23820 case OPC_CMPU_LE_QB:
23821 check_dsp(ctx);
23822 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23823 break;
23824 case OPC_CMPGU_EQ_QB:
23825 check_dsp(ctx);
23826 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23827 break;
23828 case OPC_CMPGU_LT_QB:
23829 check_dsp(ctx);
23830 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23831 break;
23832 case OPC_CMPGU_LE_QB:
23833 check_dsp(ctx);
23834 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23835 break;
23836 case OPC_CMPGDU_EQ_QB:
908f6be1 23837 check_dsp_r2(ctx);
26690560
JL
23838 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23839 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23840 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23841 tcg_gen_shli_tl(t1, t1, 24);
23842 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23843 break;
23844 case OPC_CMPGDU_LT_QB:
908f6be1 23845 check_dsp_r2(ctx);
26690560
JL
23846 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23847 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23848 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23849 tcg_gen_shli_tl(t1, t1, 24);
23850 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23851 break;
23852 case OPC_CMPGDU_LE_QB:
908f6be1 23853 check_dsp_r2(ctx);
26690560
JL
23854 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23855 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23856 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23857 tcg_gen_shli_tl(t1, t1, 24);
23858 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23859 break;
23860 case OPC_CMP_EQ_PH:
23861 check_dsp(ctx);
23862 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23863 break;
23864 case OPC_CMP_LT_PH:
23865 check_dsp(ctx);
23866 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_CMP_LE_PH:
23869 check_dsp(ctx);
23870 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_PICK_QB:
23873 check_dsp(ctx);
23874 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23875 break;
23876 case OPC_PICK_PH:
23877 check_dsp(ctx);
23878 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23879 break;
23880 case OPC_PACKRL_PH:
23881 check_dsp(ctx);
23882 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23883 break;
23884 }
23885 break;
23886#ifdef TARGET_MIPS64
23887 case OPC_CMPU_EQ_OB_DSP:
23888 switch (op2) {
23889 case OPC_CMP_EQ_PW:
23890 check_dsp(ctx);
23891 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23892 break;
23893 case OPC_CMP_LT_PW:
23894 check_dsp(ctx);
23895 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23896 break;
23897 case OPC_CMP_LE_PW:
23898 check_dsp(ctx);
23899 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23900 break;
23901 case OPC_CMP_EQ_QH:
23902 check_dsp(ctx);
23903 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23904 break;
23905 case OPC_CMP_LT_QH:
23906 check_dsp(ctx);
23907 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23908 break;
23909 case OPC_CMP_LE_QH:
23910 check_dsp(ctx);
23911 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23912 break;
23913 case OPC_CMPGDU_EQ_OB:
908f6be1 23914 check_dsp_r2(ctx);
26690560
JL
23915 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23916 break;
23917 case OPC_CMPGDU_LT_OB:
908f6be1 23918 check_dsp_r2(ctx);
26690560
JL
23919 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23920 break;
23921 case OPC_CMPGDU_LE_OB:
908f6be1 23922 check_dsp_r2(ctx);
26690560
JL
23923 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23924 break;
23925 case OPC_CMPGU_EQ_OB:
23926 check_dsp(ctx);
23927 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23928 break;
23929 case OPC_CMPGU_LT_OB:
23930 check_dsp(ctx);
23931 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23932 break;
23933 case OPC_CMPGU_LE_OB:
23934 check_dsp(ctx);
23935 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23936 break;
23937 case OPC_CMPU_EQ_OB:
23938 check_dsp(ctx);
23939 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23940 break;
23941 case OPC_CMPU_LT_OB:
23942 check_dsp(ctx);
23943 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23944 break;
23945 case OPC_CMPU_LE_OB:
23946 check_dsp(ctx);
23947 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23948 break;
23949 case OPC_PACKRL_PW:
23950 check_dsp(ctx);
23951 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23952 break;
23953 case OPC_PICK_OB:
23954 check_dsp(ctx);
23955 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23956 break;
23957 case OPC_PICK_PW:
23958 check_dsp(ctx);
23959 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23960 break;
23961 case OPC_PICK_QH:
23962 check_dsp(ctx);
23963 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23964 break;
23965 }
23966 break;
df6126a7
AJ
23967#endif
23968 }
23969
23970 tcg_temp_free(t1);
23971 tcg_temp_free(v1_t);
23972 tcg_temp_free(v2_t);
df6126a7
AJ
23973}
23974
23975static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23976 uint32_t op1, int rt, int rs, int sa)
23977{
df6126a7
AJ
23978 TCGv t0;
23979
908f6be1 23980 check_dsp_r2(ctx);
df6126a7
AJ
23981
23982 if (rt == 0) {
23983 /* Treat as NOP. */
df6126a7
AJ
23984 return;
23985 }
23986
23987 t0 = tcg_temp_new();
23988 gen_load_gpr(t0, rs);
23989
23990 switch (op1) {
23991 case OPC_APPEND_DSP:
23992 switch (MASK_APPEND(ctx->opcode)) {
23993 case OPC_APPEND:
23994 if (sa != 0) {
23995 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23996 }
23997 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23998 break;
23999 case OPC_PREPEND:
24000 if (sa != 0) {
24001 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24002 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24003 tcg_gen_shli_tl(t0, t0, 32 - sa);
24004 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24005 }
24006 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24007 break;
24008 case OPC_BALIGN:
24009 sa &= 3;
24010 if (sa != 0 && sa != 2) {
24011 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24012 tcg_gen_ext32u_tl(t0, t0);
24013 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24014 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24015 }
24016 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24017 break;
24018 default: /* Invalid */
24019 MIPS_INVAL("MASK APPEND");
9c708c7f 24020 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
24021 break;
24022 }
24023 break;
24024#ifdef TARGET_MIPS64
26690560 24025 case OPC_DAPPEND_DSP:
df6126a7 24026 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 24027 case OPC_DAPPEND:
df6126a7
AJ
24028 if (sa != 0) {
24029 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24030 }
26690560
JL
24031 break;
24032 case OPC_PREPENDD:
df6126a7
AJ
24033 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24034 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24035 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
24036 break;
24037 case OPC_PREPENDW:
df6126a7
AJ
24038 if (sa != 0) {
24039 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24040 tcg_gen_shli_tl(t0, t0, 64 - sa);
24041 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24042 }
26690560
JL
24043 break;
24044 case OPC_DBALIGN:
df6126a7
AJ
24045 sa &= 7;
24046 if (sa != 0 && sa != 2 && sa != 4) {
24047 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24048 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24049 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24050 }
26690560
JL
24051 break;
24052 default: /* Invalid */
24053 MIPS_INVAL("MASK DAPPEND");
9c708c7f 24054 generate_exception_end(ctx, EXCP_RI);
26690560
JL
24055 break;
24056 }
24057 break;
24058#endif
24059 }
df6126a7 24060 tcg_temp_free(t0);
26690560
JL
24061}
24062
b53371ed
JL
24063static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24064 int ret, int v1, int v2, int check_ret)
24065
24066{
b53371ed
JL
24067 TCGv t0;
24068 TCGv t1;
24069 TCGv v1_t;
24070 TCGv v2_t;
24071 int16_t imm;
24072
24073 if ((ret == 0) && (check_ret == 1)) {
24074 /* Treat as NOP. */
b53371ed
JL
24075 return;
24076 }
24077
24078 t0 = tcg_temp_new();
24079 t1 = tcg_temp_new();
24080 v1_t = tcg_temp_new();
24081 v2_t = tcg_temp_new();
24082
24083 gen_load_gpr(v1_t, v1);
24084 gen_load_gpr(v2_t, v2);
24085
24086 switch (op1) {
24087 case OPC_EXTR_W_DSP:
24088 check_dsp(ctx);
24089 switch (op2) {
24090 case OPC_EXTR_W:
24091 tcg_gen_movi_tl(t0, v2);
24092 tcg_gen_movi_tl(t1, v1);
24093 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24094 break;
24095 case OPC_EXTR_R_W:
24096 tcg_gen_movi_tl(t0, v2);
24097 tcg_gen_movi_tl(t1, v1);
24098 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24099 break;
24100 case OPC_EXTR_RS_W:
24101 tcg_gen_movi_tl(t0, v2);
24102 tcg_gen_movi_tl(t1, v1);
24103 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24104 break;
24105 case OPC_EXTR_S_H:
24106 tcg_gen_movi_tl(t0, v2);
24107 tcg_gen_movi_tl(t1, v1);
24108 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24109 break;
24110 case OPC_EXTRV_S_H:
24111 tcg_gen_movi_tl(t0, v2);
24112 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24113 break;
24114 case OPC_EXTRV_W:
24115 tcg_gen_movi_tl(t0, v2);
24116 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24117 break;
24118 case OPC_EXTRV_R_W:
24119 tcg_gen_movi_tl(t0, v2);
24120 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24121 break;
24122 case OPC_EXTRV_RS_W:
24123 tcg_gen_movi_tl(t0, v2);
24124 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24125 break;
24126 case OPC_EXTP:
24127 tcg_gen_movi_tl(t0, v2);
24128 tcg_gen_movi_tl(t1, v1);
24129 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24130 break;
24131 case OPC_EXTPV:
24132 tcg_gen_movi_tl(t0, v2);
24133 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24134 break;
24135 case OPC_EXTPDP:
24136 tcg_gen_movi_tl(t0, v2);
24137 tcg_gen_movi_tl(t1, v1);
24138 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24139 break;
24140 case OPC_EXTPDPV:
24141 tcg_gen_movi_tl(t0, v2);
24142 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24143 break;
24144 case OPC_SHILO:
24145 imm = (ctx->opcode >> 20) & 0x3F;
24146 tcg_gen_movi_tl(t0, ret);
24147 tcg_gen_movi_tl(t1, imm);
24148 gen_helper_shilo(t0, t1, cpu_env);
24149 break;
24150 case OPC_SHILOV:
24151 tcg_gen_movi_tl(t0, ret);
24152 gen_helper_shilo(t0, v1_t, cpu_env);
24153 break;
24154 case OPC_MTHLIP:
24155 tcg_gen_movi_tl(t0, ret);
24156 gen_helper_mthlip(t0, v1_t, cpu_env);
24157 break;
24158 case OPC_WRDSP:
24159 imm = (ctx->opcode >> 11) & 0x3FF;
24160 tcg_gen_movi_tl(t0, imm);
24161 gen_helper_wrdsp(v1_t, t0, cpu_env);
24162 break;
24163 case OPC_RDDSP:
24164 imm = (ctx->opcode >> 16) & 0x03FF;
24165 tcg_gen_movi_tl(t0, imm);
24166 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24167 break;
24168 }
24169 break;
24170#ifdef TARGET_MIPS64
24171 case OPC_DEXTR_W_DSP:
24172 check_dsp(ctx);
24173 switch (op2) {
24174 case OPC_DMTHLIP:
24175 tcg_gen_movi_tl(t0, ret);
24176 gen_helper_dmthlip(v1_t, t0, cpu_env);
24177 break;
24178 case OPC_DSHILO:
24179 {
24180 int shift = (ctx->opcode >> 19) & 0x7F;
24181 int ac = (ctx->opcode >> 11) & 0x03;
24182 tcg_gen_movi_tl(t0, shift);
24183 tcg_gen_movi_tl(t1, ac);
24184 gen_helper_dshilo(t0, t1, cpu_env);
24185 break;
24186 }
24187 case OPC_DSHILOV:
24188 {
24189 int ac = (ctx->opcode >> 11) & 0x03;
24190 tcg_gen_movi_tl(t0, ac);
24191 gen_helper_dshilo(v1_t, t0, cpu_env);
24192 break;
24193 }
24194 case OPC_DEXTP:
24195 tcg_gen_movi_tl(t0, v2);
24196 tcg_gen_movi_tl(t1, v1);
24197
24198 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24199 break;
24200 case OPC_DEXTPV:
24201 tcg_gen_movi_tl(t0, v2);
24202 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24203 break;
24204 case OPC_DEXTPDP:
24205 tcg_gen_movi_tl(t0, v2);
24206 tcg_gen_movi_tl(t1, v1);
24207 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24208 break;
24209 case OPC_DEXTPDPV:
24210 tcg_gen_movi_tl(t0, v2);
24211 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24212 break;
24213 case OPC_DEXTR_L:
24214 tcg_gen_movi_tl(t0, v2);
24215 tcg_gen_movi_tl(t1, v1);
24216 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24217 break;
24218 case OPC_DEXTR_R_L:
24219 tcg_gen_movi_tl(t0, v2);
24220 tcg_gen_movi_tl(t1, v1);
24221 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24222 break;
24223 case OPC_DEXTR_RS_L:
24224 tcg_gen_movi_tl(t0, v2);
24225 tcg_gen_movi_tl(t1, v1);
24226 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24227 break;
24228 case OPC_DEXTR_W:
24229 tcg_gen_movi_tl(t0, v2);
24230 tcg_gen_movi_tl(t1, v1);
24231 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24232 break;
24233 case OPC_DEXTR_R_W:
24234 tcg_gen_movi_tl(t0, v2);
24235 tcg_gen_movi_tl(t1, v1);
24236 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24237 break;
24238 case OPC_DEXTR_RS_W:
24239 tcg_gen_movi_tl(t0, v2);
24240 tcg_gen_movi_tl(t1, v1);
24241 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24242 break;
24243 case OPC_DEXTR_S_H:
24244 tcg_gen_movi_tl(t0, v2);
24245 tcg_gen_movi_tl(t1, v1);
24246 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24247 break;
24248 case OPC_DEXTRV_S_H:
24249 tcg_gen_movi_tl(t0, v2);
24250 tcg_gen_movi_tl(t1, v1);
24251 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24252 break;
24253 case OPC_DEXTRV_L:
24254 tcg_gen_movi_tl(t0, v2);
24255 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24256 break;
24257 case OPC_DEXTRV_R_L:
24258 tcg_gen_movi_tl(t0, v2);
24259 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24260 break;
24261 case OPC_DEXTRV_RS_L:
24262 tcg_gen_movi_tl(t0, v2);
24263 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24264 break;
24265 case OPC_DEXTRV_W:
24266 tcg_gen_movi_tl(t0, v2);
24267 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24268 break;
24269 case OPC_DEXTRV_R_W:
24270 tcg_gen_movi_tl(t0, v2);
24271 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24272 break;
24273 case OPC_DEXTRV_RS_W:
24274 tcg_gen_movi_tl(t0, v2);
24275 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24276 break;
24277 }
24278 break;
24279#endif
24280 }
24281
24282 tcg_temp_free(t0);
24283 tcg_temp_free(t1);
24284 tcg_temp_free(v1_t);
24285 tcg_temp_free(v2_t);
b53371ed
JL
24286}
24287
9b1a1d68
JL
24288/* End MIPSDSP functions. */
24289
10dc65db
LA
24290static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24291{
4267d3e6 24292 int rs, rt, rd, sa;
b42ee5e1 24293 uint32_t op1, op2;
10dc65db
LA
24294
24295 rs = (ctx->opcode >> 21) & 0x1f;
24296 rt = (ctx->opcode >> 16) & 0x1f;
24297 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 24298 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24299
24300 op1 = MASK_SPECIAL(ctx->opcode);
24301 switch (op1) {
d4ea6acd 24302 case OPC_LSA:
1f1b4c00 24303 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24304 break;
c2e19f3c
AM
24305 case OPC_MULT:
24306 case OPC_MULTU:
24307 case OPC_DIV:
24308 case OPC_DIVU:
b42ee5e1
LA
24309 op2 = MASK_R6_MULDIV(ctx->opcode);
24310 switch (op2) {
24311 case R6_OPC_MUL:
24312 case R6_OPC_MUH:
24313 case R6_OPC_MULU:
24314 case R6_OPC_MUHU:
24315 case R6_OPC_DIV:
24316 case R6_OPC_MOD:
24317 case R6_OPC_DIVU:
24318 case R6_OPC_MODU:
24319 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24320 break;
24321 default:
24322 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24323 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24324 break;
24325 }
24326 break;
10dc65db
LA
24327 case OPC_SELEQZ:
24328 case OPC_SELNEZ:
24329 gen_cond_move(ctx, op1, rd, rs, rt);
24330 break;
4267d3e6
LA
24331 case R6_OPC_CLO:
24332 case R6_OPC_CLZ:
24333 if (rt == 0 && sa == 1) {
7480515f
AM
24334 /*
24335 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24336 * We need additionally to check other fields.
24337 */
4267d3e6
LA
24338 gen_cl(ctx, op1, rd, rs);
24339 } else {
9c708c7f 24340 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24341 }
24342 break;
24343 case R6_OPC_SDBBP:
3b3c1694
LA
24344 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24345 gen_helper_do_semihosting(cpu_env);
faf1f68b 24346 } else {
3b3c1694 24347 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 24348 generate_exception_end(ctx, EXCP_RI);
3b3c1694 24349 } else {
9c708c7f 24350 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24351 }
faf1f68b 24352 }
4267d3e6 24353 break;
b42ee5e1 24354#if defined(TARGET_MIPS64)
d4ea6acd
LA
24355 case OPC_DLSA:
24356 check_mips_64(ctx);
1f1b4c00 24357 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24358 break;
4267d3e6
LA
24359 case R6_OPC_DCLO:
24360 case R6_OPC_DCLZ:
24361 if (rt == 0 && sa == 1) {
7480515f
AM
24362 /*
24363 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24364 * We need additionally to check other fields.
24365 */
4267d3e6
LA
24366 check_mips_64(ctx);
24367 gen_cl(ctx, op1, rd, rs);
24368 } else {
9c708c7f 24369 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24370 }
24371 break;
c2e19f3c
AM
24372 case OPC_DMULT:
24373 case OPC_DMULTU:
24374 case OPC_DDIV:
24375 case OPC_DDIVU:
24376
b42ee5e1
LA
24377 op2 = MASK_R6_MULDIV(ctx->opcode);
24378 switch (op2) {
24379 case R6_OPC_DMUL:
24380 case R6_OPC_DMUH:
24381 case R6_OPC_DMULU:
24382 case R6_OPC_DMUHU:
24383 case R6_OPC_DDIV:
24384 case R6_OPC_DMOD:
24385 case R6_OPC_DDIVU:
24386 case R6_OPC_DMODU:
24387 check_mips_64(ctx);
24388 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24389 break;
24390 default:
24391 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24392 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24393 break;
24394 }
24395 break;
24396#endif
10dc65db
LA
24397 default: /* Invalid */
24398 MIPS_INVAL("special_r6");
9c708c7f 24399 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24400 break;
24401 }
24402}
24403
9dc324ce
FN
24404static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24405{
24406 int rs = extract32(ctx->opcode, 21, 5);
24407 int rt = extract32(ctx->opcode, 16, 5);
24408 int rd = extract32(ctx->opcode, 11, 5);
24409 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24410
24411 switch (op1) {
24412 case OPC_MOVN: /* Conditional move */
24413 case OPC_MOVZ:
24414 gen_cond_move(ctx, op1, rd, rs, rt);
24415 break;
24416 case OPC_MFHI: /* Move from HI/LO */
24417 case OPC_MFLO:
24418 gen_HILO(ctx, op1, 0, rd);
24419 break;
24420 case OPC_MTHI:
24421 case OPC_MTLO: /* Move to HI/LO */
24422 gen_HILO(ctx, op1, 0, rs);
24423 break;
24424 case OPC_MULT:
24425 case OPC_MULTU:
24426 gen_mul_txx9(ctx, op1, rd, rs, rt);
24427 break;
24428 case OPC_DIV:
24429 case OPC_DIVU:
24430 gen_muldiv(ctx, op1, 0, rs, rt);
24431 break;
24432#if defined(TARGET_MIPS64)
24433 case OPC_DMULT:
24434 case OPC_DMULTU:
24435 case OPC_DDIV:
24436 case OPC_DDIVU:
24437 check_insn_opc_user_only(ctx, INSN_R5900);
24438 gen_muldiv(ctx, op1, 0, rs, rt);
24439 break;
24440#endif
24441 case OPC_JR:
24442 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24443 break;
24444 default: /* Invalid */
24445 MIPS_INVAL("special_tx79");
24446 generate_exception_end(ctx, EXCP_RI);
24447 break;
24448 }
24449}
24450
10dc65db
LA
24451static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24452{
b42ee5e1 24453 int rs, rt, rd, sa;
10dc65db
LA
24454 uint32_t op1;
24455
24456 rs = (ctx->opcode >> 21) & 0x1f;
24457 rt = (ctx->opcode >> 16) & 0x1f;
24458 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24459 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24460
24461 op1 = MASK_SPECIAL(ctx->opcode);
24462 switch (op1) {
24463 case OPC_MOVN: /* Conditional move */
24464 case OPC_MOVZ:
24465 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
9dc324ce 24466 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24467 gen_cond_move(ctx, op1, rd, rs, rt);
24468 break;
24469 case OPC_MFHI: /* Move from HI/LO */
24470 case OPC_MFLO:
24471 gen_HILO(ctx, op1, rs & 3, rd);
24472 break;
24473 case OPC_MTHI:
24474 case OPC_MTLO: /* Move to HI/LO */
24475 gen_HILO(ctx, op1, rd & 3, rs);
24476 break;
24477 case OPC_MOVCI:
24478 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24479 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24480 check_cp1_enabled(ctx);
24481 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24482 (ctx->opcode >> 16) & 1);
24483 } else {
24484 generate_exception_err(ctx, EXCP_CpU, 1);
24485 }
24486 break;
b42ee5e1
LA
24487 case OPC_MULT:
24488 case OPC_MULTU:
24489 if (sa) {
24490 check_insn(ctx, INSN_VR54XX);
24491 op1 = MASK_MUL_VR54XX(ctx->opcode);
24492 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24493 } else {
24494 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24495 }
24496 break;
24497 case OPC_DIV:
24498 case OPC_DIVU:
24499 gen_muldiv(ctx, op1, 0, rs, rt);
24500 break;
24501#if defined(TARGET_MIPS64)
c2e19f3c
AM
24502 case OPC_DMULT:
24503 case OPC_DMULTU:
24504 case OPC_DDIV:
24505 case OPC_DDIVU:
b42ee5e1
LA
24506 check_insn(ctx, ISA_MIPS3);
24507 check_mips_64(ctx);
24508 gen_muldiv(ctx, op1, 0, rs, rt);
24509 break;
24510#endif
0aefa333 24511 case OPC_JR:
b231c103 24512 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24513 break;
4267d3e6
LA
24514 case OPC_SPIM:
24515#ifdef MIPS_STRICT_STANDARD
24516 MIPS_INVAL("SPIM");
9c708c7f 24517 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24518#else
24519 /* Implemented as RI exception for now. */
24520 MIPS_INVAL("spim (unofficial)");
9c708c7f 24521 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24522#endif
24523 break;
10dc65db
LA
24524 default: /* Invalid */
24525 MIPS_INVAL("special_legacy");
9c708c7f 24526 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24527 break;
24528 }
24529}
24530
099e5b4d 24531static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24532{
3c824109 24533 int rs, rt, rd, sa;
099e5b4d 24534 uint32_t op1;
3c824109 24535
3c824109
NF
24536 rs = (ctx->opcode >> 21) & 0x1f;
24537 rt = (ctx->opcode >> 16) & 0x1f;
24538 rd = (ctx->opcode >> 11) & 0x1f;
24539 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24540
24541 op1 = MASK_SPECIAL(ctx->opcode);
24542 switch (op1) {
24543 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24544 if (sa == 5 && rd == 0 &&
24545 rs == 0 && rt == 0) { /* PAUSE */
24546 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24547 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24548 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24549 break;
24550 }
24551 }
24552 /* Fallthrough */
099e5b4d
LA
24553 case OPC_SRA:
24554 gen_shift_imm(ctx, op1, rd, rt, sa);
24555 break;
24556 case OPC_SRL:
24557 switch ((ctx->opcode >> 21) & 0x1f) {
24558 case 1:
24559 /* rotr is decoded as srl on non-R2 CPUs */
24560 if (ctx->insn_flags & ISA_MIPS32R2) {
24561 op1 = OPC_ROTR;
ea63e2c3 24562 }
099e5b4d
LA
24563 /* Fallthrough */
24564 case 0:
24565 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24566 break;
099e5b4d 24567 default:
9c708c7f 24568 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24569 break;
099e5b4d
LA
24570 }
24571 break;
c2e19f3c
AM
24572 case OPC_ADD:
24573 case OPC_ADDU:
24574 case OPC_SUB:
24575 case OPC_SUBU:
099e5b4d
LA
24576 gen_arith(ctx, op1, rd, rs, rt);
24577 break;
24578 case OPC_SLLV: /* Shifts */
24579 case OPC_SRAV:
24580 gen_shift(ctx, op1, rd, rs, rt);
24581 break;
24582 case OPC_SRLV:
24583 switch ((ctx->opcode >> 6) & 0x1f) {
24584 case 1:
24585 /* rotrv is decoded as srlv on non-R2 CPUs */
24586 if (ctx->insn_flags & ISA_MIPS32R2) {
24587 op1 = OPC_ROTRV;
26135ead 24588 }
099e5b4d
LA
24589 /* Fallthrough */
24590 case 0:
24591 gen_shift(ctx, op1, rd, rs, rt);
26135ead 24592 break;
099e5b4d 24593 default:
9c708c7f 24594 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 24595 break;
099e5b4d
LA
24596 }
24597 break;
24598 case OPC_SLT: /* Set on less than */
24599 case OPC_SLTU:
24600 gen_slt(ctx, op1, rd, rs, rt);
24601 break;
24602 case OPC_AND: /* Logic*/
24603 case OPC_OR:
24604 case OPC_NOR:
24605 case OPC_XOR:
24606 gen_logic(ctx, op1, rd, rs, rt);
24607 break;
0aefa333 24608 case OPC_JALR:
b231c103 24609 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 24610 break;
c2e19f3c
AM
24611 case OPC_TGE: /* Traps */
24612 case OPC_TGEU:
24613 case OPC_TLT:
24614 case OPC_TLTU:
24615 case OPC_TEQ:
099e5b4d 24616 case OPC_TNE:
d9224450 24617 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
24618 gen_trap(ctx, op1, rs, rt, -1);
24619 break;
d4ea6acd 24620 case OPC_LSA: /* OPC_PMON */
f7685877
YK
24621 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24622 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
24623 decode_opc_special_r6(env, ctx);
24624 } else {
24625 /* Pmon entry point, also R4010 selsl */
b48cfdff 24626#ifdef MIPS_STRICT_STANDARD
d4ea6acd 24627 MIPS_INVAL("PMON / selsl");
9c708c7f 24628 generate_exception_end(ctx, EXCP_RI);
b48cfdff 24629#else
d4ea6acd 24630 gen_helper_0e0i(pmon, sa);
b48cfdff 24631#endif
d4ea6acd 24632 }
099e5b4d
LA
24633 break;
24634 case OPC_SYSCALL:
9c708c7f 24635 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
24636 break;
24637 case OPC_BREAK:
9c708c7f 24638 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 24639 break;
099e5b4d 24640 case OPC_SYNC:
d9224450 24641 check_insn(ctx, ISA_MIPS2);
d208ac0c 24642 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 24643 break;
4ad40f36 24644
d26bc211 24645#if defined(TARGET_MIPS64)
099e5b4d
LA
24646 /* MIPS64 specific opcodes */
24647 case OPC_DSLL:
24648 case OPC_DSRA:
24649 case OPC_DSLL32:
24650 case OPC_DSRA32:
24651 check_insn(ctx, ISA_MIPS3);
24652 check_mips_64(ctx);
24653 gen_shift_imm(ctx, op1, rd, rt, sa);
24654 break;
24655 case OPC_DSRL:
24656 switch ((ctx->opcode >> 21) & 0x1f) {
24657 case 1:
24658 /* drotr is decoded as dsrl on non-R2 CPUs */
24659 if (ctx->insn_flags & ISA_MIPS32R2) {
24660 op1 = OPC_DROTR;
ea63e2c3 24661 }
099e5b4d
LA
24662 /* Fallthrough */
24663 case 0:
d75c135e 24664 check_insn(ctx, ISA_MIPS3);
e189e748 24665 check_mips_64(ctx);
099e5b4d 24666 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24667 break;
099e5b4d 24668 default:
9c708c7f 24669 generate_exception_end(ctx, EXCP_RI);
460f00c4 24670 break;
099e5b4d
LA
24671 }
24672 break;
24673 case OPC_DSRL32:
24674 switch ((ctx->opcode >> 21) & 0x1f) {
24675 case 1:
24676 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24677 if (ctx->insn_flags & ISA_MIPS32R2) {
24678 op1 = OPC_DROTR32;
ea63e2c3 24679 }
099e5b4d
LA
24680 /* Fallthrough */
24681 case 0:
d75c135e 24682 check_insn(ctx, ISA_MIPS3);
e189e748 24683 check_mips_64(ctx);
099e5b4d 24684 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24685 break;
099e5b4d 24686 default:
9c708c7f 24687 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24688 break;
24689 }
24690 break;
c2e19f3c
AM
24691 case OPC_DADD:
24692 case OPC_DADDU:
24693 case OPC_DSUB:
24694 case OPC_DSUBU:
099e5b4d
LA
24695 check_insn(ctx, ISA_MIPS3);
24696 check_mips_64(ctx);
24697 gen_arith(ctx, op1, rd, rs, rt);
24698 break;
24699 case OPC_DSLLV:
24700 case OPC_DSRAV:
24701 check_insn(ctx, ISA_MIPS3);
24702 check_mips_64(ctx);
24703 gen_shift(ctx, op1, rd, rs, rt);
24704 break;
24705 case OPC_DSRLV:
24706 switch ((ctx->opcode >> 6) & 0x1f) {
24707 case 1:
24708 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24709 if (ctx->insn_flags & ISA_MIPS32R2) {
24710 op1 = OPC_DROTRV;
6af0bf9c 24711 }
099e5b4d
LA
24712 /* Fallthrough */
24713 case 0:
24714 check_insn(ctx, ISA_MIPS3);
e189e748 24715 check_mips_64(ctx);
099e5b4d 24716 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 24717 break;
099e5b4d 24718 default:
9c708c7f 24719 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24720 break;
24721 }
24722 break;
f7685877
YK
24723 case OPC_DLSA:
24724 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24725 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24726 decode_opc_special_r6(env, ctx);
24727 }
24728 break;
099e5b4d 24729#endif
10dc65db
LA
24730 default:
24731 if (ctx->insn_flags & ISA_MIPS32R6) {
24732 decode_opc_special_r6(env, ctx);
9dc324ce
FN
24733 } else if (ctx->insn_flags & INSN_R5900) {
24734 decode_opc_special_tx79(env, ctx);
10dc65db
LA
24735 } else {
24736 decode_opc_special_legacy(env, ctx);
24737 }
24738 }
24739}
24740
d67da337 24741
37b9aae2
MM
24742#if defined(TARGET_MIPS64)
24743
24744/*
24745 *
24746 * MMI (MultiMedia Interface) ASE instructions
24747 * ===========================================
24748 */
24749
24750/*
24751 * MMI instructions category: data communication
24752 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24753 *
24754 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24755 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24756 * PCPYUD PEXEH PEXTLW PPACW
24757 * PEXEW PEXTUB
24758 * PEXTUH
24759 * PEXTUW
24760 */
24761
d3434d9f
MM
24762/*
24763 * PCPYH rd, rt
24764 *
24765 * Parallel Copy Halfword
24766 *
24767 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24768 * +-----------+---------+---------+---------+---------+-----------+
24769 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24770 * +-----------+---------+---------+---------+---------+-----------+
24771 */
24772static void gen_mmi_pcpyh(DisasContext *ctx)
24773{
24774 uint32_t pd, rt, rd;
24775 uint32_t opcode;
24776
24777 opcode = ctx->opcode;
24778
24779 pd = extract32(opcode, 21, 5);
24780 rt = extract32(opcode, 16, 5);
24781 rd = extract32(opcode, 11, 5);
24782
24783 if (unlikely(pd != 0)) {
24784 generate_exception_end(ctx, EXCP_RI);
24785 } else if (rd == 0) {
24786 /* nop */
24787 } else if (rt == 0) {
24788 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24789 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24790 } else {
24791 TCGv_i64 t0 = tcg_temp_new();
24792 TCGv_i64 t1 = tcg_temp_new();
24793 uint64_t mask = (1ULL << 16) - 1;
24794
24795 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24796 tcg_gen_movi_i64(t1, 0);
24797 tcg_gen_or_i64(t1, t0, t1);
24798 tcg_gen_shli_i64(t0, t0, 16);
24799 tcg_gen_or_i64(t1, t0, t1);
24800 tcg_gen_shli_i64(t0, t0, 16);
24801 tcg_gen_or_i64(t1, t0, t1);
24802 tcg_gen_shli_i64(t0, t0, 16);
24803 tcg_gen_or_i64(t1, t0, t1);
24804
24805 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24806
24807 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24808 tcg_gen_movi_i64(t1, 0);
24809 tcg_gen_or_i64(t1, t0, t1);
24810 tcg_gen_shli_i64(t0, t0, 16);
24811 tcg_gen_or_i64(t1, t0, t1);
24812 tcg_gen_shli_i64(t0, t0, 16);
24813 tcg_gen_or_i64(t1, t0, t1);
24814 tcg_gen_shli_i64(t0, t0, 16);
24815 tcg_gen_or_i64(t1, t0, t1);
24816
24817 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24818
24819 tcg_temp_free(t0);
24820 tcg_temp_free(t1);
24821 }
24822}
24823
b87eef31
MM
24824/*
24825 * PCPYLD rd, rs, rt
24826 *
24827 * Parallel Copy Lower Doubleword
24828 *
24829 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24830 * +-----------+---------+---------+---------+---------+-----------+
24831 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24832 * +-----------+---------+---------+---------+---------+-----------+
24833 */
24834static void gen_mmi_pcpyld(DisasContext *ctx)
24835{
24836 uint32_t rs, rt, rd;
24837 uint32_t opcode;
24838
24839 opcode = ctx->opcode;
24840
24841 rs = extract32(opcode, 21, 5);
24842 rt = extract32(opcode, 16, 5);
24843 rd = extract32(opcode, 11, 5);
24844
24845 if (rd == 0) {
24846 /* nop */
24847 } else {
24848 if (rs == 0) {
24849 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24850 } else {
24851 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24852 }
24853 if (rt == 0) {
24854 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24855 } else {
24856 if (rd != rt) {
24857 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24858 }
24859 }
24860 }
24861}
24862
fd487f83
MM
24863/*
24864 * PCPYUD rd, rs, rt
24865 *
24866 * Parallel Copy Upper Doubleword
24867 *
24868 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24869 * +-----------+---------+---------+---------+---------+-----------+
24870 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24871 * +-----------+---------+---------+---------+---------+-----------+
24872 */
24873static void gen_mmi_pcpyud(DisasContext *ctx)
24874{
24875 uint32_t rs, rt, rd;
24876 uint32_t opcode;
24877
24878 opcode = ctx->opcode;
24879
24880 rs = extract32(opcode, 21, 5);
24881 rt = extract32(opcode, 16, 5);
24882 rd = extract32(opcode, 11, 5);
24883
24884 if (rd == 0) {
24885 /* nop */
24886 } else {
24887 if (rs == 0) {
24888 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24889 } else {
24890 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24891 }
24892 if (rt == 0) {
24893 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24894 } else {
24895 if (rd != rt) {
24896 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24897 }
24898 }
24899 }
24900}
24901
37b9aae2
MM
24902#endif
24903
24904
b621f018
AM
24905#if !defined(TARGET_MIPS64)
24906
d67da337
AM
24907/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24908#define MXU_APTN1_A 0
24909#define MXU_APTN1_S 1
24910
b70bb918
CJ
24911/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24912#define MXU_APTN2_AA 0
24913#define MXU_APTN2_AS 1
24914#define MXU_APTN2_SA 2
24915#define MXU_APTN2_SS 3
24916
5bb29992
AM
24917/* MXU execute add/subtract 2-bit pattern 'eptn2' */
24918#define MXU_EPTN2_AA 0
24919#define MXU_EPTN2_AS 1
24920#define MXU_EPTN2_SA 2
24921#define MXU_EPTN2_SS 3
24922
a35723f4 24923/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
24924#define MXU_OPTN2_PTN0 0
24925#define MXU_OPTN2_PTN1 1
24926#define MXU_OPTN2_PTN2 2
24927#define MXU_OPTN2_PTN3 3
24928/* alternative naming scheme for 'optn2' */
a35723f4
CJ
24929#define MXU_OPTN2_WW 0
24930#define MXU_OPTN2_LW 1
24931#define MXU_OPTN2_HW 2
24932#define MXU_OPTN2_XW 3
24933
53f1131f
CJ
24934/* MXU operand getting pattern 'optn3' */
24935#define MXU_OPTN3_PTN0 0
24936#define MXU_OPTN3_PTN1 1
24937#define MXU_OPTN3_PTN2 2
24938#define MXU_OPTN3_PTN3 3
24939#define MXU_OPTN3_PTN4 4
24940#define MXU_OPTN3_PTN5 5
24941#define MXU_OPTN3_PTN6 6
24942#define MXU_OPTN3_PTN7 7
24943
d67da337 24944
96992d1a
CJ
24945/*
24946 * S32I2M XRa, rb - Register move from GRF to XRF
24947 */
24948static void gen_mxu_s32i2m(DisasContext *ctx)
24949{
24950 TCGv t0;
24951 uint32_t XRa, Rb;
24952
24953 t0 = tcg_temp_new();
24954
24955 XRa = extract32(ctx->opcode, 6, 5);
24956 Rb = extract32(ctx->opcode, 16, 5);
24957
24958 gen_load_gpr(t0, Rb);
24959 if (XRa <= 15) {
24960 gen_store_mxu_gpr(t0, XRa);
24961 } else if (XRa == 16) {
24962 gen_store_mxu_cr(t0);
24963 }
24964
24965 tcg_temp_free(t0);
24966}
24967
24968/*
24969 * S32M2I XRa, rb - Register move from XRF to GRF
24970 */
24971static void gen_mxu_s32m2i(DisasContext *ctx)
24972{
24973 TCGv t0;
24974 uint32_t XRa, Rb;
24975
24976 t0 = tcg_temp_new();
24977
24978 XRa = extract32(ctx->opcode, 6, 5);
24979 Rb = extract32(ctx->opcode, 16, 5);
24980
24981 if (XRa <= 15) {
24982 gen_load_mxu_gpr(t0, XRa);
24983 } else if (XRa == 16) {
24984 gen_load_mxu_cr(t0);
24985 }
24986
24987 gen_store_gpr(t0, Rb);
24988
24989 tcg_temp_free(t0);
24990}
24991
be57bcdb
CJ
24992/*
24993 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24994 */
24995static void gen_mxu_s8ldd(DisasContext *ctx)
24996{
24997 TCGv t0, t1;
be57bcdb
CJ
24998 uint32_t XRa, Rb, s8, optn3;
24999
25000 t0 = tcg_temp_new();
25001 t1 = tcg_temp_new();
25002
be57bcdb
CJ
25003 XRa = extract32(ctx->opcode, 6, 4);
25004 s8 = extract32(ctx->opcode, 10, 8);
25005 optn3 = extract32(ctx->opcode, 18, 3);
25006 Rb = extract32(ctx->opcode, 21, 5);
25007
be57bcdb
CJ
25008 gen_load_gpr(t0, Rb);
25009 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25010
25011 switch (optn3) {
25012 /* XRa[7:0] = tmp8 */
25013 case MXU_OPTN3_PTN0:
25014 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25015 gen_load_mxu_gpr(t0, XRa);
25016 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25017 break;
25018 /* XRa[15:8] = tmp8 */
25019 case MXU_OPTN3_PTN1:
25020 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25021 gen_load_mxu_gpr(t0, XRa);
25022 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25023 break;
25024 /* XRa[23:16] = tmp8 */
25025 case MXU_OPTN3_PTN2:
25026 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25027 gen_load_mxu_gpr(t0, XRa);
25028 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25029 break;
25030 /* XRa[31:24] = tmp8 */
25031 case MXU_OPTN3_PTN3:
25032 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25033 gen_load_mxu_gpr(t0, XRa);
25034 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25035 break;
25036 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25037 case MXU_OPTN3_PTN4:
25038 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25039 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25040 break;
25041 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25042 case MXU_OPTN3_PTN5:
25043 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25044 tcg_gen_shli_tl(t1, t1, 8);
25045 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25046 break;
25047 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25048 case MXU_OPTN3_PTN6:
25049 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25050 tcg_gen_mov_tl(t0, t1);
25051 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25052 tcg_gen_shli_tl(t1, t1, 16);
25053 tcg_gen_or_tl(t0, t0, t1);
25054 break;
25055 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25056 case MXU_OPTN3_PTN7:
25057 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25058 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25059 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25060 break;
25061 }
25062
25063 gen_store_mxu_gpr(t0, XRa);
25064
be57bcdb
CJ
25065 tcg_temp_free(t0);
25066 tcg_temp_free(t1);
25067}
25068
72c9bcf8
CJ
25069/*
25070 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25071 */
25072static void gen_mxu_d16mul(DisasContext *ctx)
25073{
25074 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
25075 uint32_t XRa, XRb, XRc, XRd, optn2;
25076
25077 t0 = tcg_temp_new();
25078 t1 = tcg_temp_new();
25079 t2 = tcg_temp_new();
25080 t3 = tcg_temp_new();
25081
72c9bcf8
CJ
25082 XRa = extract32(ctx->opcode, 6, 4);
25083 XRb = extract32(ctx->opcode, 10, 4);
25084 XRc = extract32(ctx->opcode, 14, 4);
25085 XRd = extract32(ctx->opcode, 18, 4);
25086 optn2 = extract32(ctx->opcode, 22, 2);
25087
72c9bcf8
CJ
25088 gen_load_mxu_gpr(t1, XRb);
25089 tcg_gen_sextract_tl(t0, t1, 0, 16);
25090 tcg_gen_sextract_tl(t1, t1, 16, 16);
25091 gen_load_mxu_gpr(t3, XRc);
25092 tcg_gen_sextract_tl(t2, t3, 0, 16);
25093 tcg_gen_sextract_tl(t3, t3, 16, 16);
25094
25095 switch (optn2) {
25096 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25097 tcg_gen_mul_tl(t3, t1, t3);
25098 tcg_gen_mul_tl(t2, t0, t2);
25099 break;
25100 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25101 tcg_gen_mul_tl(t3, t0, t3);
25102 tcg_gen_mul_tl(t2, t0, t2);
25103 break;
25104 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25105 tcg_gen_mul_tl(t3, t1, t3);
25106 tcg_gen_mul_tl(t2, t1, t2);
25107 break;
25108 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25109 tcg_gen_mul_tl(t3, t0, t3);
25110 tcg_gen_mul_tl(t2, t1, t2);
25111 break;
25112 }
25113 gen_store_mxu_gpr(t3, XRa);
25114 gen_store_mxu_gpr(t2, XRd);
25115
72c9bcf8
CJ
25116 tcg_temp_free(t0);
25117 tcg_temp_free(t1);
25118 tcg_temp_free(t2);
25119 tcg_temp_free(t3);
25120}
25121
e67915b4
CJ
25122/*
25123 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25124 * and accumulate
25125 */
25126static void gen_mxu_d16mac(DisasContext *ctx)
25127{
25128 TCGv t0, t1, t2, t3;
e67915b4
CJ
25129 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25130
25131 t0 = tcg_temp_new();
25132 t1 = tcg_temp_new();
25133 t2 = tcg_temp_new();
25134 t3 = tcg_temp_new();
25135
e67915b4
CJ
25136 XRa = extract32(ctx->opcode, 6, 4);
25137 XRb = extract32(ctx->opcode, 10, 4);
25138 XRc = extract32(ctx->opcode, 14, 4);
25139 XRd = extract32(ctx->opcode, 18, 4);
25140 optn2 = extract32(ctx->opcode, 22, 2);
25141 aptn2 = extract32(ctx->opcode, 24, 2);
25142
e67915b4
CJ
25143 gen_load_mxu_gpr(t1, XRb);
25144 tcg_gen_sextract_tl(t0, t1, 0, 16);
25145 tcg_gen_sextract_tl(t1, t1, 16, 16);
25146
25147 gen_load_mxu_gpr(t3, XRc);
25148 tcg_gen_sextract_tl(t2, t3, 0, 16);
25149 tcg_gen_sextract_tl(t3, t3, 16, 16);
25150
25151 switch (optn2) {
25152 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25153 tcg_gen_mul_tl(t3, t1, t3);
25154 tcg_gen_mul_tl(t2, t0, t2);
25155 break;
25156 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25157 tcg_gen_mul_tl(t3, t0, t3);
25158 tcg_gen_mul_tl(t2, t0, t2);
25159 break;
25160 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25161 tcg_gen_mul_tl(t3, t1, t3);
25162 tcg_gen_mul_tl(t2, t1, t2);
25163 break;
25164 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25165 tcg_gen_mul_tl(t3, t0, t3);
25166 tcg_gen_mul_tl(t2, t1, t2);
25167 break;
25168 }
25169 gen_load_mxu_gpr(t0, XRa);
25170 gen_load_mxu_gpr(t1, XRd);
25171
25172 switch (aptn2) {
25173 case MXU_APTN2_AA:
25174 tcg_gen_add_tl(t3, t0, t3);
25175 tcg_gen_add_tl(t2, t1, t2);
25176 break;
25177 case MXU_APTN2_AS:
25178 tcg_gen_add_tl(t3, t0, t3);
25179 tcg_gen_sub_tl(t2, t1, t2);
25180 break;
25181 case MXU_APTN2_SA:
25182 tcg_gen_sub_tl(t3, t0, t3);
25183 tcg_gen_add_tl(t2, t1, t2);
25184 break;
25185 case MXU_APTN2_SS:
25186 tcg_gen_sub_tl(t3, t0, t3);
25187 tcg_gen_sub_tl(t2, t1, t2);
25188 break;
25189 }
25190 gen_store_mxu_gpr(t3, XRa);
25191 gen_store_mxu_gpr(t2, XRd);
25192
e67915b4
CJ
25193 tcg_temp_free(t0);
25194 tcg_temp_free(t1);
25195 tcg_temp_free(t2);
25196 tcg_temp_free(t3);
25197}
25198
a9a4181b
CJ
25199/*
25200 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25201 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25202 */
25203static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25204{
25205 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
25206 uint32_t XRa, XRb, XRc, XRd, sel;
25207
25208 t0 = tcg_temp_new();
25209 t1 = tcg_temp_new();
25210 t2 = tcg_temp_new();
25211 t3 = tcg_temp_new();
25212 t4 = tcg_temp_new();
25213 t5 = tcg_temp_new();
25214 t6 = tcg_temp_new();
25215 t7 = tcg_temp_new();
25216
a9a4181b
CJ
25217 XRa = extract32(ctx->opcode, 6, 4);
25218 XRb = extract32(ctx->opcode, 10, 4);
25219 XRc = extract32(ctx->opcode, 14, 4);
25220 XRd = extract32(ctx->opcode, 18, 4);
25221 sel = extract32(ctx->opcode, 22, 2);
25222
a9a4181b
CJ
25223 gen_load_mxu_gpr(t3, XRb);
25224 gen_load_mxu_gpr(t7, XRc);
25225
25226 if (sel == 0x2) {
25227 /* Q8MULSU */
25228 tcg_gen_ext8s_tl(t0, t3);
25229 tcg_gen_shri_tl(t3, t3, 8);
25230 tcg_gen_ext8s_tl(t1, t3);
25231 tcg_gen_shri_tl(t3, t3, 8);
25232 tcg_gen_ext8s_tl(t2, t3);
25233 tcg_gen_shri_tl(t3, t3, 8);
25234 tcg_gen_ext8s_tl(t3, t3);
25235 } else {
25236 /* Q8MUL */
25237 tcg_gen_ext8u_tl(t0, t3);
25238 tcg_gen_shri_tl(t3, t3, 8);
25239 tcg_gen_ext8u_tl(t1, t3);
25240 tcg_gen_shri_tl(t3, t3, 8);
25241 tcg_gen_ext8u_tl(t2, t3);
25242 tcg_gen_shri_tl(t3, t3, 8);
25243 tcg_gen_ext8u_tl(t3, t3);
25244 }
25245
25246 tcg_gen_ext8u_tl(t4, t7);
25247 tcg_gen_shri_tl(t7, t7, 8);
25248 tcg_gen_ext8u_tl(t5, t7);
25249 tcg_gen_shri_tl(t7, t7, 8);
25250 tcg_gen_ext8u_tl(t6, t7);
25251 tcg_gen_shri_tl(t7, t7, 8);
25252 tcg_gen_ext8u_tl(t7, t7);
25253
25254 tcg_gen_mul_tl(t0, t0, t4);
25255 tcg_gen_mul_tl(t1, t1, t5);
25256 tcg_gen_mul_tl(t2, t2, t6);
25257 tcg_gen_mul_tl(t3, t3, t7);
25258
25259 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25260 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25261 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25262 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25263
25264 tcg_gen_shli_tl(t1, t1, 16);
25265 tcg_gen_shli_tl(t3, t3, 16);
25266
25267 tcg_gen_or_tl(t0, t0, t1);
25268 tcg_gen_or_tl(t1, t2, t3);
25269
25270 gen_store_mxu_gpr(t0, XRd);
25271 gen_store_mxu_gpr(t1, XRa);
25272
a9a4181b
CJ
25273 tcg_temp_free(t0);
25274 tcg_temp_free(t1);
25275 tcg_temp_free(t2);
25276 tcg_temp_free(t3);
25277 tcg_temp_free(t4);
25278 tcg_temp_free(t5);
25279 tcg_temp_free(t6);
25280 tcg_temp_free(t7);
25281}
25282
4ca83721
CJ
25283/*
25284 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25285 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25286 */
25287static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25288{
25289 TCGv t0, t1;
4ca83721
CJ
25290 uint32_t XRa, Rb, s12, sel;
25291
25292 t0 = tcg_temp_new();
25293 t1 = tcg_temp_new();
25294
4ca83721
CJ
25295 XRa = extract32(ctx->opcode, 6, 4);
25296 s12 = extract32(ctx->opcode, 10, 10);
25297 sel = extract32(ctx->opcode, 20, 1);
25298 Rb = extract32(ctx->opcode, 21, 5);
25299
4ca83721
CJ
25300 gen_load_gpr(t0, Rb);
25301
25302 tcg_gen_movi_tl(t1, s12);
25303 tcg_gen_shli_tl(t1, t1, 2);
25304 if (s12 & 0x200) {
25305 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25306 }
25307 tcg_gen_add_tl(t1, t0, t1);
25308 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25309
25310 if (sel == 1) {
25311 /* S32LDDR */
25312 tcg_gen_bswap32_tl(t1, t1);
25313 }
25314 gen_store_mxu_gpr(t1, XRa);
25315
4ca83721
CJ
25316 tcg_temp_free(t0);
25317 tcg_temp_free(t1);
25318}
25319
96992d1a 25320
b621f018
AM
25321/*
25322 * MXU instruction category: logic
25323 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25324 *
25325 * S32NOR S32AND S32OR S32XOR
25326 */
25327
25328/*
25329 * S32NOR XRa, XRb, XRc
25330 * Update XRa with the result of logical bitwise 'nor' operation
25331 * applied to the content of XRb and XRc.
25332 *
25333 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25334 * +-----------+---------+-----+-------+-------+-------+-----------+
25335 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25336 * +-----------+---------+-----+-------+-------+-------+-----------+
25337 */
25338static void gen_mxu_S32NOR(DisasContext *ctx)
25339{
25340 uint32_t pad, XRc, XRb, XRa;
25341
25342 pad = extract32(ctx->opcode, 21, 5);
25343 XRc = extract32(ctx->opcode, 14, 4);
25344 XRb = extract32(ctx->opcode, 10, 4);
25345 XRa = extract32(ctx->opcode, 6, 4);
25346
25347 if (unlikely(pad != 0)) {
25348 /* opcode padding incorrect -> do nothing */
25349 } else if (unlikely(XRa == 0)) {
25350 /* destination is zero register -> do nothing */
25351 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25352 /* both operands zero registers -> just set destination to all 1s */
25353 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25354 } else if (unlikely(XRb == 0)) {
25355 /* XRb zero register -> just set destination to the negation of XRc */
25356 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25357 } else if (unlikely(XRc == 0)) {
25358 /* XRa zero register -> just set destination to the negation of XRb */
25359 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25360 } else if (unlikely(XRb == XRc)) {
25361 /* both operands same -> just set destination to the negation of XRb */
25362 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25363 } else {
25364 /* the most general case */
25365 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25366 }
25367}
25368
25369/*
25370 * S32AND XRa, XRb, XRc
25371 * Update XRa with the result of logical bitwise 'and' operation
25372 * applied to the content of XRb and XRc.
25373 *
25374 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25375 * +-----------+---------+-----+-------+-------+-------+-----------+
25376 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25377 * +-----------+---------+-----+-------+-------+-------+-----------+
25378 */
25379static void gen_mxu_S32AND(DisasContext *ctx)
25380{
25381 uint32_t pad, XRc, XRb, XRa;
25382
25383 pad = extract32(ctx->opcode, 21, 5);
25384 XRc = extract32(ctx->opcode, 14, 4);
25385 XRb = extract32(ctx->opcode, 10, 4);
25386 XRa = extract32(ctx->opcode, 6, 4);
25387
25388 if (unlikely(pad != 0)) {
25389 /* opcode padding incorrect -> do nothing */
25390 } else if (unlikely(XRa == 0)) {
25391 /* destination is zero register -> do nothing */
25392 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25393 /* one of operands zero register -> just set destination to all 0s */
25394 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25395 } else if (unlikely(XRb == XRc)) {
25396 /* both operands same -> just set destination to one of them */
25397 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25398 } else {
25399 /* the most general case */
25400 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25401 }
25402}
25403
25404/*
25405 * S32OR XRa, XRb, XRc
25406 * Update XRa with the result of logical bitwise 'or' operation
25407 * applied to the content of XRb and XRc.
25408 *
25409 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25410 * +-----------+---------+-----+-------+-------+-------+-----------+
25411 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25412 * +-----------+---------+-----+-------+-------+-------+-----------+
25413 */
25414static void gen_mxu_S32OR(DisasContext *ctx)
25415{
25416 uint32_t pad, XRc, XRb, XRa;
25417
25418 pad = extract32(ctx->opcode, 21, 5);
25419 XRc = extract32(ctx->opcode, 14, 4);
25420 XRb = extract32(ctx->opcode, 10, 4);
25421 XRa = extract32(ctx->opcode, 6, 4);
25422
25423 if (unlikely(pad != 0)) {
25424 /* opcode padding incorrect -> do nothing */
25425 } else if (unlikely(XRa == 0)) {
25426 /* destination is zero register -> do nothing */
25427 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25428 /* both operands zero registers -> just set destination to all 0s */
25429 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25430 } else if (unlikely(XRb == 0)) {
25431 /* XRb zero register -> just set destination to the content of XRc */
25432 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25433 } else if (unlikely(XRc == 0)) {
25434 /* XRc zero register -> just set destination to the content of XRb */
25435 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25436 } else if (unlikely(XRb == XRc)) {
25437 /* both operands same -> just set destination to one of them */
25438 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25439 } else {
25440 /* the most general case */
25441 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25442 }
25443}
25444
25445/*
25446 * S32XOR XRa, XRb, XRc
25447 * Update XRa with the result of logical bitwise 'xor' operation
25448 * applied to the content of XRb and XRc.
25449 *
25450 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25451 * +-----------+---------+-----+-------+-------+-------+-----------+
25452 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25453 * +-----------+---------+-----+-------+-------+-------+-----------+
25454 */
25455static void gen_mxu_S32XOR(DisasContext *ctx)
25456{
25457 uint32_t pad, XRc, XRb, XRa;
25458
25459 pad = extract32(ctx->opcode, 21, 5);
25460 XRc = extract32(ctx->opcode, 14, 4);
25461 XRb = extract32(ctx->opcode, 10, 4);
25462 XRa = extract32(ctx->opcode, 6, 4);
25463
25464 if (unlikely(pad != 0)) {
25465 /* opcode padding incorrect -> do nothing */
25466 } else if (unlikely(XRa == 0)) {
25467 /* destination is zero register -> do nothing */
25468 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25469 /* both operands zero registers -> just set destination to all 0s */
25470 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25471 } else if (unlikely(XRb == 0)) {
25472 /* XRb zero register -> just set destination to the content of XRc */
25473 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25474 } else if (unlikely(XRc == 0)) {
25475 /* XRc zero register -> just set destination to the content of XRb */
25476 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25477 } else if (unlikely(XRb == XRc)) {
25478 /* both operands same -> just set destination to all 0s */
25479 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25480 } else {
25481 /* the most general case */
25482 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25483 }
25484}
25485
25486
bb84cbf3
AM
25487/*
25488 * MXU instruction category max/min
25489 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25490 *
25491 * S32MAX D16MAX Q8MAX
25492 * S32MIN D16MIN Q8MIN
25493 */
25494
25495/*
25496 * S32MAX XRa, XRb, XRc
25497 * Update XRa with the maximum of signed 32-bit integers contained
25498 * in XRb and XRc.
25499 *
25500 * S32MIN XRa, XRb, XRc
25501 * Update XRa with the minimum of signed 32-bit integers contained
25502 * in XRb and XRc.
25503 *
25504 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25505 * +-----------+---------+-----+-------+-------+-------+-----------+
25506 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25507 * +-----------+---------+-----+-------+-------+-------+-----------+
25508 */
25509static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25510{
25511 uint32_t pad, opc, XRc, XRb, XRa;
25512
25513 pad = extract32(ctx->opcode, 21, 5);
25514 opc = extract32(ctx->opcode, 18, 3);
25515 XRc = extract32(ctx->opcode, 14, 4);
25516 XRb = extract32(ctx->opcode, 10, 4);
25517 XRa = extract32(ctx->opcode, 6, 4);
25518
25519 if (unlikely(pad != 0)) {
25520 /* opcode padding incorrect -> do nothing */
25521 } else if (unlikely(XRa == 0)) {
25522 /* destination is zero register -> do nothing */
25523 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25524 /* both operands zero registers -> just set destination to zero */
25525 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25526 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25527 /* exactly one operand is zero register - find which one is not...*/
25528 uint32_t XRx = XRb ? XRb : XRc;
25529 /* ...and do max/min operation with one operand 0 */
25530 if (opc == OPC_MXU_S32MAX) {
25531 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25532 } else {
25533 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25534 }
25535 } else if (unlikely(XRb == XRc)) {
25536 /* both operands same -> just set destination to one of them */
25537 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25538 } else {
25539 /* the most general case */
25540 if (opc == OPC_MXU_S32MAX) {
25541 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25542 mxu_gpr[XRc - 1]);
25543 } else {
25544 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25545 mxu_gpr[XRc - 1]);
25546 }
25547 }
25548}
25549
25550/*
25551 * D16MAX
25552 * Update XRa with the 16-bit-wise maximums of signed integers
25553 * contained in XRb and XRc.
25554 *
25555 * D16MIN
25556 * Update XRa with the 16-bit-wise minimums of signed integers
25557 * contained in XRb and XRc.
25558 *
25559 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25560 * +-----------+---------+-----+-------+-------+-------+-----------+
25561 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25562 * +-----------+---------+-----+-------+-------+-------+-----------+
25563 */
25564static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25565{
25566 uint32_t pad, opc, XRc, XRb, XRa;
25567
25568 pad = extract32(ctx->opcode, 21, 5);
25569 opc = extract32(ctx->opcode, 18, 3);
25570 XRc = extract32(ctx->opcode, 14, 4);
25571 XRb = extract32(ctx->opcode, 10, 4);
25572 XRa = extract32(ctx->opcode, 6, 4);
25573
25574 if (unlikely(pad != 0)) {
25575 /* opcode padding incorrect -> do nothing */
25576 } else if (unlikely(XRc == 0)) {
25577 /* destination is zero register -> do nothing */
25578 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25579 /* both operands zero registers -> just set destination to zero */
25580 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25581 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25582 /* exactly one operand is zero register - find which one is not...*/
25583 uint32_t XRx = XRb ? XRb : XRc;
25584 /* ...and do half-word-wise max/min with one operand 0 */
25585 TCGv_i32 t0 = tcg_temp_new();
25586 TCGv_i32 t1 = tcg_const_i32(0);
25587
25588 /* the left half-word first */
25589 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25590 if (opc == OPC_MXU_D16MAX) {
25591 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25592 } else {
25593 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25594 }
25595
25596 /* the right half-word */
25597 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25598 /* move half-words to the leftmost position */
25599 tcg_gen_shli_i32(t0, t0, 16);
25600 /* t0 will be max/min of t0 and t1 */
25601 if (opc == OPC_MXU_D16MAX) {
25602 tcg_gen_smax_i32(t0, t0, t1);
25603 } else {
25604 tcg_gen_smin_i32(t0, t0, t1);
25605 }
25606 /* return resulting half-words to its original position */
25607 tcg_gen_shri_i32(t0, t0, 16);
25608 /* finaly update the destination */
25609 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25610
25611 tcg_temp_free(t1);
25612 tcg_temp_free(t0);
25613 } else if (unlikely(XRb == XRc)) {
25614 /* both operands same -> just set destination to one of them */
25615 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25616 } else {
25617 /* the most general case */
25618 TCGv_i32 t0 = tcg_temp_new();
25619 TCGv_i32 t1 = tcg_temp_new();
25620
25621 /* the left half-word first */
25622 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25623 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25624 if (opc == OPC_MXU_D16MAX) {
25625 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25626 } else {
25627 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25628 }
25629
25630 /* the right half-word */
25631 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25632 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25633 /* move half-words to the leftmost position */
25634 tcg_gen_shli_i32(t0, t0, 16);
25635 tcg_gen_shli_i32(t1, t1, 16);
25636 /* t0 will be max/min of t0 and t1 */
25637 if (opc == OPC_MXU_D16MAX) {
25638 tcg_gen_smax_i32(t0, t0, t1);
25639 } else {
25640 tcg_gen_smin_i32(t0, t0, t1);
25641 }
25642 /* return resulting half-words to its original position */
25643 tcg_gen_shri_i32(t0, t0, 16);
25644 /* finaly update the destination */
25645 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25646
25647 tcg_temp_free(t1);
25648 tcg_temp_free(t0);
25649 }
25650}
25651
25652/*
25653 * Q8MAX
25654 * Update XRa with the 8-bit-wise maximums of signed integers
25655 * contained in XRb and XRc.
25656 *
25657 * Q8MIN
25658 * Update XRa with the 8-bit-wise minimums of signed integers
25659 * contained in XRb and XRc.
25660 *
25661 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25662 * +-----------+---------+-----+-------+-------+-------+-----------+
25663 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25664 * +-----------+---------+-----+-------+-------+-------+-----------+
25665 */
25666static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25667{
25668 uint32_t pad, opc, XRc, XRb, XRa;
25669
25670 pad = extract32(ctx->opcode, 21, 5);
25671 opc = extract32(ctx->opcode, 18, 3);
25672 XRc = extract32(ctx->opcode, 14, 4);
25673 XRb = extract32(ctx->opcode, 10, 4);
25674 XRa = extract32(ctx->opcode, 6, 4);
25675
25676 if (unlikely(pad != 0)) {
25677 /* opcode padding incorrect -> do nothing */
25678 } else if (unlikely(XRa == 0)) {
25679 /* destination is zero register -> do nothing */
25680 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25681 /* both operands zero registers -> just set destination to zero */
25682 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25683 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25684 /* exactly one operand is zero register - make it be the first...*/
25685 uint32_t XRx = XRb ? XRb : XRc;
25686 /* ...and do byte-wise max/min with one operand 0 */
25687 TCGv_i32 t0 = tcg_temp_new();
25688 TCGv_i32 t1 = tcg_const_i32(0);
25689 int32_t i;
25690
25691 /* the leftmost byte (byte 3) first */
25692 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25693 if (opc == OPC_MXU_Q8MAX) {
25694 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25695 } else {
25696 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25697 }
25698
25699 /* bytes 2, 1, 0 */
25700 for (i = 2; i >= 0; i--) {
25701 /* extract the byte */
25702 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25703 /* move the byte to the leftmost position */
25704 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25705 /* t0 will be max/min of t0 and t1 */
25706 if (opc == OPC_MXU_Q8MAX) {
25707 tcg_gen_smax_i32(t0, t0, t1);
25708 } else {
25709 tcg_gen_smin_i32(t0, t0, t1);
25710 }
25711 /* return resulting byte to its original position */
25712 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25713 /* finaly update the destination */
25714 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25715 }
25716
25717 tcg_temp_free(t1);
25718 tcg_temp_free(t0);
25719 } else if (unlikely(XRb == XRc)) {
25720 /* both operands same -> just set destination to one of them */
25721 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25722 } else {
25723 /* the most general case */
25724 TCGv_i32 t0 = tcg_temp_new();
25725 TCGv_i32 t1 = tcg_temp_new();
25726 int32_t i;
25727
25728 /* the leftmost bytes (bytes 3) first */
25729 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25730 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25731 if (opc == OPC_MXU_Q8MAX) {
25732 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25733 } else {
25734 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25735 }
25736
25737 /* bytes 2, 1, 0 */
25738 for (i = 2; i >= 0; i--) {
25739 /* extract corresponding bytes */
25740 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25741 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25742 /* move the bytes to the leftmost position */
25743 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25744 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25745 /* t0 will be max/min of t0 and t1 */
25746 if (opc == OPC_MXU_Q8MAX) {
25747 tcg_gen_smax_i32(t0, t0, t1);
25748 } else {
25749 tcg_gen_smin_i32(t0, t0, t1);
25750 }
25751 /* return resulting byte to its original position */
25752 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25753 /* finaly update the destination */
25754 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25755 }
25756
25757 tcg_temp_free(t1);
25758 tcg_temp_free(t0);
25759 }
25760}
25761
25762
79f5fee7
AM
25763/*
25764 * MXU instruction category: align
25765 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25766 *
25767 * S32ALN S32ALNI
25768 */
25769
25770/*
25771 * S32ALNI XRc, XRb, XRa, optn3
25772 * Arrange bytes from XRb and XRc according to one of five sets of
25773 * rules determined by optn3, and place the result in XRa.
25774 *
25775 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25776 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25777 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25778 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25779 *
25780 */
25781static void gen_mxu_S32ALNI(DisasContext *ctx)
25782{
25783 uint32_t optn3, pad, XRc, XRb, XRa;
25784
25785 optn3 = extract32(ctx->opcode, 23, 3);
25786 pad = extract32(ctx->opcode, 21, 2);
25787 XRc = extract32(ctx->opcode, 14, 4);
25788 XRb = extract32(ctx->opcode, 10, 4);
25789 XRa = extract32(ctx->opcode, 6, 4);
25790
25791 if (unlikely(pad != 0)) {
25792 /* opcode padding incorrect -> do nothing */
25793 } else if (unlikely(XRa == 0)) {
25794 /* destination is zero register -> do nothing */
25795 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25796 /* both operands zero registers -> just set destination to all 0s */
25797 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25798 } else if (unlikely(XRb == 0)) {
25799 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25800 switch (optn3) {
25801 case MXU_OPTN3_PTN0:
25802 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25803 break;
25804 case MXU_OPTN3_PTN1:
25805 case MXU_OPTN3_PTN2:
25806 case MXU_OPTN3_PTN3:
25807 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25808 8 * (4 - optn3));
25809 break;
25810 case MXU_OPTN3_PTN4:
25811 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25812 break;
25813 }
25814 } else if (unlikely(XRc == 0)) {
25815 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25816 switch (optn3) {
25817 case MXU_OPTN3_PTN0:
25818 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25819 break;
25820 case MXU_OPTN3_PTN1:
25821 case MXU_OPTN3_PTN2:
25822 case MXU_OPTN3_PTN3:
25823 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25824 break;
25825 case MXU_OPTN3_PTN4:
25826 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25827 break;
25828 }
25829 } else if (unlikely(XRb == XRc)) {
25830 /* both operands same -> just rotation or moving from any of them */
25831 switch (optn3) {
25832 case MXU_OPTN3_PTN0:
25833 case MXU_OPTN3_PTN4:
25834 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25835 break;
25836 case MXU_OPTN3_PTN1:
25837 case MXU_OPTN3_PTN2:
25838 case MXU_OPTN3_PTN3:
25839 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25840 break;
25841 }
25842 } else {
25843 /* the most general case */
25844 switch (optn3) {
25845 case MXU_OPTN3_PTN0:
25846 {
25847 /* */
25848 /* XRb XRc */
25849 /* +---------------+ */
25850 /* | A B C D | E F G H */
25851 /* +-------+-------+ */
25852 /* | */
25853 /* XRa */
25854 /* */
25855
25856 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25857 }
25858 break;
25859 case MXU_OPTN3_PTN1:
25860 {
25861 /* */
25862 /* XRb XRc */
25863 /* +-------------------+ */
25864 /* A | B C D E | F G H */
25865 /* +---------+---------+ */
25866 /* | */
25867 /* XRa */
25868 /* */
25869
25870 TCGv_i32 t0 = tcg_temp_new();
25871 TCGv_i32 t1 = tcg_temp_new();
25872
25873 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25874 tcg_gen_shli_i32(t0, t0, 8);
25875
25876 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25877 tcg_gen_shri_i32(t1, t1, 24);
25878
25879 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25880
25881 tcg_temp_free(t1);
25882 tcg_temp_free(t0);
25883 }
25884 break;
25885 case MXU_OPTN3_PTN2:
25886 {
25887 /* */
25888 /* XRb XRc */
25889 /* +-------------------+ */
25890 /* A B | C D E F | G H */
25891 /* +---------+---------+ */
25892 /* | */
25893 /* XRa */
25894 /* */
25895
25896 TCGv_i32 t0 = tcg_temp_new();
25897 TCGv_i32 t1 = tcg_temp_new();
25898
25899 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25900 tcg_gen_shli_i32(t0, t0, 16);
25901
25902 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25903 tcg_gen_shri_i32(t1, t1, 16);
25904
25905 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25906
25907 tcg_temp_free(t1);
25908 tcg_temp_free(t0);
25909 }
25910 break;
25911 case MXU_OPTN3_PTN3:
25912 {
25913 /* */
25914 /* XRb XRc */
25915 /* +-------------------+ */
25916 /* A B C | D E F G | H */
25917 /* +---------+---------+ */
25918 /* | */
25919 /* XRa */
25920 /* */
25921
25922 TCGv_i32 t0 = tcg_temp_new();
25923 TCGv_i32 t1 = tcg_temp_new();
25924
25925 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25926 tcg_gen_shli_i32(t0, t0, 24);
25927
25928 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25929 tcg_gen_shri_i32(t1, t1, 8);
25930
25931 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25932
25933 tcg_temp_free(t1);
25934 tcg_temp_free(t0);
25935 }
25936 break;
25937 case MXU_OPTN3_PTN4:
25938 {
25939 /* */
25940 /* XRb XRc */
25941 /* +---------------+ */
25942 /* A B C D | E F G H | */
25943 /* +-------+-------+ */
25944 /* | */
25945 /* XRa */
25946 /* */
25947
25948 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25949 }
25950 break;
25951 }
25952 }
25953}
25954
25955
96992d1a
CJ
25956/*
25957 * Decoding engine for MXU
25958 * =======================
25959 */
25960
03f40088
AM
25961/*
25962 *
25963 * Decode MXU pool00
25964 *
25965 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25966 * +-----------+---------+-----+-------+-------+-------+-----------+
25967 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25968 * +-----------+---------+-----+-------+-------+-------+-----------+
25969 *
25970 */
25971static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25972{
25973 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25974
25975 switch (opcode) {
25976 case OPC_MXU_S32MAX:
03f40088 25977 case OPC_MXU_S32MIN:
bb84cbf3 25978 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
25979 break;
25980 case OPC_MXU_D16MAX:
03f40088 25981 case OPC_MXU_D16MIN:
bb84cbf3 25982 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
25983 break;
25984 case OPC_MXU_Q8MAX:
03f40088 25985 case OPC_MXU_Q8MIN:
bb84cbf3 25986 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
25987 break;
25988 case OPC_MXU_Q8SLT:
25989 /* TODO: Implement emulation of Q8SLT instruction. */
25990 MIPS_INVAL("OPC_MXU_Q8SLT");
25991 generate_exception_end(ctx, EXCP_RI);
25992 break;
25993 case OPC_MXU_Q8SLTU:
25994 /* TODO: Implement emulation of Q8SLTU instruction. */
25995 MIPS_INVAL("OPC_MXU_Q8SLTU");
25996 generate_exception_end(ctx, EXCP_RI);
25997 break;
25998 default:
25999 MIPS_INVAL("decode_opc_mxu");
26000 generate_exception_end(ctx, EXCP_RI);
26001 break;
26002 }
26003}
26004
26005/*
26006 *
26007 * Decode MXU pool01
26008 *
26009 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26010 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26011 * +-----------+---------+-----+-------+-------+-------+-----------+
26012 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26013 * +-----------+---------+-----+-------+-------+-------+-----------+
26014 *
26015 * Q8ADD:
26016 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26017 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26018 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26019 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26020 *
26021 */
26022static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26023{
26024 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26025
26026 switch (opcode) {
26027 case OPC_MXU_S32SLT:
26028 /* TODO: Implement emulation of S32SLT instruction. */
26029 MIPS_INVAL("OPC_MXU_S32SLT");
26030 generate_exception_end(ctx, EXCP_RI);
26031 break;
26032 case OPC_MXU_D16SLT:
26033 /* TODO: Implement emulation of D16SLT instruction. */
26034 MIPS_INVAL("OPC_MXU_D16SLT");
26035 generate_exception_end(ctx, EXCP_RI);
26036 break;
26037 case OPC_MXU_D16AVG:
26038 /* TODO: Implement emulation of D16AVG instruction. */
26039 MIPS_INVAL("OPC_MXU_D16AVG");
26040 generate_exception_end(ctx, EXCP_RI);
26041 break;
26042 case OPC_MXU_D16AVGR:
26043 /* TODO: Implement emulation of D16AVGR instruction. */
26044 MIPS_INVAL("OPC_MXU_D16AVGR");
26045 generate_exception_end(ctx, EXCP_RI);
26046 break;
26047 case OPC_MXU_Q8AVG:
26048 /* TODO: Implement emulation of Q8AVG instruction. */
26049 MIPS_INVAL("OPC_MXU_Q8AVG");
26050 generate_exception_end(ctx, EXCP_RI);
26051 break;
26052 case OPC_MXU_Q8AVGR:
26053 /* TODO: Implement emulation of Q8AVGR instruction. */
26054 MIPS_INVAL("OPC_MXU_Q8AVGR");
26055 generate_exception_end(ctx, EXCP_RI);
26056 break;
26057 case OPC_MXU_Q8ADD:
26058 /* TODO: Implement emulation of Q8ADD instruction. */
26059 MIPS_INVAL("OPC_MXU_Q8ADD");
26060 generate_exception_end(ctx, EXCP_RI);
26061 break;
26062 default:
26063 MIPS_INVAL("decode_opc_mxu");
26064 generate_exception_end(ctx, EXCP_RI);
26065 break;
26066 }
26067}
26068
26069/*
26070 *
26071 * Decode MXU pool02
26072 *
26073 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26074 * +-----------+---------+-----+-------+-------+-------+-----------+
26075 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26076 * +-----------+---------+-----+-------+-------+-------+-----------+
26077 *
26078 */
26079static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26080{
26081 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26082
26083 switch (opcode) {
26084 case OPC_MXU_S32CPS:
26085 /* TODO: Implement emulation of S32CPS instruction. */
26086 MIPS_INVAL("OPC_MXU_S32CPS");
26087 generate_exception_end(ctx, EXCP_RI);
26088 break;
26089 case OPC_MXU_D16CPS:
26090 /* TODO: Implement emulation of D16CPS instruction. */
26091 MIPS_INVAL("OPC_MXU_D16CPS");
26092 generate_exception_end(ctx, EXCP_RI);
26093 break;
26094 case OPC_MXU_Q8ABD:
26095 /* TODO: Implement emulation of Q8ABD instruction. */
26096 MIPS_INVAL("OPC_MXU_Q8ABD");
26097 generate_exception_end(ctx, EXCP_RI);
26098 break;
26099 case OPC_MXU_Q16SAT:
26100 /* TODO: Implement emulation of Q16SAT instruction. */
26101 MIPS_INVAL("OPC_MXU_Q16SAT");
26102 generate_exception_end(ctx, EXCP_RI);
26103 break;
26104 default:
26105 MIPS_INVAL("decode_opc_mxu");
26106 generate_exception_end(ctx, EXCP_RI);
26107 break;
26108 }
26109}
26110
26111/*
26112 *
26113 * Decode MXU pool03
26114 *
26115 * D16MULF:
26116 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26117 * +-----------+---+---+-------+-------+-------+-------+-----------+
26118 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26119 * +-----------+---+---+-------+-------+-------+-------+-----------+
26120 *
26121 * D16MULE:
26122 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26123 * +-----------+---+---+-------+-------+-------+-------+-----------+
26124 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26125 * +-----------+---+---+-------+-------+-------+-------+-----------+
26126 *
26127 */
26128static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26129{
26130 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26131
26132 switch (opcode) {
26133 case OPC_MXU_D16MULF:
26134 /* TODO: Implement emulation of D16MULF instruction. */
26135 MIPS_INVAL("OPC_MXU_D16MULF");
26136 generate_exception_end(ctx, EXCP_RI);
26137 break;
26138 case OPC_MXU_D16MULE:
26139 /* TODO: Implement emulation of D16MULE instruction. */
26140 MIPS_INVAL("OPC_MXU_D16MULE");
26141 generate_exception_end(ctx, EXCP_RI);
26142 break;
26143 default:
26144 MIPS_INVAL("decode_opc_mxu");
26145 generate_exception_end(ctx, EXCP_RI);
26146 break;
26147 }
26148}
26149
26150/*
26151 *
26152 * Decode MXU pool04
26153 *
26154 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26155 * +-----------+---------+-+-------------------+-------+-----------+
26156 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26157 * +-----------+---------+-+-------------------+-------+-----------+
26158 *
26159 */
26160static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26161{
26162 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26163
26164 switch (opcode) {
26165 case OPC_MXU_S32LDD:
03f40088 26166 case OPC_MXU_S32LDDR:
4ca83721 26167 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
26168 break;
26169 default:
26170 MIPS_INVAL("decode_opc_mxu");
26171 generate_exception_end(ctx, EXCP_RI);
26172 break;
26173 }
26174}
26175
26176/*
26177 *
26178 * Decode MXU pool05
26179 *
26180 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26181 * +-----------+---------+-+-------------------+-------+-----------+
26182 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26183 * +-----------+---------+-+-------------------+-------+-----------+
26184 *
26185 */
26186static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26187{
26188 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26189
26190 switch (opcode) {
26191 case OPC_MXU_S32STD:
26192 /* TODO: Implement emulation of S32STD instruction. */
26193 MIPS_INVAL("OPC_MXU_S32STD");
26194 generate_exception_end(ctx, EXCP_RI);
26195 break;
26196 case OPC_MXU_S32STDR:
26197 /* TODO: Implement emulation of S32STDR instruction. */
26198 MIPS_INVAL("OPC_MXU_S32STDR");
26199 generate_exception_end(ctx, EXCP_RI);
26200 break;
26201 default:
26202 MIPS_INVAL("decode_opc_mxu");
26203 generate_exception_end(ctx, EXCP_RI);
26204 break;
26205 }
26206}
26207
26208/*
26209 *
26210 * Decode MXU pool06
26211 *
26212 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26213 * +-----------+---------+---------+---+-------+-------+-----------+
26214 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26215 * +-----------+---------+---------+---+-------+-------+-----------+
26216 *
26217 */
26218static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26219{
26220 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26221
26222 switch (opcode) {
26223 case OPC_MXU_S32LDDV:
26224 /* TODO: Implement emulation of S32LDDV instruction. */
26225 MIPS_INVAL("OPC_MXU_S32LDDV");
26226 generate_exception_end(ctx, EXCP_RI);
26227 break;
26228 case OPC_MXU_S32LDDVR:
26229 /* TODO: Implement emulation of S32LDDVR instruction. */
26230 MIPS_INVAL("OPC_MXU_S32LDDVR");
26231 generate_exception_end(ctx, EXCP_RI);
26232 break;
26233 default:
26234 MIPS_INVAL("decode_opc_mxu");
26235 generate_exception_end(ctx, EXCP_RI);
26236 break;
26237 }
26238}
26239
26240/*
26241 *
26242 * Decode MXU pool07
26243 *
26244 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26245 * +-----------+---------+---------+---+-------+-------+-----------+
26246 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26247 * +-----------+---------+---------+---+-------+-------+-----------+
26248 *
26249 */
26250static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26251{
26252 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26253
26254 switch (opcode) {
26255 case OPC_MXU_S32STDV:
26256 /* TODO: Implement emulation of S32TDV instruction. */
26257 MIPS_INVAL("OPC_MXU_S32TDV");
26258 generate_exception_end(ctx, EXCP_RI);
26259 break;
26260 case OPC_MXU_S32STDVR:
26261 /* TODO: Implement emulation of S32TDVR instruction. */
26262 MIPS_INVAL("OPC_MXU_S32TDVR");
26263 generate_exception_end(ctx, EXCP_RI);
26264 break;
26265 default:
26266 MIPS_INVAL("decode_opc_mxu");
26267 generate_exception_end(ctx, EXCP_RI);
26268 break;
26269 }
26270}
26271
26272/*
26273 *
26274 * Decode MXU pool08
26275 *
26276 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26277 * +-----------+---------+-+-------------------+-------+-----------+
26278 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26279 * +-----------+---------+-+-------------------+-------+-----------+
26280 *
7480515f 26281 */
03f40088
AM
26282static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26283{
26284 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26285
26286 switch (opcode) {
26287 case OPC_MXU_S32LDI:
26288 /* TODO: Implement emulation of S32LDI instruction. */
26289 MIPS_INVAL("OPC_MXU_S32LDI");
26290 generate_exception_end(ctx, EXCP_RI);
26291 break;
26292 case OPC_MXU_S32LDIR:
26293 /* TODO: Implement emulation of S32LDIR instruction. */
26294 MIPS_INVAL("OPC_MXU_S32LDIR");
26295 generate_exception_end(ctx, EXCP_RI);
26296 break;
26297 default:
26298 MIPS_INVAL("decode_opc_mxu");
26299 generate_exception_end(ctx, EXCP_RI);
26300 break;
26301 }
26302}
26303
26304/*
26305 *
26306 * Decode MXU pool09
26307 *
26308 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26309 * +-----------+---------+-+-------------------+-------+-----------+
26310 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26311 * +-----------+---------+-+-------------------+-------+-----------+
26312 *
26313 */
26314static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26315{
26316 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26317
26318 switch (opcode) {
26319 case OPC_MXU_S32SDI:
26320 /* TODO: Implement emulation of S32SDI instruction. */
26321 MIPS_INVAL("OPC_MXU_S32SDI");
26322 generate_exception_end(ctx, EXCP_RI);
26323 break;
26324 case OPC_MXU_S32SDIR:
26325 /* TODO: Implement emulation of S32SDIR instruction. */
26326 MIPS_INVAL("OPC_MXU_S32SDIR");
26327 generate_exception_end(ctx, EXCP_RI);
26328 break;
26329 default:
26330 MIPS_INVAL("decode_opc_mxu");
26331 generate_exception_end(ctx, EXCP_RI);
26332 break;
26333 }
26334}
26335
26336/*
26337 *
26338 * Decode MXU pool10
26339 *
26340 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26341 * +-----------+---------+---------+---+-------+-------+-----------+
26342 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26343 * +-----------+---------+---------+---+-------+-------+-----------+
26344 *
26345 */
26346static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26347{
26348 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26349
26350 switch (opcode) {
26351 case OPC_MXU_S32LDIV:
26352 /* TODO: Implement emulation of S32LDIV instruction. */
26353 MIPS_INVAL("OPC_MXU_S32LDIV");
26354 generate_exception_end(ctx, EXCP_RI);
26355 break;
26356 case OPC_MXU_S32LDIVR:
26357 /* TODO: Implement emulation of S32LDIVR instruction. */
26358 MIPS_INVAL("OPC_MXU_S32LDIVR");
26359 generate_exception_end(ctx, EXCP_RI);
26360 break;
26361 default:
26362 MIPS_INVAL("decode_opc_mxu");
26363 generate_exception_end(ctx, EXCP_RI);
26364 break;
26365 }
26366}
26367
26368/*
26369 *
26370 * Decode MXU pool11
26371 *
26372 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26373 * +-----------+---------+---------+---+-------+-------+-----------+
26374 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26375 * +-----------+---------+---------+---+-------+-------+-----------+
26376 *
26377 */
26378static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26379{
26380 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26381
26382 switch (opcode) {
26383 case OPC_MXU_S32SDIV:
26384 /* TODO: Implement emulation of S32SDIV instruction. */
26385 MIPS_INVAL("OPC_MXU_S32SDIV");
26386 generate_exception_end(ctx, EXCP_RI);
26387 break;
26388 case OPC_MXU_S32SDIVR:
26389 /* TODO: Implement emulation of S32SDIVR instruction. */
26390 MIPS_INVAL("OPC_MXU_S32SDIVR");
26391 generate_exception_end(ctx, EXCP_RI);
26392 break;
26393 default:
26394 MIPS_INVAL("decode_opc_mxu");
26395 generate_exception_end(ctx, EXCP_RI);
26396 break;
26397 }
26398}
26399
26400/*
26401 *
26402 * Decode MXU pool12
26403 *
26404 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26405 * +-----------+---+---+-------+-------+-------+-------+-----------+
26406 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26407 * +-----------+---+---+-------+-------+-------+-------+-----------+
26408 *
26409 */
26410static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26411{
26412 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26413
26414 switch (opcode) {
26415 case OPC_MXU_D32ACC:
26416 /* TODO: Implement emulation of D32ACC instruction. */
26417 MIPS_INVAL("OPC_MXU_D32ACC");
26418 generate_exception_end(ctx, EXCP_RI);
26419 break;
26420 case OPC_MXU_D32ACCM:
26421 /* TODO: Implement emulation of D32ACCM instruction. */
26422 MIPS_INVAL("OPC_MXU_D32ACCM");
26423 generate_exception_end(ctx, EXCP_RI);
26424 break;
26425 case OPC_MXU_D32ASUM:
26426 /* TODO: Implement emulation of D32ASUM instruction. */
26427 MIPS_INVAL("OPC_MXU_D32ASUM");
26428 generate_exception_end(ctx, EXCP_RI);
26429 break;
26430 default:
26431 MIPS_INVAL("decode_opc_mxu");
26432 generate_exception_end(ctx, EXCP_RI);
26433 break;
26434 }
26435}
26436
26437/*
26438 *
26439 * Decode MXU pool13
26440 *
26441 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26442 * +-----------+---+---+-------+-------+-------+-------+-----------+
26443 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26444 * +-----------+---+---+-------+-------+-------+-------+-----------+
26445 *
26446 */
26447static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26448{
26449 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26450
26451 switch (opcode) {
26452 case OPC_MXU_Q16ACC:
26453 /* TODO: Implement emulation of Q16ACC instruction. */
26454 MIPS_INVAL("OPC_MXU_Q16ACC");
26455 generate_exception_end(ctx, EXCP_RI);
26456 break;
26457 case OPC_MXU_Q16ACCM:
26458 /* TODO: Implement emulation of Q16ACCM instruction. */
26459 MIPS_INVAL("OPC_MXU_Q16ACCM");
26460 generate_exception_end(ctx, EXCP_RI);
26461 break;
26462 case OPC_MXU_Q16ASUM:
26463 /* TODO: Implement emulation of Q16ASUM instruction. */
26464 MIPS_INVAL("OPC_MXU_Q16ASUM");
26465 generate_exception_end(ctx, EXCP_RI);
26466 break;
26467 default:
26468 MIPS_INVAL("decode_opc_mxu");
26469 generate_exception_end(ctx, EXCP_RI);
26470 break;
26471 }
26472}
26473
26474/*
26475 *
26476 * Decode MXU pool14
26477 *
26478 * Q8ADDE, Q8ACCE:
26479 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26480 * +-----------+---+---+-------+-------+-------+-------+-----------+
26481 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26482 * +-----------+---+---+-------+-------+-------+-------+-----------+
26483 *
26484 * D8SUM, D8SUMC:
26485 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26486 * +-----------+---+---+-------+-------+-------+-------+-----------+
26487 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26488 * +-----------+---+---+-------+-------+-------+-------+-----------+
26489 *
26490 */
26491static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26492{
26493 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26494
26495 switch (opcode) {
26496 case OPC_MXU_Q8ADDE:
26497 /* TODO: Implement emulation of Q8ADDE instruction. */
26498 MIPS_INVAL("OPC_MXU_Q8ADDE");
26499 generate_exception_end(ctx, EXCP_RI);
26500 break;
26501 case OPC_MXU_D8SUM:
26502 /* TODO: Implement emulation of D8SUM instruction. */
26503 MIPS_INVAL("OPC_MXU_D8SUM");
26504 generate_exception_end(ctx, EXCP_RI);
26505 break;
26506 case OPC_MXU_D8SUMC:
26507 /* TODO: Implement emulation of D8SUMC instruction. */
26508 MIPS_INVAL("OPC_MXU_D8SUMC");
26509 generate_exception_end(ctx, EXCP_RI);
26510 break;
26511 default:
26512 MIPS_INVAL("decode_opc_mxu");
26513 generate_exception_end(ctx, EXCP_RI);
26514 break;
26515 }
26516}
26517
26518/*
26519 *
26520 * Decode MXU pool15
26521 *
26522 * S32MUL, S32MULU, S32EXTRV:
26523 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26524 * +-----------+---------+---------+---+-------+-------+-----------+
26525 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26526 * +-----------+---------+---------+---+-------+-------+-----------+
26527 *
26528 * S32EXTR:
26529 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26530 * +-----------+---------+---------+---+-------+-------+-----------+
26531 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26532 * +-----------+---------+---------+---+-------+-------+-----------+
26533 *
26534 */
26535static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26536{
26537 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26538
26539 switch (opcode) {
26540 case OPC_MXU_S32MUL:
26541 /* TODO: Implement emulation of S32MUL instruction. */
26542 MIPS_INVAL("OPC_MXU_S32MUL");
26543 generate_exception_end(ctx, EXCP_RI);
26544 break;
26545 case OPC_MXU_S32MULU:
26546 /* TODO: Implement emulation of S32MULU instruction. */
26547 MIPS_INVAL("OPC_MXU_S32MULU");
26548 generate_exception_end(ctx, EXCP_RI);
26549 break;
26550 case OPC_MXU_S32EXTR:
26551 /* TODO: Implement emulation of S32EXTR instruction. */
26552 MIPS_INVAL("OPC_MXU_S32EXTR");
26553 generate_exception_end(ctx, EXCP_RI);
26554 break;
26555 case OPC_MXU_S32EXTRV:
26556 /* TODO: Implement emulation of S32EXTRV instruction. */
26557 MIPS_INVAL("OPC_MXU_S32EXTRV");
26558 generate_exception_end(ctx, EXCP_RI);
26559 break;
26560 default:
26561 MIPS_INVAL("decode_opc_mxu");
26562 generate_exception_end(ctx, EXCP_RI);
26563 break;
26564 }
26565}
26566
26567/*
26568 *
26569 * Decode MXU pool16
26570 *
26571 * D32SARW:
26572 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26573 * +-----------+---------+-----+-------+-------+-------+-----------+
26574 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26575 * +-----------+---------+-----+-------+-------+-------+-----------+
26576 *
26577 * S32ALN:
26578 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26579 * +-----------+---------+-----+-------+-------+-------+-----------+
26580 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26581 * +-----------+---------+-----+-------+-------+-------+-----------+
26582 *
26583 * S32ALNI:
26584 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26585 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26586 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26587 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26588 *
03f40088
AM
26589 * S32LUI:
26590 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26591 * +-----------+-----+---+-----+-------+---------------+-----------+
26592 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26593 * +-----------+-----+---+-----+-------+---------------+-----------+
26594 *
b621f018
AM
26595 * S32NOR, S32AND, S32OR, S32XOR:
26596 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26597 * +-----------+---------+-----+-------+-------+-------+-----------+
26598 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26599 * +-----------+---------+-----+-------+-------+-------+-----------+
26600 *
03f40088
AM
26601 */
26602static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26603{
26604 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26605
26606 switch (opcode) {
26607 case OPC_MXU_D32SARW:
26608 /* TODO: Implement emulation of D32SARW instruction. */
26609 MIPS_INVAL("OPC_MXU_D32SARW");
26610 generate_exception_end(ctx, EXCP_RI);
26611 break;
26612 case OPC_MXU_S32ALN:
26613 /* TODO: Implement emulation of S32ALN instruction. */
26614 MIPS_INVAL("OPC_MXU_S32ALN");
26615 generate_exception_end(ctx, EXCP_RI);
26616 break;
26617 case OPC_MXU_S32ALNI:
79f5fee7 26618 gen_mxu_S32ALNI(ctx);
03f40088 26619 break;
b621f018
AM
26620 case OPC_MXU_S32LUI:
26621 /* TODO: Implement emulation of S32LUI instruction. */
26622 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
26623 generate_exception_end(ctx, EXCP_RI);
26624 break;
b621f018
AM
26625 case OPC_MXU_S32NOR:
26626 gen_mxu_S32NOR(ctx);
26627 break;
03f40088 26628 case OPC_MXU_S32AND:
b621f018 26629 gen_mxu_S32AND(ctx);
03f40088
AM
26630 break;
26631 case OPC_MXU_S32OR:
b621f018 26632 gen_mxu_S32OR(ctx);
03f40088
AM
26633 break;
26634 case OPC_MXU_S32XOR:
b621f018 26635 gen_mxu_S32XOR(ctx);
03f40088
AM
26636 break;
26637 default:
26638 MIPS_INVAL("decode_opc_mxu");
26639 generate_exception_end(ctx, EXCP_RI);
26640 break;
26641 }
26642}
26643
26644/*
26645 *
26646 * Decode MXU pool17
26647 *
26648 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
c233bf07
AM
26649 * +-----------+---------+---------+---+---------+-----+-----------+
26650 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26651 * +-----------+---------+---------+---+---------+-----+-----------+
26652 *
26653 */
26654static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26655{
26656 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26657
26658 switch (opcode) {
26659 case OPC_MXU_LXW:
26660 /* TODO: Implement emulation of LXW instruction. */
26661 MIPS_INVAL("OPC_MXU_LXW");
26662 generate_exception_end(ctx, EXCP_RI);
26663 break;
26664 case OPC_MXU_LXH:
26665 /* TODO: Implement emulation of LXH instruction. */
26666 MIPS_INVAL("OPC_MXU_LXH");
26667 generate_exception_end(ctx, EXCP_RI);
26668 break;
26669 case OPC_MXU_LXHU:
26670 /* TODO: Implement emulation of LXHU instruction. */
26671 MIPS_INVAL("OPC_MXU_LXHU");
26672 generate_exception_end(ctx, EXCP_RI);
26673 break;
26674 case OPC_MXU_LXB:
26675 /* TODO: Implement emulation of LXB instruction. */
26676 MIPS_INVAL("OPC_MXU_LXB");
26677 generate_exception_end(ctx, EXCP_RI);
26678 break;
26679 case OPC_MXU_LXBU:
26680 /* TODO: Implement emulation of LXBU instruction. */
26681 MIPS_INVAL("OPC_MXU_LXBU");
26682 generate_exception_end(ctx, EXCP_RI);
26683 break;
26684 default:
26685 MIPS_INVAL("decode_opc_mxu");
26686 generate_exception_end(ctx, EXCP_RI);
26687 break;
26688 }
26689}
26690/*
26691 *
26692 * Decode MXU pool18
26693 *
26694 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
03f40088 26695 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26696 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
26697 * +-----------+---------+-----+-------+-------+-------+-----------+
26698 *
26699 */
c233bf07 26700static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26701{
26702 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26703
26704 switch (opcode) {
26705 case OPC_MXU_D32SLLV:
26706 /* TODO: Implement emulation of D32SLLV instruction. */
26707 MIPS_INVAL("OPC_MXU_D32SLLV");
26708 generate_exception_end(ctx, EXCP_RI);
26709 break;
26710 case OPC_MXU_D32SLRV:
26711 /* TODO: Implement emulation of D32SLRV instruction. */
26712 MIPS_INVAL("OPC_MXU_D32SLRV");
26713 generate_exception_end(ctx, EXCP_RI);
26714 break;
26715 case OPC_MXU_D32SARV:
26716 /* TODO: Implement emulation of D32SARV instruction. */
26717 MIPS_INVAL("OPC_MXU_D32SARV");
26718 generate_exception_end(ctx, EXCP_RI);
26719 break;
26720 case OPC_MXU_Q16SLLV:
26721 /* TODO: Implement emulation of Q16SLLV instruction. */
26722 MIPS_INVAL("OPC_MXU_Q16SLLV");
26723 generate_exception_end(ctx, EXCP_RI);
26724 break;
26725 case OPC_MXU_Q16SLRV:
26726 /* TODO: Implement emulation of Q16SLRV instruction. */
26727 MIPS_INVAL("OPC_MXU_Q16SLRV");
26728 generate_exception_end(ctx, EXCP_RI);
26729 break;
26730 case OPC_MXU_Q16SARV:
26731 /* TODO: Implement emulation of Q16SARV instruction. */
26732 MIPS_INVAL("OPC_MXU_Q16SARV");
26733 generate_exception_end(ctx, EXCP_RI);
26734 break;
26735 default:
26736 MIPS_INVAL("decode_opc_mxu");
26737 generate_exception_end(ctx, EXCP_RI);
26738 break;
26739 }
26740}
26741
26742/*
26743 *
c233bf07 26744 * Decode MXU pool19
03f40088
AM
26745 *
26746 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26747 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26748 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
26749 * +-----------+---+---+-------+-------+-------+-------+-----------+
26750 *
26751 */
c233bf07 26752static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26753{
26754 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26755
26756 switch (opcode) {
26757 case OPC_MXU_Q8MUL:
03f40088 26758 case OPC_MXU_Q8MULSU:
a9a4181b 26759 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
26760 break;
26761 default:
26762 MIPS_INVAL("decode_opc_mxu");
26763 generate_exception_end(ctx, EXCP_RI);
26764 break;
26765 }
26766}
26767
26768/*
26769 *
c233bf07 26770 * Decode MXU pool20
03f40088
AM
26771 *
26772 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26773 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26774 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
26775 * +-----------+---------+-----+-------+-------+-------+-----------+
26776 *
26777 */
c233bf07 26778static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26779{
26780 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26781
26782 switch (opcode) {
26783 case OPC_MXU_Q8MOVZ:
26784 /* TODO: Implement emulation of Q8MOVZ instruction. */
26785 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26786 generate_exception_end(ctx, EXCP_RI);
26787 break;
26788 case OPC_MXU_Q8MOVN:
26789 /* TODO: Implement emulation of Q8MOVN instruction. */
26790 MIPS_INVAL("OPC_MXU_Q8MOVN");
26791 generate_exception_end(ctx, EXCP_RI);
26792 break;
26793 case OPC_MXU_D16MOVZ:
26794 /* TODO: Implement emulation of D16MOVZ instruction. */
26795 MIPS_INVAL("OPC_MXU_D16MOVZ");
26796 generate_exception_end(ctx, EXCP_RI);
26797 break;
26798 case OPC_MXU_D16MOVN:
26799 /* TODO: Implement emulation of D16MOVN instruction. */
26800 MIPS_INVAL("OPC_MXU_D16MOVN");
26801 generate_exception_end(ctx, EXCP_RI);
26802 break;
26803 case OPC_MXU_S32MOVZ:
26804 /* TODO: Implement emulation of S32MOVZ instruction. */
26805 MIPS_INVAL("OPC_MXU_S32MOVZ");
26806 generate_exception_end(ctx, EXCP_RI);
26807 break;
26808 case OPC_MXU_S32MOVN:
26809 /* TODO: Implement emulation of S32MOVN instruction. */
26810 MIPS_INVAL("OPC_MXU_S32MOVN");
26811 generate_exception_end(ctx, EXCP_RI);
26812 break;
26813 default:
26814 MIPS_INVAL("decode_opc_mxu");
26815 generate_exception_end(ctx, EXCP_RI);
26816 break;
26817 }
26818}
26819
26820/*
26821 *
c233bf07 26822 * Decode MXU pool21
03f40088
AM
26823 *
26824 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26825 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26826 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
26827 * +-----------+---+---+-------+-------+-------+-------+-----------+
26828 *
26829 */
c233bf07 26830static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26831{
26832 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26833
26834 switch (opcode) {
26835 case OPC_MXU_Q8MAC:
26836 /* TODO: Implement emulation of Q8MAC instruction. */
26837 MIPS_INVAL("OPC_MXU_Q8MAC");
26838 generate_exception_end(ctx, EXCP_RI);
26839 break;
26840 case OPC_MXU_Q8MACSU:
26841 /* TODO: Implement emulation of Q8MACSU instruction. */
26842 MIPS_INVAL("OPC_MXU_Q8MACSU");
26843 generate_exception_end(ctx, EXCP_RI);
26844 break;
26845 default:
26846 MIPS_INVAL("decode_opc_mxu");
26847 generate_exception_end(ctx, EXCP_RI);
26848 break;
26849 }
26850}
26851
26852
26853/*
26854 * Main MXU decoding function
26855 *
26856 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26857 * +-----------+---------------------------------------+-----------+
26858 * | SPECIAL2 | |x x x x x x|
26859 * +-----------+---------------------------------------+-----------+
26860 *
26861 */
0a348b9a
AM
26862static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26863{
11d56f61
CJ
26864 /*
26865 * TODO: Investigate necessity of including handling of
26866 * CLZ, CLO, SDBB in this function, as they belong to
26867 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26868 */
03f40088
AM
26869 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26870
87860df5
AM
26871 if (opcode == OPC__MXU_MUL) {
26872 uint32_t rs, rt, rd, op1;
26873
26874 rs = extract32(ctx->opcode, 21, 5);
26875 rt = extract32(ctx->opcode, 16, 5);
26876 rd = extract32(ctx->opcode, 11, 5);
26877 op1 = MASK_SPECIAL2(ctx->opcode);
26878
26879 gen_arith(ctx, op1, rd, rs, rt);
26880
26881 return;
26882 }
26883
26884 if (opcode == OPC_MXU_S32M2I) {
26885 gen_mxu_s32m2i(ctx);
26886 return;
26887 }
26888
26889 if (opcode == OPC_MXU_S32I2M) {
26890 gen_mxu_s32i2m(ctx);
26891 return;
26892 }
26893
e5bf8a08
AM
26894 {
26895 TCGv t_mxu_cr = tcg_temp_new();
26896 TCGLabel *l_exit = gen_new_label();
26897
26898 gen_load_mxu_cr(t_mxu_cr);
26899 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26900 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26901
26902 switch (opcode) {
26903 case OPC_MXU_S32MADD:
26904 /* TODO: Implement emulation of S32MADD instruction. */
26905 MIPS_INVAL("OPC_MXU_S32MADD");
26906 generate_exception_end(ctx, EXCP_RI);
26907 break;
26908 case OPC_MXU_S32MADDU:
26909 /* TODO: Implement emulation of S32MADDU instruction. */
26910 MIPS_INVAL("OPC_MXU_S32MADDU");
26911 generate_exception_end(ctx, EXCP_RI);
26912 break;
26913 case OPC_MXU__POOL00:
26914 decode_opc_mxu__pool00(env, ctx);
26915 break;
26916 case OPC_MXU_S32MSUB:
26917 /* TODO: Implement emulation of S32MSUB instruction. */
26918 MIPS_INVAL("OPC_MXU_S32MSUB");
26919 generate_exception_end(ctx, EXCP_RI);
26920 break;
26921 case OPC_MXU_S32MSUBU:
26922 /* TODO: Implement emulation of S32MSUBU instruction. */
26923 MIPS_INVAL("OPC_MXU_S32MSUBU");
26924 generate_exception_end(ctx, EXCP_RI);
26925 break;
26926 case OPC_MXU__POOL01:
26927 decode_opc_mxu__pool01(env, ctx);
26928 break;
26929 case OPC_MXU__POOL02:
26930 decode_opc_mxu__pool02(env, ctx);
26931 break;
26932 case OPC_MXU_D16MUL:
26933 gen_mxu_d16mul(ctx);
26934 break;
26935 case OPC_MXU__POOL03:
26936 decode_opc_mxu__pool03(env, ctx);
26937 break;
26938 case OPC_MXU_D16MAC:
26939 gen_mxu_d16mac(ctx);
26940 break;
26941 case OPC_MXU_D16MACF:
26942 /* TODO: Implement emulation of D16MACF instruction. */
26943 MIPS_INVAL("OPC_MXU_D16MACF");
26944 generate_exception_end(ctx, EXCP_RI);
26945 break;
26946 case OPC_MXU_D16MADL:
26947 /* TODO: Implement emulation of D16MADL instruction. */
26948 MIPS_INVAL("OPC_MXU_D16MADL");
26949 generate_exception_end(ctx, EXCP_RI);
26950 break;
26951 case OPC_MXU_S16MAD:
26952 /* TODO: Implement emulation of S16MAD instruction. */
26953 MIPS_INVAL("OPC_MXU_S16MAD");
26954 generate_exception_end(ctx, EXCP_RI);
26955 break;
26956 case OPC_MXU_Q16ADD:
26957 /* TODO: Implement emulation of Q16ADD instruction. */
26958 MIPS_INVAL("OPC_MXU_Q16ADD");
26959 generate_exception_end(ctx, EXCP_RI);
26960 break;
26961 case OPC_MXU_D16MACE:
26962 /* TODO: Implement emulation of D16MACE instruction. */
26963 MIPS_INVAL("OPC_MXU_D16MACE");
26964 generate_exception_end(ctx, EXCP_RI);
26965 break;
26966 case OPC_MXU__POOL04:
26967 decode_opc_mxu__pool04(env, ctx);
26968 break;
26969 case OPC_MXU__POOL05:
26970 decode_opc_mxu__pool05(env, ctx);
26971 break;
26972 case OPC_MXU__POOL06:
26973 decode_opc_mxu__pool06(env, ctx);
26974 break;
26975 case OPC_MXU__POOL07:
26976 decode_opc_mxu__pool07(env, ctx);
26977 break;
26978 case OPC_MXU__POOL08:
26979 decode_opc_mxu__pool08(env, ctx);
26980 break;
26981 case OPC_MXU__POOL09:
26982 decode_opc_mxu__pool09(env, ctx);
26983 break;
26984 case OPC_MXU__POOL10:
26985 decode_opc_mxu__pool10(env, ctx);
26986 break;
26987 case OPC_MXU__POOL11:
26988 decode_opc_mxu__pool11(env, ctx);
26989 break;
26990 case OPC_MXU_D32ADD:
26991 /* TODO: Implement emulation of D32ADD instruction. */
26992 MIPS_INVAL("OPC_MXU_D32ADD");
26993 generate_exception_end(ctx, EXCP_RI);
26994 break;
26995 case OPC_MXU__POOL12:
26996 decode_opc_mxu__pool12(env, ctx);
26997 break;
26998 case OPC_MXU__POOL13:
26999 decode_opc_mxu__pool13(env, ctx);
27000 break;
27001 case OPC_MXU__POOL14:
27002 decode_opc_mxu__pool14(env, ctx);
27003 break;
27004 case OPC_MXU_Q8ACCE:
27005 /* TODO: Implement emulation of Q8ACCE instruction. */
27006 MIPS_INVAL("OPC_MXU_Q8ACCE");
27007 generate_exception_end(ctx, EXCP_RI);
27008 break;
27009 case OPC_MXU_S8LDD:
27010 gen_mxu_s8ldd(ctx);
27011 break;
27012 case OPC_MXU_S8STD:
27013 /* TODO: Implement emulation of S8STD instruction. */
27014 MIPS_INVAL("OPC_MXU_S8STD");
27015 generate_exception_end(ctx, EXCP_RI);
27016 break;
27017 case OPC_MXU_S8LDI:
27018 /* TODO: Implement emulation of S8LDI instruction. */
27019 MIPS_INVAL("OPC_MXU_S8LDI");
27020 generate_exception_end(ctx, EXCP_RI);
27021 break;
27022 case OPC_MXU_S8SDI:
27023 /* TODO: Implement emulation of S8SDI instruction. */
27024 MIPS_INVAL("OPC_MXU_S8SDI");
27025 generate_exception_end(ctx, EXCP_RI);
27026 break;
27027 case OPC_MXU__POOL15:
27028 decode_opc_mxu__pool15(env, ctx);
27029 break;
27030 case OPC_MXU__POOL16:
27031 decode_opc_mxu__pool16(env, ctx);
27032 break;
c233bf07
AM
27033 case OPC_MXU__POOL17:
27034 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
27035 break;
27036 case OPC_MXU_S16LDD:
27037 /* TODO: Implement emulation of S16LDD instruction. */
27038 MIPS_INVAL("OPC_MXU_S16LDD");
27039 generate_exception_end(ctx, EXCP_RI);
27040 break;
27041 case OPC_MXU_S16STD:
27042 /* TODO: Implement emulation of S16STD instruction. */
27043 MIPS_INVAL("OPC_MXU_S16STD");
27044 generate_exception_end(ctx, EXCP_RI);
27045 break;
27046 case OPC_MXU_S16LDI:
27047 /* TODO: Implement emulation of S16LDI instruction. */
27048 MIPS_INVAL("OPC_MXU_S16LDI");
27049 generate_exception_end(ctx, EXCP_RI);
27050 break;
27051 case OPC_MXU_S16SDI:
27052 /* TODO: Implement emulation of S16SDI instruction. */
27053 MIPS_INVAL("OPC_MXU_S16SDI");
27054 generate_exception_end(ctx, EXCP_RI);
27055 break;
27056 case OPC_MXU_D32SLL:
27057 /* TODO: Implement emulation of D32SLL instruction. */
27058 MIPS_INVAL("OPC_MXU_D32SLL");
27059 generate_exception_end(ctx, EXCP_RI);
27060 break;
27061 case OPC_MXU_D32SLR:
27062 /* TODO: Implement emulation of D32SLR instruction. */
27063 MIPS_INVAL("OPC_MXU_D32SLR");
27064 generate_exception_end(ctx, EXCP_RI);
27065 break;
27066 case OPC_MXU_D32SARL:
27067 /* TODO: Implement emulation of D32SARL instruction. */
27068 MIPS_INVAL("OPC_MXU_D32SARL");
27069 generate_exception_end(ctx, EXCP_RI);
27070 break;
27071 case OPC_MXU_D32SAR:
27072 /* TODO: Implement emulation of D32SAR instruction. */
27073 MIPS_INVAL("OPC_MXU_D32SAR");
27074 generate_exception_end(ctx, EXCP_RI);
27075 break;
27076 case OPC_MXU_Q16SLL:
27077 /* TODO: Implement emulation of Q16SLL instruction. */
27078 MIPS_INVAL("OPC_MXU_Q16SLL");
27079 generate_exception_end(ctx, EXCP_RI);
27080 break;
27081 case OPC_MXU_Q16SLR:
27082 /* TODO: Implement emulation of Q16SLR instruction. */
27083 MIPS_INVAL("OPC_MXU_Q16SLR");
27084 generate_exception_end(ctx, EXCP_RI);
27085 break;
c233bf07
AM
27086 case OPC_MXU__POOL18:
27087 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
27088 break;
27089 case OPC_MXU_Q16SAR:
27090 /* TODO: Implement emulation of Q16SAR instruction. */
27091 MIPS_INVAL("OPC_MXU_Q16SAR");
27092 generate_exception_end(ctx, EXCP_RI);
27093 break;
e5bf8a08
AM
27094 case OPC_MXU__POOL19:
27095 decode_opc_mxu__pool19(env, ctx);
27096 break;
27097 case OPC_MXU__POOL20:
27098 decode_opc_mxu__pool20(env, ctx);
27099 break;
c233bf07
AM
27100 case OPC_MXU__POOL21:
27101 decode_opc_mxu__pool21(env, ctx);
27102 break;
e5bf8a08
AM
27103 case OPC_MXU_Q16SCOP:
27104 /* TODO: Implement emulation of Q16SCOP instruction. */
27105 MIPS_INVAL("OPC_MXU_Q16SCOP");
27106 generate_exception_end(ctx, EXCP_RI);
27107 break;
27108 case OPC_MXU_Q8MADL:
27109 /* TODO: Implement emulation of Q8MADL instruction. */
27110 MIPS_INVAL("OPC_MXU_Q8MADL");
27111 generate_exception_end(ctx, EXCP_RI);
27112 break;
27113 case OPC_MXU_S32SFL:
27114 /* TODO: Implement emulation of S32SFL instruction. */
27115 MIPS_INVAL("OPC_MXU_S32SFL");
27116 generate_exception_end(ctx, EXCP_RI);
27117 break;
27118 case OPC_MXU_Q8SAD:
27119 /* TODO: Implement emulation of Q8SAD instruction. */
27120 MIPS_INVAL("OPC_MXU_Q8SAD");
27121 generate_exception_end(ctx, EXCP_RI);
27122 break;
27123 default:
27124 MIPS_INVAL("decode_opc_mxu");
27125 generate_exception_end(ctx, EXCP_RI);
27126 }
27127
27128 gen_set_label(l_exit);
27129 tcg_temp_free(t_mxu_cr);
03f40088 27130 }
0a348b9a
AM
27131}
27132
b621f018
AM
27133#endif /* !defined(TARGET_MIPS64) */
27134
03f40088 27135
10dc65db 27136static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
27137{
27138 int rs, rt, rd;
27139 uint32_t op1;
6c5c1e20 27140
4267d3e6
LA
27141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27142
099e5b4d
LA
27143 rs = (ctx->opcode >> 21) & 0x1f;
27144 rt = (ctx->opcode >> 16) & 0x1f;
27145 rd = (ctx->opcode >> 11) & 0x1f;
27146
27147 op1 = MASK_SPECIAL2(ctx->opcode);
27148 switch (op1) {
c2e19f3c
AM
27149 case OPC_MADD: /* Multiply and add/sub */
27150 case OPC_MADDU:
27151 case OPC_MSUB:
27152 case OPC_MSUBU:
099e5b4d
LA
27153 check_insn(ctx, ISA_MIPS32);
27154 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27155 break;
27156 case OPC_MUL:
099e5b4d
LA
27157 gen_arith(ctx, op1, rd, rs, rt);
27158 break;
fac5a073
LA
27159 case OPC_DIV_G_2F:
27160 case OPC_DIVU_G_2F:
27161 case OPC_MULT_G_2F:
27162 case OPC_MULTU_G_2F:
27163 case OPC_MOD_G_2F:
27164 case OPC_MODU_G_2F:
8e2d5831 27165 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
fac5a073
LA
27166 gen_loongson_integer(ctx, op1, rd, rs, rt);
27167 break;
099e5b4d
LA
27168 case OPC_CLO:
27169 case OPC_CLZ:
27170 check_insn(ctx, ISA_MIPS32);
27171 gen_cl(ctx, op1, rd, rs);
27172 break;
27173 case OPC_SDBBP:
3b3c1694
LA
27174 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27175 gen_helper_do_semihosting(cpu_env);
27176 } else {
7480515f
AM
27177 /*
27178 * XXX: not clear which exception should be raised
3b3c1694
LA
27179 * when in debug mode...
27180 */
27181 check_insn(ctx, ISA_MIPS32);
9c708c7f 27182 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 27183 }
099e5b4d 27184 break;
9b1a1d68 27185#if defined(TARGET_MIPS64)
099e5b4d
LA
27186 case OPC_DCLO:
27187 case OPC_DCLZ:
27188 check_insn(ctx, ISA_MIPS64);
27189 check_mips_64(ctx);
27190 gen_cl(ctx, op1, rd, rs);
27191 break;
4267d3e6
LA
27192 case OPC_DMULT_G_2F:
27193 case OPC_DMULTU_G_2F:
27194 case OPC_DDIV_G_2F:
27195 case OPC_DDIVU_G_2F:
27196 case OPC_DMOD_G_2F:
27197 case OPC_DMODU_G_2F:
8e2d5831 27198 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
4267d3e6
LA
27199 gen_loongson_integer(ctx, op1, rd, rs, rt);
27200 break;
10dc65db 27201#endif
4267d3e6
LA
27202 default: /* Invalid */
27203 MIPS_INVAL("special2_legacy");
9c708c7f 27204 generate_exception_end(ctx, EXCP_RI);
4267d3e6 27205 break;
10dc65db
LA
27206 }
27207}
27208
27209static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27210{
15eacb9b
YK
27211 int rs, rt, rd, sa;
27212 uint32_t op1, op2;
10dc65db
LA
27213 int16_t imm;
27214
27215 rs = (ctx->opcode >> 21) & 0x1f;
27216 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
27217 rd = (ctx->opcode >> 11) & 0x1f;
27218 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
27219 imm = (int16_t)ctx->opcode >> 7;
27220
27221 op1 = MASK_SPECIAL3(ctx->opcode);
27222 switch (op1) {
bf7910c6
LA
27223 case R6_OPC_PREF:
27224 if (rt >= 24) {
27225 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 27226 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
27227 }
27228 /* Treat as NOP. */
27229 break;
27230 case R6_OPC_CACHE:
40d48212 27231 check_cp0_enabled(ctx);
0d74a222
LA
27232 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27233 gen_cache_operation(ctx, rt, rs, imm);
27234 }
bf7910c6 27235 break;
10dc65db 27236 case R6_OPC_SC:
33a07fa2 27237 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
27238 break;
27239 case R6_OPC_LL:
27240 gen_ld(ctx, op1, rt, rs, imm);
27241 break;
15eacb9b
YK
27242 case OPC_BSHFL:
27243 {
27244 if (rd == 0) {
27245 /* Treat as NOP. */
27246 break;
27247 }
15eacb9b
YK
27248 op2 = MASK_BSHFL(ctx->opcode);
27249 switch (op2) {
c2e19f3c 27250 case OPC_ALIGN:
373ecd38
AM
27251 case OPC_ALIGN_1:
27252 case OPC_ALIGN_2:
27253 case OPC_ALIGN_3:
821f2008 27254 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
27255 break;
27256 case OPC_BITSWAP:
1f1b4c00 27257 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27258 break;
27259 }
15eacb9b
YK
27260 }
27261 break;
99029be1
YK
27262#ifndef CONFIG_USER_ONLY
27263 case OPC_GINV:
27264 if (unlikely(ctx->gi <= 1)) {
27265 generate_exception_end(ctx, EXCP_RI);
27266 }
27267 check_cp0_enabled(ctx);
27268 switch ((ctx->opcode >> 6) & 3) {
27269 case 0: /* GINVI */
27270 /* Treat as NOP. */
27271 break;
27272 case 2: /* GINVT */
27273 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27274 break;
27275 default:
27276 generate_exception_end(ctx, EXCP_RI);
27277 break;
27278 }
27279 break;
27280#endif
bf7910c6
LA
27281#if defined(TARGET_MIPS64)
27282 case R6_OPC_SCD:
33a07fa2 27283 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
27284 break;
27285 case R6_OPC_LLD:
27286 gen_ld(ctx, op1, rt, rs, imm);
27287 break;
15eacb9b
YK
27288 case OPC_DBSHFL:
27289 check_mips_64(ctx);
27290 {
27291 if (rd == 0) {
27292 /* Treat as NOP. */
27293 break;
27294 }
15eacb9b
YK
27295 op2 = MASK_DBSHFL(ctx->opcode);
27296 switch (op2) {
c2e19f3c 27297 case OPC_DALIGN:
373ecd38
AM
27298 case OPC_DALIGN_1:
27299 case OPC_DALIGN_2:
27300 case OPC_DALIGN_3:
27301 case OPC_DALIGN_4:
27302 case OPC_DALIGN_5:
27303 case OPC_DALIGN_6:
27304 case OPC_DALIGN_7:
821f2008 27305 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
27306 break;
27307 case OPC_DBITSWAP:
1f1b4c00 27308 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27309 break;
27310 }
1f1b4c00 27311
15eacb9b
YK
27312 }
27313 break;
bf7910c6 27314#endif
10dc65db
LA
27315 default: /* Invalid */
27316 MIPS_INVAL("special3_r6");
9c708c7f 27317 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
27318 break;
27319 }
27320}
27321
27322static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27323{
fac5a073 27324 int rs, rt, rd;
099e5b4d 27325 uint32_t op1, op2;
099e5b4d
LA
27326
27327 rs = (ctx->opcode >> 21) & 0x1f;
27328 rt = (ctx->opcode >> 16) & 0x1f;
27329 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
27330
27331 op1 = MASK_SPECIAL3(ctx->opcode);
27332 switch (op1) {
c2e19f3c
AM
27333 case OPC_DIV_G_2E:
27334 case OPC_DIVU_G_2E:
27335 case OPC_MOD_G_2E:
27336 case OPC_MODU_G_2E:
27337 case OPC_MULT_G_2E:
27338 case OPC_MULTU_G_2E:
7480515f
AM
27339 /*
27340 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27341 * the same mask and op1.
27342 */
908f6be1 27343 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 27344 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 27345 switch (op2) {
099e5b4d
LA
27346 case OPC_ADDUH_QB:
27347 case OPC_ADDUH_R_QB:
27348 case OPC_ADDQH_PH:
27349 case OPC_ADDQH_R_PH:
27350 case OPC_ADDQH_W:
27351 case OPC_ADDQH_R_W:
27352 case OPC_SUBUH_QB:
27353 case OPC_SUBUH_R_QB:
27354 case OPC_SUBQH_PH:
27355 case OPC_SUBQH_R_PH:
27356 case OPC_SUBQH_W:
27357 case OPC_SUBQH_R_W:
461c08df
JL
27358 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27359 break;
099e5b4d
LA
27360 case OPC_MUL_PH:
27361 case OPC_MUL_S_PH:
27362 case OPC_MULQ_S_W:
27363 case OPC_MULQ_RS_W:
27364 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27365 break;
461c08df 27366 default:
099e5b4d 27367 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 27368 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
27369 break;
27370 }
099e5b4d
LA
27371 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27372 gen_loongson_integer(ctx, op1, rd, rs, rt);
27373 } else {
9c708c7f 27374 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27375 }
27376 break;
27377 case OPC_LX_DSP:
27378 op2 = MASK_LX(ctx->opcode);
27379 switch (op2) {
27380#if defined(TARGET_MIPS64)
27381 case OPC_LDX:
27382#endif
27383 case OPC_LBUX:
27384 case OPC_LHX:
27385 case OPC_LWX:
27386 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27387 break;
27388 default: /* Invalid */
27389 MIPS_INVAL("MASK LX");
9c708c7f 27390 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27391 break;
27392 }
27393 break;
27394 case OPC_ABSQ_S_PH_DSP:
27395 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27396 switch (op2) {
27397 case OPC_ABSQ_S_QB:
27398 case OPC_ABSQ_S_PH:
27399 case OPC_ABSQ_S_W:
27400 case OPC_PRECEQ_W_PHL:
27401 case OPC_PRECEQ_W_PHR:
27402 case OPC_PRECEQU_PH_QBL:
27403 case OPC_PRECEQU_PH_QBR:
27404 case OPC_PRECEQU_PH_QBLA:
27405 case OPC_PRECEQU_PH_QBRA:
27406 case OPC_PRECEU_PH_QBL:
27407 case OPC_PRECEU_PH_QBR:
27408 case OPC_PRECEU_PH_QBLA:
27409 case OPC_PRECEU_PH_QBRA:
27410 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27411 break;
27412 case OPC_BITREV:
27413 case OPC_REPL_QB:
27414 case OPC_REPLV_QB:
27415 case OPC_REPL_PH:
27416 case OPC_REPLV_PH:
27417 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27418 break;
27419 default:
27420 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 27421 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27422 break;
27423 }
27424 break;
27425 case OPC_ADDU_QB_DSP:
27426 op2 = MASK_ADDU_QB(ctx->opcode);
27427 switch (op2) {
27428 case OPC_ADDQ_PH:
27429 case OPC_ADDQ_S_PH:
27430 case OPC_ADDQ_S_W:
27431 case OPC_ADDU_QB:
27432 case OPC_ADDU_S_QB:
27433 case OPC_ADDU_PH:
27434 case OPC_ADDU_S_PH:
27435 case OPC_SUBQ_PH:
27436 case OPC_SUBQ_S_PH:
27437 case OPC_SUBQ_S_W:
27438 case OPC_SUBU_QB:
27439 case OPC_SUBU_S_QB:
27440 case OPC_SUBU_PH:
27441 case OPC_SUBU_S_PH:
27442 case OPC_ADDSC:
27443 case OPC_ADDWC:
27444 case OPC_MODSUB:
27445 case OPC_RADDU_W_QB:
27446 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27447 break;
27448 case OPC_MULEU_S_PH_QBL:
27449 case OPC_MULEU_S_PH_QBR:
27450 case OPC_MULQ_RS_PH:
27451 case OPC_MULEQ_S_W_PHL:
27452 case OPC_MULEQ_S_W_PHR:
27453 case OPC_MULQ_S_PH:
27454 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27455 break;
27456 default: /* Invalid */
27457 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 27458 generate_exception_end(ctx, EXCP_RI);
461c08df 27459 break;
461c08df 27460
099e5b4d
LA
27461 }
27462 break;
27463 case OPC_CMPU_EQ_QB_DSP:
27464 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27465 switch (op2) {
27466 case OPC_PRECR_SRA_PH_W:
27467 case OPC_PRECR_SRA_R_PH_W:
27468 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 27469 break;
099e5b4d
LA
27470 case OPC_PRECR_QB_PH:
27471 case OPC_PRECRQ_QB_PH:
27472 case OPC_PRECRQ_PH_W:
27473 case OPC_PRECRQ_RS_PH_W:
27474 case OPC_PRECRQU_S_QB_PH:
27475 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 27476 break;
099e5b4d
LA
27477 case OPC_CMPU_EQ_QB:
27478 case OPC_CMPU_LT_QB:
27479 case OPC_CMPU_LE_QB:
27480 case OPC_CMP_EQ_PH:
27481 case OPC_CMP_LT_PH:
27482 case OPC_CMP_LE_PH:
27483 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 27484 break;
099e5b4d
LA
27485 case OPC_CMPGU_EQ_QB:
27486 case OPC_CMPGU_LT_QB:
27487 case OPC_CMPGU_LE_QB:
27488 case OPC_CMPGDU_EQ_QB:
27489 case OPC_CMPGDU_LT_QB:
27490 case OPC_CMPGDU_LE_QB:
27491 case OPC_PICK_QB:
27492 case OPC_PICK_PH:
27493 case OPC_PACKRL_PH:
27494 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27495 break;
27496 default: /* Invalid */
27497 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 27498 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27499 break;
27500 }
27501 break;
27502 case OPC_SHLL_QB_DSP:
27503 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27504 break;
27505 case OPC_DPA_W_PH_DSP:
27506 op2 = MASK_DPA_W_PH(ctx->opcode);
27507 switch (op2) {
27508 case OPC_DPAU_H_QBL:
27509 case OPC_DPAU_H_QBR:
27510 case OPC_DPSU_H_QBL:
27511 case OPC_DPSU_H_QBR:
27512 case OPC_DPA_W_PH:
27513 case OPC_DPAX_W_PH:
27514 case OPC_DPAQ_S_W_PH:
27515 case OPC_DPAQX_S_W_PH:
27516 case OPC_DPAQX_SA_W_PH:
27517 case OPC_DPS_W_PH:
27518 case OPC_DPSX_W_PH:
27519 case OPC_DPSQ_S_W_PH:
27520 case OPC_DPSQX_S_W_PH:
27521 case OPC_DPSQX_SA_W_PH:
27522 case OPC_MULSAQ_S_W_PH:
27523 case OPC_DPAQ_SA_L_W:
27524 case OPC_DPSQ_SA_L_W:
27525 case OPC_MAQ_S_W_PHL:
27526 case OPC_MAQ_S_W_PHR:
27527 case OPC_MAQ_SA_W_PHL:
27528 case OPC_MAQ_SA_W_PHR:
27529 case OPC_MULSA_W_PH:
27530 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27531 break;
27532 default: /* Invalid */
27533 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 27534 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27535 break;
27536 }
27537 break;
27538 case OPC_INSV_DSP:
27539 op2 = MASK_INSV(ctx->opcode);
27540 switch (op2) {
27541 case OPC_INSV:
27542 check_dsp(ctx);
27543 {
27544 TCGv t0, t1;
27545
27546 if (rt == 0) {
099e5b4d
LA
27547 break;
27548 }
27549
27550 t0 = tcg_temp_new();
27551 t1 = tcg_temp_new();
27552
27553 gen_load_gpr(t0, rt);
27554 gen_load_gpr(t1, rs);
27555
27556 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27557
27558 tcg_temp_free(t0);
27559 tcg_temp_free(t1);
a22260ae
JL
27560 break;
27561 }
099e5b4d
LA
27562 default: /* Invalid */
27563 MIPS_INVAL("MASK INSV");
9c708c7f 27564 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27565 break;
27566 }
27567 break;
27568 case OPC_APPEND_DSP:
27569 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27570 break;
27571 case OPC_EXTR_W_DSP:
27572 op2 = MASK_EXTR_W(ctx->opcode);
27573 switch (op2) {
27574 case OPC_EXTR_W:
27575 case OPC_EXTR_R_W:
27576 case OPC_EXTR_RS_W:
27577 case OPC_EXTR_S_H:
27578 case OPC_EXTRV_S_H:
27579 case OPC_EXTRV_W:
27580 case OPC_EXTRV_R_W:
27581 case OPC_EXTRV_RS_W:
27582 case OPC_EXTP:
27583 case OPC_EXTPV:
27584 case OPC_EXTPDP:
27585 case OPC_EXTPDPV:
27586 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27587 break;
27588 case OPC_RDDSP:
27589 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27590 break;
27591 case OPC_SHILO:
27592 case OPC_SHILOV:
27593 case OPC_MTHLIP:
27594 case OPC_WRDSP:
27595 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27596 break;
27597 default: /* Invalid */
27598 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27599 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27600 break;
27601 }
27602 break;
099e5b4d 27603#if defined(TARGET_MIPS64)
c2e19f3c
AM
27604 case OPC_DDIV_G_2E:
27605 case OPC_DDIVU_G_2E:
27606 case OPC_DMULT_G_2E:
27607 case OPC_DMULTU_G_2E:
27608 case OPC_DMOD_G_2E:
27609 case OPC_DMODU_G_2E:
fac5a073
LA
27610 check_insn(ctx, INSN_LOONGSON2E);
27611 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 27612 break;
099e5b4d
LA
27613 case OPC_ABSQ_S_QH_DSP:
27614 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27615 switch (op2) {
27616 case OPC_PRECEQ_L_PWL:
27617 case OPC_PRECEQ_L_PWR:
27618 case OPC_PRECEQ_PW_QHL:
27619 case OPC_PRECEQ_PW_QHR:
27620 case OPC_PRECEQ_PW_QHLA:
27621 case OPC_PRECEQ_PW_QHRA:
27622 case OPC_PRECEQU_QH_OBL:
27623 case OPC_PRECEQU_QH_OBR:
27624 case OPC_PRECEQU_QH_OBLA:
27625 case OPC_PRECEQU_QH_OBRA:
27626 case OPC_PRECEU_QH_OBL:
27627 case OPC_PRECEU_QH_OBR:
27628 case OPC_PRECEU_QH_OBLA:
27629 case OPC_PRECEU_QH_OBRA:
27630 case OPC_ABSQ_S_OB:
27631 case OPC_ABSQ_S_PW:
27632 case OPC_ABSQ_S_QH:
27633 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27634 break;
27635 case OPC_REPL_OB:
27636 case OPC_REPL_PW:
27637 case OPC_REPL_QH:
27638 case OPC_REPLV_OB:
27639 case OPC_REPLV_PW:
27640 case OPC_REPLV_QH:
27641 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27642 break;
27643 default: /* Invalid */
27644 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 27645 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27646 break;
27647 }
27648 break;
27649 case OPC_ADDU_OB_DSP:
27650 op2 = MASK_ADDU_OB(ctx->opcode);
27651 switch (op2) {
27652 case OPC_RADDU_L_OB:
27653 case OPC_SUBQ_PW:
27654 case OPC_SUBQ_S_PW:
27655 case OPC_SUBQ_QH:
27656 case OPC_SUBQ_S_QH:
27657 case OPC_SUBU_OB:
27658 case OPC_SUBU_S_OB:
27659 case OPC_SUBU_QH:
27660 case OPC_SUBU_S_QH:
27661 case OPC_SUBUH_OB:
27662 case OPC_SUBUH_R_OB:
27663 case OPC_ADDQ_PW:
27664 case OPC_ADDQ_S_PW:
27665 case OPC_ADDQ_QH:
27666 case OPC_ADDQ_S_QH:
27667 case OPC_ADDU_OB:
27668 case OPC_ADDU_S_OB:
27669 case OPC_ADDU_QH:
27670 case OPC_ADDU_S_QH:
27671 case OPC_ADDUH_OB:
27672 case OPC_ADDUH_R_OB:
27673 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 27674 break;
099e5b4d
LA
27675 case OPC_MULEQ_S_PW_QHL:
27676 case OPC_MULEQ_S_PW_QHR:
27677 case OPC_MULEU_S_QH_OBL:
27678 case OPC_MULEU_S_QH_OBR:
27679 case OPC_MULQ_RS_QH:
27680 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27681 break;
099e5b4d
LA
27682 default: /* Invalid */
27683 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 27684 generate_exception_end(ctx, EXCP_RI);
26690560 27685 break;
099e5b4d
LA
27686 }
27687 break;
27688 case OPC_CMPU_EQ_OB_DSP:
27689 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27690 switch (op2) {
27691 case OPC_PRECR_SRA_QH_PW:
27692 case OPC_PRECR_SRA_R_QH_PW:
27693 /* Return value is rt. */
27694 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 27695 break;
099e5b4d
LA
27696 case OPC_PRECR_OB_QH:
27697 case OPC_PRECRQ_OB_QH:
27698 case OPC_PRECRQ_PW_L:
27699 case OPC_PRECRQ_QH_PW:
27700 case OPC_PRECRQ_RS_QH_PW:
27701 case OPC_PRECRQU_S_OB_QH:
27702 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 27703 break;
099e5b4d
LA
27704 case OPC_CMPU_EQ_OB:
27705 case OPC_CMPU_LT_OB:
27706 case OPC_CMPU_LE_OB:
27707 case OPC_CMP_EQ_QH:
27708 case OPC_CMP_LT_QH:
27709 case OPC_CMP_LE_QH:
27710 case OPC_CMP_EQ_PW:
27711 case OPC_CMP_LT_PW:
27712 case OPC_CMP_LE_PW:
27713 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 27714 break;
099e5b4d
LA
27715 case OPC_CMPGDU_EQ_OB:
27716 case OPC_CMPGDU_LT_OB:
27717 case OPC_CMPGDU_LE_OB:
27718 case OPC_CMPGU_EQ_OB:
27719 case OPC_CMPGU_LT_OB:
27720 case OPC_CMPGU_LE_OB:
27721 case OPC_PACKRL_PW:
27722 case OPC_PICK_OB:
27723 case OPC_PICK_PW:
27724 case OPC_PICK_QH:
27725 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 27726 break;
099e5b4d
LA
27727 default: /* Invalid */
27728 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 27729 generate_exception_end(ctx, EXCP_RI);
161f85e6 27730 break;
099e5b4d
LA
27731 }
27732 break;
27733 case OPC_DAPPEND_DSP:
27734 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27735 break;
27736 case OPC_DEXTR_W_DSP:
27737 op2 = MASK_DEXTR_W(ctx->opcode);
27738 switch (op2) {
27739 case OPC_DEXTP:
27740 case OPC_DEXTPDP:
27741 case OPC_DEXTPDPV:
27742 case OPC_DEXTPV:
27743 case OPC_DEXTR_L:
27744 case OPC_DEXTR_R_L:
27745 case OPC_DEXTR_RS_L:
27746 case OPC_DEXTR_W:
27747 case OPC_DEXTR_R_W:
27748 case OPC_DEXTR_RS_W:
27749 case OPC_DEXTR_S_H:
27750 case OPC_DEXTRV_L:
27751 case OPC_DEXTRV_R_L:
27752 case OPC_DEXTRV_RS_L:
27753 case OPC_DEXTRV_S_H:
27754 case OPC_DEXTRV_W:
27755 case OPC_DEXTRV_R_W:
27756 case OPC_DEXTRV_RS_W:
27757 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 27758 break;
099e5b4d
LA
27759 case OPC_DMTHLIP:
27760 case OPC_DSHILO:
27761 case OPC_DSHILOV:
27762 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 27763 break;
099e5b4d
LA
27764 default: /* Invalid */
27765 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27766 generate_exception_end(ctx, EXCP_RI);
461c08df 27767 break;
099e5b4d
LA
27768 }
27769 break;
27770 case OPC_DPAQ_W_QH_DSP:
27771 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27772 switch (op2) {
27773 case OPC_DPAU_H_OBL:
27774 case OPC_DPAU_H_OBR:
27775 case OPC_DPSU_H_OBL:
27776 case OPC_DPSU_H_OBR:
27777 case OPC_DPA_W_QH:
27778 case OPC_DPAQ_S_W_QH:
27779 case OPC_DPS_W_QH:
27780 case OPC_DPSQ_S_W_QH:
27781 case OPC_MULSAQ_S_W_QH:
27782 case OPC_DPAQ_SA_L_PW:
27783 case OPC_DPSQ_SA_L_PW:
27784 case OPC_MULSAQ_S_L_PW:
27785 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27786 break;
27787 case OPC_MAQ_S_W_QHLL:
27788 case OPC_MAQ_S_W_QHLR:
27789 case OPC_MAQ_S_W_QHRL:
27790 case OPC_MAQ_S_W_QHRR:
27791 case OPC_MAQ_SA_W_QHLL:
27792 case OPC_MAQ_SA_W_QHLR:
27793 case OPC_MAQ_SA_W_QHRL:
27794 case OPC_MAQ_SA_W_QHRR:
27795 case OPC_MAQ_S_L_PWL:
27796 case OPC_MAQ_S_L_PWR:
27797 case OPC_DMADD:
27798 case OPC_DMADDU:
27799 case OPC_DMSUB:
27800 case OPC_DMSUBU:
27801 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 27802 break;
099e5b4d
LA
27803 default: /* Invalid */
27804 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 27805 generate_exception_end(ctx, EXCP_RI);
b53371ed 27806 break;
099e5b4d
LA
27807 }
27808 break;
27809 case OPC_DINSV_DSP:
27810 op2 = MASK_INSV(ctx->opcode);
27811 switch (op2) {
27812 case OPC_DINSV:
27813 {
27814 TCGv t0, t1;
27815
27816 if (rt == 0) {
a22260ae
JL
27817 break;
27818 }
099e5b4d 27819 check_dsp(ctx);
1cb6686c 27820
099e5b4d
LA
27821 t0 = tcg_temp_new();
27822 t1 = tcg_temp_new();
1cb6686c 27823
099e5b4d
LA
27824 gen_load_gpr(t0, rt);
27825 gen_load_gpr(t1, rs);
1cb6686c 27826
099e5b4d 27827 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 27828
099e5b4d
LA
27829 tcg_temp_free(t0);
27830 tcg_temp_free(t1);
77c5fa8b 27831 break;
099e5b4d 27832 }
7a387fff 27833 default: /* Invalid */
099e5b4d 27834 MIPS_INVAL("MASK DINSV");
9c708c7f 27835 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
27836 break;
27837 }
27838 break;
099e5b4d
LA
27839 case OPC_SHLL_OB_DSP:
27840 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27841 break;
27842#endif
fac5a073
LA
27843 default: /* Invalid */
27844 MIPS_INVAL("special3_legacy");
9c708c7f 27845 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
27846 break;
27847 }
27848}
27849
37b9aae2
MM
27850
27851#if defined(TARGET_MIPS64)
27852
874b2879 27853static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 27854{
c8341e00 27855 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
27856
27857 switch (opc) {
baa609db
AM
27858 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27859 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27860 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27861 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27862 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27863 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27864 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27865 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27866 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27867 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27868 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27869 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27870 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27871 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27872 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27873 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27874 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27875 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27876 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27877 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27878 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27879 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27880 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27881 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27882 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27883 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
27884 break;
27885 default:
27886 MIPS_INVAL("TX79 MMI class MMI0");
27887 generate_exception_end(ctx, EXCP_RI);
27888 break;
27889 }
27890}
27891
874b2879 27892static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 27893{
c8341e00 27894 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
27895
27896 switch (opc) {
baa609db
AM
27897 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27898 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27899 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27900 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27901 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27902 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27903 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27904 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27905 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27906 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27907 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27908 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27909 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27910 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27911 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27912 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27913 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27914 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27915 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
27916 break;
27917 default:
27918 MIPS_INVAL("TX79 MMI class MMI1");
27919 generate_exception_end(ctx, EXCP_RI);
27920 break;
27921 }
27922}
27923
874b2879 27924static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 27925{
c8341e00 27926 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
27927
27928 switch (opc) {
baa609db
AM
27929 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27930 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27931 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27932 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27933 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27934 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27935 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27936 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27937 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
baa609db
AM
27938 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27939 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27940 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27941 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27942 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27943 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27944 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27945 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27946 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27947 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27948 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27949 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27950 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3 27951 break;
b87eef31
MM
27952 case MMI_OPC_2_PCPYLD:
27953 gen_mmi_pcpyld(ctx);
27954 break;
6c1e48d3
FN
27955 default:
27956 MIPS_INVAL("TX79 MMI class MMI2");
27957 generate_exception_end(ctx, EXCP_RI);
27958 break;
27959 }
27960}
27961
874b2879 27962static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 27963{
c8341e00 27964 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
27965
27966 switch (opc) {
baa609db
AM
27967 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27968 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27969 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27970 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27971 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27972 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27973 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
baa609db
AM
27974 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27975 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27976 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
baa609db
AM
27977 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27978 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc 27979 break;
d3434d9f
MM
27980 case MMI_OPC_3_PCPYH:
27981 gen_mmi_pcpyh(ctx);
27982 break;
fd487f83
MM
27983 case MMI_OPC_3_PCPYUD:
27984 gen_mmi_pcpyud(ctx);
27985 break;
ec1944fc
FN
27986 default:
27987 MIPS_INVAL("TX79 MMI class MMI3");
27988 generate_exception_end(ctx, EXCP_RI);
27989 break;
27990 }
27991}
27992
874b2879 27993static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 27994{
c8341e00 27995 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
27996 int rs = extract32(ctx->opcode, 21, 5);
27997 int rt = extract32(ctx->opcode, 16, 5);
27998 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
27999
28000 switch (opc) {
baa609db 28001 case MMI_OPC_CLASS_MMI0:
874b2879 28002 decode_mmi0(env, ctx);
88eafe0b 28003 break;
baa609db 28004 case MMI_OPC_CLASS_MMI1:
874b2879 28005 decode_mmi1(env, ctx);
7a803ca2 28006 break;
baa609db 28007 case MMI_OPC_CLASS_MMI2:
874b2879 28008 decode_mmi2(env, ctx);
6c1e48d3 28009 break;
baa609db 28010 case MMI_OPC_CLASS_MMI3:
874b2879 28011 decode_mmi3(env, ctx);
ec1944fc 28012 break;
baa609db
AM
28013 case MMI_OPC_MULT1:
28014 case MMI_OPC_MULTU1:
3b948f05
PMD
28015 case MMI_OPC_MADD:
28016 case MMI_OPC_MADDU:
a95c4c26
FN
28017 case MMI_OPC_MADD1:
28018 case MMI_OPC_MADDU1:
06de726b
FN
28019 gen_mul_txx9(ctx, opc, rd, rs, rt);
28020 break;
baa609db
AM
28021 case MMI_OPC_DIV1:
28022 case MMI_OPC_DIVU1:
c42171c3 28023 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 28024 break;
baa609db
AM
28025 case MMI_OPC_MTLO1:
28026 case MMI_OPC_MTHI1:
86efbfb6 28027 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 28028 break;
baa609db
AM
28029 case MMI_OPC_MFLO1:
28030 case MMI_OPC_MFHI1:
86efbfb6 28031 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 28032 break;
baa609db 28033 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
28034 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28035 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28036 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28037 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28038 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28039 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28040 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28041 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28042 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
28043 break;
28044 default:
28045 MIPS_INVAL("TX79 MMI class");
28046 generate_exception_end(ctx, EXCP_RI);
28047 break;
28048 }
28049}
28050
874b2879 28051static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 28052{
baa609db 28053 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
28054}
28055
874b2879 28056static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 28057{
baa609db 28058 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
28059}
28060
28061/*
28062 * The TX79-specific instruction Store Quadword
28063 *
28064 * +--------+-------+-------+------------------------+
28065 * | 011111 | base | rt | offset | SQ
28066 * +--------+-------+-------+------------------------+
28067 * 6 5 5 16
28068 *
28069 * has the same opcode as the Read Hardware Register instruction
28070 *
28071 * +--------+-------+-------+-------+-------+--------+
28072 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28073 * +--------+-------+-------+-------+-------+--------+
28074 * 6 5 5 5 5 6
28075 *
28076 * that is required, trapped and emulated by the Linux kernel. However, all
28077 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28078 * offset is odd. Therefore all valid SQ instructions can execute normally.
28079 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28080 * between SQ and RDHWR, as the Linux kernel does.
28081 */
874b2879 28082static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
28083{
28084 int base = extract32(ctx->opcode, 21, 5);
28085 int rt = extract32(ctx->opcode, 16, 5);
28086 int offset = extract32(ctx->opcode, 0, 16);
28087
28088#ifdef CONFIG_USER_ONLY
28089 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28090 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28091
28092 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28093 int rd = extract32(ctx->opcode, 11, 5);
28094
28095 gen_rdhwr(ctx, rt, rd, 0);
28096 return;
28097 }
28098#endif
28099
874b2879 28100 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
28101}
28102
37b9aae2
MM
28103#endif
28104
fac5a073
LA
28105static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28106{
28107 int rs, rt, rd, sa;
28108 uint32_t op1, op2;
76964147 28109 int16_t imm;
fac5a073
LA
28110
28111 rs = (ctx->opcode >> 21) & 0x1f;
28112 rt = (ctx->opcode >> 16) & 0x1f;
28113 rd = (ctx->opcode >> 11) & 0x1f;
28114 sa = (ctx->opcode >> 6) & 0x1f;
76964147 28115 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
28116
28117 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
28118
28119 /*
28120 * EVA loads and stores overlap Loongson 2E instructions decoded by
28121 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28122 * EVA is absent.
28123 */
28124 if (ctx->eva) {
28125 switch (op1) {
c2e19f3c
AM
28126 case OPC_LWLE:
28127 case OPC_LWRE:
76964147
JH
28128 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28129 /* fall through */
c2e19f3c
AM
28130 case OPC_LBUE:
28131 case OPC_LHUE:
28132 case OPC_LBE:
28133 case OPC_LHE:
28134 case OPC_LLE:
28135 case OPC_LWE:
76964147
JH
28136 check_cp0_enabled(ctx);
28137 gen_ld(ctx, op1, rt, rs, imm);
28138 return;
c2e19f3c
AM
28139 case OPC_SWLE:
28140 case OPC_SWRE:
76964147
JH
28141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28142 /* fall through */
c2e19f3c
AM
28143 case OPC_SBE:
28144 case OPC_SHE:
76964147
JH
28145 case OPC_SWE:
28146 check_cp0_enabled(ctx);
28147 gen_st(ctx, op1, rt, rs, imm);
28148 return;
28149 case OPC_SCE:
28150 check_cp0_enabled(ctx);
33a07fa2 28151 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
28152 return;
28153 case OPC_CACHEE:
28154 check_cp0_enabled(ctx);
28155 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28156 gen_cache_operation(ctx, rt, rs, imm);
28157 }
28158 /* Treat as NOP. */
28159 return;
28160 case OPC_PREFE:
28161 check_cp0_enabled(ctx);
28162 /* Treat as NOP. */
28163 return;
28164 }
28165 }
28166
fac5a073
LA
28167 switch (op1) {
28168 case OPC_EXT:
28169 case OPC_INS:
28170 check_insn(ctx, ISA_MIPS32R2);
28171 gen_bitops(ctx, op1, rt, rs, sa, rd);
28172 break;
28173 case OPC_BSHFL:
fac5a073 28174 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 28175 switch (op2) {
c2e19f3c 28176 case OPC_ALIGN:
373ecd38
AM
28177 case OPC_ALIGN_1:
28178 case OPC_ALIGN_2:
28179 case OPC_ALIGN_3:
15eacb9b
YK
28180 case OPC_BITSWAP:
28181 check_insn(ctx, ISA_MIPS32R6);
28182 decode_opc_special3_r6(env, ctx);
28183 break;
28184 default:
28185 check_insn(ctx, ISA_MIPS32R2);
28186 gen_bshfl(ctx, op2, rt, rd);
28187 break;
28188 }
fac5a073
LA
28189 break;
28190#if defined(TARGET_MIPS64)
c2e19f3c
AM
28191 case OPC_DEXTM:
28192 case OPC_DEXTU:
28193 case OPC_DEXT:
28194 case OPC_DINSM:
28195 case OPC_DINSU:
28196 case OPC_DINS:
fac5a073
LA
28197 check_insn(ctx, ISA_MIPS64R2);
28198 check_mips_64(ctx);
28199 gen_bitops(ctx, op1, rt, rs, sa, rd);
28200 break;
28201 case OPC_DBSHFL:
fac5a073 28202 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 28203 switch (op2) {
c2e19f3c 28204 case OPC_DALIGN:
373ecd38
AM
28205 case OPC_DALIGN_1:
28206 case OPC_DALIGN_2:
28207 case OPC_DALIGN_3:
28208 case OPC_DALIGN_4:
28209 case OPC_DALIGN_5:
28210 case OPC_DALIGN_6:
28211 case OPC_DALIGN_7:
15eacb9b
YK
28212 case OPC_DBITSWAP:
28213 check_insn(ctx, ISA_MIPS32R6);
28214 decode_opc_special3_r6(env, ctx);
28215 break;
28216 default:
28217 check_insn(ctx, ISA_MIPS64R2);
28218 check_mips_64(ctx);
28219 op2 = MASK_DBSHFL(ctx->opcode);
28220 gen_bshfl(ctx, op2, rt, rd);
28221 break;
28222 }
fac5a073
LA
28223 break;
28224#endif
28225 case OPC_RDHWR:
b00c7218 28226 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
28227 break;
28228 case OPC_FORK:
9affc1c5 28229 check_mt(ctx);
fac5a073
LA
28230 {
28231 TCGv t0 = tcg_temp_new();
28232 TCGv t1 = tcg_temp_new();
28233
28234 gen_load_gpr(t0, rt);
28235 gen_load_gpr(t1, rs);
28236 gen_helper_fork(t0, t1);
28237 tcg_temp_free(t0);
28238 tcg_temp_free(t1);
28239 }
28240 break;
28241 case OPC_YIELD:
9affc1c5 28242 check_mt(ctx);
fac5a073
LA
28243 {
28244 TCGv t0 = tcg_temp_new();
28245
fac5a073
LA
28246 gen_load_gpr(t0, rs);
28247 gen_helper_yield(t0, cpu_env, t0);
28248 gen_store_gpr(t0, rd);
28249 tcg_temp_free(t0);
28250 }
28251 break;
10dc65db
LA
28252 default:
28253 if (ctx->insn_flags & ISA_MIPS32R6) {
28254 decode_opc_special3_r6(env, ctx);
28255 } else {
28256 decode_opc_special3_legacy(env, ctx);
28257 }
099e5b4d
LA
28258 }
28259}
28260
863f264d
YK
28261/* MIPS SIMD Architecture (MSA) */
28262static inline int check_msa_access(DisasContext *ctx)
28263{
28264 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28265 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 28266 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28267 return 0;
28268 }
28269
28270 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28271 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 28272 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
28273 return 0;
28274 } else {
9c708c7f 28275 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28276 return 0;
28277 }
28278 }
28279 return 1;
28280}
28281
5692c6e1
YK
28282static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28283{
28284 /* generates tcg ops to check if any element is 0 */
28285 /* Note this function only works with MSA_WRLEN = 128 */
28286 uint64_t eval_zero_or_big = 0;
28287 uint64_t eval_big = 0;
28288 TCGv_i64 t0 = tcg_temp_new_i64();
28289 TCGv_i64 t1 = tcg_temp_new_i64();
28290 switch (df) {
28291 case DF_BYTE:
28292 eval_zero_or_big = 0x0101010101010101ULL;
28293 eval_big = 0x8080808080808080ULL;
28294 break;
28295 case DF_HALF:
28296 eval_zero_or_big = 0x0001000100010001ULL;
28297 eval_big = 0x8000800080008000ULL;
28298 break;
28299 case DF_WORD:
28300 eval_zero_or_big = 0x0000000100000001ULL;
28301 eval_big = 0x8000000080000000ULL;
28302 break;
28303 case DF_DOUBLE:
28304 eval_zero_or_big = 0x0000000000000001ULL;
28305 eval_big = 0x8000000000000000ULL;
28306 break;
28307 }
235785e8
AM
28308 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28309 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
5692c6e1 28310 tcg_gen_andi_i64(t0, t0, eval_big);
235785e8
AM
28311 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28312 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28313 tcg_gen_andi_i64(t1, t1, eval_big);
28314 tcg_gen_or_i64(t0, t0, t1);
28315 /* if all bits are zero then all elements are not zero */
28316 /* if some bit is non-zero then some element is zero */
28317 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28318 tcg_gen_trunc_i64_tl(tresult, t0);
28319 tcg_temp_free_i64(t0);
28320 tcg_temp_free_i64(t1);
28321}
28322
28323static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28324{
28325 uint8_t df = (ctx->opcode >> 21) & 0x3;
28326 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28327 int64_t s16 = (int16_t)ctx->opcode;
28328
28329 check_msa_access(ctx);
28330
075a1fe7 28331 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 28332 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
28333 return;
28334 }
28335 switch (op1) {
28336 case OPC_BZ_V:
28337 case OPC_BNZ_V:
28338 {
28339 TCGv_i64 t0 = tcg_temp_new_i64();
235785e8 28340 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28341 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28342 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28343 tcg_gen_trunc_i64_tl(bcond, t0);
28344 tcg_temp_free_i64(t0);
28345 }
28346 break;
28347 case OPC_BZ_B:
28348 case OPC_BZ_H:
28349 case OPC_BZ_W:
28350 case OPC_BZ_D:
28351 gen_check_zero_element(bcond, df, wt);
28352 break;
28353 case OPC_BNZ_B:
28354 case OPC_BNZ_H:
28355 case OPC_BNZ_W:
28356 case OPC_BNZ_D:
28357 gen_check_zero_element(bcond, df, wt);
28358 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28359 break;
28360 }
28361
eeb3bba8 28362 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
28363
28364 ctx->hflags |= MIPS_HFLAG_BC;
28365 ctx->hflags |= MIPS_HFLAG_BDS32;
28366}
28367
4c789546
YK
28368static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28369{
28370#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28371 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28372 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28373 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28374
28375 TCGv_i32 twd = tcg_const_i32(wd);
28376 TCGv_i32 tws = tcg_const_i32(ws);
28377 TCGv_i32 ti8 = tcg_const_i32(i8);
28378
28379 switch (MASK_MSA_I8(ctx->opcode)) {
28380 case OPC_ANDI_B:
28381 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28382 break;
28383 case OPC_ORI_B:
28384 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28385 break;
28386 case OPC_NORI_B:
28387 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28388 break;
28389 case OPC_XORI_B:
28390 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28391 break;
28392 case OPC_BMNZI_B:
28393 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28394 break;
28395 case OPC_BMZI_B:
28396 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28397 break;
28398 case OPC_BSELI_B:
28399 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28400 break;
28401 case OPC_SHF_B:
28402 case OPC_SHF_H:
28403 case OPC_SHF_W:
28404 {
28405 uint8_t df = (ctx->opcode >> 24) & 0x3;
28406 if (df == DF_DOUBLE) {
9c708c7f 28407 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28408 } else {
28409 TCGv_i32 tdf = tcg_const_i32(df);
28410 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28411 tcg_temp_free_i32(tdf);
28412 }
28413 }
28414 break;
28415 default:
28416 MIPS_INVAL("MSA instruction");
9c708c7f 28417 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28418 break;
28419 }
28420
28421 tcg_temp_free_i32(twd);
28422 tcg_temp_free_i32(tws);
28423 tcg_temp_free_i32(ti8);
28424}
28425
80e71591
YK
28426static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28427{
28428#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28429 uint8_t df = (ctx->opcode >> 21) & 0x3;
28430 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28431 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28432 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28433 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28434
28435 TCGv_i32 tdf = tcg_const_i32(df);
28436 TCGv_i32 twd = tcg_const_i32(wd);
28437 TCGv_i32 tws = tcg_const_i32(ws);
28438 TCGv_i32 timm = tcg_temp_new_i32();
28439 tcg_gen_movi_i32(timm, u5);
28440
28441 switch (MASK_MSA_I5(ctx->opcode)) {
28442 case OPC_ADDVI_df:
28443 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28444 break;
28445 case OPC_SUBVI_df:
28446 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28447 break;
28448 case OPC_MAXI_S_df:
28449 tcg_gen_movi_i32(timm, s5);
28450 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28451 break;
28452 case OPC_MAXI_U_df:
28453 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28454 break;
28455 case OPC_MINI_S_df:
28456 tcg_gen_movi_i32(timm, s5);
28457 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28458 break;
28459 case OPC_MINI_U_df:
28460 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28461 break;
28462 case OPC_CEQI_df:
28463 tcg_gen_movi_i32(timm, s5);
28464 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28465 break;
28466 case OPC_CLTI_S_df:
28467 tcg_gen_movi_i32(timm, s5);
28468 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28469 break;
28470 case OPC_CLTI_U_df:
28471 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28472 break;
28473 case OPC_CLEI_S_df:
28474 tcg_gen_movi_i32(timm, s5);
28475 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28476 break;
28477 case OPC_CLEI_U_df:
28478 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28479 break;
28480 case OPC_LDI_df:
28481 {
28482 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28483 tcg_gen_movi_i32(timm, s10);
28484 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28485 }
28486 break;
28487 default:
28488 MIPS_INVAL("MSA instruction");
9c708c7f 28489 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
28490 break;
28491 }
28492
28493 tcg_temp_free_i32(tdf);
28494 tcg_temp_free_i32(twd);
28495 tcg_temp_free_i32(tws);
28496 tcg_temp_free_i32(timm);
28497}
28498
d4cf28de
YK
28499static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28500{
28501#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28502 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28503 uint32_t df = 0, m = 0;
28504 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28505 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28506
28507 TCGv_i32 tdf;
28508 TCGv_i32 tm;
28509 TCGv_i32 twd;
28510 TCGv_i32 tws;
28511
28512 if ((dfm & 0x40) == 0x00) {
28513 m = dfm & 0x3f;
28514 df = DF_DOUBLE;
28515 } else if ((dfm & 0x60) == 0x40) {
28516 m = dfm & 0x1f;
28517 df = DF_WORD;
28518 } else if ((dfm & 0x70) == 0x60) {
28519 m = dfm & 0x0f;
28520 df = DF_HALF;
28521 } else if ((dfm & 0x78) == 0x70) {
28522 m = dfm & 0x7;
28523 df = DF_BYTE;
28524 } else {
9c708c7f 28525 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28526 return;
28527 }
28528
28529 tdf = tcg_const_i32(df);
28530 tm = tcg_const_i32(m);
28531 twd = tcg_const_i32(wd);
28532 tws = tcg_const_i32(ws);
28533
28534 switch (MASK_MSA_BIT(ctx->opcode)) {
28535 case OPC_SLLI_df:
28536 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28537 break;
28538 case OPC_SRAI_df:
28539 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28540 break;
28541 case OPC_SRLI_df:
28542 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28543 break;
28544 case OPC_BCLRI_df:
28545 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28546 break;
28547 case OPC_BSETI_df:
28548 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28549 break;
28550 case OPC_BNEGI_df:
28551 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28552 break;
28553 case OPC_BINSLI_df:
28554 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28555 break;
28556 case OPC_BINSRI_df:
28557 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28558 break;
28559 case OPC_SAT_S_df:
28560 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28561 break;
28562 case OPC_SAT_U_df:
28563 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28564 break;
28565 case OPC_SRARI_df:
28566 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28567 break;
28568 case OPC_SRLRI_df:
28569 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28570 break;
28571 default:
28572 MIPS_INVAL("MSA instruction");
9c708c7f 28573 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28574 break;
28575 }
28576
28577 tcg_temp_free_i32(tdf);
28578 tcg_temp_free_i32(tm);
28579 tcg_temp_free_i32(twd);
28580 tcg_temp_free_i32(tws);
28581}
28582
28f99f08
YK
28583static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28584{
28585#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28586 uint8_t df = (ctx->opcode >> 21) & 0x3;
28587 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28588 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28589 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28590
28591 TCGv_i32 tdf = tcg_const_i32(df);
28592 TCGv_i32 twd = tcg_const_i32(wd);
28593 TCGv_i32 tws = tcg_const_i32(ws);
28594 TCGv_i32 twt = tcg_const_i32(wt);
28595
28596 switch (MASK_MSA_3R(ctx->opcode)) {
2e3eddb0
AM
28597 case OPC_BINSL_df:
28598 switch (df) {
28599 case DF_BYTE:
28600 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28601 break;
28602 case DF_HALF:
28603 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28604 break;
28605 case DF_WORD:
28606 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28607 break;
28608 case DF_DOUBLE:
28609 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28610 break;
28611 }
28612 break;
28613 case OPC_BINSR_df:
28614 switch (df) {
28615 case DF_BYTE:
28616 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28617 break;
28618 case DF_HALF:
28619 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28620 break;
28621 case DF_WORD:
28622 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28623 break;
28624 case DF_DOUBLE:
28625 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28626 break;
28627 }
28628 break;
a44d6d14
AM
28629 case OPC_BCLR_df:
28630 switch (df) {
28631 case DF_BYTE:
28632 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28633 break;
28634 case DF_HALF:
28635 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28636 break;
28637 case DF_WORD:
28638 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28639 break;
28640 case DF_DOUBLE:
28641 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28642 break;
28643 }
28644 break;
28645 case OPC_BNEG_df:
28646 switch (df) {
28647 case DF_BYTE:
28648 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28649 break;
28650 case DF_HALF:
28651 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28652 break;
28653 case DF_WORD:
28654 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28655 break;
28656 case DF_DOUBLE:
28657 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28658 break;
28659 }
28660 break;
28661 case OPC_BSET_df:
28662 switch (df) {
28663 case DF_BYTE:
28664 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28665 break;
28666 case DF_HALF:
28667 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28668 break;
28669 case DF_WORD:
28670 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28671 break;
28672 case DF_DOUBLE:
28673 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28674 break;
28675 }
28676 break;
c65ca134
AM
28677 case OPC_ADD_A_df:
28678 switch (df) {
28679 case DF_BYTE:
28680 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28681 break;
28682 case DF_HALF:
28683 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28684 break;
28685 case DF_WORD:
28686 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28687 break;
28688 case DF_DOUBLE:
28689 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28690 break;
28691 }
28692 break;
28693 case OPC_ADDS_A_df:
28694 switch (df) {
28695 case DF_BYTE:
28696 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28697 break;
28698 case DF_HALF:
28699 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28700 break;
28701 case DF_WORD:
28702 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28703 break;
28704 case DF_DOUBLE:
28705 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28706 break;
28707 }
28708 break;
28709 case OPC_ADDS_S_df:
28710 switch (df) {
28711 case DF_BYTE:
28712 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28713 break;
28714 case DF_HALF:
28715 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28716 break;
28717 case DF_WORD:
28718 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28719 break;
28720 case DF_DOUBLE:
28721 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28722 break;
28723 }
28724 break;
28725 case OPC_ADDS_U_df:
28726 switch (df) {
28727 case DF_BYTE:
28728 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28729 break;
28730 case DF_HALF:
28731 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28732 break;
28733 case DF_WORD:
28734 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28735 break;
28736 case DF_DOUBLE:
28737 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28738 break;
28739 }
28740 break;
28741 case OPC_ADDV_df:
28742 switch (df) {
28743 case DF_BYTE:
28744 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28745 break;
28746 case DF_HALF:
28747 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28748 break;
28749 case DF_WORD:
28750 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28751 break;
28752 case DF_DOUBLE:
28753 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28754 break;
28755 }
28756 break;
7672edc4
AM
28757 case OPC_AVE_S_df:
28758 switch (df) {
28759 case DF_BYTE:
28760 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28761 break;
28762 case DF_HALF:
28763 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28764 break;
28765 case DF_WORD:
28766 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28767 break;
28768 case DF_DOUBLE:
28769 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28770 break;
28771 }
28772 break;
28773 case OPC_AVE_U_df:
28774 switch (df) {
28775 case DF_BYTE:
28776 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28777 break;
28778 case DF_HALF:
28779 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28780 break;
28781 case DF_WORD:
28782 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28783 break;
28784 case DF_DOUBLE:
28785 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28786 break;
28787 }
28788 break;
755107e2
AM
28789 case OPC_AVER_S_df:
28790 switch (df) {
28791 case DF_BYTE:
28792 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28793 break;
28794 case DF_HALF:
28795 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28796 break;
28797 case DF_WORD:
28798 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28799 break;
28800 case DF_DOUBLE:
28801 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28802 break;
28803 }
28804 break;
28805 case OPC_AVER_U_df:
28806 switch (df) {
28807 case DF_BYTE:
28808 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28809 break;
28810 case DF_HALF:
28811 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28812 break;
28813 case DF_WORD:
28814 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28815 break;
28816 case DF_DOUBLE:
28817 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28818 break;
28819 }
28820 break;
ade7e788
AM
28821 case OPC_CEQ_df:
28822 switch (df) {
28823 case DF_BYTE:
28824 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28825 break;
28826 case DF_HALF:
28827 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28828 break;
28829 case DF_WORD:
28830 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28831 break;
28832 case DF_DOUBLE:
28833 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28834 break;
28835 }
28836 break;
0501bb1a
AM
28837 case OPC_CLE_S_df:
28838 switch (df) {
28839 case DF_BYTE:
28840 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28841 break;
28842 case DF_HALF:
28843 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28844 break;
28845 case DF_WORD:
28846 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28847 break;
28848 case DF_DOUBLE:
28849 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28850 break;
28851 }
28852 break;
28853 case OPC_CLE_U_df:
28854 switch (df) {
28855 case DF_BYTE:
28856 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28857 break;
28858 case DF_HALF:
28859 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28860 break;
28861 case DF_WORD:
28862 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28863 break;
28864 case DF_DOUBLE:
28865 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28866 break;
28867 }
28868 break;
11656699
AM
28869 case OPC_CLT_S_df:
28870 switch (df) {
28871 case DF_BYTE:
28872 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28873 break;
28874 case DF_HALF:
28875 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28876 break;
28877 case DF_WORD:
28878 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28879 break;
28880 case DF_DOUBLE:
28881 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28882 break;
28883 }
28884 break;
28885 case OPC_CLT_U_df:
28886 switch (df) {
28887 case DF_BYTE:
28888 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28889 break;
28890 case DF_HALF:
28891 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28892 break;
28893 case DF_WORD:
28894 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28895 break;
28896 case DF_DOUBLE:
28897 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28898 break;
28899 }
28900 break;
64a0257f
AM
28901 case OPC_DIV_S_df:
28902 switch (df) {
28903 case DF_BYTE:
28904 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28905 break;
28906 case DF_HALF:
28907 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28908 break;
28909 case DF_WORD:
28910 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28911 break;
28912 case DF_DOUBLE:
28913 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28914 break;
28915 }
28916 break;
28917 case OPC_DIV_U_df:
28918 switch (df) {
28919 case DF_BYTE:
28920 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28921 break;
28922 case DF_HALF:
28923 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28924 break;
28925 case DF_WORD:
28926 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28927 break;
28928 case DF_DOUBLE:
28929 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28930 break;
28931 }
28932 break;
e8e01ef0
AM
28933 case OPC_MAX_A_df:
28934 switch (df) {
28935 case DF_BYTE:
28936 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28937 break;
28938 case DF_HALF:
28939 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28940 break;
28941 case DF_WORD:
28942 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28943 break;
28944 case DF_DOUBLE:
28945 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28946 break;
28947 }
28948 break;
2db26305
AM
28949 case OPC_MAX_S_df:
28950 switch (df) {
28951 case DF_BYTE:
28952 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28953 break;
28954 case DF_HALF:
28955 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28956 break;
28957 case DF_WORD:
28958 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28959 break;
28960 case DF_DOUBLE:
28961 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28962 break;
28963 }
28964 break;
28965 case OPC_MAX_U_df:
28966 switch (df) {
28967 case DF_BYTE:
28968 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28969 break;
28970 case DF_HALF:
28971 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28972 break;
28973 case DF_WORD:
28974 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28975 break;
28976 case DF_DOUBLE:
28977 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28978 break;
28979 }
28980 break;
e8e01ef0
AM
28981 case OPC_MIN_A_df:
28982 switch (df) {
28983 case DF_BYTE:
28984 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28985 break;
28986 case DF_HALF:
28987 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28988 break;
28989 case DF_WORD:
28990 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28991 break;
28992 case DF_DOUBLE:
28993 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28994 break;
28995 }
28996 break;
2db26305
AM
28997 case OPC_MIN_S_df:
28998 switch (df) {
28999 case DF_BYTE:
29000 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29001 break;
29002 case DF_HALF:
29003 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29004 break;
29005 case DF_WORD:
29006 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29007 break;
29008 case DF_DOUBLE:
29009 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29010 break;
29011 }
29012 break;
29013 case OPC_MIN_U_df:
29014 switch (df) {
29015 case DF_BYTE:
29016 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29017 break;
29018 case DF_HALF:
29019 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29020 break;
29021 case DF_WORD:
29022 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29023 break;
29024 case DF_DOUBLE:
29025 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29026 break;
29027 }
29028 break;
a6387ea5
AM
29029 case OPC_MOD_S_df:
29030 switch (df) {
29031 case DF_BYTE:
29032 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29033 break;
29034 case DF_HALF:
29035 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29036 break;
29037 case DF_WORD:
29038 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29039 break;
29040 case DF_DOUBLE:
29041 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29042 break;
29043 }
29044 break;
29045 case OPC_MOD_U_df:
29046 switch (df) {
29047 case DF_BYTE:
29048 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29049 break;
29050 case DF_HALF:
29051 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29052 break;
29053 case DF_WORD:
29054 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29055 break;
29056 case DF_DOUBLE:
29057 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29058 break;
29059 }
29060 break;
7a7a162a
AM
29061 case OPC_MADDV_df:
29062 switch (df) {
29063 case DF_BYTE:
29064 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29065 break;
29066 case DF_HALF:
29067 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29068 break;
29069 case DF_WORD:
29070 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29071 break;
29072 case DF_DOUBLE:
29073 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29074 break;
29075 }
29076 break;
5f148a02
AM
29077 case OPC_MSUBV_df:
29078 switch (df) {
29079 case DF_BYTE:
29080 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29081 break;
29082 case DF_HALF:
29083 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29084 break;
29085 case DF_WORD:
29086 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29087 break;
29088 case DF_DOUBLE:
29089 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29090 break;
29091 }
29092 break;
f392d134
AM
29093 case OPC_ASUB_S_df:
29094 switch (df) {
29095 case DF_BYTE:
29096 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29097 break;
29098 case DF_HALF:
29099 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29100 break;
29101 case DF_WORD:
29102 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29103 break;
29104 case DF_DOUBLE:
29105 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29106 break;
29107 }
29108 break;
29109 case OPC_ASUB_U_df:
29110 switch (df) {
29111 case DF_BYTE:
29112 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29113 break;
29114 case DF_HALF:
29115 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29116 break;
29117 case DF_WORD:
29118 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29119 break;
29120 case DF_DOUBLE:
29121 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29122 break;
29123 }
29124 break;
fb5f59b4
AM
29125 case OPC_ILVEV_df:
29126 switch (df) {
29127 case DF_BYTE:
29128 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29129 break;
29130 case DF_HALF:
29131 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29132 break;
29133 case DF_WORD:
29134 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29135 break;
29136 case DF_DOUBLE:
29137 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29138 break;
29139 }
29140 break;
29141 case OPC_ILVOD_df:
29142 switch (df) {
29143 case DF_BYTE:
29144 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29145 break;
29146 case DF_HALF:
29147 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29148 break;
29149 case DF_WORD:
29150 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29151 break;
29152 case DF_DOUBLE:
29153 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29154 break;
29155 }
29156 break;
29157 case OPC_ILVL_df:
29158 switch (df) {
29159 case DF_BYTE:
29160 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29161 break;
29162 case DF_HALF:
29163 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29164 break;
29165 case DF_WORD:
29166 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29167 break;
29168 case DF_DOUBLE:
29169 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29170 break;
29171 }
29172 break;
29173 case OPC_ILVR_df:
29174 switch (df) {
29175 case DF_BYTE:
29176 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29177 break;
29178 case DF_HALF:
29179 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29180 break;
29181 case DF_WORD:
29182 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29183 break;
29184 case DF_DOUBLE:
29185 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29186 break;
29187 }
29188 break;
8a0ee380
AM
29189 case OPC_PCKEV_df:
29190 switch (df) {
29191 case DF_BYTE:
29192 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29193 break;
29194 case DF_HALF:
29195 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29196 break;
29197 case DF_WORD:
29198 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29199 break;
29200 case DF_DOUBLE:
29201 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29202 break;
29203 }
29204 break;
29205 case OPC_PCKOD_df:
29206 switch (df) {
29207 case DF_BYTE:
29208 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29209 break;
29210 case DF_HALF:
29211 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29212 break;
29213 case DF_WORD:
29214 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29215 break;
29216 case DF_DOUBLE:
29217 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29218 break;
29219 }
29220 break;
28f99f08 29221 case OPC_SLL_df:
4d52cc2b
AM
29222 switch (df) {
29223 case DF_BYTE:
29224 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29225 break;
29226 case DF_HALF:
29227 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29228 break;
29229 case DF_WORD:
29230 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29231 break;
29232 case DF_DOUBLE:
29233 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29234 break;
29235 }
29236 break;
29237 case OPC_SRA_df:
29238 switch (df) {
29239 case DF_BYTE:
29240 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29241 break;
29242 case DF_HALF:
29243 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29244 break;
29245 case DF_WORD:
29246 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29247 break;
29248 case DF_DOUBLE:
29249 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29250 break;
29251 }
29252 break;
29253 case OPC_SRAR_df:
29254 switch (df) {
29255 case DF_BYTE:
29256 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29257 break;
29258 case DF_HALF:
29259 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29260 break;
29261 case DF_WORD:
29262 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29263 break;
29264 case DF_DOUBLE:
29265 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29266 break;
29267 }
29268 break;
29269 case OPC_SRL_df:
29270 switch (df) {
29271 case DF_BYTE:
29272 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29273 break;
29274 case DF_HALF:
29275 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29276 break;
29277 case DF_WORD:
29278 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29279 break;
29280 case DF_DOUBLE:
29281 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29282 break;
29283 }
29284 break;
29285 case OPC_SRLR_df:
29286 switch (df) {
29287 case DF_BYTE:
29288 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29289 break;
29290 case DF_HALF:
29291 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29292 break;
29293 case DF_WORD:
29294 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29295 break;
29296 case DF_DOUBLE:
29297 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29298 break;
29299 }
28f99f08 29300 break;
28f99f08 29301 case OPC_SUBS_S_df:
534e4001
AM
29302 switch (df) {
29303 case DF_BYTE:
29304 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29305 break;
29306 case DF_HALF:
29307 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29308 break;
29309 case DF_WORD:
29310 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29311 break;
29312 case DF_DOUBLE:
29313 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29314 break;
29315 }
28f99f08
YK
29316 break;
29317 case OPC_MULV_df:
05135034
AM
29318 switch (df) {
29319 case DF_BYTE:
29320 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29321 break;
29322 case DF_HALF:
29323 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29324 break;
29325 case DF_WORD:
29326 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29327 break;
29328 case DF_DOUBLE:
29329 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29330 break;
29331 }
28f99f08
YK
29332 break;
29333 case OPC_SLD_df:
29334 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29335 break;
29336 case OPC_VSHF_df:
29337 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29338 break;
28f99f08 29339 case OPC_SUBV_df:
83b2e79a
AM
29340 switch (df) {
29341 case DF_BYTE:
29342 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29343 break;
29344 case DF_HALF:
29345 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29346 break;
29347 case DF_WORD:
29348 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29349 break;
29350 case DF_DOUBLE:
29351 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29352 break;
29353 }
28f99f08 29354 break;
28f99f08 29355 case OPC_SUBS_U_df:
81b53858
AM
29356 switch (df) {
29357 case DF_BYTE:
29358 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29359 break;
29360 case DF_HALF:
29361 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29362 break;
29363 case DF_WORD:
29364 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29365 break;
29366 case DF_DOUBLE:
29367 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29368 break;
29369 }
28f99f08 29370 break;
28f99f08
YK
29371 case OPC_SPLAT_df:
29372 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29373 break;
28f99f08 29374 case OPC_SUBSUS_U_df:
55a04640
AM
29375 switch (df) {
29376 case DF_BYTE:
29377 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29378 break;
29379 case DF_HALF:
29380 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29381 break;
29382 case DF_WORD:
29383 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29384 break;
29385 case DF_DOUBLE:
29386 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29387 break;
29388 }
28f99f08 29389 break;
28f99f08 29390 case OPC_SUBSUU_S_df:
cb4ac991
AM
29391 switch (df) {
29392 case DF_BYTE:
29393 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29394 break;
29395 case DF_HALF:
29396 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29397 break;
29398 case DF_WORD:
29399 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29400 break;
29401 case DF_DOUBLE:
29402 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29403 break;
29404 }
28f99f08 29405 break;
28f99f08
YK
29406
29407 case OPC_DOTP_S_df:
29408 case OPC_DOTP_U_df:
29409 case OPC_DPADD_S_df:
29410 case OPC_DPADD_U_df:
29411 case OPC_DPSUB_S_df:
29412 case OPC_HADD_S_df:
29413 case OPC_DPSUB_U_df:
29414 case OPC_HADD_U_df:
29415 case OPC_HSUB_S_df:
29416 case OPC_HSUB_U_df:
29417 if (df == DF_BYTE) {
9c708c7f
PD
29418 generate_exception_end(ctx, EXCP_RI);
29419 break;
28f99f08
YK
29420 }
29421 switch (MASK_MSA_3R(ctx->opcode)) {
dc0af931
AM
29422 case OPC_HADD_S_df:
29423 switch (df) {
29424 case DF_HALF:
29425 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29426 break;
29427 case DF_WORD:
29428 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29429 break;
29430 case DF_DOUBLE:
29431 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29432 break;
29433 }
29434 break;
29435 case OPC_HADD_U_df:
29436 switch (df) {
29437 case DF_HALF:
29438 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29439 break;
29440 case DF_WORD:
29441 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29442 break;
29443 case DF_DOUBLE:
29444 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29445 break;
29446 }
29447 break;
b24b9aec
AM
29448 case OPC_HSUB_S_df:
29449 switch (df) {
29450 case DF_HALF:
29451 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29452 break;
29453 case DF_WORD:
29454 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29455 break;
29456 case DF_DOUBLE:
29457 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29458 break;
29459 }
29460 break;
29461 case OPC_HSUB_U_df:
29462 switch (df) {
29463 case DF_HALF:
29464 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29465 break;
29466 case DF_WORD:
29467 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29468 break;
29469 case DF_DOUBLE:
29470 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29471 break;
29472 }
29473 break;
28f99f08 29474 case OPC_DOTP_S_df:
165cacb6
AM
29475 switch (df) {
29476 case DF_HALF:
29477 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29478 break;
29479 case DF_WORD:
29480 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29481 break;
29482 case DF_DOUBLE:
29483 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29484 break;
29485 }
28f99f08
YK
29486 break;
29487 case OPC_DOTP_U_df:
72c6a6e2
AM
29488 switch (df) {
29489 case DF_HALF:
29490 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29491 break;
29492 case DF_WORD:
29493 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29494 break;
29495 case DF_DOUBLE:
29496 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29497 break;
29498 }
28f99f08
YK
29499 break;
29500 case OPC_DPADD_S_df:
9f5840a6
AM
29501 switch (df) {
29502 case DF_HALF:
29503 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29504 break;
29505 case DF_WORD:
29506 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29507 break;
29508 case DF_DOUBLE:
29509 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29510 break;
29511 }
28f99f08
YK
29512 break;
29513 case OPC_DPADD_U_df:
e5e0777e
AM
29514 switch (df) {
29515 case DF_HALF:
29516 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29517 break;
29518 case DF_WORD:
29519 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29520 break;
29521 case DF_DOUBLE:
29522 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29523 break;
29524 }
28f99f08
YK
29525 break;
29526 case OPC_DPSUB_S_df:
8ed86716
AM
29527 switch (df) {
29528 case DF_HALF:
29529 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29530 break;
29531 case DF_WORD:
29532 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29533 break;
29534 case DF_DOUBLE:
29535 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29536 break;
29537 }
28f99f08 29538 break;
28f99f08 29539 case OPC_DPSUB_U_df:
0c8c76ac
AM
29540 switch (df) {
29541 case DF_HALF:
29542 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29543 break;
29544 case DF_WORD:
29545 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29546 break;
29547 case DF_DOUBLE:
29548 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29549 break;
29550 }
28f99f08 29551 break;
28f99f08
YK
29552 }
29553 break;
29554 default:
29555 MIPS_INVAL("MSA instruction");
9c708c7f 29556 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
29557 break;
29558 }
29559 tcg_temp_free_i32(twd);
29560 tcg_temp_free_i32(tws);
29561 tcg_temp_free_i32(twt);
29562 tcg_temp_free_i32(tdf);
29563}
29564
1e608ec1
YK
29565static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29566{
29567#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29568 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29569 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29570 TCGv telm = tcg_temp_new();
29571 TCGv_i32 tsr = tcg_const_i32(source);
29572 TCGv_i32 tdt = tcg_const_i32(dest);
29573
29574 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29575 case OPC_CTCMSA:
29576 gen_load_gpr(telm, source);
29577 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29578 break;
29579 case OPC_CFCMSA:
29580 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29581 gen_store_gpr(telm, dest);
29582 break;
29583 case OPC_MOVE_V:
29584 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29585 break;
29586 default:
29587 MIPS_INVAL("MSA instruction");
9c708c7f 29588 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29589 break;
29590 }
29591
29592 tcg_temp_free(telm);
29593 tcg_temp_free_i32(tdt);
29594 tcg_temp_free_i32(tsr);
29595}
29596
29597static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29598 uint32_t n)
29599{
29600#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29601 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29602 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29603
29604 TCGv_i32 tws = tcg_const_i32(ws);
29605 TCGv_i32 twd = tcg_const_i32(wd);
29606 TCGv_i32 tn = tcg_const_i32(n);
29607 TCGv_i32 tdf = tcg_const_i32(df);
29608
29609 switch (MASK_MSA_ELM(ctx->opcode)) {
29610 case OPC_SLDI_df:
29611 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29612 break;
29613 case OPC_SPLATI_df:
29614 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29615 break;
29616 case OPC_INSVE_df:
29617 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29618 break;
29619 case OPC_COPY_S_df:
29620 case OPC_COPY_U_df:
29621 case OPC_INSERT_df:
29622#if !defined(TARGET_MIPS64)
29623 /* Double format valid only for MIPS64 */
29624 if (df == DF_DOUBLE) {
9c708c7f 29625 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29626 break;
29627 }
41d28858
MM
29628 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29629 (df == DF_WORD)) {
29630 generate_exception_end(ctx, EXCP_RI);
29631 break;
29632 }
1e608ec1
YK
29633#endif
29634 switch (MASK_MSA_ELM(ctx->opcode)) {
29635 case OPC_COPY_S_df:
cab48881 29636 if (likely(wd != 0)) {
631c4674
MM
29637 switch (df) {
29638 case DF_BYTE:
29639 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29640 break;
29641 case DF_HALF:
29642 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29643 break;
29644 case DF_WORD:
29645 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29646 break;
29647#if defined(TARGET_MIPS64)
29648 case DF_DOUBLE:
29649 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29650 break;
29651#endif
29652 default:
29653 assert(0);
29654 }
cab48881 29655 }
1e608ec1
YK
29656 break;
29657 case OPC_COPY_U_df:
cab48881 29658 if (likely(wd != 0)) {
41d28858
MM
29659 switch (df) {
29660 case DF_BYTE:
29661 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29662 break;
29663 case DF_HALF:
29664 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29665 break;
29666#if defined(TARGET_MIPS64)
29667 case DF_WORD:
29668 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29669 break;
29670#endif
29671 default:
29672 assert(0);
29673 }
cab48881 29674 }
1e608ec1
YK
29675 break;
29676 case OPC_INSERT_df:
c1c9a10f
MM
29677 switch (df) {
29678 case DF_BYTE:
29679 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29680 break;
29681 case DF_HALF:
29682 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29683 break;
29684 case DF_WORD:
29685 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29686 break;
29687#if defined(TARGET_MIPS64)
29688 case DF_DOUBLE:
29689 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29690 break;
29691#endif
29692 default:
29693 assert(0);
29694 }
1e608ec1
YK
29695 break;
29696 }
29697 break;
29698 default:
29699 MIPS_INVAL("MSA instruction");
9c708c7f 29700 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29701 }
29702 tcg_temp_free_i32(twd);
29703 tcg_temp_free_i32(tws);
29704 tcg_temp_free_i32(tn);
29705 tcg_temp_free_i32(tdf);
29706}
29707
29708static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29709{
29710 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29711 uint32_t df = 0, n = 0;
29712
29713 if ((dfn & 0x30) == 0x00) {
29714 n = dfn & 0x0f;
29715 df = DF_BYTE;
29716 } else if ((dfn & 0x38) == 0x20) {
29717 n = dfn & 0x07;
29718 df = DF_HALF;
29719 } else if ((dfn & 0x3c) == 0x30) {
29720 n = dfn & 0x03;
29721 df = DF_WORD;
29722 } else if ((dfn & 0x3e) == 0x38) {
29723 n = dfn & 0x01;
29724 df = DF_DOUBLE;
29725 } else if (dfn == 0x3E) {
29726 /* CTCMSA, CFCMSA, MOVE.V */
29727 gen_msa_elm_3e(env, ctx);
29728 return;
29729 } else {
9c708c7f 29730 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29731 return;
29732 }
29733
29734 gen_msa_elm_df(env, ctx, df, n);
29735}
29736
7d05b9c8
YK
29737static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29738{
29739#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29740 uint8_t df = (ctx->opcode >> 21) & 0x1;
29741 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29742 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29743 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29744
29745 TCGv_i32 twd = tcg_const_i32(wd);
29746 TCGv_i32 tws = tcg_const_i32(ws);
29747 TCGv_i32 twt = tcg_const_i32(wt);
29748 TCGv_i32 tdf = tcg_temp_new_i32();
29749
29750 /* adjust df value for floating-point instruction */
29751 tcg_gen_movi_i32(tdf, df + 2);
29752
29753 switch (MASK_MSA_3RF(ctx->opcode)) {
29754 case OPC_FCAF_df:
29755 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29756 break;
29757 case OPC_FADD_df:
29758 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29759 break;
29760 case OPC_FCUN_df:
29761 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29762 break;
29763 case OPC_FSUB_df:
29764 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29765 break;
29766 case OPC_FCOR_df:
29767 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29768 break;
29769 case OPC_FCEQ_df:
29770 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29771 break;
29772 case OPC_FMUL_df:
29773 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29774 break;
29775 case OPC_FCUNE_df:
29776 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29777 break;
29778 case OPC_FCUEQ_df:
29779 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29780 break;
29781 case OPC_FDIV_df:
29782 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29783 break;
29784 case OPC_FCNE_df:
29785 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29786 break;
29787 case OPC_FCLT_df:
29788 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29789 break;
29790 case OPC_FMADD_df:
29791 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29792 break;
29793 case OPC_MUL_Q_df:
29794 tcg_gen_movi_i32(tdf, df + 1);
29795 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29796 break;
29797 case OPC_FCULT_df:
29798 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29799 break;
29800 case OPC_FMSUB_df:
29801 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29802 break;
29803 case OPC_MADD_Q_df:
29804 tcg_gen_movi_i32(tdf, df + 1);
29805 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29806 break;
29807 case OPC_FCLE_df:
29808 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29809 break;
29810 case OPC_MSUB_Q_df:
29811 tcg_gen_movi_i32(tdf, df + 1);
29812 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29813 break;
29814 case OPC_FCULE_df:
29815 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29816 break;
29817 case OPC_FEXP2_df:
29818 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29819 break;
29820 case OPC_FSAF_df:
29821 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29822 break;
29823 case OPC_FEXDO_df:
29824 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29825 break;
29826 case OPC_FSUN_df:
29827 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29828 break;
29829 case OPC_FSOR_df:
29830 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29831 break;
29832 case OPC_FSEQ_df:
29833 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29834 break;
29835 case OPC_FTQ_df:
29836 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29837 break;
29838 case OPC_FSUNE_df:
29839 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29840 break;
29841 case OPC_FSUEQ_df:
29842 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29843 break;
29844 case OPC_FSNE_df:
29845 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29846 break;
29847 case OPC_FSLT_df:
29848 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29849 break;
29850 case OPC_FMIN_df:
29851 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29852 break;
29853 case OPC_MULR_Q_df:
29854 tcg_gen_movi_i32(tdf, df + 1);
29855 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29856 break;
29857 case OPC_FSULT_df:
29858 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29859 break;
29860 case OPC_FMIN_A_df:
29861 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29862 break;
29863 case OPC_MADDR_Q_df:
29864 tcg_gen_movi_i32(tdf, df + 1);
29865 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29866 break;
29867 case OPC_FSLE_df:
29868 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29869 break;
29870 case OPC_FMAX_df:
29871 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29872 break;
29873 case OPC_MSUBR_Q_df:
29874 tcg_gen_movi_i32(tdf, df + 1);
29875 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29876 break;
29877 case OPC_FSULE_df:
29878 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29879 break;
29880 case OPC_FMAX_A_df:
29881 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29882 break;
29883 default:
29884 MIPS_INVAL("MSA instruction");
9c708c7f 29885 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
29886 break;
29887 }
29888
29889 tcg_temp_free_i32(twd);
29890 tcg_temp_free_i32(tws);
29891 tcg_temp_free_i32(twt);
29892 tcg_temp_free_i32(tdf);
29893}
29894
cbe50b9a
YK
29895static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29896{
29897#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29898 (op & (0x7 << 18)))
29899 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29900 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29901 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29902 uint8_t df = (ctx->opcode >> 16) & 0x3;
29903 TCGv_i32 twd = tcg_const_i32(wd);
29904 TCGv_i32 tws = tcg_const_i32(ws);
29905 TCGv_i32 twt = tcg_const_i32(wt);
29906 TCGv_i32 tdf = tcg_const_i32(df);
29907
29908 switch (MASK_MSA_2R(ctx->opcode)) {
29909 case OPC_FILL_df:
29910#if !defined(TARGET_MIPS64)
29911 /* Double format valid only for MIPS64 */
29912 if (df == DF_DOUBLE) {
9c708c7f 29913 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29914 break;
29915 }
29916#endif
29917 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29918 break;
cbe50b9a 29919 case OPC_NLOC_df:
81c4b059
AM
29920 switch (df) {
29921 case DF_BYTE:
29922 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29923 break;
29924 case DF_HALF:
29925 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29926 break;
29927 case DF_WORD:
29928 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29929 break;
29930 case DF_DOUBLE:
29931 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29932 break;
29933 }
cbe50b9a
YK
29934 break;
29935 case OPC_NLZC_df:
81c4b059
AM
29936 switch (df) {
29937 case DF_BYTE:
29938 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29939 break;
29940 case DF_HALF:
29941 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29942 break;
29943 case DF_WORD:
29944 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29945 break;
29946 case DF_DOUBLE:
29947 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29948 break;
29949 }
cbe50b9a 29950 break;
4c5daf38
AM
29951 case OPC_PCNT_df:
29952 switch (df) {
29953 case DF_BYTE:
29954 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29955 break;
29956 case DF_HALF:
29957 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29958 break;
29959 case DF_WORD:
29960 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29961 break;
29962 case DF_DOUBLE:
29963 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29964 break;
29965 }
29966 break;
cbe50b9a
YK
29967 default:
29968 MIPS_INVAL("MSA instruction");
9c708c7f 29969 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29970 break;
29971 }
29972
29973 tcg_temp_free_i32(twd);
29974 tcg_temp_free_i32(tws);
29975 tcg_temp_free_i32(twt);
29976 tcg_temp_free_i32(tdf);
29977}
29978
3bdeb688
YK
29979static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29980{
29981#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29982 (op & (0xf << 17)))
29983 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29984 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29985 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29986 uint8_t df = (ctx->opcode >> 16) & 0x1;
29987 TCGv_i32 twd = tcg_const_i32(wd);
29988 TCGv_i32 tws = tcg_const_i32(ws);
29989 TCGv_i32 twt = tcg_const_i32(wt);
29990 /* adjust df value for floating-point instruction */
29991 TCGv_i32 tdf = tcg_const_i32(df + 2);
29992
29993 switch (MASK_MSA_2RF(ctx->opcode)) {
29994 case OPC_FCLASS_df:
29995 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29996 break;
29997 case OPC_FTRUNC_S_df:
29998 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29999 break;
30000 case OPC_FTRUNC_U_df:
30001 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30002 break;
30003 case OPC_FSQRT_df:
30004 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30005 break;
30006 case OPC_FRSQRT_df:
30007 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30008 break;
30009 case OPC_FRCP_df:
30010 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30011 break;
30012 case OPC_FRINT_df:
30013 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30014 break;
30015 case OPC_FLOG2_df:
30016 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30017 break;
30018 case OPC_FEXUPL_df:
30019 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30020 break;
30021 case OPC_FEXUPR_df:
30022 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30023 break;
30024 case OPC_FFQL_df:
30025 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30026 break;
30027 case OPC_FFQR_df:
30028 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30029 break;
30030 case OPC_FTINT_S_df:
30031 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30032 break;
30033 case OPC_FTINT_U_df:
30034 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30035 break;
30036 case OPC_FFINT_S_df:
30037 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30038 break;
30039 case OPC_FFINT_U_df:
30040 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30041 break;
30042 }
30043
30044 tcg_temp_free_i32(twd);
30045 tcg_temp_free_i32(tws);
30046 tcg_temp_free_i32(twt);
30047 tcg_temp_free_i32(tdf);
30048}
30049
cbe50b9a
YK
30050static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30051{
30052#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30053 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30054 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30055 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30056 TCGv_i32 twd = tcg_const_i32(wd);
30057 TCGv_i32 tws = tcg_const_i32(ws);
30058 TCGv_i32 twt = tcg_const_i32(wt);
30059
30060 switch (MASK_MSA_VEC(ctx->opcode)) {
30061 case OPC_AND_V:
30062 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30063 break;
30064 case OPC_OR_V:
30065 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30066 break;
30067 case OPC_NOR_V:
30068 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30069 break;
30070 case OPC_XOR_V:
30071 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30072 break;
30073 case OPC_BMNZ_V:
30074 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30075 break;
30076 case OPC_BMZ_V:
30077 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30078 break;
30079 case OPC_BSEL_V:
30080 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30081 break;
30082 default:
30083 MIPS_INVAL("MSA instruction");
9c708c7f 30084 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30085 break;
30086 }
30087
30088 tcg_temp_free_i32(twd);
30089 tcg_temp_free_i32(tws);
30090 tcg_temp_free_i32(twt);
30091}
30092
30093static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30094{
30095 switch (MASK_MSA_VEC(ctx->opcode)) {
30096 case OPC_AND_V:
30097 case OPC_OR_V:
30098 case OPC_NOR_V:
30099 case OPC_XOR_V:
30100 case OPC_BMNZ_V:
30101 case OPC_BMZ_V:
30102 case OPC_BSEL_V:
30103 gen_msa_vec_v(env, ctx);
30104 break;
30105 case OPC_MSA_2R:
30106 gen_msa_2r(env, ctx);
30107 break;
3bdeb688
YK
30108 case OPC_MSA_2RF:
30109 gen_msa_2rf(env, ctx);
30110 break;
cbe50b9a
YK
30111 default:
30112 MIPS_INVAL("MSA instruction");
9c708c7f 30113 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30114 break;
30115 }
30116}
30117
4c789546
YK
30118static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30119{
30120 uint32_t opcode = ctx->opcode;
30121 check_insn(ctx, ASE_MSA);
30122 check_msa_access(ctx);
30123
30124 switch (MASK_MSA_MINOR(opcode)) {
30125 case OPC_MSA_I8_00:
30126 case OPC_MSA_I8_01:
30127 case OPC_MSA_I8_02:
30128 gen_msa_i8(env, ctx);
30129 break;
80e71591
YK
30130 case OPC_MSA_I5_06:
30131 case OPC_MSA_I5_07:
30132 gen_msa_i5(env, ctx);
30133 break;
d4cf28de
YK
30134 case OPC_MSA_BIT_09:
30135 case OPC_MSA_BIT_0A:
30136 gen_msa_bit(env, ctx);
30137 break;
28f99f08
YK
30138 case OPC_MSA_3R_0D:
30139 case OPC_MSA_3R_0E:
30140 case OPC_MSA_3R_0F:
30141 case OPC_MSA_3R_10:
30142 case OPC_MSA_3R_11:
30143 case OPC_MSA_3R_12:
30144 case OPC_MSA_3R_13:
30145 case OPC_MSA_3R_14:
30146 case OPC_MSA_3R_15:
30147 gen_msa_3r(env, ctx);
30148 break;
1e608ec1
YK
30149 case OPC_MSA_ELM:
30150 gen_msa_elm(env, ctx);
30151 break;
7d05b9c8
YK
30152 case OPC_MSA_3RF_1A:
30153 case OPC_MSA_3RF_1B:
30154 case OPC_MSA_3RF_1C:
30155 gen_msa_3rf(env, ctx);
30156 break;
cbe50b9a
YK
30157 case OPC_MSA_VEC:
30158 gen_msa_vec(env, ctx);
30159 break;
f7685877
YK
30160 case OPC_LD_B:
30161 case OPC_LD_H:
30162 case OPC_LD_W:
30163 case OPC_LD_D:
30164 case OPC_ST_B:
30165 case OPC_ST_H:
30166 case OPC_ST_W:
30167 case OPC_ST_D:
30168 {
30169 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30170 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30171 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30172 uint8_t df = (ctx->opcode >> 0) & 0x3;
30173
f7685877 30174 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
30175 TCGv taddr = tcg_temp_new();
30176 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
30177
30178 switch (MASK_MSA_MINOR(opcode)) {
30179 case OPC_LD_B:
adc370a4
YK
30180 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30181 break;
f7685877 30182 case OPC_LD_H:
adc370a4
YK
30183 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30184 break;
f7685877 30185 case OPC_LD_W:
adc370a4
YK
30186 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30187 break;
f7685877 30188 case OPC_LD_D:
adc370a4 30189 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
30190 break;
30191 case OPC_ST_B:
adc370a4
YK
30192 gen_helper_msa_st_b(cpu_env, twd, taddr);
30193 break;
f7685877 30194 case OPC_ST_H:
adc370a4
YK
30195 gen_helper_msa_st_h(cpu_env, twd, taddr);
30196 break;
f7685877 30197 case OPC_ST_W:
adc370a4
YK
30198 gen_helper_msa_st_w(cpu_env, twd, taddr);
30199 break;
f7685877 30200 case OPC_ST_D:
adc370a4 30201 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
30202 break;
30203 }
30204
30205 tcg_temp_free_i32(twd);
adc370a4 30206 tcg_temp_free(taddr);
f7685877
YK
30207 }
30208 break;
4c789546
YK
30209 default:
30210 MIPS_INVAL("MSA instruction");
9c708c7f 30211 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
30212 break;
30213 }
30214
30215}
30216
d2bfa6e6 30217static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
30218{
30219 int32_t offset;
30220 int rs, rt, rd, sa;
30221 uint32_t op, op1;
30222 int16_t imm;
30223
30224 /* make sure instructions are on a word boundary */
eeb3bba8
EC
30225 if (ctx->base.pc_next & 0x3) {
30226 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 30227 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
30228 return;
30229 }
30230
30231 /* Handle blikely not taken case */
30232 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 30233 TCGLabel *l1 = gen_new_label();
099e5b4d 30234
099e5b4d
LA
30235 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30236 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 30237 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
30238 gen_set_label(l1);
30239 }
30240
099e5b4d
LA
30241 op = MASK_OP_MAJOR(ctx->opcode);
30242 rs = (ctx->opcode >> 21) & 0x1f;
30243 rt = (ctx->opcode >> 16) & 0x1f;
30244 rd = (ctx->opcode >> 11) & 0x1f;
30245 sa = (ctx->opcode >> 6) & 0x1f;
30246 imm = (int16_t)ctx->opcode;
30247 switch (op) {
30248 case OPC_SPECIAL:
30249 decode_opc_special(env, ctx);
30250 break;
30251 case OPC_SPECIAL2:
37b9aae2 30252#if defined(TARGET_MIPS64)
71b8a6b3 30253 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 30254 decode_mmi(env, ctx);
37b9aae2
MM
30255#else
30256 if (ctx->insn_flags & ASE_MXU) {
0a348b9a 30257 decode_opc_mxu(env, ctx);
b621f018 30258#endif
71b8a6b3
FN
30259 } else {
30260 decode_opc_special2_legacy(env, ctx);
30261 }
099e5b4d
LA
30262 break;
30263 case OPC_SPECIAL3:
37b9aae2 30264#if defined(TARGET_MIPS64)
bb41e74b 30265 if (ctx->insn_flags & INSN_R5900) {
874b2879 30266 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
30267 } else {
30268 decode_opc_special3(env, ctx);
30269 }
37b9aae2
MM
30270#else
30271 decode_opc_special3(env, ctx);
30272#endif
099e5b4d 30273 break;
7a387fff
TS
30274 case OPC_REGIMM:
30275 op1 = MASK_REGIMM(ctx->opcode);
30276 switch (op1) {
fecd2646
LA
30277 case OPC_BLTZL: /* REGIMM branches */
30278 case OPC_BGEZL:
30279 case OPC_BLTZALL:
30280 case OPC_BGEZALL:
d9224450 30281 check_insn(ctx, ISA_MIPS2);
fecd2646 30282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30283 /* Fallthrough */
fecd2646
LA
30284 case OPC_BLTZ:
30285 case OPC_BGEZ:
b231c103 30286 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30287 break;
fecd2646
LA
30288 case OPC_BLTZAL:
30289 case OPC_BGEZAL:
0aefa333
YK
30290 if (ctx->insn_flags & ISA_MIPS32R6) {
30291 if (rs == 0) {
30292 /* OPC_NAL, OPC_BAL */
b231c103 30293 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 30294 } else {
9c708c7f 30295 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
30296 }
30297 } else {
b231c103 30298 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30299 }
c9602061 30300 break;
c2e19f3c
AM
30301 case OPC_TGEI: /* REGIMM traps */
30302 case OPC_TGEIU:
30303 case OPC_TLTI:
30304 case OPC_TLTIU:
30305 case OPC_TEQI:
30306
7a387fff 30307 case OPC_TNEI:
d9224450 30308 check_insn(ctx, ISA_MIPS2);
fecd2646 30309 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
30310 gen_trap(ctx, op1, rs, -1, imm);
30311 break;
bb238210
YK
30312 case OPC_SIGRIE:
30313 check_insn(ctx, ISA_MIPS32R6);
30314 generate_exception_end(ctx, EXCP_RI);
30315 break;
7a387fff 30316 case OPC_SYNCI:
d75c135e 30317 check_insn(ctx, ISA_MIPS32R2);
7480515f
AM
30318 /*
30319 * Break the TB to be able to sync copied instructions
30320 * immediately.
30321 */
eeb3bba8 30322 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 30323 break;
e45a93e2
JL
30324 case OPC_BPOSGE32: /* MIPS DSP branch */
30325#if defined(TARGET_MIPS64)
30326 case OPC_BPOSGE64:
30327#endif
30328 check_dsp(ctx);
b231c103 30329 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 30330 break;
d4ea6acd
LA
30331#if defined(TARGET_MIPS64)
30332 case OPC_DAHI:
30333 check_insn(ctx, ISA_MIPS32R6);
30334 check_mips_64(ctx);
30335 if (rs != 0) {
30336 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30337 }
d4ea6acd
LA
30338 break;
30339 case OPC_DATI:
30340 check_insn(ctx, ISA_MIPS32R6);
30341 check_mips_64(ctx);
30342 if (rs != 0) {
30343 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30344 }
d4ea6acd
LA
30345 break;
30346#endif
6af0bf9c 30347 default: /* Invalid */
923617a3 30348 MIPS_INVAL("regimm");
9c708c7f 30349 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30350 break;
30351 }
30352 break;
7a387fff 30353 case OPC_CP0:
387a8fe5 30354 check_cp0_enabled(ctx);
7a387fff 30355 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 30356 switch (op1) {
7a387fff
TS
30357 case OPC_MFC0:
30358 case OPC_MTC0:
ead9360e
TS
30359 case OPC_MFTR:
30360 case OPC_MTTR:
5204ea79
LA
30361 case OPC_MFHC0:
30362 case OPC_MTHC0:
d26bc211 30363#if defined(TARGET_MIPS64)
7a387fff
TS
30364 case OPC_DMFC0:
30365 case OPC_DMTC0:
30366#endif
f1aa6320 30367#ifndef CONFIG_USER_ONLY
932e71cd 30368 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 30369#endif /* !CONFIG_USER_ONLY */
7a387fff 30370 break;
c38a1d52
AR
30371 case OPC_C0:
30372 case OPC_C0_1:
30373 case OPC_C0_2:
30374 case OPC_C0_3:
30375 case OPC_C0_4:
30376 case OPC_C0_5:
30377 case OPC_C0_6:
30378 case OPC_C0_7:
30379 case OPC_C0_8:
30380 case OPC_C0_9:
30381 case OPC_C0_A:
30382 case OPC_C0_B:
30383 case OPC_C0_C:
30384 case OPC_C0_D:
30385 case OPC_C0_E:
30386 case OPC_C0_F:
f1aa6320 30387#ifndef CONFIG_USER_ONLY
932e71cd 30388 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 30389#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
30390 break;
30391 case OPC_MFMC0:
8706c382 30392#ifndef CONFIG_USER_ONLY
932e71cd 30393 {
099e5b4d 30394 uint32_t op2;
35fbce2c 30395 TCGv t0 = tcg_temp_new();
6c5c1e20 30396
0eaef5aa 30397 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
30398 switch (op2) {
30399 case OPC_DMT:
9affc1c5 30400 check_cp0_mt(ctx);
9ed5726c 30401 gen_helper_dmt(t0);
35fbce2c 30402 gen_store_gpr(t0, rt);
6c5c1e20
TS
30403 break;
30404 case OPC_EMT:
9affc1c5 30405 check_cp0_mt(ctx);
9ed5726c 30406 gen_helper_emt(t0);
35fbce2c 30407 gen_store_gpr(t0, rt);
da80682b 30408 break;
6c5c1e20 30409 case OPC_DVPE:
9affc1c5 30410 check_cp0_mt(ctx);
895c2d04 30411 gen_helper_dvpe(t0, cpu_env);
35fbce2c 30412 gen_store_gpr(t0, rt);
6c5c1e20
TS
30413 break;
30414 case OPC_EVPE:
9affc1c5 30415 check_cp0_mt(ctx);
895c2d04 30416 gen_helper_evpe(t0, cpu_env);
35fbce2c 30417 gen_store_gpr(t0, rt);
6c5c1e20 30418 break;
01bc435b
YK
30419 case OPC_DVP:
30420 check_insn(ctx, ISA_MIPS32R6);
30421 if (ctx->vp) {
30422 gen_helper_dvp(t0, cpu_env);
30423 gen_store_gpr(t0, rt);
30424 }
30425 break;
30426 case OPC_EVP:
30427 check_insn(ctx, ISA_MIPS32R6);
30428 if (ctx->vp) {
30429 gen_helper_evp(t0, cpu_env);
30430 gen_store_gpr(t0, rt);
30431 }
30432 break;
6c5c1e20 30433 case OPC_DI:
d75c135e 30434 check_insn(ctx, ISA_MIPS32R2);
867abc7e 30435 save_cpu_state(ctx, 1);
895c2d04 30436 gen_helper_di(t0, cpu_env);
35fbce2c 30437 gen_store_gpr(t0, rt);
7480515f
AM
30438 /*
30439 * Stop translation as we may have switched
30440 * the execution mode.
30441 */
eeb3bba8 30442 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
30443 break;
30444 case OPC_EI:
d75c135e 30445 check_insn(ctx, ISA_MIPS32R2);
867abc7e 30446 save_cpu_state(ctx, 1);
895c2d04 30447 gen_helper_ei(t0, cpu_env);
35fbce2c 30448 gen_store_gpr(t0, rt);
7480515f
AM
30449 /*
30450 * DISAS_STOP isn't sufficient, we need to ensure we break
30451 * out of translated code to check for pending interrupts.
30452 */
eeb3bba8
EC
30453 gen_save_pc(ctx->base.pc_next + 4);
30454 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
30455 break;
30456 default: /* Invalid */
30457 MIPS_INVAL("mfmc0");
9c708c7f 30458 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
30459 break;
30460 }
6c5c1e20 30461 tcg_temp_free(t0);
7a387fff 30462 }
0eaef5aa 30463#endif /* !CONFIG_USER_ONLY */
6af0bf9c 30464 break;
7a387fff 30465 case OPC_RDPGPR:
d75c135e 30466 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 30467 gen_load_srsgpr(rt, rd);
ead9360e 30468 break;
7a387fff 30469 case OPC_WRPGPR:
d75c135e 30470 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 30471 gen_store_srsgpr(rt, rd);
38121543 30472 break;
6af0bf9c 30473 default:
923617a3 30474 MIPS_INVAL("cp0");
9c708c7f 30475 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30476 break;
30477 }
30478 break;
31837be3
YK
30479 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30480 if (ctx->insn_flags & ISA_MIPS32R6) {
30481 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30482 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30483 } else {
30484 /* OPC_ADDI */
30485 /* Arithmetic with immediate opcode */
30486 gen_arith_imm(ctx, op, rt, rs, imm);
30487 }
30488 break;
324d9e32 30489 case OPC_ADDIU:
d75c135e 30490 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 30491 break;
324d9e32
AJ
30492 case OPC_SLTI: /* Set on less than with immediate opcode */
30493 case OPC_SLTIU:
d75c135e 30494 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
30495 break;
30496 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 30497 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
30498 case OPC_ORI:
30499 case OPC_XORI:
d75c135e 30500 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 30501 break;
c2e19f3c
AM
30502 case OPC_J: /* Jump */
30503 case OPC_JAL:
7a387fff 30504 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30505 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 30506 break;
31837be3
YK
30507 /* Branch */
30508 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30509 if (ctx->insn_flags & ISA_MIPS32R6) {
30510 if (rt == 0) {
9c708c7f 30511 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30512 break;
30513 }
30514 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30515 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30516 } else {
30517 /* OPC_BLEZL */
b231c103 30518 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30519 }
30520 break;
30521 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30522 if (ctx->insn_flags & ISA_MIPS32R6) {
30523 if (rt == 0) {
9c708c7f 30524 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30525 break;
30526 }
30527 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30528 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30529 } else {
30530 /* OPC_BGTZL */
b231c103 30531 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30532 }
30533 break;
30534 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30535 if (rt == 0) {
30536 /* OPC_BLEZ */
b231c103 30537 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30538 } else {
30539 check_insn(ctx, ISA_MIPS32R6);
30540 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30541 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30542 }
30543 break;
30544 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30545 if (rt == 0) {
30546 /* OPC_BGTZ */
b231c103 30547 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30548 } else {
30549 check_insn(ctx, ISA_MIPS32R6);
30550 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30551 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30552 }
30553 break;
30554 case OPC_BEQL:
30555 case OPC_BNEL:
d9224450 30556 check_insn(ctx, ISA_MIPS2);
fecd2646 30557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30558 /* Fallthrough */
31837be3
YK
30559 case OPC_BEQ:
30560 case OPC_BNE:
b231c103 30561 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 30562 break;
d9224450
MR
30563 case OPC_LL: /* Load and stores */
30564 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
30565 if (ctx->insn_flags & INSN_R5900) {
30566 check_insn_opc_user_only(ctx, INSN_R5900);
30567 }
d9224450
MR
30568 /* Fallthrough */
30569 case OPC_LWL:
fecd2646
LA
30570 case OPC_LWR:
30571 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30572 /* Fallthrough */
c2e19f3c
AM
30573 case OPC_LB:
30574 case OPC_LH:
30575 case OPC_LW:
30576 case OPC_LWPC:
30577 case OPC_LBU:
30578 case OPC_LHU:
d75c135e 30579 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 30580 break;
fecd2646 30581 case OPC_SWL:
7a387fff 30582 case OPC_SWR:
fecd2646 30583 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30584 /* fall through */
c2e19f3c
AM
30585 case OPC_SB:
30586 case OPC_SH:
fecd2646 30587 case OPC_SW:
5c13fdfd 30588 gen_st(ctx, op, rt, rs, imm);
7a387fff 30589 break;
d66c7132 30590 case OPC_SC:
d9224450 30591 check_insn(ctx, ISA_MIPS2);
4368b29a 30592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
55fc7a69
FN
30593 if (ctx->insn_flags & INSN_R5900) {
30594 check_insn_opc_user_only(ctx, INSN_R5900);
30595 }
33a07fa2
LA
30596 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30597 break;
7a387fff 30598 case OPC_CACHE:
bf7910c6 30599 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 30600 check_cp0_enabled(ctx);
d75c135e 30601 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
30602 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30603 gen_cache_operation(ctx, rt, rs, imm);
30604 }
ead9360e 30605 /* Treat as NOP. */
34ae7b51 30606 break;
7a387fff 30607 case OPC_PREF:
bf7910c6 30608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
992e8176
FN
30609 if (ctx->insn_flags & INSN_R5900) {
30610 /* Treat as NOP. */
30611 } else {
30612 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30613 /* Treat as NOP. */
30614 }
6af0bf9c 30615 break;
4ad40f36 30616
923617a3 30617 /* Floating point (COP1). */
7a387fff
TS
30618 case OPC_LWC1:
30619 case OPC_LDC1:
30620 case OPC_SWC1:
30621 case OPC_SDC1:
5ab5c041 30622 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
30623 break;
30624
7a387fff 30625 case OPC_CP1:
5692c6e1
YK
30626 op1 = MASK_CP1(ctx->opcode);
30627
30628 switch (op1) {
30629 case OPC_MFHC1:
30630 case OPC_MTHC1:
5e755519 30631 check_cp1_enabled(ctx);
5692c6e1 30632 check_insn(ctx, ISA_MIPS32R2);
146dd620 30633 /* fall through */
5692c6e1
YK
30634 case OPC_MFC1:
30635 case OPC_CFC1:
30636 case OPC_MTC1:
30637 case OPC_CTC1:
30638 check_cp1_enabled(ctx);
30639 gen_cp1(ctx, op1, rt, rd);
30640 break;
d26bc211 30641#if defined(TARGET_MIPS64)
5692c6e1
YK
30642 case OPC_DMFC1:
30643 case OPC_DMTC1:
30644 check_cp1_enabled(ctx);
30645 check_insn(ctx, ISA_MIPS3);
d9224450 30646 check_mips_64(ctx);
5692c6e1
YK
30647 gen_cp1(ctx, op1, rt, rd);
30648 break;
e189e748 30649#endif
5692c6e1
YK
30650 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30651 check_cp1_enabled(ctx);
30652 if (ctx->insn_flags & ISA_MIPS32R6) {
30653 /* OPC_BC1EQZ */
31837be3 30654 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 30655 rt, imm << 2, 4);
5692c6e1
YK
30656 } else {
30657 /* OPC_BC1ANY2 */
b8aa4598 30658 check_cop1x(ctx);
d75c135e 30659 check_insn(ctx, ASE_MIPS3D);
d75c135e 30660 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 30661 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
30662 }
30663 break;
30664 case OPC_BC1NEZ:
30665 check_cp1_enabled(ctx);
30666 check_insn(ctx, ISA_MIPS32R6);
30667 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 30668 rt, imm << 2, 4);
5692c6e1
YK
30669 break;
30670 case OPC_BC1ANY4:
30671 check_cp1_enabled(ctx);
30672 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30673 check_cop1x(ctx);
30674 check_insn(ctx, ASE_MIPS3D);
30675 /* fall through */
30676 case OPC_BC1:
30677 check_cp1_enabled(ctx);
30678 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30679 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30680 (rt >> 2) & 0x7, imm << 2);
30681 break;
30682 case OPC_PS_FMT:
e29c9628 30683 check_ps(ctx);
b6f3b233 30684 /* fall through */
5692c6e1
YK
30685 case OPC_S_FMT:
30686 case OPC_D_FMT:
30687 check_cp1_enabled(ctx);
30688 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30689 (imm >> 8) & 0x7);
30690 break;
30691 case OPC_W_FMT:
30692 case OPC_L_FMT:
30693 {
30694 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30695 check_cp1_enabled(ctx);
30696 if (ctx->insn_flags & ISA_MIPS32R6) {
30697 switch (r6_op) {
30698 case R6_OPC_CMP_AF_S:
30699 case R6_OPC_CMP_UN_S:
30700 case R6_OPC_CMP_EQ_S:
30701 case R6_OPC_CMP_UEQ_S:
30702 case R6_OPC_CMP_LT_S:
30703 case R6_OPC_CMP_ULT_S:
30704 case R6_OPC_CMP_LE_S:
30705 case R6_OPC_CMP_ULE_S:
30706 case R6_OPC_CMP_SAF_S:
30707 case R6_OPC_CMP_SUN_S:
30708 case R6_OPC_CMP_SEQ_S:
30709 case R6_OPC_CMP_SEUQ_S:
30710 case R6_OPC_CMP_SLT_S:
30711 case R6_OPC_CMP_SULT_S:
30712 case R6_OPC_CMP_SLE_S:
30713 case R6_OPC_CMP_SULE_S:
30714 case R6_OPC_CMP_OR_S:
30715 case R6_OPC_CMP_UNE_S:
30716 case R6_OPC_CMP_NE_S:
30717 case R6_OPC_CMP_SOR_S:
30718 case R6_OPC_CMP_SUNE_S:
30719 case R6_OPC_CMP_SNE_S:
30720 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30721 break;
30722 case R6_OPC_CMP_AF_D:
30723 case R6_OPC_CMP_UN_D:
30724 case R6_OPC_CMP_EQ_D:
30725 case R6_OPC_CMP_UEQ_D:
30726 case R6_OPC_CMP_LT_D:
30727 case R6_OPC_CMP_ULT_D:
30728 case R6_OPC_CMP_LE_D:
30729 case R6_OPC_CMP_ULE_D:
30730 case R6_OPC_CMP_SAF_D:
30731 case R6_OPC_CMP_SUN_D:
30732 case R6_OPC_CMP_SEQ_D:
30733 case R6_OPC_CMP_SEUQ_D:
30734 case R6_OPC_CMP_SLT_D:
30735 case R6_OPC_CMP_SULT_D:
30736 case R6_OPC_CMP_SLE_D:
30737 case R6_OPC_CMP_SULE_D:
30738 case R6_OPC_CMP_OR_D:
30739 case R6_OPC_CMP_UNE_D:
30740 case R6_OPC_CMP_NE_D:
30741 case R6_OPC_CMP_SOR_D:
30742 case R6_OPC_CMP_SUNE_D:
30743 case R6_OPC_CMP_SNE_D:
30744 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30745 break;
30746 default:
d2bfa6e6
MR
30747 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30748 rt, rd, sa, (imm >> 8) & 0x7);
30749
5692c6e1 30750 break;
3f493883 30751 }
5692c6e1
YK
30752 } else {
30753 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30754 (imm >> 8) & 0x7);
36d23958 30755 }
5692c6e1
YK
30756 break;
30757 }
30758 case OPC_BZ_V:
30759 case OPC_BNZ_V:
30760 case OPC_BZ_B:
30761 case OPC_BZ_H:
30762 case OPC_BZ_W:
30763 case OPC_BZ_D:
30764 case OPC_BNZ_B:
30765 case OPC_BNZ_H:
30766 case OPC_BNZ_W:
30767 case OPC_BNZ_D:
30768 check_insn(ctx, ASE_MSA);
30769 gen_msa_branch(env, ctx, op1);
30770 break;
30771 default:
30772 MIPS_INVAL("cp1");
9c708c7f 30773 generate_exception_end(ctx, EXCP_RI);
5692c6e1 30774 break;
6ea83fed 30775 }
4ad40f36
FB
30776 break;
30777
31837be3
YK
30778 /* Compact branches [R6] and COP2 [non-R6] */
30779 case OPC_BC: /* OPC_LWC2 */
30780 case OPC_BALC: /* OPC_SWC2 */
30781 if (ctx->insn_flags & ISA_MIPS32R6) {
30782 /* OPC_BC, OPC_BALC */
30783 gen_compute_compact_branch(ctx, op, 0, 0,
30784 sextract32(ctx->opcode << 2, 0, 28));
30785 } else {
30786 /* OPC_LWC2, OPC_SWC2 */
30787 /* COP2: Not implemented. */
30788 generate_exception_err(ctx, EXCP_CpU, 2);
30789 }
30790 break;
30791 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30792 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30793 if (ctx->insn_flags & ISA_MIPS32R6) {
30794 if (rs != 0) {
30795 /* OPC_BEQZC, OPC_BNEZC */
30796 gen_compute_compact_branch(ctx, op, rs, 0,
30797 sextract32(ctx->opcode << 2, 0, 23));
30798 } else {
30799 /* OPC_JIC, OPC_JIALC */
30800 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30801 }
30802 } else {
30803 /* OPC_LWC2, OPC_SWC2 */
30804 /* COP2: Not implemented. */
30805 generate_exception_err(ctx, EXCP_CpU, 2);
30806 }
4ad40f36 30807 break;
bd277fa1 30808 case OPC_CP2:
8e2d5831 30809 check_insn(ctx, ASE_LMMI);
bd277fa1
RH
30810 /* Note that these instructions use different fields. */
30811 gen_loongson_multimedia(ctx, sa, rd, rt);
30812 break;
4ad40f36 30813
7a387fff 30814 case OPC_CP3:
fecd2646 30815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 30816 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 30817 check_cp1_enabled(ctx);
36d23958
TS
30818 op1 = MASK_CP3(ctx->opcode);
30819 switch (op1) {
d9224450
MR
30820 case OPC_LUXC1:
30821 case OPC_SUXC1:
30822 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30823 /* Fallthrough */
5a5012ec
TS
30824 case OPC_LWXC1:
30825 case OPC_LDXC1:
5a5012ec
TS
30826 case OPC_SWXC1:
30827 case OPC_SDXC1:
d9224450 30828 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 30829 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 30830 break;
e0c84da7 30831 case OPC_PREFX:
d9224450 30832 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 30833 /* Treat as NOP. */
e0c84da7 30834 break;
5a5012ec 30835 case OPC_ALNV_PS:
d9224450
MR
30836 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30837 /* Fallthrough */
5a5012ec
TS
30838 case OPC_MADD_S:
30839 case OPC_MADD_D:
30840 case OPC_MADD_PS:
30841 case OPC_MSUB_S:
30842 case OPC_MSUB_D:
30843 case OPC_MSUB_PS:
30844 case OPC_NMADD_S:
30845 case OPC_NMADD_D:
30846 case OPC_NMADD_PS:
30847 case OPC_NMSUB_S:
30848 case OPC_NMSUB_D:
30849 case OPC_NMSUB_PS:
d9224450 30850 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
30851 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30852 break;
36d23958 30853 default:
923617a3 30854 MIPS_INVAL("cp3");
9c708c7f 30855 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
30856 break;
30857 }
30858 } else {
e397ee33 30859 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 30860 }
4ad40f36
FB
30861 break;
30862
d26bc211 30863#if defined(TARGET_MIPS64)
7a387fff 30864 /* MIPS64 opcodes */
96631327 30865 case OPC_LLD:
55fc7a69
FN
30866 if (ctx->insn_flags & INSN_R5900) {
30867 check_insn_opc_user_only(ctx, INSN_R5900);
30868 }
96631327 30869 /* fall through */
c2e19f3c
AM
30870 case OPC_LDL:
30871 case OPC_LDR:
fecd2646 30872 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30873 /* fall through */
fecd2646 30874 case OPC_LWU:
7a387fff 30875 case OPC_LD:
d75c135e 30876 check_insn(ctx, ISA_MIPS3);
5c13fdfd 30877 check_mips_64(ctx);
d75c135e 30878 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 30879 break;
c2e19f3c
AM
30880 case OPC_SDL:
30881 case OPC_SDR:
fecd2646 30882 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30883 /* fall through */
7a387fff 30884 case OPC_SD:
d75c135e 30885 check_insn(ctx, ISA_MIPS3);
e189e748 30886 check_mips_64(ctx);
5c13fdfd 30887 gen_st(ctx, op, rt, rs, imm);
7a387fff 30888 break;
d66c7132 30889 case OPC_SCD:
bf7910c6 30890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 30891 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
30892 if (ctx->insn_flags & INSN_R5900) {
30893 check_insn_opc_user_only(ctx, INSN_R5900);
30894 }
d66c7132 30895 check_mips_64(ctx);
33a07fa2 30896 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 30897 break;
31837be3
YK
30898 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30899 if (ctx->insn_flags & ISA_MIPS32R6) {
30900 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30901 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30902 } else {
30903 /* OPC_DADDI */
30904 check_insn(ctx, ISA_MIPS3);
30905 check_mips_64(ctx);
30906 gen_arith_imm(ctx, op, rt, rs, imm);
30907 }
30908 break;
324d9e32 30909 case OPC_DADDIU:
d75c135e 30910 check_insn(ctx, ISA_MIPS3);
e189e748 30911 check_mips_64(ctx);
d75c135e 30912 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 30913 break;
31837be3
YK
30914#else
30915 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30916 if (ctx->insn_flags & ISA_MIPS32R6) {
30917 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30918 } else {
30919 MIPS_INVAL("major opcode");
9c708c7f 30920 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30921 }
30922 break;
6af0bf9c 30923#endif
d4ea6acd
LA
30924 case OPC_DAUI: /* OPC_JALX */
30925 if (ctx->insn_flags & ISA_MIPS32R6) {
30926#if defined(TARGET_MIPS64)
30927 /* OPC_DAUI */
30928 check_mips_64(ctx);
db77d852
LA
30929 if (rs == 0) {
30930 generate_exception(ctx, EXCP_RI);
30931 } else if (rt != 0) {
d4ea6acd
LA
30932 TCGv t0 = tcg_temp_new();
30933 gen_load_gpr(t0, rs);
30934 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30935 tcg_temp_free(t0);
30936 }
d4ea6acd 30937#else
9c708c7f 30938 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
30939 MIPS_INVAL("major opcode");
30940#endif
30941 } else {
30942 /* OPC_JALX */
30943 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30944 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30945 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 30946 }
364d4831 30947 break;
4c789546 30948 case OPC_MSA: /* OPC_MDMX */
f08099ad 30949 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 30950#if defined(TARGET_MIPS64)
874b2879 30951 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
37b9aae2 30952#endif
f08099ad
FN
30953 } else {
30954 /* MDMX: Not implemented. */
30955 gen_msa(env, ctx);
30956 }
d4ea6acd
LA
30957 break;
30958 case OPC_PCREL:
30959 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 30960 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 30961 break;
6af0bf9c 30962 default: /* Invalid */
923617a3 30963 MIPS_INVAL("major opcode");
9c708c7f 30964 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30965 break;
30966 }
6af0bf9c
FB
30967}
30968
18f440ed 30969static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 30970{
18f440ed 30971 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 30972 CPUMIPSState *env = cs->env_ptr;
12be9258 30973
18f440ed 30974 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
30975 ctx->saved_pc = -1;
30976 ctx->insn_flags = env->insn_flags;
30977 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 30978 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
30979 ctx->CP0_Config3 = env->CP0_Config3;
30980 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
30981 ctx->btarget = 0;
30982 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30983 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30984 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30985 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30986 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30987 ctx->PAMask = env->PAMask;
30988 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30989 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30990 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30991 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30992 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 30993 /* Restore delay slot state from the tb context. */
12be9258
EC
30994 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30995 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30996 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 30997 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
30998 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30999 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31000 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31001 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 31002 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
99029be1 31003 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
12be9258 31004 restore_cpu_state(env, ctx);
932e71cd 31005#ifdef CONFIG_USER_ONLY
12be9258 31006 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 31007#else
12be9258 31008 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 31009#endif
12be9258
EC
31010 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
31011 MO_UNALN : MO_ALIGN;
190ce7fb 31012
18f440ed
EC
31013 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31014 ctx->hflags);
31015}
12be9258 31016
18f440ed
EC
31017static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31018{
31019}
b933066a 31020
18f440ed
EC
31021static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31022{
31023 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 31024
18f440ed
EC
31025 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31026 ctx->btarget);
31027}
31837be3 31028
18f440ed
EC
31029static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31030 const CPUBreakpoint *bp)
31031{
31032 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 31033
18f440ed
EC
31034 save_cpu_state(ctx, 1);
31035 ctx->base.is_jmp = DISAS_NORETURN;
31036 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
31037 /*
31038 * The address covered by the breakpoint must be included in
31039 * [tb->pc, tb->pc + tb->size) in order to for it to be
31040 * properly cleared -- thus we increment the PC here so that
31041 * the logic setting tb->size below does the right thing.
31042 */
18f440ed
EC
31043 ctx->base.pc_next += 4;
31044 return true;
31045}
4ad40f36 31046
18f440ed
EC
31047static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31048{
31049 CPUMIPSState *env = cs->env_ptr;
31050 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31051 int insn_bytes;
31052 int is_slot;
4ad40f36 31053
18f440ed 31054 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
31055 if (ctx->insn_flags & ISA_NANOMIPS32) {
31056 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31057 insn_bytes = decode_nanomips_opc(env, ctx);
31058 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
31059 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31060 insn_bytes = 4;
31061 decode_opc(env, ctx);
31062 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31063 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31064 insn_bytes = decode_micromips_opc(env, ctx);
31065 } else if (ctx->insn_flags & ASE_MIPS16) {
31066 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31067 insn_bytes = decode_mips16_opc(env, ctx);
31068 } else {
31069 generate_exception_end(ctx, EXCP_RI);
31070 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31071 return;
31072 }
faf7aaa9 31073
18f440ed
EC
31074 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31075 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31076 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
31077 /*
31078 * Force to generate branch as there is neither delay nor
31079 * forbidden slot.
31080 */
18f440ed
EC
31081 is_slot = 1;
31082 }
31083 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31084 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
31085 /*
31086 * Force to generate branch as microMIPS R6 doesn't restrict
31087 * branches in the forbidden slot.
31088 */
18f440ed 31089 is_slot = 1;
eeb3bba8 31090 }
18f440ed
EC
31091 }
31092 if (is_slot) {
31093 gen_branch(ctx, insn_bytes);
31094 }
31095 ctx->base.pc_next += insn_bytes;
1b530a6d 31096
18f440ed
EC
31097 if (ctx->base.is_jmp != DISAS_NEXT) {
31098 return;
6af0bf9c 31099 }
7480515f
AM
31100 /*
31101 * Execute a branch and its delay slot as a single instruction.
31102 * This is what GDB expects and is consistent with what the
31103 * hardware does (e.g. if a delay slot instruction faults, the
31104 * reported PC is the PC of the branch).
31105 */
18f440ed
EC
31106 if (ctx->base.singlestep_enabled &&
31107 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31108 ctx->base.is_jmp = DISAS_TOO_MANY;
31109 }
31110 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31111 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 31112 }
18f440ed
EC
31113}
31114
31115static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31116{
31117 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31118
12be9258
EC
31119 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31120 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 31121 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 31122 } else {
12be9258 31123 switch (ctx->base.is_jmp) {
b28425ba 31124 case DISAS_STOP:
12be9258 31125 gen_save_pc(ctx->base.pc_next);
cd314a7d 31126 tcg_gen_lookup_and_goto_ptr();
df1561e2 31127 break;
b28425ba 31128 case DISAS_NEXT:
18f440ed 31129 case DISAS_TOO_MANY:
12be9258
EC
31130 save_cpu_state(ctx, 0);
31131 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 31132 break;
b28425ba 31133 case DISAS_EXIT:
07ea28b4 31134 tcg_gen_exit_tb(NULL, 0);
16c00cb2 31135 break;
b28425ba 31136 case DISAS_NORETURN:
5a5012ec 31137 break;
18f440ed
EC
31138 default:
31139 g_assert_not_reached();
6958549d 31140 }
6af0bf9c 31141 }
18f440ed
EC
31142}
31143
31144static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31145{
31146 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31147 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31148}
31149
31150static const TranslatorOps mips_tr_ops = {
31151 .init_disas_context = mips_tr_init_disas_context,
31152 .tb_start = mips_tr_tb_start,
31153 .insn_start = mips_tr_insn_start,
31154 .breakpoint_check = mips_tr_breakpoint_check,
31155 .translate_insn = mips_tr_translate_insn,
31156 .tb_stop = mips_tr_tb_stop,
31157 .disas_log = mips_tr_disas_log,
31158};
31159
8b86d6d2 31160void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
31161{
31162 DisasContext ctx;
31163
8b86d6d2 31164 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
31165}
31166
71375b59 31167static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
31168{
31169 int i;
5e755519 31170 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 31171
2a5612e6
SW
31172#define printfpr(fp) \
31173 do { \
31174 if (is_fpu64) \
90c84c56
MA
31175 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31176 " fd:%13g fs:%13g psu: %13g\n", \
31177 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31178 (double)(fp)->fd, \
31179 (double)(fp)->fs[FP_ENDIAN_IDX], \
31180 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
31181 else { \
31182 fpr_t tmp; \
31183 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31184 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
31185 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31186 " fd:%13g fs:%13g psu:%13g\n", \
31187 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31188 (double)tmp.fd, \
31189 (double)tmp.fs[FP_ENDIAN_IDX], \
31190 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 31191 } \
71375b59 31192 } while (0)
6ea83fed 31193
5a5012ec 31194
90c84c56
MA
31195 qemu_fprintf(f,
31196 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31197 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31198 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 31199 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 31200 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 31201 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
31202 }
31203
31204#undef printfpr
31205}
31206
90c84c56 31207void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 31208{
878096ee
AF
31209 MIPSCPU *cpu = MIPS_CPU(cs);
31210 CPUMIPSState *env = &cpu->env;
6af0bf9c 31211 int i;
3b46e624 31212
90c84c56
MA
31213 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31214 " LO=0x" TARGET_FMT_lx " ds %04x "
31215 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31216 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31217 env->hflags, env->btarget, env->bcond);
6af0bf9c 31218 for (i = 0; i < 32; i++) {
1f8929d2 31219 if ((i & 3) == 0) {
90c84c56 31220 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 31221 }
90c84c56
MA
31222 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31223 regnames[i], env->active_tc.gpr[i]);
1f8929d2 31224 if ((i & 3) == 3) {
90c84c56 31225 qemu_fprintf(f, "\n");
1f8929d2 31226 }
90c84c56
MA
31227 }
31228
71375b59
AM
31229 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31230 TARGET_FMT_lx "\n",
90c84c56
MA
31231 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31232 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31233 PRIx64 "\n",
31234 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31235 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31236 env->CP0_Config2, env->CP0_Config3);
31237 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31238 env->CP0_Config4, env->CP0_Config5);
1cc5af69 31239 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 31240 fpu_dump_state(env, f, flags);
1cc5af69 31241 }
6af0bf9c
FB
31242}
31243
78ce64f4 31244void mips_tcg_init(void)
39454628 31245{
f01be154 31246 int i;
39454628 31247
f764718d 31248 cpu_gpr[0] = NULL;
bb928dbe 31249 for (i = 1; i < 32; i++)
e1ccc054 31250 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
71375b59
AM
31251 offsetof(CPUMIPSState,
31252 active_tc.gpr[i]),
4b2eb8d2 31253 regnames[i]);
d73ee8a2 31254
863f264d
YK
31255 for (i = 0; i < 32; i++) {
31256 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31257 msa_wr_d[i * 2] =
e1ccc054 31258 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
7480515f
AM
31259 /*
31260 * The scalar floating-point unit (FPU) registers are mapped on
31261 * the MSA vector registers.
31262 */
cb269f27 31263 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
31264 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31265 msa_wr_d[i * 2 + 1] =
e1ccc054 31266 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
31267 }
31268
e1ccc054 31269 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 31270 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 31271 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 31272 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 31273 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 31274 regnames_HI[i]);
e1ccc054 31275 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 31276 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 31277 regnames_LO[i]);
4b2eb8d2 31278 }
e1ccc054 31279 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
31280 offsetof(CPUMIPSState,
31281 active_tc.DSPControl),
4b2eb8d2 31282 "DSPControl");
e1ccc054 31283 bcond = tcg_global_mem_new(cpu_env,
7db13fae 31284 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 31285 btarget = tcg_global_mem_new(cpu_env,
7db13fae 31286 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 31287 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 31288 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 31289
e1ccc054 31290 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31291 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 31292 "fcr0");
e1ccc054 31293 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31294 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 31295 "fcr31");
33a07fa2
LA
31296 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31297 "lladdr");
31298 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31299 "llval");
a168a796
FN
31300
31301#if defined(TARGET_MIPS64)
31302 cpu_mmr[0] = NULL;
31303 for (i = 1; i < 32; i++) {
31304 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31305 offsetof(CPUMIPSState,
31306 active_tc.mmr[i]),
31307 regnames[i]);
31308 }
31309#endif
31310
b621f018 31311#if !defined(TARGET_MIPS64)
eb5559f6
CJ
31312 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31313 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31314 offsetof(CPUMIPSState,
31315 active_tc.mxu_gpr[i]),
31316 mxuregnames[i]);
31317 }
31318
31319 mxu_CR = tcg_global_mem_new(cpu_env,
31320 offsetof(CPUMIPSState, active_tc.mxu_cr),
31321 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 31322#endif
39454628
TS
31323}
31324
139c1837 31325#include "translate_init.c.inc"
aaed909a 31326
27e38392
PMD
31327void cpu_mips_realize_env(CPUMIPSState *env)
31328{
31329 env->exception_base = (int32_t)0xBFC00000;
31330
31331#ifndef CONFIG_USER_ONLY
31332 mmu_init(env, env->cpu_model);
31333#endif
31334 fpu_init(env, env->cpu_model);
31335 mvp_init(env, env->cpu_model);
31336}
31337
a7519f2b 31338bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 31339{
a7519f2b
IM
31340 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31341 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
31342}
31343
5b1e0981 31344bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
bed9e5ce 31345{
a7519f2b
IM
31346 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31347 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
31348}
31349
89777fd1
LA
31350void cpu_set_exception_base(int vp_index, target_ulong address)
31351{
31352 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31353 vp->env.exception_base = address;
31354}
31355
1bba0dc9 31356void cpu_state_reset(CPUMIPSState *env)
6ae81775 31357{
5a7330b3 31358 CPUState *cs = env_cpu(env);
6ae81775 31359
51cc2e78
BS
31360 /* Reset registers to their default values */
31361 env->CP0_PRid = env->cpu_model->CP0_PRid;
31362 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31363#ifdef TARGET_WORDS_BIGENDIAN
31364 env->CP0_Config0 |= (1 << CP0C0_BE);
31365#endif
31366 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31367 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31368 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
31369 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31370 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
31371 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31372 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78 31373 env->CP0_Config6 = env->cpu_model->CP0_Config6;
af868995 31374 env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
51cc2e78 31375 env->CP0_Config7 = env->cpu_model->CP0_Config7;
af868995 31376 env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
2a6e32dd
AJ
31377 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31378 << env->cpu_model->CP0_LLAddr_shift;
31379 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
31380 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31381 env->CCRes = env->cpu_model->CCRes;
31382 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31383 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31384 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31385 env->current_tc = 0;
31386 env->SEGBITS = env->cpu_model->SEGBITS;
31387 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31388#if defined(TARGET_MIPS64)
31389 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31390 env->SEGMask |= 3ULL << 62;
31391 }
31392#endif
31393 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
31394 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31395 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31396 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31397 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31398 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31399 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31400 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31401 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31402 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31403 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
31404 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31405 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 31406 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 31407 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 31408 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 31409 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 31410 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
31411 env->insn_flags = env->cpu_model->insn_flags;
31412
0eaef5aa 31413#if defined(CONFIG_USER_ONLY)
03e6e501 31414 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
31415# ifdef TARGET_MIPS64
31416 /* Enable 64-bit register mode. */
31417 env->CP0_Status |= (1 << CP0St_PX);
31418# endif
31419# ifdef TARGET_ABI_MIPSN64
31420 /* Enable 64-bit address mode. */
31421 env->CP0_Status |= (1 << CP0St_UX);
31422# endif
7480515f
AM
31423 /*
31424 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31425 * hardware registers.
31426 */
94159135 31427 env->CP0_HWREna |= 0x0000000F;
91a75935 31428 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 31429 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 31430 }
6f0af304
PJ
31431 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31432 env->CP0_Status |= (1 << CP0St_MX);
853c3240 31433 }
4d66261f
PJ
31434# if defined(TARGET_MIPS64)
31435 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31436 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31437 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
31438 env->CP0_Status |= (1 << CP0St_FR);
31439 }
4d66261f 31440# endif
932e71cd
AJ
31441#else
31442 if (env->hflags & MIPS_HFLAG_BMASK) {
7480515f
AM
31443 /*
31444 * If the exception was raised from a delay slot,
31445 * come back to the jump.
31446 */
c3577479
MR
31447 env->CP0_ErrorEPC = (env->active_tc.PC
31448 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 31449 } else {
932e71cd
AJ
31450 env->CP0_ErrorEPC = env->active_tc.PC;
31451 }
89777fd1 31452 env->active_tc.PC = env->exception_base;
51cc2e78
BS
31453 env->CP0_Random = env->tlb->nb_tlb - 1;
31454 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 31455 env->CP0_Wired = 0;
01bc435b 31456 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 31457 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 31458 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
31459 env->CP0_EBase |= 0x40000000;
31460 } else {
74dbf824 31461 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 31462 }
c870e3f5
YK
31463 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31464 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31465 }
99029be1
YK
31466 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
31467 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
932e71cd 31468 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
7480515f
AM
31469 /*
31470 * Vectored interrupts not implemented, timer on int 7,
31471 * no performance counters.
31472 */
932e71cd
AJ
31473 env->CP0_IntCtl = 0xe0000000;
31474 {
31475 int i;
31476
31477 for (i = 0; i < 7; i++) {
31478 env->CP0_WatchLo[i] = 0;
31479 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 31480 }
932e71cd
AJ
31481 env->CP0_WatchLo[7] = 0;
31482 env->CP0_WatchHi[7] = 0;
fd88b6ab 31483 }
932e71cd
AJ
31484 /* Count register increments in debug mode, EJTAG version 1 */
31485 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 31486
4b69c7e2
JH
31487 cpu_mips_store_count(env, 1);
31488
9e56e756
EI
31489 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31490 int i;
31491
31492 /* Only TC0 on VPE 0 starts as active. */
31493 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 31494 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
31495 env->tcs[i].CP0_TCHalt = 1;
31496 }
31497 env->active_tc.CP0_TCHalt = 1;
259186a7 31498 cs->halted = 1;
9e56e756 31499
55e5c285 31500 if (cs->cpu_index == 0) {
9e56e756
EI
31501 /* VPE0 starts up enabled. */
31502 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31503 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31504
31505 /* TC0 starts up unhalted. */
259186a7 31506 cs->halted = 0;
9e56e756
EI
31507 env->active_tc.CP0_TCHalt = 0;
31508 env->tcs[0].CP0_TCHalt = 0;
31509 /* With thread 0 active. */
31510 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31511 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31512 }
31513 }
cec56a73
JH
31514
31515 /*
31516 * Configure default legacy segmentation control. We use this regardless of
31517 * whether segmentation control is presented to the guest.
31518 */
31519 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31520 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31521 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31522 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31523 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31524 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31525 (2 << CP0SC_C);
31526 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31527 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31528 (3 << CP0SC_C)) << 16;
31529 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31530 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31531 (1 << CP0SC_EU) | (2 << CP0SC_C);
31532 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31533 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31534 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31535 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31536 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 31537#endif
ddc584bd
LA
31538 if ((env->insn_flags & ISA_MIPS32R6) &&
31539 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31540 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31541 env->CP0_Status |= (1 << CP0St_FR);
31542 }
31543
63010795
YK
31544 if (env->insn_flags & ISA_MIPS32R6) {
31545 /* PTW = 1 */
31546 env->CP0_PWSize = 0x40;
31547 /* GDI = 12 */
31548 /* UDI = 12 */
31549 /* MDI = 12 */
31550 /* PRI = 12 */
31551 /* PTEI = 2 */
31552 env->CP0_PWField = 0x0C30C302;
31553 } else {
31554 /* GDI = 0 */
31555 /* UDI = 0 */
31556 /* MDI = 0 */
31557 /* PRI = 0 */
31558 /* PTEI = 2 */
31559 env->CP0_PWField = 0x02;
31560 }
31561
0bbc0396
SM
31562 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31563 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
31564 env->hflags |= MIPS_HFLAG_M16;
31565 }
31566
863f264d
YK
31567 /* MSA */
31568 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31569 msa_reset(env);
31570 }
31571
03e6e501 31572 compute_hflags(env);
599bc5e8 31573 restore_fp_status(env);
e117f526 31574 restore_pamask(env);
27103424 31575 cs->exception_index = EXCP_NONE;
3b3c1694
LA
31576
31577 if (semihosting_get_argc()) {
31578 /* UHI interface can be used to obtain argc and argv */
31579 env->active_tc.gpr[4] = -1;
31580 }
6af0bf9c 31581}
d2856f1a 31582
bad729e2
RH
31583void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31584 target_ulong *data)
d2856f1a 31585{
bad729e2 31586 env->active_tc.PC = data[0];
d2856f1a 31587 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 31588 env->hflags |= data[1];
4636401d
AJ
31589 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31590 case MIPS_HFLAG_BR:
31591 break;
31592 case MIPS_HFLAG_BC:
31593 case MIPS_HFLAG_BL:
31594 case MIPS_HFLAG_B:
bad729e2 31595 env->btarget = data[2];
4636401d
AJ
31596 break;
31597 }
d2856f1a 31598}