]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20190903' into staging
[mirror_qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c 1/*
ab99e0e4 2 * MIPS emulation for QEMU - main translation routines
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
6af0bf9c
FB
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
8167ee88 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
22 */
23
c684822a 24#include "qemu/osdep.h"
6af0bf9c 25#include "cpu.h"
26aa3d9a 26#include "internal.h"
76cad711 27#include "disas/disas.h"
63c91552 28#include "exec/exec-all.h"
57fec1fe 29#include "tcg-op.h"
f08b6170 30#include "exec/cpu_ldst.h"
d3d93c6c 31#include "hw/mips/cpudevs.h"
6af0bf9c 32
2ef6175a
RH
33#include "exec/helper-proto.h"
34#include "exec/helper-gen.h"
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,
161f85e6
AJ
391
392 /* Loongson 2E */
393 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
394 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
395 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
396 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
397 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
398 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
399 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
400 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
401 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
402 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
403 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
404 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
405
406 /* MIPS DSP Load */
407 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
408 /* MIPS DSP Arithmetic */
409 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 410 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 411 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 412 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
413 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
414 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 416 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
417 /* MIPS DSP GPR-Based Shift Sub-class */
418 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 419 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
420 /* MIPS DSP Multiply Sub-class insns */
421 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
422 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
423 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 424 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
425 /* DSP Bit/Manipulation Sub-class */
426 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 427 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 428 /* MIPS DSP Append Sub-class */
26690560 429 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 430 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
431 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
432 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 433 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 434
76964147
JH
435 /* EVA */
436 OPC_LWLE = 0x19 | OPC_SPECIAL3,
437 OPC_LWRE = 0x1A | OPC_SPECIAL3,
438 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
439 OPC_SBE = 0x1C | OPC_SPECIAL3,
440 OPC_SHE = 0x1D | OPC_SPECIAL3,
441 OPC_SCE = 0x1E | OPC_SPECIAL3,
442 OPC_SWE = 0x1F | OPC_SPECIAL3,
443 OPC_SWLE = 0x21 | OPC_SPECIAL3,
444 OPC_SWRE = 0x22 | OPC_SPECIAL3,
445 OPC_PREFE = 0x23 | OPC_SPECIAL3,
446 OPC_LBUE = 0x28 | OPC_SPECIAL3,
447 OPC_LHUE = 0x29 | OPC_SPECIAL3,
448 OPC_LBE = 0x2C | OPC_SPECIAL3,
449 OPC_LHE = 0x2D | OPC_SPECIAL3,
450 OPC_LLE = 0x2E | OPC_SPECIAL3,
451 OPC_LWE = 0x2F | OPC_SPECIAL3,
452
4368b29a 453 /* R6 */
bf7910c6
LA
454 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
455 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
456 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
457 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
458 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
459 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
460};
461
7a387fff 462/* BSHFL opcodes */
71375b59 463#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 464
e37e863f 465enum {
15eacb9b
YK
466 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
467 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
468 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
469 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
470 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
471 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
472 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 473 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
474};
475
7a387fff 476/* DBSHFL opcodes */
71375b59 477#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 478
e37e863f 479enum {
15eacb9b
YK
480 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
481 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
482 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
483 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
484 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
485 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
486 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
487 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
488 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
489 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 490 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
491};
492
e45a93e2
JL
493/* MIPS DSP REGIMM opcodes */
494enum {
495 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 496 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
497};
498
71375b59 499#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
500/* MIPS DSP Load */
501enum {
502 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
503 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
504 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 505 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
506};
507
71375b59 508#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
509enum {
510 /* MIPS DSP Arithmetic Sub-class */
511 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
525 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
527 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
528 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
529 /* MIPS DSP Multiply Sub-class insns */
530 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
536};
537
538#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 539#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
540enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
554 /* MIPS DSP Multiply Sub-class insns */
555 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
559};
560
71375b59 561#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
562enum {
563 /* MIPS DSP Arithmetic Sub-class */
564 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
577 /* DSP Bit/Manipulation Sub-class */
578 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
583};
584
71375b59 585#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
586enum {
587 /* MIPS DSP Arithmetic Sub-class */
588 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
595 /* DSP Compare-Pick Sub-class */
596 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 611};
a22260ae 612
71375b59 613#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
614enum {
615 /* MIPS DSP GPR-Based Shift Sub-class */
616 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
638};
461c08df 639
71375b59 640#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
641enum {
642 /* MIPS DSP Multiply Sub-class insns */
643 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
665};
666
71375b59 667#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
668enum {
669 /* DSP Bit/Manipulation Sub-class */
670 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
671};
672
71375b59 673#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 674enum {
df6126a7 675 /* MIPS DSP Append Sub-class */
26690560
JL
676 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
677 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
678 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
679};
680
71375b59 681#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
682enum {
683 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
684 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
696 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
698 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
699 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
700 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
701};
702
71375b59 703#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
704enum {
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
723 /* DSP Bit/Manipulation Sub-class */
724 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 730};
461c08df 731
71375b59 732#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 733enum {
a22260ae
JL
734 /* MIPS DSP Multiply Sub-class insns */
735 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
762};
461c08df 763
71375b59 764#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 765enum {
26690560
JL
766 /* DSP Compare-Pick Sub-class */
767 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
786 /* MIPS DSP Arithmetic Sub-class */
787 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
795};
461c08df 796
71375b59 797#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 798enum {
df6126a7 799 /* DSP Append Sub-class */
26690560
JL
800 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
801 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
803 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
804};
26690560 805
71375b59 806#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
807enum {
808 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
809 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
810 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
830};
831
71375b59 832#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
833enum {
834 /* DSP Bit/Manipulation Sub-class */
835 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
836};
1cb6686c 837
71375b59 838#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
839enum {
840 /* MIPS DSP Multiply Sub-class insns */
841 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
867};
a22260ae 868
71375b59 869#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
870enum {
871 /* MIPS DSP GPR-Based Shift Sub-class */
872 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
898};
77c5fa8b 899
7a387fff 900/* Coprocessor 0 (rs field) */
71375b59 901#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 902
6ea83fed 903enum {
7a387fff
TS
904 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
905 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 906 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
907 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
908 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 909 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 910 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
911 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
912 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 913 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
914 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
915 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
916 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
917 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
918 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
919 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
920 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
921 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
922 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
923 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
924 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
925 OPC_C0_A = (0x1A << 21) | OPC_CP0,
926 OPC_C0_B = (0x1B << 21) | OPC_CP0,
927 OPC_C0_C = (0x1C << 21) | OPC_CP0,
928 OPC_C0_D = (0x1D << 21) | OPC_CP0,
929 OPC_C0_E = (0x1E << 21) | OPC_CP0,
930 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 931};
7a387fff
TS
932
933/* MFMC0 opcodes */
71375b59 934#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
935
936enum {
ead9360e
TS
937 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
938 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
940 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
941 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
942 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
943 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
944 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
945};
946
947/* Coprocessor 0 (with rs == C0) */
71375b59 948#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
949
950enum {
951 OPC_TLBR = 0x01 | OPC_C0,
952 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
953 OPC_TLBINV = 0x03 | OPC_C0,
954 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
955 OPC_TLBWR = 0x06 | OPC_C0,
956 OPC_TLBP = 0x08 | OPC_C0,
957 OPC_RFE = 0x10 | OPC_C0,
958 OPC_ERET = 0x18 | OPC_C0,
959 OPC_DERET = 0x1F | OPC_C0,
960 OPC_WAIT = 0x20 | OPC_C0,
961};
962
963/* Coprocessor 1 (rs field) */
71375b59 964#define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 965
bf4120ad
NF
966/* Values for the fmt field in FP instructions */
967enum {
968 /* 0 - 15 are reserved */
e459440a
AJ
969 FMT_S = 16, /* single fp */
970 FMT_D = 17, /* double fp */
971 FMT_E = 18, /* extended fp */
972 FMT_Q = 19, /* quad fp */
973 FMT_W = 20, /* 32-bit fixed */
974 FMT_L = 21, /* 64-bit fixed */
975 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
976 /* 23 - 31 are reserved */
977};
978
7a387fff
TS
979enum {
980 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
981 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
982 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 983 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
984 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
985 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
986 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 987 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 988 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
989 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
990 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
991 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
992 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
993 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
994 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
995 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
996 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
997 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
998 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
999 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
1000 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1001 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
1002 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1003 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1004 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1005 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1006 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1007 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1008 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1009 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
1010};
1011
71375b59
AM
1012#define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1013#define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
5a5012ec 1014
7a387fff
TS
1015enum {
1016 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1017 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1018 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1019 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1020};
1021
5a5012ec
TS
1022enum {
1023 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1024 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1025};
1026
1027enum {
1028 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1029 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1030};
7a387fff 1031
71375b59 1032#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
1033
1034enum {
1035 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1036 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1037 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1038 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1039 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1040 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1041 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1042 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1043 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1044 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1045 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1046};
1047
71375b59 1048#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1049
1050enum {
71375b59
AM
1051 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1059
1060 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1068
1069 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1073 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1074 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1075 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1076 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1077
1078 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1086
1087 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1088 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1093
1094 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1100
1101 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1107
1108 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1114
1115 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1116 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1117 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1118 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1121
1122 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1123 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1125 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1128
1129 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1130 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1131 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1135
1136 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1138 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1139 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1140 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1141 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1142};
1143
1144
71375b59 1145#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1146
1147enum {
71375b59
AM
1148 OPC_LWXC1 = 0x00 | OPC_CP3,
1149 OPC_LDXC1 = 0x01 | OPC_CP3,
1150 OPC_LUXC1 = 0x05 | OPC_CP3,
1151 OPC_SWXC1 = 0x08 | OPC_CP3,
1152 OPC_SDXC1 = 0x09 | OPC_CP3,
1153 OPC_SUXC1 = 0x0D | OPC_CP3,
1154 OPC_PREFX = 0x0F | OPC_CP3,
1155 OPC_ALNV_PS = 0x1E | OPC_CP3,
1156 OPC_MADD_S = 0x20 | OPC_CP3,
1157 OPC_MADD_D = 0x21 | OPC_CP3,
1158 OPC_MADD_PS = 0x26 | OPC_CP3,
1159 OPC_MSUB_S = 0x28 | OPC_CP3,
1160 OPC_MSUB_D = 0x29 | OPC_CP3,
1161 OPC_MSUB_PS = 0x2E | OPC_CP3,
1162 OPC_NMADD_S = 0x30 | OPC_CP3,
1163 OPC_NMADD_D = 0x31 | OPC_CP3,
1164 OPC_NMADD_PS = 0x36 | OPC_CP3,
1165 OPC_NMSUB_S = 0x38 | OPC_CP3,
1166 OPC_NMSUB_D = 0x39 | OPC_CP3,
1167 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1168};
1169
239dfebe 1170/* MSA Opcodes */
71375b59 1171#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
239dfebe
YK
1172enum {
1173 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1174 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1175 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1176 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1177 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1178 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1179 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1180 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1181 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1182 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1183 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1184 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1185 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1186 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1187 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1188 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1189 OPC_MSA_ELM = 0x19 | OPC_MSA,
1190 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1191 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1192 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1193 OPC_MSA_VEC = 0x1E | OPC_MSA,
1194
1195 /* MI10 instruction */
71375b59
AM
1196 OPC_LD_B = (0x20) | OPC_MSA,
1197 OPC_LD_H = (0x21) | OPC_MSA,
1198 OPC_LD_W = (0x22) | OPC_MSA,
1199 OPC_LD_D = (0x23) | OPC_MSA,
1200 OPC_ST_B = (0x24) | OPC_MSA,
1201 OPC_ST_H = (0x25) | OPC_MSA,
1202 OPC_ST_W = (0x26) | OPC_MSA,
1203 OPC_ST_D = (0x27) | OPC_MSA,
239dfebe
YK
1204};
1205
1206enum {
1207 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1208 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1209 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1210 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1211 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1213 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1214 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1217 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1218 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1219 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1220
1221 /* I8 instruction */
71375b59
AM
1222 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1223 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1225 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1226 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1228 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1229 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1230 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1231 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
239dfebe
YK
1232
1233 /* VEC/2R/2RF instruction */
71375b59
AM
1234 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1235 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1236 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1237 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1238 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1239 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1240 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
239dfebe
YK
1241
1242 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1244
1245 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
71375b59
AM
1246 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1247 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1248 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1249 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
239dfebe
YK
1250
1251 /* 2RF instruction df(bit 16) = _w, _d */
1252 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1253 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1255 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1256 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1257 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1258 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1259 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1260 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1262 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1263 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1264 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1266 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1268
1269 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1270 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1271 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1272 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1273 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1274 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1275 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1276 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1277 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1278 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1279 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1280 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1281 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1282 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1283 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1284 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1285 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1286 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1287 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1289 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1290 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1291 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1292 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1293 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1294 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1295 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1296 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1297 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1298 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1299 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1300 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1301 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1302 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1303 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1304 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1305 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1306 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1307 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1308 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1309 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1310 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1311 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1312 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1313 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1314 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1315 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1316 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1317 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1318 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1319 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1320 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1321 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1322 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1323 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1324 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1325 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1326 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1327 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1328 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1329 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1330 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1331 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1332 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1333
1334 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1335 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1341 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344
1345 /* 3RF instruction _df(bit 21) = _w, _d */
1346 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1361 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1362 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1364 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1365 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1369 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1370 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1372 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1373 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1375 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1378 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1381 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1384 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1385 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1386 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1387
1388 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1389 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1392 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1393 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1396 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1397 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1398 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1399 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1401};
1402
b158d449
AM
1403
1404/*
b158d449 1405 *
84e2c895
AM
1406 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1407 * ============================================
1408 *
1409 *
1410 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
b158d449
AM
1411 * instructions set. It is designed to fit the needs of signal, graphical and
1412 * video processing applications. MXU instruction set is used in Xburst family
1413 * of microprocessors by Ingenic.
1414 *
1415 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1416 * the control register.
1417 *
093ade12 1418 *
84e2c895
AM
1419 * The notation used in MXU assembler mnemonics
1420 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1421 *
1422 * Register operands:
1d0e663c
AM
1423 *
1424 * XRa, XRb, XRc, XRd - MXU registers
1425 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
093ade12 1426 *
84e2c895 1427 * Non-register operands:
093ade12 1428 *
84e2c895
AM
1429 * aptn1 - 1-bit accumulate add/subtract pattern
1430 * aptn2 - 2-bit accumulate add/subtract pattern
1431 * eptn2 - 2-bit execute add/subtract pattern
1432 * optn2 - 2-bit operand pattern
1433 * optn3 - 3-bit operand pattern
1434 * sft4 - 4-bit shift amount
1435 * strd2 - 2-bit stride amount
093ade12
AM
1436 *
1437 * Prefixes:
1438 *
84e2c895
AM
1439 * Level of parallelism: Operand size:
1440 * S - single operation at a time 32 - word
1441 * D - two operations in parallel 16 - half word
1442 * Q - four operations in parallel 8 - byte
093ade12
AM
1443 *
1444 * Operations:
1445 *
1446 * ADD - Add or subtract
1447 * ADDC - Add with carry-in
1448 * ACC - Accumulate
1449 * ASUM - Sum together then accumulate (add or subtract)
1450 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1451 * AVG - Average between 2 operands
1452 * ABD - Absolute difference
1453 * ALN - Align data
1454 * AND - Logical bitwise 'and' operation
1455 * CPS - Copy sign
1456 * EXTR - Extract bits
1457 * I2M - Move from GPR register to MXU register
1458 * LDD - Load data from memory to XRF
1459 * LDI - Load data from memory to XRF (and increase the address base)
1460 * LUI - Load unsigned immediate
1461 * MUL - Multiply
1462 * MULU - Unsigned multiply
1463 * MADD - 64-bit operand add 32x32 product
1464 * MSUB - 64-bit operand subtract 32x32 product
1465 * MAC - Multiply and accumulate (add or subtract)
1466 * MAD - Multiply and add or subtract
1467 * MAX - Maximum between 2 operands
1468 * MIN - Minimum between 2 operands
1469 * M2I - Move from MXU register to GPR register
1470 * MOVZ - Move if zero
1471 * MOVN - Move if non-zero
1472 * NOR - Logical bitwise 'nor' operation
1473 * OR - Logical bitwise 'or' operation
1474 * STD - Store data from XRF to memory
1475 * SDI - Store data from XRF to memory (and increase the address base)
1476 * SLT - Set of less than comparison
1477 * SAD - Sum of absolute differences
1478 * SLL - Logical shift left
1479 * SLR - Logical shift right
1480 * SAR - Arithmetic shift right
1481 * SAT - Saturation
1482 * SFL - Shuffle
1483 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1484 * XOR - Logical bitwise 'exclusive or' operation
1d0e663c 1485 *
84e2c895
AM
1486 * Suffixes:
1487 *
1488 * E - Expand results
1489 * F - Fixed point multiplication
1490 * L - Low part result
1491 * R - Doing rounding
1492 * V - Variable instead of immediate
1493 * W - Combine above L and V
1494 *
1495 *
1496 * The list of MXU instructions grouped by functionality
1497 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1498 *
1d0e663c
AM
1499 * Load/Store instructions Multiplication instructions
1500 * ----------------------- ---------------------------
1501 *
1502 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1503 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
093ade12
AM
1504 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1505 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1d0e663c
AM
1506 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1507 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1508 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1509 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1510 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1511 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1516 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1517 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1518 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1519 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1520 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1521 * S16SDI XRa, Rb, s10, eptn2
1522 * S8LDD XRa, Rb, s8, eptn3
1523 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1524 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1525 * S8SDI XRa, Rb, s8, eptn3
1526 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1527 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1528 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1529 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1530 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1531 * S32CPS XRa, XRb, XRc
1532 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1533 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1534 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1535 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1536 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1537 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1538 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1539 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1540 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1541 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1542 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1543 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1544 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1545 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1546 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1547 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1548 * Q8SLT XRa, XRb, XRc
1549 * Q8SLTU XRa, XRb, XRc
1550 * Q8MOVZ XRa, XRb, XRc Shift instructions
1551 * Q8MOVN XRa, XRb, XRc ------------------
1552 *
1553 * D32SLL XRa, XRb, XRc, XRd, sft4
1554 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1555 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1556 * D32SARL XRa, XRb, XRc, sft4
1557 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1558 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1559 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1560 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1561 * Q16SLL XRa, XRb, XRc, XRd, sft4
1562 * Q16SLR XRa, XRb, XRc, XRd, sft4
eab0bdb0 1563 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1d0e663c
AM
1564 * ------------------------- Q16SLLV XRa, XRb, Rb
1565 * Q16SLRV XRa, XRb, Rb
1566 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1567 * S32ALN XRa, XRb, XRc, Rb
1568 * S32ALNI XRa, XRb, XRc, s3
1569 * S32LUI XRa, s8, optn3 Move instructions
1570 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1571 * S32EXTRV XRa, XRb, Rs, Rt
1572 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1573 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1574 *
9ef5bff9 1575 *
84e2c895
AM
1576 * The opcode organization of MXU instructions
1577 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1578 *
1579 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1580 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1581 * other bits up to the instruction level is as follows:
1582 *
9ef5bff9
AM
1583 * bits
1584 * 05..00
1585 *
1586 * ┌─ 000000 ─ OPC_MXU_S32MADD
1587 * ├─ 000001 ─ OPC_MXU_S32MADDU
eab0bdb0
AM
1588 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1589 * │
9ef5bff9
AM
1590 * │ 20..18
1591 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1592 * │ ├─ 001 ─ OPC_MXU_S32MIN
1593 * │ ├─ 010 ─ OPC_MXU_D16MAX
1594 * │ ├─ 011 ─ OPC_MXU_D16MIN
1595 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1596 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1597 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1598 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1599 * ├─ 000100 ─ OPC_MXU_S32MSUB
1600 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1601 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1602 * │ ├─ 001 ─ OPC_MXU_D16SLT
1603 * │ ├─ 010 ─ OPC_MXU_D16AVG
1604 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1605 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1606 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1607 * │ └─ 111 ─ OPC_MXU_Q8ADD
1608 * │
1609 * │ 20..18
1610 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1611 * │ ├─ 010 ─ OPC_MXU_D16CPS
1612 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1613 * │ └─ 110 ─ OPC_MXU_Q16SAT
1614 * ├─ 001000 ─ OPC_MXU_D16MUL
1615 * │ 25..24
1616 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1617 * │ └─ 01 ─ OPC_MXU_D16MULE
1618 * ├─ 001010 ─ OPC_MXU_D16MAC
1619 * ├─ 001011 ─ OPC_MXU_D16MACF
1620 * ├─ 001100 ─ OPC_MXU_D16MADL
eab0bdb0 1621 * ├─ 001101 ─ OPC_MXU_S16MAD
9ef5bff9 1622 * ├─ 001110 ─ OPC_MXU_Q16ADD
eab0bdb0
AM
1623 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1624 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1625 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
9ef5bff9
AM
1626 * │
1627 * │ 23
eab0bdb0 1628 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
9ef5bff9
AM
1629 * │ └─ 1 ─ OPC_MXU_S32STDR
1630 * │
1631 * │ 13..10
eab0bdb0 1632 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
9ef5bff9
AM
1633 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1634 * │
1635 * │ 13..10
eab0bdb0 1636 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
9ef5bff9
AM
1637 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1638 * │
1639 * │ 23
eab0bdb0 1640 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
9ef5bff9
AM
1641 * │ └─ 1 ─ OPC_MXU_S32LDIR
1642 * │
1643 * │ 23
eab0bdb0 1644 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
9ef5bff9
AM
1645 * │ └─ 1 ─ OPC_MXU_S32SDIR
1646 * │
1647 * │ 13..10
eab0bdb0 1648 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
9ef5bff9
AM
1649 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1650 * │
1651 * │ 13..10
eab0bdb0 1652 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
9ef5bff9
AM
1653 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1654 * ├─ 011000 ─ OPC_MXU_D32ADD
1655 * │ 23..22
eab0bdb0 1656 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
9ef5bff9
AM
1657 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1658 * │ └─ 10 ─ OPC_MXU_D32ASUM
1659 * ├─ 011010 ─ <not assigned>
1660 * │ 23..22
eab0bdb0 1661 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
9ef5bff9
AM
1662 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1663 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1664 * │
1665 * │ 23..22
eab0bdb0 1666 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
9ef5bff9
AM
1667 * │ ├─ 01 ─ OPC_MXU_D8SUM
1668 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1669 * ├─ 011110 ─ <not assigned>
1670 * ├─ 011111 ─ <not assigned>
eab0bdb0
AM
1671 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1672 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
9ef5bff9 1673 * ├─ 100010 ─ OPC_MXU_S8LDD
eab0bdb0
AM
1674 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1675 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1676 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
9ef5bff9 1677 * │ ├─ 00 ─ OPC_MXU_S32EXTR
eab0bdb0 1678 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
9ef5bff9
AM
1679 * │
1680 * │ 20..18
eab0bdb0 1681 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
9ef5bff9 1682 * │ ├─ 001 ─ OPC_MXU_S32ALN
c233bf07 1683 * │ ├─ 010 ─ OPC_MXU_S32ALNI
b621f018
AM
1684 * │ ├─ 011 ─ OPC_MXU_S32LUI
1685 * │ ├─ 100 ─ OPC_MXU_S32NOR
1686 * │ ├─ 101 ─ OPC_MXU_S32AND
1687 * │ ├─ 110 ─ OPC_MXU_S32OR
1688 * │ └─ 111 ─ OPC_MXU_S32XOR
c233bf07
AM
1689 * │
1690 * │ 7..5
1691 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1692 * │ ├─ 001 ─ OPC_MXU_LXH
1693 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1694 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1695 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1696 * ├─ 101100 ─ OPC_MXU_S16LDI
1697 * ├─ 101101 ─ OPC_MXU_S16SDI
9ef5bff9
AM
1698 * ├─ 101110 ─ OPC_MXU_S32M2I
1699 * ├─ 101111 ─ OPC_MXU_S32I2M
1700 * ├─ 110000 ─ OPC_MXU_D32SLL
eab0bdb0
AM
1701 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1702 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1703 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1704 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1705 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
9ef5bff9 1706 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
c233bf07 1707 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
eab0bdb0 1708 * │
9ef5bff9
AM
1709 * ├─ 110111 ─ OPC_MXU_Q16SAR
1710 * │ 23..22
c233bf07 1711 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
9ef5bff9
AM
1712 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1713 * │
1714 * │ 20..18
c233bf07 1715 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
9ef5bff9
AM
1716 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1717 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1718 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1719 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
84e2c895 1720 * │ └─ 101 ─ OPC_MXU_S32MOVN
9ef5bff9
AM
1721 * │
1722 * │ 23..22
c233bf07 1723 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
9ef5bff9
AM
1724 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1725 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1726 * ├─ 111100 ─ OPC_MXU_Q8MADL
1727 * ├─ 111101 ─ OPC_MXU_S32SFL
1728 * ├─ 111110 ─ OPC_MXU_Q8SAD
eab0bdb0 1729 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
9ef5bff9
AM
1730 *
1731 *
84e2c895 1732 * Compiled after:
b158d449
AM
1733 *
1734 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
84e2c895 1735 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
b158d449
AM
1736 */
1737
8bacd1ff
AM
1738enum {
1739 OPC_MXU_S32MADD = 0x00,
1740 OPC_MXU_S32MADDU = 0x01,
11d56f61 1741 OPC__MXU_MUL = 0x02,
8bacd1ff
AM
1742 OPC_MXU__POOL00 = 0x03,
1743 OPC_MXU_S32MSUB = 0x04,
1744 OPC_MXU_S32MSUBU = 0x05,
1745 OPC_MXU__POOL01 = 0x06,
1746 OPC_MXU__POOL02 = 0x07,
1747 OPC_MXU_D16MUL = 0x08,
1748 OPC_MXU__POOL03 = 0x09,
1749 OPC_MXU_D16MAC = 0x0A,
1750 OPC_MXU_D16MACF = 0x0B,
1751 OPC_MXU_D16MADL = 0x0C,
eab0bdb0 1752 OPC_MXU_S16MAD = 0x0D,
8bacd1ff
AM
1753 OPC_MXU_Q16ADD = 0x0E,
1754 OPC_MXU_D16MACE = 0x0F,
eab0bdb0
AM
1755 OPC_MXU__POOL04 = 0x10,
1756 OPC_MXU__POOL05 = 0x11,
1757 OPC_MXU__POOL06 = 0x12,
1758 OPC_MXU__POOL07 = 0x13,
1759 OPC_MXU__POOL08 = 0x14,
1760 OPC_MXU__POOL09 = 0x15,
1761 OPC_MXU__POOL10 = 0x16,
1762 OPC_MXU__POOL11 = 0x17,
8bacd1ff 1763 OPC_MXU_D32ADD = 0x18,
eab0bdb0 1764 OPC_MXU__POOL12 = 0x19,
8bacd1ff 1765 /* not assigned 0x1A */
eab0bdb0
AM
1766 OPC_MXU__POOL13 = 0x1B,
1767 OPC_MXU__POOL14 = 0x1C,
8bacd1ff
AM
1768 OPC_MXU_Q8ACCE = 0x1D,
1769 /* not assigned 0x1E */
1770 /* not assigned 0x1F */
1771 /* not assigned 0x20 */
1772 /* not assigned 0x21 */
1773 OPC_MXU_S8LDD = 0x22,
1774 OPC_MXU_S8STD = 0x23,
1775 OPC_MXU_S8LDI = 0x24,
1776 OPC_MXU_S8SDI = 0x25,
eab0bdb0
AM
1777 OPC_MXU__POOL15 = 0x26,
1778 OPC_MXU__POOL16 = 0x27,
c233bf07 1779 OPC_MXU__POOL17 = 0x28,
8bacd1ff
AM
1780 /* not assigned 0x29 */
1781 OPC_MXU_S16LDD = 0x2A,
1782 OPC_MXU_S16STD = 0x2B,
1783 OPC_MXU_S16LDI = 0x2C,
1784 OPC_MXU_S16SDI = 0x2D,
1785 OPC_MXU_S32M2I = 0x2E,
1786 OPC_MXU_S32I2M = 0x2F,
1787 OPC_MXU_D32SLL = 0x30,
1788 OPC_MXU_D32SLR = 0x31,
1789 OPC_MXU_D32SARL = 0x32,
1790 OPC_MXU_D32SAR = 0x33,
1791 OPC_MXU_Q16SLL = 0x34,
1792 OPC_MXU_Q16SLR = 0x35,
c233bf07 1793 OPC_MXU__POOL18 = 0x36,
8bacd1ff 1794 OPC_MXU_Q16SAR = 0x37,
c233bf07
AM
1795 OPC_MXU__POOL19 = 0x38,
1796 OPC_MXU__POOL20 = 0x39,
1797 OPC_MXU__POOL21 = 0x3A,
8bacd1ff
AM
1798 OPC_MXU_Q16SCOP = 0x3B,
1799 OPC_MXU_Q8MADL = 0x3C,
1800 OPC_MXU_S32SFL = 0x3D,
1801 OPC_MXU_Q8SAD = 0x3E,
1802 /* not assigned 0x3F */
1803};
1804
1805
1806/*
1807 * MXU pool 00
1808 */
1809enum {
1810 OPC_MXU_S32MAX = 0x00,
1811 OPC_MXU_S32MIN = 0x01,
1812 OPC_MXU_D16MAX = 0x02,
1813 OPC_MXU_D16MIN = 0x03,
1814 OPC_MXU_Q8MAX = 0x04,
1815 OPC_MXU_Q8MIN = 0x05,
1816 OPC_MXU_Q8SLT = 0x06,
1817 OPC_MXU_Q8SLTU = 0x07,
1818};
1819
1820/*
1821 * MXU pool 01
1822 */
1823enum {
1824 OPC_MXU_S32SLT = 0x00,
1825 OPC_MXU_D16SLT = 0x01,
1826 OPC_MXU_D16AVG = 0x02,
1827 OPC_MXU_D16AVGR = 0x03,
1828 OPC_MXU_Q8AVG = 0x04,
1829 OPC_MXU_Q8AVGR = 0x05,
1830 OPC_MXU_Q8ADD = 0x07,
1831};
1832
1833/*
1834 * MXU pool 02
1835 */
1836enum {
1837 OPC_MXU_S32CPS = 0x00,
1838 OPC_MXU_D16CPS = 0x02,
1839 OPC_MXU_Q8ABD = 0x04,
1840 OPC_MXU_Q16SAT = 0x06,
1841};
1842
1843/*
1844 * MXU pool 03
1845 */
1846enum {
1847 OPC_MXU_D16MULF = 0x00,
1848 OPC_MXU_D16MULE = 0x01,
1849};
1850
1851/*
1852 * MXU pool 04
1853 */
8bacd1ff
AM
1854enum {
1855 OPC_MXU_S32LDD = 0x00,
1856 OPC_MXU_S32LDDR = 0x01,
1857};
1858
1859/*
eab0bdb0 1860 * MXU pool 05
8bacd1ff
AM
1861 */
1862enum {
1863 OPC_MXU_S32STD = 0x00,
1864 OPC_MXU_S32STDR = 0x01,
1865};
1866
1867/*
eab0bdb0 1868 * MXU pool 06
8bacd1ff
AM
1869 */
1870enum {
1871 OPC_MXU_S32LDDV = 0x00,
1872 OPC_MXU_S32LDDVR = 0x01,
1873};
1874
1875/*
eab0bdb0 1876 * MXU pool 07
8bacd1ff
AM
1877 */
1878enum {
1879 OPC_MXU_S32STDV = 0x00,
1880 OPC_MXU_S32STDVR = 0x01,
1881};
1882
1883/*
eab0bdb0 1884 * MXU pool 08
8bacd1ff
AM
1885 */
1886enum {
1887 OPC_MXU_S32LDI = 0x00,
1888 OPC_MXU_S32LDIR = 0x01,
1889};
1890
1891/*
eab0bdb0 1892 * MXU pool 09
8bacd1ff
AM
1893 */
1894enum {
1895 OPC_MXU_S32SDI = 0x00,
1896 OPC_MXU_S32SDIR = 0x01,
1897};
1898
1899/*
eab0bdb0 1900 * MXU pool 10
8bacd1ff
AM
1901 */
1902enum {
1903 OPC_MXU_S32LDIV = 0x00,
1904 OPC_MXU_S32LDIVR = 0x01,
1905};
1906
1907/*
eab0bdb0 1908 * MXU pool 11
8bacd1ff
AM
1909 */
1910enum {
1911 OPC_MXU_S32SDIV = 0x00,
1912 OPC_MXU_S32SDIVR = 0x01,
1913};
1914
1915/*
eab0bdb0 1916 * MXU pool 12
8bacd1ff
AM
1917 */
1918enum {
1919 OPC_MXU_D32ACC = 0x00,
1920 OPC_MXU_D32ACCM = 0x01,
1921 OPC_MXU_D32ASUM = 0x02,
1922};
1923
1924/*
eab0bdb0 1925 * MXU pool 13
8bacd1ff
AM
1926 */
1927enum {
1928 OPC_MXU_Q16ACC = 0x00,
1929 OPC_MXU_Q16ACCM = 0x01,
1930 OPC_MXU_Q16ASUM = 0x02,
1931};
1932
1933/*
eab0bdb0 1934 * MXU pool 14
8bacd1ff
AM
1935 */
1936enum {
1937 OPC_MXU_Q8ADDE = 0x00,
1938 OPC_MXU_D8SUM = 0x01,
1939 OPC_MXU_D8SUMC = 0x02,
1940};
1941
1942/*
eab0bdb0 1943 * MXU pool 15
8bacd1ff
AM
1944 */
1945enum {
1946 OPC_MXU_S32MUL = 0x00,
1947 OPC_MXU_S32MULU = 0x01,
1948 OPC_MXU_S32EXTR = 0x02,
1949 OPC_MXU_S32EXTRV = 0x03,
1950};
1951
1952/*
eab0bdb0 1953 * MXU pool 16
8bacd1ff
AM
1954 */
1955enum {
1956 OPC_MXU_D32SARW = 0x00,
1957 OPC_MXU_S32ALN = 0x01,
1958 OPC_MXU_S32ALNI = 0x02,
b621f018
AM
1959 OPC_MXU_S32LUI = 0x03,
1960 OPC_MXU_S32NOR = 0x04,
1961 OPC_MXU_S32AND = 0x05,
1962 OPC_MXU_S32OR = 0x06,
1963 OPC_MXU_S32XOR = 0x07,
8bacd1ff
AM
1964};
1965
1966/*
eab0bdb0 1967 * MXU pool 17
8bacd1ff 1968 */
c233bf07
AM
1969enum {
1970 OPC_MXU_LXB = 0x00,
1971 OPC_MXU_LXH = 0x01,
1972 OPC_MXU_LXW = 0x03,
1973 OPC_MXU_LXBU = 0x04,
1974 OPC_MXU_LXHU = 0x05,
1975};
1976
1977/*
1978 * MXU pool 18
1979 */
8bacd1ff
AM
1980enum {
1981 OPC_MXU_D32SLLV = 0x00,
1982 OPC_MXU_D32SLRV = 0x01,
1983 OPC_MXU_D32SARV = 0x03,
1984 OPC_MXU_Q16SLLV = 0x04,
1985 OPC_MXU_Q16SLRV = 0x05,
1986 OPC_MXU_Q16SARV = 0x07,
1987};
1988
1989/*
c233bf07 1990 * MXU pool 19
8bacd1ff
AM
1991 */
1992enum {
1993 OPC_MXU_Q8MUL = 0x00,
1994 OPC_MXU_Q8MULSU = 0x01,
1995};
1996
1997/*
c233bf07 1998 * MXU pool 20
8bacd1ff
AM
1999 */
2000enum {
2001 OPC_MXU_Q8MOVZ = 0x00,
2002 OPC_MXU_Q8MOVN = 0x01,
2003 OPC_MXU_D16MOVZ = 0x02,
2004 OPC_MXU_D16MOVN = 0x03,
2005 OPC_MXU_S32MOVZ = 0x04,
2006 OPC_MXU_S32MOVN = 0x05,
2007};
2008
2009/*
c233bf07 2010 * MXU pool 21
8bacd1ff
AM
2011 */
2012enum {
2013 OPC_MXU_Q8MAC = 0x00,
2014 OPC_MXU_Q8MACSU = 0x01,
2015};
2016
497f072b
FN
2017/*
2018 * Overview of the TX79-specific instruction set
2019 * =============================================
2020 *
2021 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2022 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2023 * instructions and certain multimedia instructions (MMIs). These MMIs
2024 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2025 * or sixteen 8-bit paths.
2026 *
2027 * Reference:
2028 *
2029 * The Toshiba TX System RISC TX79 Core Architecture manual,
2030 * https://wiki.qemu.org/File:C790.pdf
2031 *
2032 * Three-Operand Multiply and Multiply-Add (4 instructions)
2033 * --------------------------------------------------------
2034 * MADD [rd,] rs, rt Multiply/Add
2035 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2036 * MULT [rd,] rs, rt Multiply (3-operand)
2037 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2038 *
2039 * Multiply Instructions for Pipeline 1 (10 instructions)
2040 * ------------------------------------------------------
2041 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2042 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2043 * DIV1 rs, rt Divide Pipeline 1
2044 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2045 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2046 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2047 * MFHI1 rd Move From HI1 Register
2048 * MFLO1 rd Move From LO1 Register
2049 * MTHI1 rs Move To HI1 Register
2050 * MTLO1 rs Move To LO1 Register
2051 *
2052 * Arithmetic (19 instructions)
2053 * ----------------------------
2054 * PADDB rd, rs, rt Parallel Add Byte
2055 * PSUBB rd, rs, rt Parallel Subtract Byte
2056 * PADDH rd, rs, rt Parallel Add Halfword
2057 * PSUBH rd, rs, rt Parallel Subtract Halfword
2058 * PADDW rd, rs, rt Parallel Add Word
2059 * PSUBW rd, rs, rt Parallel Subtract Word
2060 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2061 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2062 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2063 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2064 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2065 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2066 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2067 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2068 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2069 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2070 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2071 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2072 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2073 *
2074 * Min/Max (4 instructions)
2075 * ------------------------
2076 * PMAXH rd, rs, rt Parallel Maximum Halfword
2077 * PMINH rd, rs, rt Parallel Minimum Halfword
2078 * PMAXW rd, rs, rt Parallel Maximum Word
2079 * PMINW rd, rs, rt Parallel Minimum Word
2080 *
2081 * Absolute (2 instructions)
2082 * -------------------------
2083 * PABSH rd, rt Parallel Absolute Halfword
2084 * PABSW rd, rt Parallel Absolute Word
2085 *
2086 * Logical (4 instructions)
2087 * ------------------------
2088 * PAND rd, rs, rt Parallel AND
2089 * POR rd, rs, rt Parallel OR
2090 * PXOR rd, rs, rt Parallel XOR
2091 * PNOR rd, rs, rt Parallel NOR
2092 *
2093 * Shift (9 instructions)
2094 * ----------------------
2095 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2096 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2097 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2098 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2099 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2100 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2101 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2102 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2103 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2104 *
2105 * Compare (6 instructions)
2106 * ------------------------
2107 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2108 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2109 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2110 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2111 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2112 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2113 *
2114 * LZC (1 instruction)
2115 * -------------------
2116 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2117 *
2118 * Quadword Load and Store (2 instructions)
2119 * ----------------------------------------
2120 * LQ rt, offset(base) Load Quadword
2121 * SQ rt, offset(base) Store Quadword
2122 *
2123 * Multiply and Divide (19 instructions)
2124 * -------------------------------------
2125 * PMULTW rd, rs, rt Parallel Multiply Word
2126 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2127 * PDIVW rs, rt Parallel Divide Word
2128 * PDIVUW rs, rt Parallel Divide Unsigned Word
2129 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2130 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2131 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2132 * PMULTH rd, rs, rt Parallel Multiply Halfword
2133 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2134 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2135 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2136 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2137 * PDIVBW rs, rt Parallel Divide Broadcast Word
2138 * PMFHI rd Parallel Move From HI Register
2139 * PMFLO rd Parallel Move From LO Register
2140 * PMTHI rs Parallel Move To HI Register
2141 * PMTLO rs Parallel Move To LO Register
2142 * PMFHL rd Parallel Move From HI/LO Register
2143 * PMTHL rs Parallel Move To HI/LO Register
2144 *
2145 * Pack/Extend (11 instructions)
2146 * -----------------------------
2147 * PPAC5 rd, rt Parallel Pack to 5 bits
2148 * PPACB rd, rs, rt Parallel Pack to Byte
2149 * PPACH rd, rs, rt Parallel Pack to Halfword
2150 * PPACW rd, rs, rt Parallel Pack to Word
2151 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2152 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2153 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2154 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2155 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2156 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2157 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2158 *
2159 * Others (16 instructions)
2160 * ------------------------
2161 * PCPYH rd, rt Parallel Copy Halfword
2162 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2163 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2164 * PREVH rd, rt Parallel Reverse Halfword
2165 * PINTH rd, rs, rt Parallel Interleave Halfword
2166 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2167 * PEXEH rd, rt Parallel Exchange Even Halfword
2168 * PEXCH rd, rt Parallel Exchange Center Halfword
2169 * PEXEW rd, rt Parallel Exchange Even Word
2170 * PEXCW rd, rt Parallel Exchange Center Word
2171 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2172 * MFSA rd Move from Shift Amount Register
2173 * MTSA rs Move to Shift Amount Register
2174 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2175 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2176 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d 2177 *
baa609db
AM
2178 * MMI (MultiMedia Instruction) encodings
2179 * ======================================
f99c0d6d 2180 *
baa609db 2181 * MMI instructions encoding table keys:
f99c0d6d
FN
2182 *
2183 * * This code is reserved for future use. An attempt to execute it
2184 * causes a Reserved Instruction exception.
2185 * % This code indicates an instruction class. The instruction word
2186 * must be further decoded by examining additional tables that show
2187 * the values for other instruction fields.
2188 * # This code is reserved for the unsupported instructions DMULT,
2189 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2190 * to execute it causes a Reserved Instruction exception.
2191 *
baa609db 2192 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
2193 *
2194 * 31 26 0
2195 * +--------+----------------------------------------+
2196 * | opcode | |
2197 * +--------+----------------------------------------+
2198 *
2199 * opcode bits 28..26
2200 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2201 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2202 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2203 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2204 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2205 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2206 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2207 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2208 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2209 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2210 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2211 */
b158d449 2212
f99c0d6d 2213enum {
baa609db
AM
2214 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2215 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2216 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
2217};
2218
d3297211 2219/*
baa609db 2220 * MMI instructions with opcode field = MMI:
d3297211
FN
2221 *
2222 * 31 26 5 0
2223 * +--------+-------------------------------+--------+
2224 * | MMI | |function|
2225 * +--------+-------------------------------+--------+
2226 *
2227 * function bits 2..0
2228 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2229 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2230 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2231 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2232 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2233 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2234 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2235 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2236 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2237 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2238 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2239 */
2240
c8341e00 2241#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 2242enum {
baa609db
AM
2243 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2244 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2245 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2249 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2250 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2251 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2252 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2253 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2254 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2255 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2256 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
d3297211
FN
2268};
2269
3ef65697 2270/*
baa609db 2271 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
3ef65697
FN
2272 *
2273 * 31 26 10 6 5 0
2274 * +--------+----------------------+--------+--------+
2275 * | MMI | |function| MMI0 |
2276 * +--------+----------------------+--------+--------+
2277 *
2278 * function bits 7..6
2279 * bits | 0 | 1 | 2 | 3
2280 * 10..8 | 00 | 01 | 10 | 11
2281 * -------+-------+-------+-------+-------
2282 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2283 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2284 * 2 010 | PADDB | PSUBB | PCGTB | *
2285 * 3 011 | * | * | * | *
2286 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2287 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2288 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2289 * 7 111 | * | * | PEXT5 | PPAC5
2290 */
2291
c8341e00 2292#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
3ef65697 2293enum {
baa609db
AM
2294 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
3ef65697
FN
2319};
2320
77596541 2321/*
baa609db 2322 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
77596541
FN
2323 *
2324 * 31 26 10 6 5 0
2325 * +--------+----------------------+--------+--------+
2326 * | MMI | |function| MMI1 |
2327 * +--------+----------------------+--------+--------+
2328 *
2329 * function bits 7..6
2330 * bits | 0 | 1 | 2 | 3
2331 * 10..8 | 00 | 01 | 10 | 11
2332 * -------+-------+-------+-------+-------
2333 * 0 000 | * | PABSW | PCEQW | PMINW
2334 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2335 * 2 010 | * | * | PCEQB | *
2336 * 3 011 | * | * | * | *
2337 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2338 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2339 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2340 * 7 111 | * | * | * | *
2341 */
2342
c8341e00 2343#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
77596541 2344enum {
baa609db
AM
2345 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
77596541
FN
2363};
2364
6c03ef6a 2365/*
baa609db 2366 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
6c03ef6a
FN
2367 *
2368 * 31 26 10 6 5 0
2369 * +--------+----------------------+--------+--------+
2370 * | MMI | |function| MMI2 |
2371 * +--------+----------------------+--------+--------+
2372 *
2373 * function bits 7..6
2374 * bits | 0 | 1 | 2 | 3
2375 * 10..8 | 00 | 01 | 10 | 11
2376 * -------+-------+-------+-------+-------
2377 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2378 * 1 001 | PMSUBW| * | * | *
2379 * 2 010 | PMFHI | PMFLO | PINTH | *
2380 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2381 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2382 * 5 101 | PMSUBH| PHMSBH| * | *
2383 * 6 110 | * | * | PEXEH | PREVH
2384 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2385 */
2386
c8341e00 2387#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
6c03ef6a 2388enum {
baa609db
AM
2389 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
6c03ef6a
FN
2411};
2412
dd581bf9 2413/*
baa609db 2414 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
dd581bf9
FN
2415 *
2416 * 31 26 10 6 5 0
2417 * +--------+----------------------+--------+--------+
2418 * | MMI | |function| MMI3 |
2419 * +--------+----------------------+--------+--------+
2420 *
2421 * function bits 7..6
2422 * bits | 0 | 1 | 2 | 3
2423 * 10..8 | 00 | 01 | 10 | 11
2424 * -------+-------+-------+-------+-------
2425 * 0 000 |PMADDUW| * | * | PSRAVW
2426 * 1 001 | * | * | * | *
2427 * 2 010 | PMTHI | PMTLO | PINTEH| *
2428 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2429 * 4 100 | * | * | POR | PNOR
2430 * 5 101 | * | * | * | *
2431 * 6 110 | * | * | PEXCH | PCPYH
2432 * 7 111 | * | * | PEXCW | *
2433 */
2434
c8341e00 2435#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
dd581bf9 2436enum {
baa609db
AM
2437 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
dd581bf9
FN
2450};
2451
39454628 2452/* global register indices */
a7812ae4 2453static TCGv cpu_gpr[32], cpu_PC;
340fff72 2454static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607 2455static TCGv cpu_dspctrl, btarget, bcond;
33a07fa2 2456static TCGv cpu_lladdr, cpu_llval;
41db4607 2457static TCGv_i32 hflags;
a7812ae4 2458static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2459static TCGv_i64 fpu_f64[32];
863f264d 2460static TCGv_i64 msa_wr_d[64];
aa0bf00b 2461
a168a796
FN
2462#if defined(TARGET_MIPS64)
2463/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2464static TCGv_i64 cpu_mmr[32];
2465#endif
2466
b621f018 2467#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2468/* MXU registers */
2469static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2470static TCGv mxu_CR;
b621f018 2471#endif
eb5559f6 2472
022c62cb 2473#include "exec/gen-icount.h"
2e70f6ef 2474
895c2d04 2475#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2476 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2477 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 2478 tcg_temp_free_i32(helper_tmp); \
71375b59 2479 } while (0)
be24bb4f 2480
895c2d04 2481#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2482 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2483 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 2484 tcg_temp_free_i32(helper_tmp); \
71375b59 2485 } while (0)
be24bb4f 2486
895c2d04
BS
2487#define gen_helper_1e0i(name, ret, arg1) do { \
2488 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2489 gen_helper_##name(ret, cpu_env, helper_tmp); \
2490 tcg_temp_free_i32(helper_tmp); \
71375b59 2491 } while (0)
895c2d04
BS
2492
2493#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2494 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2495 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2496 tcg_temp_free_i32(helper_tmp); \
71375b59 2497 } while (0)
895c2d04
BS
2498
2499#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2500 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2501 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2502 tcg_temp_free_i32(helper_tmp); \
71375b59 2503 } while (0)
895c2d04
BS
2504
2505#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2506 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2507 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 2508 tcg_temp_free_i32(helper_tmp); \
71375b59 2509 } while (0)
be24bb4f 2510
895c2d04 2511#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2512 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2513 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 2514 tcg_temp_free_i32(helper_tmp); \
71375b59 2515 } while (0)
c239529e 2516
8e9ade68 2517typedef struct DisasContext {
eeb3bba8
EC
2518 DisasContextBase base;
2519 target_ulong saved_pc;
18f440ed 2520 target_ulong page_start;
8e9ade68 2521 uint32_t opcode;
f9c9cd63 2522 uint64_t insn_flags;
5ab5c041 2523 int32_t CP0_Config1;
49735f76 2524 int32_t CP0_Config2;
ab77fc61
DN
2525 int32_t CP0_Config3;
2526 int32_t CP0_Config5;
8e9ade68
TS
2527 /* Routine used to access memory */
2528 int mem_idx;
14776ab5 2529 MemOp default_tcg_memop_mask;
8e9ade68 2530 uint32_t hflags, saved_hflags;
8e9ade68 2531 target_ulong btarget;
d279279e 2532 bool ulri;
e98c0d17 2533 int kscrexist;
7207c7f9 2534 bool rxi;
9456c2fb 2535 int ie;
aea14095
LA
2536 bool bi;
2537 bool bp;
5204ea79
LA
2538 uint64_t PAMask;
2539 bool mvh;
76964147 2540 bool eva;
cec56a73 2541 bool sc;
5204ea79 2542 int CP0_LLAddr_shift;
e29c9628 2543 bool ps;
01bc435b 2544 bool vp;
c870e3f5 2545 bool cmgcr;
f6d4dd81 2546 bool mrp;
87552089 2547 bool nan2008;
6be77480 2548 bool abs2008;
5fb2dcd1 2549 bool saar;
8e9ade68
TS
2550} DisasContext;
2551
b28425ba
EC
2552#define DISAS_STOP DISAS_TARGET_0
2553#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2554
d73ee8a2
RH
2555static const char * const regnames[] = {
2556 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2557 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2558 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2559 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2560};
6af0bf9c 2561
d73ee8a2
RH
2562static const char * const regnames_HI[] = {
2563 "HI0", "HI1", "HI2", "HI3",
2564};
4b2eb8d2 2565
d73ee8a2
RH
2566static const char * const regnames_LO[] = {
2567 "LO0", "LO1", "LO2", "LO3",
2568};
4b2eb8d2 2569
d73ee8a2
RH
2570static const char * const fregnames[] = {
2571 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2572 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2573 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2574 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2575};
958fb4a9 2576
863f264d
YK
2577static const char * const msaregnames[] = {
2578 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2579 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2580 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2581 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2582 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2583 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2584 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2585 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2586 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2587 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2588 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2589 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2590 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2591 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2592 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2593 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2594};
2595
b621f018 2596#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2597static const char * const mxuregnames[] = {
2598 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2599 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2600};
b621f018 2601#endif
eb5559f6 2602
9d68ac14 2603#define LOG_DISAS(...) \
fb7729e2
RH
2604 do { \
2605 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2606 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2607 } \
2608 } while (0)
2609
9d68ac14 2610#define MIPS_INVAL(op) \
fb7729e2
RH
2611 do { \
2612 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2613 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2614 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2615 ctx->base.pc_next, ctx->opcode, op, \
2616 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2617 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2618 } \
2619 } while (0)
958fb4a9 2620
8e9ade68 2621/* General purpose registers moves. */
235785e8 2622static inline void gen_load_gpr(TCGv t, int reg)
aaa9128a 2623{
1f8929d2 2624 if (reg == 0) {
8e9ade68 2625 tcg_gen_movi_tl(t, 0);
1f8929d2 2626 } else {
4b2eb8d2 2627 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 2628 }
aaa9128a
TS
2629}
2630
235785e8 2631static inline void gen_store_gpr(TCGv t, int reg)
aaa9128a 2632{
1f8929d2 2633 if (reg != 0) {
4b2eb8d2 2634 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 2635 }
aaa9128a
TS
2636}
2637
8e9ade68 2638/* Moves to/from shadow registers. */
235785e8 2639static inline void gen_load_srsgpr(int from, int to)
aaa9128a 2640{
d9bea114 2641 TCGv t0 = tcg_temp_new();
be24bb4f 2642
1f8929d2 2643 if (from == 0) {
d9bea114 2644 tcg_gen_movi_tl(t0, 0);
1f8929d2 2645 } else {
d9bea114 2646 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2647 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2648
7db13fae 2649 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2650 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2651 tcg_gen_andi_i32(t2, t2, 0xf);
2652 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2653 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2654 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2655
d9bea114 2656 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2657 tcg_temp_free_ptr(addr);
d9bea114 2658 tcg_temp_free_i32(t2);
8e9ade68 2659 }
d9bea114
AJ
2660 gen_store_gpr(t0, to);
2661 tcg_temp_free(t0);
aaa9128a
TS
2662}
2663
71375b59 2664static inline void gen_store_srsgpr(int from, int to)
aaa9128a 2665{
be24bb4f 2666 if (to != 0) {
d9bea114
AJ
2667 TCGv t0 = tcg_temp_new();
2668 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2669 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2670
d9bea114 2671 gen_load_gpr(t0, from);
7db13fae 2672 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2673 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2674 tcg_gen_andi_i32(t2, t2, 0xf);
2675 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2676 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2677 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2678
d9bea114 2679 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2680 tcg_temp_free_ptr(addr);
d9bea114
AJ
2681 tcg_temp_free_i32(t2);
2682 tcg_temp_free(t0);
8e9ade68 2683 }
aaa9128a
TS
2684}
2685
b621f018 2686#if !defined(TARGET_MIPS64)
96992d1a
CJ
2687/* MXU General purpose registers moves. */
2688static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2689{
2690 if (reg == 0) {
2691 tcg_gen_movi_tl(t, 0);
2692 } else if (reg <= 15) {
2693 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2694 }
2695}
2696
2697static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2698{
2699 if (reg > 0 && reg <= 15) {
2700 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2701 }
2702}
2703
2704/* MXU control register moves. */
2705static inline void gen_load_mxu_cr(TCGv t)
2706{
2707 tcg_gen_mov_tl(t, mxu_CR);
2708}
2709
2710static inline void gen_store_mxu_cr(TCGv t)
2711{
2712 /* TODO: Add handling of RW rules for MXU_CR. */
2713 tcg_gen_mov_tl(mxu_CR, t);
2714}
b621f018 2715#endif
96992d1a
CJ
2716
2717
eab9944c
LA
2718/* Tests */
2719static inline void gen_save_pc(target_ulong pc)
2720{
2721 tcg_gen_movi_tl(cpu_PC, pc);
2722}
2723
2724static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2725{
2726 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2727 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2728 gen_save_pc(ctx->base.pc_next);
2729 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2730 }
2731 if (ctx->hflags != ctx->saved_hflags) {
2732 tcg_gen_movi_i32(hflags, ctx->hflags);
2733 ctx->saved_hflags = ctx->hflags;
2734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2735 case MIPS_HFLAG_BR:
2736 break;
2737 case MIPS_HFLAG_BC:
2738 case MIPS_HFLAG_BL:
2739 case MIPS_HFLAG_B:
2740 tcg_gen_movi_tl(btarget, ctx->btarget);
2741 break;
2742 }
2743 }
2744}
2745
2746static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2747{
2748 ctx->saved_hflags = ctx->hflags;
2749 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2750 case MIPS_HFLAG_BR:
2751 break;
2752 case MIPS_HFLAG_BC:
2753 case MIPS_HFLAG_BL:
2754 case MIPS_HFLAG_B:
2755 ctx->btarget = env->btarget;
2756 break;
2757 }
2758}
2759
2760static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2761{
2762 TCGv_i32 texcp = tcg_const_i32(excp);
2763 TCGv_i32 terr = tcg_const_i32(err);
2764 save_cpu_state(ctx, 1);
2765 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2766 tcg_temp_free_i32(terr);
2767 tcg_temp_free_i32(texcp);
eeb3bba8 2768 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2769}
2770
2771static inline void generate_exception(DisasContext *ctx, int excp)
2772{
eab9944c
LA
2773 gen_helper_0e0i(raise_exception, excp);
2774}
2775
9c708c7f
PD
2776static inline void generate_exception_end(DisasContext *ctx, int excp)
2777{
2778 generate_exception_err(ctx, excp, 0);
2779}
2780
aaa9128a 2781/* Floating point register moves. */
7c979afd 2782static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2783{
7c979afd
LA
2784 if (ctx->hflags & MIPS_HFLAG_FRE) {
2785 generate_exception(ctx, EXCP_RI);
2786 }
ecc7b3aa 2787 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2788}
2789
7c979afd 2790static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2791{
7c979afd
LA
2792 TCGv_i64 t64;
2793 if (ctx->hflags & MIPS_HFLAG_FRE) {
2794 generate_exception(ctx, EXCP_RI);
2795 }
2796 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2797 tcg_gen_extu_i32_i64(t64, t);
2798 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2799 tcg_temp_free_i64(t64);
6d066274
AJ
2800}
2801
7f6613ce 2802static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2803{
7f6613ce 2804 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2805 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2806 } else {
7c979afd 2807 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2808 }
6d066274
AJ
2809}
2810
7f6613ce 2811static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2812{
7f6613ce
PJ
2813 if (ctx->hflags & MIPS_HFLAG_F64) {
2814 TCGv_i64 t64 = tcg_temp_new_i64();
2815 tcg_gen_extu_i32_i64(t64, t);
2816 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2817 tcg_temp_free_i64(t64);
2818 } else {
7c979afd 2819 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2820 }
aa0bf00b 2821}
6ea83fed 2822
d73ee8a2 2823static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2824{
f364515c 2825 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2826 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2827 } else {
d73ee8a2 2828 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2829 }
2830}
6ea83fed 2831
d73ee8a2 2832static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2833{
f364515c 2834 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2835 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2836 } else {
d73ee8a2
RH
2837 TCGv_i64 t0;
2838 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2839 t0 = tcg_temp_new_i64();
6d066274 2840 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2841 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2842 tcg_temp_free_i64(t0);
aa0bf00b
TS
2843 }
2844}
6ea83fed 2845
235785e8 2846static inline int get_fp_bit(int cc)
a16336e4 2847{
1f8929d2 2848 if (cc) {
d94536f4 2849 return 24 + cc;
1f8929d2 2850 } else {
d94536f4 2851 return 23;
1f8929d2 2852 }
a16336e4
TS
2853}
2854
48d38ca5 2855/* Addresses computation */
235785e8
AM
2856static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2857 TCGv arg1)
4ad40f36 2858{
941694d0 2859 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2860
2861#if defined(TARGET_MIPS64)
01f72885 2862 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2863 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2864 }
2865#endif
4ad40f36
FB
2866}
2867
bf0718c5
SM
2868static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2869 target_long ofs)
2870{
2871 tcg_gen_addi_tl(ret, base, ofs);
2872
2873#if defined(TARGET_MIPS64)
2874 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2875 tcg_gen_ext32s_i64(ret, ret);
2876 }
2877#endif
2878}
2879
31837be3
YK
2880/* Addresses computation (translation time) */
2881static target_long addr_add(DisasContext *ctx, target_long base,
2882 target_long offset)
2883{
2884 target_long sum = base + offset;
2885
2886#if defined(TARGET_MIPS64)
2887 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2888 sum = (int32_t)sum;
2889 }
2890#endif
2891 return sum;
2892}
2893
71f303cd 2894/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2895static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2896{
2897#if defined(TARGET_MIPS64)
71f303cd
RH
2898 tcg_gen_ext32s_i64(ret, arg);
2899#else
2900 tcg_gen_extrl_i64_i32(ret, arg);
2901#endif
2902}
2903
2904/* Sign-extract the high 32-bits to a target_long. */
2905static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2906{
2907#if defined(TARGET_MIPS64)
2908 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2909#else
71f303cd 2910 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2911#endif
2912}
2913
356265ae 2914static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2915{
1f8929d2 2916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
c2c65dab 2917 generate_exception_err(ctx, EXCP_CpU, 0);
1f8929d2 2918 }
387a8fe5
TS
2919}
2920
356265ae 2921static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2922{
1f8929d2 2923 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 2924 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 2925 }
5e755519
TS
2926}
2927
7480515f
AM
2928/*
2929 * Verify that the processor is running with COP1X instructions enabled.
2930 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2931 * opcode tables.
2932 */
356265ae 2933static inline void check_cop1x(DisasContext *ctx)
b8aa4598 2934{
1f8929d2 2935 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
9c708c7f 2936 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2937 }
b8aa4598
TS
2938}
2939
7480515f
AM
2940/*
2941 * Verify that the processor is running with 64-bit floating-point
2942 * operations enabled.
2943 */
356265ae 2944static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2945{
1f8929d2 2946 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
9c708c7f 2947 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2948 }
5e755519
TS
2949}
2950
2951/*
2952 * Verify if floating point register is valid; an operation is not defined
2953 * if bit 0 of any register specification is set and the FR bit in the
2954 * Status register equals zero, since the register numbers specify an
2955 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2956 * in the Status register equals one, both even and odd register numbers
2957 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2958 *
2959 * Multiple 64 bit wide registers can be checked by calling
2960 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2961 */
356265ae 2962static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2963{
1f8929d2 2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
9c708c7f 2965 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2966 }
5e755519
TS
2967}
2968
7480515f
AM
2969/*
2970 * Verify that the processor is running with DSP instructions enabled.
2971 * This is enabled by CP0 Status register MX(24) bit.
853c3240 2972 */
853c3240
JL
2973static inline void check_dsp(DisasContext *ctx)
2974{
2975 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2976 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2977 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2978 } else {
9c708c7f 2979 generate_exception_end(ctx, EXCP_RI);
ad153f15 2980 }
853c3240
JL
2981 }
2982}
2983
908f6be1 2984static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2985{
908f6be1 2986 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2987 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2988 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2989 } else {
9c708c7f 2990 generate_exception_end(ctx, EXCP_RI);
ad153f15 2991 }
853c3240
JL
2992 }
2993}
2994
908f6be1 2995static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2996{
908f6be1 2997 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
2998 if (ctx->insn_flags & ASE_DSP) {
2999 generate_exception_end(ctx, EXCP_DSPDIS);
3000 } else {
3001 generate_exception_end(ctx, EXCP_RI);
3002 }
3003 }
3004}
3005
7480515f
AM
3006/*
3007 * This code generates a "reserved instruction" exception if the
3008 * CPU does not support the instruction set corresponding to flags.
3009 */
f9c9cd63 3010static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 3011{
d75c135e 3012 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 3013 generate_exception_end(ctx, EXCP_RI);
d75c135e 3014 }
3a95e3a7
TS
3015}
3016
7480515f
AM
3017/*
3018 * This code generates a "reserved instruction" exception if the
3019 * CPU has corresponding flag set which indicates that the instruction
3020 * has been removed.
3021 */
f9c9cd63 3022static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3023{
3024 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3025 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3026 }
3027}
3028
96631327
FN
3029/*
3030 * The Linux kernel traps certain reserved instruction exceptions to
3031 * emulate the corresponding instructions. QEMU is the kernel in user
3032 * mode, so those traps are emulated by accepting the instructions.
3033 *
3034 * A reserved instruction exception is generated for flagged CPUs if
3035 * QEMU runs in system mode.
3036 */
3037static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3038{
3039#ifndef CONFIG_USER_ONLY
3040 check_insn_opc_removed(ctx, flags);
3041#endif
3042}
3043
7480515f
AM
3044/*
3045 * This code generates a "reserved instruction" exception if the
3046 * CPU does not support 64-bit paired-single (PS) floating point data type.
3047 */
e29c9628
YK
3048static inline void check_ps(DisasContext *ctx)
3049{
3050 if (unlikely(!ctx->ps)) {
3051 generate_exception(ctx, EXCP_RI);
3052 }
3053 check_cp1_64bitmode(ctx);
3054}
3055
c7986fd6 3056#ifdef TARGET_MIPS64
7480515f
AM
3057/*
3058 * This code generates a "reserved instruction" exception if 64-bit
3059 * instructions are not enabled.
3060 */
356265ae 3061static inline void check_mips_64(DisasContext *ctx)
e189e748 3062{
1f8929d2 3063 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
9c708c7f 3064 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3065 }
e189e748 3066}
c7986fd6 3067#endif
e189e748 3068
5204ea79
LA
3069#ifndef CONFIG_USER_ONLY
3070static inline void check_mvh(DisasContext *ctx)
3071{
3072 if (unlikely(!ctx->mvh)) {
3073 generate_exception(ctx, EXCP_RI);
3074 }
3075}
3076#endif
3077
0b16dcd1
AR
3078/*
3079 * This code generates a "reserved instruction" exception if the
3080 * Config5 XNP bit is set.
3081 */
3082static inline void check_xnp(DisasContext *ctx)
3083{
3084 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3085 generate_exception_end(ctx, EXCP_RI);
3086 }
3087}
3088
5e31fdd5
YK
3089#ifndef CONFIG_USER_ONLY
3090/*
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 PW bit is NOT set.
3093 */
3094static inline void check_pw(DisasContext *ctx)
3095{
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3097 generate_exception_end(ctx, EXCP_RI);
3098 }
3099}
3100#endif
3101
9affc1c5
AR
3102/*
3103 * This code generates a "reserved instruction" exception if the
3104 * Config3 MT bit is NOT set.
3105 */
3106static inline void check_mt(DisasContext *ctx)
3107{
3108 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3109 generate_exception_end(ctx, EXCP_RI);
3110 }
3111}
3112
3113#ifndef CONFIG_USER_ONLY
3114/*
3115 * This code generates a "coprocessor unusable" exception if CP0 is not
3116 * available, and, if that is not the case, generates a "reserved instruction"
3117 * exception if the Config5 MT bit is NOT set. This is needed for availability
3118 * control of some of MT ASE instructions.
3119 */
3120static inline void check_cp0_mt(DisasContext *ctx)
3121{
3122 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3123 generate_exception_err(ctx, EXCP_CpU, 0);
3124 } else {
3125 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3126 generate_exception_err(ctx, EXCP_RI, 0);
3127 }
3128 }
3129}
3130#endif
3131
fb32f8c8
DN
3132/*
3133 * This code generates a "reserved instruction" exception if the
3134 * Config5 NMS bit is set.
3135 */
3136static inline void check_nms(DisasContext *ctx)
3137{
3138 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3139 generate_exception_end(ctx, EXCP_RI);
3140 }
3141}
3142
d046a9ea
DN
3143/*
3144 * This code generates a "reserved instruction" exception if the
3145 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3146 * Config2 TL, and Config5 L2C are unset.
3147 */
3148static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3149{
1f8929d2
AM
3150 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3151 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3152 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3153 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3154 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3155 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
d046a9ea
DN
3156 generate_exception_end(ctx, EXCP_RI);
3157 }
3158}
3159
3160/*
3161 * This code generates a "reserved instruction" exception if the
3162 * Config5 EVA bit is NOT set.
3163 */
3164static inline void check_eva(DisasContext *ctx)
3165{
3166 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3167 generate_exception_end(ctx, EXCP_RI);
3168 }
3169}
3170
0b16dcd1 3171
7480515f
AM
3172/*
3173 * Define small wrappers for gen_load_fpr* so that we have a uniform
3174 * calling interface for 32 and 64-bit FPRs. No sense in changing
3175 * all callers for gen_load_fpr32 when we need the CTX parameter for
3176 * this one use.
3177 */
7c979afd 3178#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3179#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3180#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3181static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3182 int ft, int fs, int cc) \
3183{ \
71375b59
AM
3184 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3185 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
3186 switch (ifmt) { \
3187 case FMT_PS: \
e29c9628 3188 check_ps(ctx); \
8153667c
NF
3189 break; \
3190 case FMT_D: \
3191 if (abs) { \
3192 check_cop1x(ctx); \
3193 } \
3194 check_cp1_registers(ctx, fs | ft); \
3195 break; \
3196 case FMT_S: \
3197 if (abs) { \
3198 check_cop1x(ctx); \
3199 } \
3200 break; \
3201 } \
71375b59
AM
3202 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3203 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 3204 switch (n) { \
1f8929d2
AM
3205 case 0: \
3206 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3207 break; \
3208 case 1: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3210 break; \
3211 case 2: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3213 break; \
3214 case 3: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3216 break; \
3217 case 4: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3219 break; \
3220 case 5: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3222 break; \
3223 case 6: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3225 break; \
3226 case 7: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3228 break; \
3229 case 8: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3231 break; \
3232 case 9: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3234 break; \
3235 case 10: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3237 break; \
3238 case 11: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3240 break; \
3241 case 12: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3243 break; \
3244 case 13: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3246 break; \
3247 case 14: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3249 break; \
3250 case 15: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3252 break; \
3253 default: \
3254 abort(); \
8153667c 3255 } \
71375b59
AM
3256 tcg_temp_free_i##bits(fp0); \
3257 tcg_temp_free_i##bits(fp1); \
8153667c
NF
3258}
3259
3260FOP_CONDS(, 0, d, FMT_D, 64)
3261FOP_CONDS(abs, 1, d, FMT_D, 64)
3262FOP_CONDS(, 0, s, FMT_S, 32)
3263FOP_CONDS(abs, 1, s, FMT_S, 32)
3264FOP_CONDS(, 0, ps, FMT_PS, 64)
3265FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3266#undef FOP_CONDS
3f493883
YK
3267
3268#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 3269static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
3270 int ft, int fs, int fd) \
3271{ \
3272 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3273 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3274 if (ifmt == FMT_D) { \
3f493883 3275 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3276 } \
3277 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3278 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3279 switch (n) { \
3280 case 0: \
3281 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 1: \
3284 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 2: \
3287 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 3: \
3290 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 4: \
3293 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 5: \
3296 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 6: \
3299 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 7: \
3302 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 8: \
3305 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 9: \
3308 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 10: \
3311 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 11: \
3314 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 12: \
3317 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 13: \
3320 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 14: \
3323 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 15: \
3326 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 17: \
3329 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 18: \
3332 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 19: \
3335 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 25: \
3338 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 26: \
3341 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 27: \
3344 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 default: \
3347 abort(); \
3348 } \
3349 STORE; \
71375b59
AM
3350 tcg_temp_free_i ## bits(fp0); \
3351 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
3352}
3353
3354FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3355FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3356#undef FOP_CONDNS
8153667c
NF
3357#undef gen_ldcmp_fpr32
3358#undef gen_ldcmp_fpr64
3359
958fb4a9 3360/* load/store instructions. */
e7139c44 3361#ifdef CONFIG_USER_ONLY
71375b59 3362#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3363static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3364 DisasContext *ctx) \
d9bea114
AJ
3365{ \
3366 TCGv t0 = tcg_temp_new(); \
3367 tcg_gen_mov_tl(t0, arg1); \
3368 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
3369 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3370 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3371 tcg_temp_free(t0); \
aaa9128a 3372}
e7139c44 3373#else
71375b59 3374#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3375static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3376 DisasContext *ctx) \
e7139c44 3377{ \
dd4096cd 3378 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3379}
3380#endif
71375b59 3381OP_LD_ATOMIC(ll, ld32s);
aaa9128a 3382#if defined(TARGET_MIPS64)
71375b59 3383OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
3384#endif
3385#undef OP_LD_ATOMIC
3386
235785e8
AM
3387static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3388 int base, int offset)
662d7485
NF
3389{
3390 if (base == 0) {
3391 tcg_gen_movi_tl(addr, offset);
3392 } else if (offset == 0) {
3393 gen_load_gpr(addr, base);
3394 } else {
3395 tcg_gen_movi_tl(addr, offset);
3396 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3397 }
3398}
3399
235785e8 3400static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 3401{
eeb3bba8 3402 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3403
3404 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3405 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3406
3407 pc -= branch_bytes;
3408 }
3409
3410 pc &= ~(target_ulong)3;
3411 return pc;
3412}
3413
5c13fdfd 3414/* Load */
d75c135e 3415static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3416 int rt, int base, int offset)
6af0bf9c 3417{
fc40787a 3418 TCGv t0, t1, t2;
dd4096cd 3419 int mem_idx = ctx->mem_idx;
afa88c3a 3420
d75c135e 3421 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
7480515f
AM
3422 /*
3423 * Loongson CPU uses a load to zero register for prefetch.
3424 * We emulate it as a NOP. On other CPU we must perform the
3425 * actual memory access.
3426 */
afa88c3a
AJ
3427 return;
3428 }
6af0bf9c 3429
afa88c3a 3430 t0 = tcg_temp_new();
662d7485 3431 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3432
6af0bf9c 3433 switch (opc) {
d26bc211 3434#if defined(TARGET_MIPS64)
6e473128 3435 case OPC_LWU:
dd4096cd 3436 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3437 ctx->default_tcg_memop_mask);
78723684 3438 gen_store_gpr(t0, rt);
6e473128 3439 break;
6af0bf9c 3440 case OPC_LD:
dd4096cd 3441 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3442 ctx->default_tcg_memop_mask);
78723684 3443 gen_store_gpr(t0, rt);
6af0bf9c 3444 break;
7a387fff 3445 case OPC_LLD:
bf7910c6 3446 case R6_OPC_LLD:
dd4096cd 3447 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3448 gen_store_gpr(t0, rt);
7a387fff 3449 break;
6af0bf9c 3450 case OPC_LDL:
3cee3050 3451 t1 = tcg_temp_new();
7480515f
AM
3452 /*
3453 * Do a byte access to possibly trigger a page
3454 * fault with the unaligned address.
3455 */
dd4096cd 3456 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3457 tcg_gen_andi_tl(t1, t0, 7);
3458#ifndef TARGET_WORDS_BIGENDIAN
3459 tcg_gen_xori_tl(t1, t1, 7);
3460#endif
3461 tcg_gen_shli_tl(t1, t1, 3);
3462 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3463 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3464 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3465 t2 = tcg_const_tl(-1);
3466 tcg_gen_shl_tl(t2, t2, t1);
78723684 3467 gen_load_gpr(t1, rt);
eb02cc3f 3468 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3469 tcg_temp_free(t2);
3470 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3471 tcg_temp_free(t1);
fc40787a 3472 gen_store_gpr(t0, rt);
6af0bf9c 3473 break;
6af0bf9c 3474 case OPC_LDR:
3cee3050 3475 t1 = tcg_temp_new();
7480515f
AM
3476 /*
3477 * Do a byte access to possibly trigger a page
3478 * fault with the unaligned address.
3479 */
dd4096cd 3480 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3481 tcg_gen_andi_tl(t1, t0, 7);
3482#ifdef TARGET_WORDS_BIGENDIAN
3483 tcg_gen_xori_tl(t1, t1, 7);
3484#endif
3485 tcg_gen_shli_tl(t1, t1, 3);
3486 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3488 tcg_gen_shr_tl(t0, t0, t1);
3489 tcg_gen_xori_tl(t1, t1, 63);
3490 t2 = tcg_const_tl(0xfffffffffffffffeull);
3491 tcg_gen_shl_tl(t2, t2, t1);
78723684 3492 gen_load_gpr(t1, rt);
fc40787a
AJ
3493 tcg_gen_and_tl(t1, t1, t2);
3494 tcg_temp_free(t2);
3495 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3496 tcg_temp_free(t1);
fc40787a 3497 gen_store_gpr(t0, rt);
6af0bf9c 3498 break;
364d4831 3499 case OPC_LDPC:
3cee3050 3500 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3501 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3502 tcg_temp_free(t1);
dd4096cd 3503 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3504 gen_store_gpr(t0, rt);
3505 break;
6af0bf9c 3506#endif
364d4831 3507 case OPC_LWPC:
3cee3050 3508 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3509 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3510 tcg_temp_free(t1);
dd4096cd 3511 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3512 gen_store_gpr(t0, rt);
3513 break;
76964147
JH
3514 case OPC_LWE:
3515 mem_idx = MIPS_HFLAG_UM;
3516 /* fall through */
6af0bf9c 3517 case OPC_LW:
dd4096cd 3518 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3519 ctx->default_tcg_memop_mask);
78723684 3520 gen_store_gpr(t0, rt);
6af0bf9c 3521 break;
76964147
JH
3522 case OPC_LHE:
3523 mem_idx = MIPS_HFLAG_UM;
3524 /* fall through */
6af0bf9c 3525 case OPC_LH:
dd4096cd 3526 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3527 ctx->default_tcg_memop_mask);
78723684 3528 gen_store_gpr(t0, rt);
6af0bf9c 3529 break;
76964147
JH
3530 case OPC_LHUE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
6af0bf9c 3533 case OPC_LHU:
dd4096cd 3534 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3535 ctx->default_tcg_memop_mask);
78723684 3536 gen_store_gpr(t0, rt);
6af0bf9c 3537 break;
76964147
JH
3538 case OPC_LBE:
3539 mem_idx = MIPS_HFLAG_UM;
3540 /* fall through */
6af0bf9c 3541 case OPC_LB:
dd4096cd 3542 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3543 gen_store_gpr(t0, rt);
6af0bf9c 3544 break;
76964147
JH
3545 case OPC_LBUE:
3546 mem_idx = MIPS_HFLAG_UM;
3547 /* fall through */
6af0bf9c 3548 case OPC_LBU:
dd4096cd 3549 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3550 gen_store_gpr(t0, rt);
6af0bf9c 3551 break;
76964147
JH
3552 case OPC_LWLE:
3553 mem_idx = MIPS_HFLAG_UM;
3554 /* fall through */
6af0bf9c 3555 case OPC_LWL:
3cee3050 3556 t1 = tcg_temp_new();
7480515f
AM
3557 /*
3558 * Do a byte access to possibly trigger a page
3559 * fault with the unaligned address.
3560 */
dd4096cd 3561 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3562 tcg_gen_andi_tl(t1, t0, 3);
3563#ifndef TARGET_WORDS_BIGENDIAN
3564 tcg_gen_xori_tl(t1, t1, 3);
3565#endif
3566 tcg_gen_shli_tl(t1, t1, 3);
3567 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3569 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3570 t2 = tcg_const_tl(-1);
3571 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3572 gen_load_gpr(t1, rt);
eb02cc3f 3573 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3574 tcg_temp_free(t2);
3575 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3576 tcg_temp_free(t1);
fc40787a
AJ
3577 tcg_gen_ext32s_tl(t0, t0);
3578 gen_store_gpr(t0, rt);
6af0bf9c 3579 break;
76964147
JH
3580 case OPC_LWRE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
6af0bf9c 3583 case OPC_LWR:
3cee3050 3584 t1 = tcg_temp_new();
7480515f
AM
3585 /*
3586 * Do a byte access to possibly trigger a page
3587 * fault with the unaligned address.
3588 */
dd4096cd 3589 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3590 tcg_gen_andi_tl(t1, t0, 3);
3591#ifdef TARGET_WORDS_BIGENDIAN
3592 tcg_gen_xori_tl(t1, t1, 3);
3593#endif
3594 tcg_gen_shli_tl(t1, t1, 3);
3595 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3596 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3597 tcg_gen_shr_tl(t0, t0, t1);
3598 tcg_gen_xori_tl(t1, t1, 31);
3599 t2 = tcg_const_tl(0xfffffffeull);
3600 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3601 gen_load_gpr(t1, rt);
fc40787a
AJ
3602 tcg_gen_and_tl(t1, t1, t2);
3603 tcg_temp_free(t2);
3604 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3605 tcg_temp_free(t1);
c728154b 3606 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3607 gen_store_gpr(t0, rt);
6af0bf9c 3608 break;
76964147
JH
3609 case OPC_LLE:
3610 mem_idx = MIPS_HFLAG_UM;
3611 /* fall through */
6af0bf9c 3612 case OPC_LL:
4368b29a 3613 case R6_OPC_LL:
dd4096cd 3614 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3615 gen_store_gpr(t0, rt);
6af0bf9c 3616 break;
d66c7132 3617 }
d66c7132 3618 tcg_temp_free(t0);
d66c7132
AJ
3619}
3620
0b16dcd1
AR
3621static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3622 uint32_t reg1, uint32_t reg2)
3623{
3624 TCGv taddr = tcg_temp_new();
3625 TCGv_i64 tval = tcg_temp_new_i64();
3626 TCGv tmp1 = tcg_temp_new();
3627 TCGv tmp2 = tcg_temp_new();
3628
3629 gen_base_offset_addr(ctx, taddr, base, offset);
3630 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3631#ifdef TARGET_WORDS_BIGENDIAN
3632 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3633#else
3634 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3635#endif
3636 gen_store_gpr(tmp1, reg1);
3637 tcg_temp_free(tmp1);
3638 gen_store_gpr(tmp2, reg2);
3639 tcg_temp_free(tmp2);
3640 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3641 tcg_temp_free_i64(tval);
3642 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3643 tcg_temp_free(taddr);
3644}
3645
5c13fdfd 3646/* Store */
235785e8
AM
3647static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3648 int base, int offset)
5c13fdfd 3649{
5c13fdfd
AJ
3650 TCGv t0 = tcg_temp_new();
3651 TCGv t1 = tcg_temp_new();
dd4096cd 3652 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3653
3654 gen_base_offset_addr(ctx, t0, base, offset);
3655 gen_load_gpr(t1, rt);
3656 switch (opc) {
3657#if defined(TARGET_MIPS64)
3658 case OPC_SD:
dd4096cd 3659 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3660 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3661 break;
3662 case OPC_SDL:
dd4096cd 3663 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3664 break;
3665 case OPC_SDR:
dd4096cd 3666 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3667 break;
3668#endif
76964147
JH
3669 case OPC_SWE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
5c13fdfd 3672 case OPC_SW:
dd4096cd 3673 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3674 ctx->default_tcg_memop_mask);
5c13fdfd 3675 break;
76964147
JH
3676 case OPC_SHE:
3677 mem_idx = MIPS_HFLAG_UM;
3678 /* fall through */
5c13fdfd 3679 case OPC_SH:
dd4096cd 3680 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3681 ctx->default_tcg_memop_mask);
5c13fdfd 3682 break;
76964147
JH
3683 case OPC_SBE:
3684 mem_idx = MIPS_HFLAG_UM;
3685 /* fall through */
5c13fdfd 3686 case OPC_SB:
dd4096cd 3687 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3688 break;
76964147
JH
3689 case OPC_SWLE:
3690 mem_idx = MIPS_HFLAG_UM;
3691 /* fall through */
5c13fdfd 3692 case OPC_SWL:
dd4096cd 3693 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3694 break;
76964147
JH
3695 case OPC_SWRE:
3696 mem_idx = MIPS_HFLAG_UM;
3697 /* fall through */
5c13fdfd 3698 case OPC_SWR:
dd4096cd 3699 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3700 break;
3701 }
5c13fdfd
AJ
3702 tcg_temp_free(t0);
3703 tcg_temp_free(t1);
3704}
3705
3706
d66c7132 3707/* Store conditional */
33a07fa2 3708static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 3709 MemOp tcg_mo, bool eva)
d66c7132 3710{
33a07fa2
LA
3711 TCGv addr, t0, val;
3712 TCGLabel *l1 = gen_new_label();
3713 TCGLabel *done = gen_new_label();
d66c7132 3714
2d2826b9 3715 t0 = tcg_temp_new();
33a07fa2
LA
3716 addr = tcg_temp_new();
3717 /* compare the address against that of the preceeding LL */
3718 gen_base_offset_addr(ctx, addr, base, offset);
3719 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3720 tcg_temp_free(addr);
3721 tcg_gen_movi_tl(t0, 0);
3722 gen_store_gpr(t0, rt);
3723 tcg_gen_br(done);
3724
3725 gen_set_label(l1);
3726 /* generate cmpxchg */
3727 val = tcg_temp_new();
3728 gen_load_gpr(val, rt);
3729 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3730 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3731 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3732 gen_store_gpr(t0, rt);
3733 tcg_temp_free(val);
3734
3735 gen_set_label(done);
d66c7132 3736 tcg_temp_free(t0);
6af0bf9c
FB
3737}
3738
33a07fa2 3739
0b16dcd1 3740static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 3741 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
3742{
3743 TCGv taddr = tcg_temp_local_new();
3744 TCGv lladdr = tcg_temp_local_new();
3745 TCGv_i64 tval = tcg_temp_new_i64();
3746 TCGv_i64 llval = tcg_temp_new_i64();
3747 TCGv_i64 val = tcg_temp_new_i64();
3748 TCGv tmp1 = tcg_temp_new();
3749 TCGv tmp2 = tcg_temp_new();
3750 TCGLabel *lab_fail = gen_new_label();
3751 TCGLabel *lab_done = gen_new_label();
3752
3753 gen_base_offset_addr(ctx, taddr, base, offset);
3754
3755 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3756 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3757
3758 gen_load_gpr(tmp1, reg1);
3759 gen_load_gpr(tmp2, reg2);
3760
3761#ifdef TARGET_WORDS_BIGENDIAN
3762 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3763#else
3764 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3765#endif
3766
3767 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3768 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 3769 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
3770 if (reg1 != 0) {
3771 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3772 }
3773 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3774
3775 gen_set_label(lab_fail);
3776
3777 if (reg1 != 0) {
3778 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3779 }
3780 gen_set_label(lab_done);
3781 tcg_gen_movi_tl(lladdr, -1);
3782 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3783}
3784
6ea83fed 3785/* Load and store */
235785e8
AM
3786static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3787 TCGv t0)
6ea83fed 3788{
7480515f
AM
3789 /*
3790 * Don't do NOP if destination is zero: we must perform the actual
3791 * memory access.
3792 */
6ea83fed
FB
3793 switch (opc) {
3794 case OPC_LWC1:
b6d96bed 3795 {
a7812ae4 3796 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3797 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3798 ctx->default_tcg_memop_mask);
7c979afd 3799 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3800 tcg_temp_free_i32(fp0);
b6d96bed 3801 }
6ea83fed
FB
3802 break;
3803 case OPC_SWC1:
b6d96bed 3804 {
a7812ae4 3805 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3806 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3807 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3808 ctx->default_tcg_memop_mask);
a7812ae4 3809 tcg_temp_free_i32(fp0);
b6d96bed 3810 }
6ea83fed
FB
3811 break;
3812 case OPC_LDC1:
b6d96bed 3813 {
a7812ae4 3814 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3815 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3816 ctx->default_tcg_memop_mask);
b6d96bed 3817 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3818 tcg_temp_free_i64(fp0);
b6d96bed 3819 }
6ea83fed
FB
3820 break;
3821 case OPC_SDC1:
b6d96bed 3822 {
a7812ae4 3823 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3824 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3825 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3826 ctx->default_tcg_memop_mask);
a7812ae4 3827 tcg_temp_free_i64(fp0);
b6d96bed 3828 }
6ea83fed
FB
3829 break;
3830 default:
9d68ac14 3831 MIPS_INVAL("flt_ldst");
9c708c7f 3832 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3833 break;
6ea83fed 3834 }
6ea83fed 3835}
6ea83fed 3836
5ab5c041
AJ
3837static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3838 int rs, int16_t imm)
26ebe468 3839{
b52d3bfa
YK
3840 TCGv t0 = tcg_temp_new();
3841
5ab5c041 3842 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3843 check_cp1_enabled(ctx);
d9224450
MR
3844 switch (op) {
3845 case OPC_LDC1:
3846 case OPC_SDC1:
3847 check_insn(ctx, ISA_MIPS2);
3848 /* Fallthrough */
3849 default:
b52d3bfa
YK
3850 gen_base_offset_addr(ctx, t0, rs, imm);
3851 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3852 }
26ebe468
NF
3853 } else {
3854 generate_exception_err(ctx, EXCP_CpU, 1);
3855 }
b52d3bfa 3856 tcg_temp_free(t0);
26ebe468
NF
3857}
3858
6af0bf9c 3859/* Arithmetic with immediate operand */
d75c135e 3860static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3861 int rt, int rs, int imm)
6af0bf9c 3862{
324d9e32 3863 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3864
7a387fff 3865 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
3866 /*
3867 * If no destination, treat it as a NOP.
3868 * For addi, we must generate the overflow exception when needed.
3869 */
324d9e32 3870 return;
6af0bf9c
FB
3871 }
3872 switch (opc) {
3873 case OPC_ADDI:
48d38ca5 3874 {
324d9e32
AJ
3875 TCGv t0 = tcg_temp_local_new();
3876 TCGv t1 = tcg_temp_new();
3877 TCGv t2 = tcg_temp_new();
42a268c2 3878 TCGLabel *l1 = gen_new_label();
48d38ca5 3879
324d9e32
AJ
3880 gen_load_gpr(t1, rs);
3881 tcg_gen_addi_tl(t0, t1, uimm);
3882 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3883
324d9e32
AJ
3884 tcg_gen_xori_tl(t1, t1, ~uimm);
3885 tcg_gen_xori_tl(t2, t0, uimm);
3886 tcg_gen_and_tl(t1, t1, t2);
3887 tcg_temp_free(t2);
3888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3889 tcg_temp_free(t1);
48d38ca5
TS
3890 /* operands of same sign, result different sign */
3891 generate_exception(ctx, EXCP_OVERFLOW);
3892 gen_set_label(l1);
78723684 3893 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3894 gen_store_gpr(t0, rt);
3895 tcg_temp_free(t0);
48d38ca5 3896 }
6af0bf9c
FB
3897 break;
3898 case OPC_ADDIU:
324d9e32
AJ
3899 if (rs != 0) {
3900 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3901 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3902 } else {
3903 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3904 }
6af0bf9c 3905 break;
d26bc211 3906#if defined(TARGET_MIPS64)
7a387fff 3907 case OPC_DADDI:
48d38ca5 3908 {
324d9e32
AJ
3909 TCGv t0 = tcg_temp_local_new();
3910 TCGv t1 = tcg_temp_new();
3911 TCGv t2 = tcg_temp_new();
42a268c2 3912 TCGLabel *l1 = gen_new_label();
48d38ca5 3913
324d9e32
AJ
3914 gen_load_gpr(t1, rs);
3915 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3916
324d9e32
AJ
3917 tcg_gen_xori_tl(t1, t1, ~uimm);
3918 tcg_gen_xori_tl(t2, t0, uimm);
3919 tcg_gen_and_tl(t1, t1, t2);
3920 tcg_temp_free(t2);
3921 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3922 tcg_temp_free(t1);
48d38ca5
TS
3923 /* operands of same sign, result different sign */
3924 generate_exception(ctx, EXCP_OVERFLOW);
3925 gen_set_label(l1);
324d9e32
AJ
3926 gen_store_gpr(t0, rt);
3927 tcg_temp_free(t0);
48d38ca5 3928 }
7a387fff
TS
3929 break;
3930 case OPC_DADDIU:
324d9e32
AJ
3931 if (rs != 0) {
3932 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3933 } else {
3934 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3935 }
7a387fff
TS
3936 break;
3937#endif
324d9e32 3938 }
324d9e32
AJ
3939}
3940
3941/* Logic with immediate operand */
d75c135e 3942static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3943 int rt, int rs, int16_t imm)
324d9e32
AJ
3944{
3945 target_ulong uimm;
324d9e32
AJ
3946
3947 if (rt == 0) {
3948 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3949 return;
3950 }
3951 uimm = (uint16_t)imm;
3952 switch (opc) {
6af0bf9c 3953 case OPC_ANDI:
1f8929d2 3954 if (likely(rs != 0)) {
324d9e32 3955 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3956 } else {
324d9e32 3957 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 3958 }
6af0bf9c
FB
3959 break;
3960 case OPC_ORI:
1f8929d2 3961 if (rs != 0) {
324d9e32 3962 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3963 } else {
324d9e32 3964 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3965 }
6af0bf9c
FB
3966 break;
3967 case OPC_XORI:
1f8929d2 3968 if (likely(rs != 0)) {
324d9e32 3969 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3970 } else {
324d9e32 3971 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3972 }
6af0bf9c
FB
3973 break;
3974 case OPC_LUI:
d4ea6acd
LA
3975 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3976 /* OPC_AUI */
3977 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3979 } else {
3980 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3981 }
7c2c3ea3
EJ
3982 break;
3983
3984 default:
6af0bf9c 3985 break;
324d9e32 3986 }
324d9e32
AJ
3987}
3988
3989/* Set on less than with immediate operand */
d75c135e 3990static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3991 int rt, int rs, int16_t imm)
324d9e32
AJ
3992{
3993 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3994 TCGv t0;
3995
3996 if (rt == 0) {
3997 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3998 return;
3999 }
4000 t0 = tcg_temp_new();
4001 gen_load_gpr(t0, rs);
4002 switch (opc) {
4003 case OPC_SLTI:
e68dd28f 4004 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4005 break;
4006 case OPC_SLTIU:
e68dd28f 4007 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4008 break;
4009 }
324d9e32
AJ
4010 tcg_temp_free(t0);
4011}
4012
4013/* Shifts with immediate operand */
d75c135e 4014static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
4015 int rt, int rs, int16_t imm)
4016{
4017 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
4018 TCGv t0;
4019
4020 if (rt == 0) {
4021 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4022 return;
4023 }
4024
4025 t0 = tcg_temp_new();
4026 gen_load_gpr(t0, rs);
4027 switch (opc) {
6af0bf9c 4028 case OPC_SLL:
78723684 4029 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 4030 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4031 break;
4032 case OPC_SRA:
324d9e32 4033 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4034 break;
4035 case OPC_SRL:
ea63e2c3
NF
4036 if (uimm != 0) {
4037 tcg_gen_ext32u_tl(t0, t0);
4038 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4039 } else {
4040 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4041 }
ea63e2c3
NF
4042 break;
4043 case OPC_ROTR:
4044 if (uimm != 0) {
4045 TCGv_i32 t1 = tcg_temp_new_i32();
4046
4047 tcg_gen_trunc_tl_i32(t1, t0);
4048 tcg_gen_rotri_i32(t1, t1, uimm);
4049 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4050 tcg_temp_free_i32(t1);
3399e30f
NF
4051 } else {
4052 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4053 }
7a387fff 4054 break;
d26bc211 4055#if defined(TARGET_MIPS64)
7a387fff 4056 case OPC_DSLL:
324d9e32 4057 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4058 break;
4059 case OPC_DSRA:
324d9e32 4060 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4061 break;
4062 case OPC_DSRL:
ea63e2c3 4063 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4064 break;
4065 case OPC_DROTR:
4066 if (uimm != 0) {
4067 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4068 } else {
4069 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4070 }
7a387fff
TS
4071 break;
4072 case OPC_DSLL32:
324d9e32 4073 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4074 break;
4075 case OPC_DSRA32:
324d9e32 4076 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4077 break;
4078 case OPC_DSRL32:
ea63e2c3 4079 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4080 break;
4081 case OPC_DROTR32:
4082 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4083 break;
7a387fff 4084#endif
6af0bf9c 4085 }
78723684 4086 tcg_temp_free(t0);
6af0bf9c
FB
4087}
4088
4089/* Arithmetic */
d75c135e
AJ
4090static void gen_arith(DisasContext *ctx, uint32_t opc,
4091 int rd, int rs, int rt)
6af0bf9c 4092{
7a387fff
TS
4093 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4094 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
4095 /*
4096 * If no destination, treat it as a NOP.
4097 * For add & sub, we must generate the overflow exception when needed.
4098 */
460f00c4 4099 return;
185f0762 4100 }
460f00c4 4101
6af0bf9c
FB
4102 switch (opc) {
4103 case OPC_ADD:
48d38ca5 4104 {
460f00c4
AJ
4105 TCGv t0 = tcg_temp_local_new();
4106 TCGv t1 = tcg_temp_new();
4107 TCGv t2 = tcg_temp_new();
42a268c2 4108 TCGLabel *l1 = gen_new_label();
48d38ca5 4109
460f00c4
AJ
4110 gen_load_gpr(t1, rs);
4111 gen_load_gpr(t2, rt);
4112 tcg_gen_add_tl(t0, t1, t2);
4113 tcg_gen_ext32s_tl(t0, t0);
4114 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4115 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4116 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4117 tcg_temp_free(t2);
4118 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4119 tcg_temp_free(t1);
48d38ca5
TS
4120 /* operands of same sign, result different sign */
4121 generate_exception(ctx, EXCP_OVERFLOW);
4122 gen_set_label(l1);
460f00c4
AJ
4123 gen_store_gpr(t0, rd);
4124 tcg_temp_free(t0);
48d38ca5 4125 }
6af0bf9c
FB
4126 break;
4127 case OPC_ADDU:
460f00c4
AJ
4128 if (rs != 0 && rt != 0) {
4129 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4130 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4131 } else if (rs == 0 && rt != 0) {
4132 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4133 } else if (rs != 0 && rt == 0) {
4134 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4135 } else {
4136 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4137 }
6af0bf9c
FB
4138 break;
4139 case OPC_SUB:
48d38ca5 4140 {
460f00c4
AJ
4141 TCGv t0 = tcg_temp_local_new();
4142 TCGv t1 = tcg_temp_new();
4143 TCGv t2 = tcg_temp_new();
42a268c2 4144 TCGLabel *l1 = gen_new_label();
48d38ca5 4145
460f00c4
AJ
4146 gen_load_gpr(t1, rs);
4147 gen_load_gpr(t2, rt);
4148 tcg_gen_sub_tl(t0, t1, t2);
4149 tcg_gen_ext32s_tl(t0, t0);
4150 tcg_gen_xor_tl(t2, t1, t2);
4151 tcg_gen_xor_tl(t1, t0, t1);
4152 tcg_gen_and_tl(t1, t1, t2);
4153 tcg_temp_free(t2);
4154 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4155 tcg_temp_free(t1);
7480515f
AM
4156 /*
4157 * operands of different sign, first operand and the result
4158 * of different sign
4159 */
48d38ca5
TS
4160 generate_exception(ctx, EXCP_OVERFLOW);
4161 gen_set_label(l1);
460f00c4
AJ
4162 gen_store_gpr(t0, rd);
4163 tcg_temp_free(t0);
48d38ca5 4164 }
6af0bf9c
FB
4165 break;
4166 case OPC_SUBU:
460f00c4
AJ
4167 if (rs != 0 && rt != 0) {
4168 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4169 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4173 } else if (rs != 0 && rt == 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4175 } else {
4176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4177 }
6af0bf9c 4178 break;
d26bc211 4179#if defined(TARGET_MIPS64)
7a387fff 4180 case OPC_DADD:
48d38ca5 4181 {
460f00c4
AJ
4182 TCGv t0 = tcg_temp_local_new();
4183 TCGv t1 = tcg_temp_new();
4184 TCGv t2 = tcg_temp_new();
42a268c2 4185 TCGLabel *l1 = gen_new_label();
48d38ca5 4186
460f00c4
AJ
4187 gen_load_gpr(t1, rs);
4188 gen_load_gpr(t2, rt);
4189 tcg_gen_add_tl(t0, t1, t2);
4190 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4191 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4192 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4193 tcg_temp_free(t2);
4194 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4195 tcg_temp_free(t1);
48d38ca5
TS
4196 /* operands of same sign, result different sign */
4197 generate_exception(ctx, EXCP_OVERFLOW);
4198 gen_set_label(l1);
460f00c4
AJ
4199 gen_store_gpr(t0, rd);
4200 tcg_temp_free(t0);
48d38ca5 4201 }
7a387fff
TS
4202 break;
4203 case OPC_DADDU:
460f00c4
AJ
4204 if (rs != 0 && rt != 0) {
4205 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4206 } else if (rs == 0 && rt != 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4208 } else if (rs != 0 && rt == 0) {
4209 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4210 } else {
4211 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4212 }
7a387fff
TS
4213 break;
4214 case OPC_DSUB:
48d38ca5 4215 {
460f00c4
AJ
4216 TCGv t0 = tcg_temp_local_new();
4217 TCGv t1 = tcg_temp_new();
4218 TCGv t2 = tcg_temp_new();
42a268c2 4219 TCGLabel *l1 = gen_new_label();
48d38ca5 4220
460f00c4
AJ
4221 gen_load_gpr(t1, rs);
4222 gen_load_gpr(t2, rt);
4223 tcg_gen_sub_tl(t0, t1, t2);
4224 tcg_gen_xor_tl(t2, t1, t2);
4225 tcg_gen_xor_tl(t1, t0, t1);
4226 tcg_gen_and_tl(t1, t1, t2);
4227 tcg_temp_free(t2);
4228 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4229 tcg_temp_free(t1);
71375b59
AM
4230 /*
4231 * Operands of different sign, first operand and result different
4232 * sign.
4233 */
48d38ca5
TS
4234 generate_exception(ctx, EXCP_OVERFLOW);
4235 gen_set_label(l1);
460f00c4
AJ
4236 gen_store_gpr(t0, rd);
4237 tcg_temp_free(t0);
48d38ca5 4238 }
7a387fff
TS
4239 break;
4240 case OPC_DSUBU:
460f00c4
AJ
4241 if (rs != 0 && rt != 0) {
4242 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4243 } else if (rs == 0 && rt != 0) {
4244 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4245 } else if (rs != 0 && rt == 0) {
4246 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4247 } else {
4248 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4249 }
7a387fff
TS
4250 break;
4251#endif
460f00c4
AJ
4252 case OPC_MUL:
4253 if (likely(rs != 0 && rt != 0)) {
4254 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4255 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4256 } else {
4257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4258 }
6af0bf9c 4259 break;
460f00c4 4260 }
460f00c4
AJ
4261}
4262
4263/* Conditional move */
d75c135e 4264static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4265 int rd, int rs, int rt)
460f00c4 4266{
acf12465 4267 TCGv t0, t1, t2;
460f00c4
AJ
4268
4269 if (rd == 0) {
acf12465 4270 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4271 return;
4272 }
4273
acf12465
AJ
4274 t0 = tcg_temp_new();
4275 gen_load_gpr(t0, rt);
4276 t1 = tcg_const_tl(0);
4277 t2 = tcg_temp_new();
4278 gen_load_gpr(t2, rs);
460f00c4
AJ
4279 switch (opc) {
4280 case OPC_MOVN:
acf12465 4281 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4282 break;
460f00c4 4283 case OPC_MOVZ:
acf12465 4284 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4285 break;
b691d9d2
LA
4286 case OPC_SELNEZ:
4287 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4288 break;
4289 case OPC_SELEQZ:
4290 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4291 break;
460f00c4 4292 }
acf12465
AJ
4293 tcg_temp_free(t2);
4294 tcg_temp_free(t1);
4295 tcg_temp_free(t0);
460f00c4
AJ
4296}
4297
4298/* Logic */
d75c135e 4299static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4300 int rd, int rs, int rt)
460f00c4 4301{
460f00c4
AJ
4302 if (rd == 0) {
4303 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4304 return;
4305 }
4306
4307 switch (opc) {
6af0bf9c 4308 case OPC_AND:
460f00c4
AJ
4309 if (likely(rs != 0 && rt != 0)) {
4310 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4311 } else {
4312 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4313 }
6af0bf9c
FB
4314 break;
4315 case OPC_NOR:
460f00c4
AJ
4316 if (rs != 0 && rt != 0) {
4317 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4318 } else if (rs == 0 && rt != 0) {
4319 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4320 } else if (rs != 0 && rt == 0) {
4321 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4322 } else {
4323 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4324 }
6af0bf9c
FB
4325 break;
4326 case OPC_OR:
460f00c4
AJ
4327 if (likely(rs != 0 && rt != 0)) {
4328 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4329 } else if (rs == 0 && rt != 0) {
4330 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4331 } else if (rs != 0 && rt == 0) {
4332 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4333 } else {
4334 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4335 }
6af0bf9c
FB
4336 break;
4337 case OPC_XOR:
460f00c4
AJ
4338 if (likely(rs != 0 && rt != 0)) {
4339 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4340 } else if (rs == 0 && rt != 0) {
4341 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4342 } else if (rs != 0 && rt == 0) {
4343 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4344 } else {
4345 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4346 }
6af0bf9c 4347 break;
460f00c4 4348 }
460f00c4
AJ
4349}
4350
4351/* Set on lower than */
d75c135e 4352static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4353 int rd, int rs, int rt)
460f00c4 4354{
460f00c4
AJ
4355 TCGv t0, t1;
4356
4357 if (rd == 0) {
4358 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4359 return;
4360 }
4361
4362 t0 = tcg_temp_new();
4363 t1 = tcg_temp_new();
4364 gen_load_gpr(t0, rs);
4365 gen_load_gpr(t1, rt);
4366 switch (opc) {
4367 case OPC_SLT:
e68dd28f 4368 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4369 break;
460f00c4 4370 case OPC_SLTU:
e68dd28f 4371 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4372 break;
4373 }
460f00c4
AJ
4374 tcg_temp_free(t0);
4375 tcg_temp_free(t1);
4376}
20c4c97c 4377
460f00c4 4378/* Shifts */
d75c135e
AJ
4379static void gen_shift(DisasContext *ctx, uint32_t opc,
4380 int rd, int rs, int rt)
460f00c4 4381{
460f00c4 4382 TCGv t0, t1;
20c4c97c 4383
460f00c4 4384 if (rd == 0) {
7480515f
AM
4385 /*
4386 * If no destination, treat it as a NOP.
4387 * For add & sub, we must generate the overflow exception when needed.
4388 */
460f00c4
AJ
4389 return;
4390 }
4391
4392 t0 = tcg_temp_new();
4393 t1 = tcg_temp_new();
4394 gen_load_gpr(t0, rs);
4395 gen_load_gpr(t1, rt);
4396 switch (opc) {
6af0bf9c 4397 case OPC_SLLV:
78723684
TS
4398 tcg_gen_andi_tl(t0, t0, 0x1f);
4399 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4400 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4401 break;
4402 case OPC_SRAV:
78723684 4403 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4404 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4405 break;
4406 case OPC_SRLV:
ea63e2c3
NF
4407 tcg_gen_ext32u_tl(t1, t1);
4408 tcg_gen_andi_tl(t0, t0, 0x1f);
4409 tcg_gen_shr_tl(t0, t1, t0);
4410 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4411 break;
4412 case OPC_ROTRV:
4413 {
4414 TCGv_i32 t2 = tcg_temp_new_i32();
4415 TCGv_i32 t3 = tcg_temp_new_i32();
4416
4417 tcg_gen_trunc_tl_i32(t2, t0);
4418 tcg_gen_trunc_tl_i32(t3, t1);
4419 tcg_gen_andi_i32(t2, t2, 0x1f);
4420 tcg_gen_rotr_i32(t2, t3, t2);
4421 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4422 tcg_temp_free_i32(t2);
4423 tcg_temp_free_i32(t3);
5a63bcb2 4424 }
7a387fff 4425 break;
d26bc211 4426#if defined(TARGET_MIPS64)
7a387fff 4427 case OPC_DSLLV:
78723684 4428 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4429 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4430 break;
4431 case OPC_DSRAV:
78723684 4432 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4433 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4434 break;
4435 case OPC_DSRLV:
ea63e2c3
NF
4436 tcg_gen_andi_tl(t0, t0, 0x3f);
4437 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4438 break;
4439 case OPC_DROTRV:
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4442 break;
7a387fff 4443#endif
6af0bf9c 4444 }
78723684
TS
4445 tcg_temp_free(t0);
4446 tcg_temp_free(t1);
6af0bf9c
FB
4447}
4448
37b9aae2 4449#if defined(TARGET_MIPS64)
86efbfb6
FN
4450/* Copy GPR to and from TX79 HI1/LO1 register. */
4451static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4452{
baa609db 4453 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4454 /* Treat as NOP. */
4455 return;
4456 }
4457
4458 switch (opc) {
baa609db 4459 case MMI_OPC_MFHI1:
86efbfb6
FN
4460 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4461 break;
baa609db 4462 case MMI_OPC_MFLO1:
86efbfb6
FN
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4464 break;
baa609db 4465 case MMI_OPC_MTHI1:
86efbfb6
FN
4466 if (reg != 0) {
4467 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4468 } else {
4469 tcg_gen_movi_tl(cpu_HI[1], 0);
4470 }
4471 break;
baa609db 4472 case MMI_OPC_MTLO1:
86efbfb6
FN
4473 if (reg != 0) {
4474 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4475 } else {
4476 tcg_gen_movi_tl(cpu_LO[1], 0);
4477 }
4478 break;
4479 default:
4480 MIPS_INVAL("mfthilo1 TX79");
4481 generate_exception_end(ctx, EXCP_RI);
4482 break;
4483 }
4484}
37b9aae2 4485#endif
86efbfb6 4486
6af0bf9c 4487/* Arithmetic on HI/LO registers */
26135ead 4488static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4489{
86efbfb6 4490 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4491 /* Treat as NOP. */
a1f6684d 4492 return;
6af0bf9c 4493 }
4133498f 4494
4133498f 4495 if (acc != 0) {
86efbfb6 4496 check_dsp(ctx);
4133498f
JL
4497 }
4498
6af0bf9c
FB
4499 switch (opc) {
4500 case OPC_MFHI:
4133498f
JL
4501#if defined(TARGET_MIPS64)
4502 if (acc != 0) {
4503 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4504 } else
4505#endif
4506 {
4507 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4508 }
6af0bf9c
FB
4509 break;
4510 case OPC_MFLO:
4133498f
JL
4511#if defined(TARGET_MIPS64)
4512 if (acc != 0) {
4513 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4514 } else
4515#endif
4516 {
4517 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4518 }
6af0bf9c
FB
4519 break;
4520 case OPC_MTHI:
4133498f
JL
4521 if (reg != 0) {
4522#if defined(TARGET_MIPS64)
4523 if (acc != 0) {
4524 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4525 } else
4526#endif
4527 {
4528 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4529 }
4530 } else {
4531 tcg_gen_movi_tl(cpu_HI[acc], 0);
4532 }
6af0bf9c
FB
4533 break;
4534 case OPC_MTLO:
4133498f
JL
4535 if (reg != 0) {
4536#if defined(TARGET_MIPS64)
4537 if (acc != 0) {
4538 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4539 } else
4540#endif
4541 {
4542 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4543 }
4544 } else {
4545 tcg_gen_movi_tl(cpu_LO[acc], 0);
4546 }
6af0bf9c 4547 break;
6af0bf9c 4548 }
6af0bf9c
FB
4549}
4550
d4ea6acd 4551static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 4552 MemOp memop)
d4ea6acd
LA
4553{
4554 TCGv t0 = tcg_const_tl(addr);
4555 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4556 gen_store_gpr(t0, reg);
4557 tcg_temp_free(t0);
4558}
4559
ab39ee45
YK
4560static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4561 int rs)
d4ea6acd
LA
4562{
4563 target_long offset;
4564 target_long addr;
4565
ab39ee45 4566 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4567 case OPC_ADDIUPC:
4568 if (rs != 0) {
4569 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4570 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4571 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4572 }
4573 break;
4574 case R6_OPC_LWPC:
4575 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4576 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4577 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4578 break;
4579#if defined(TARGET_MIPS64)
4580 case OPC_LWUPC:
4581 check_mips_64(ctx);
4582 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4583 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4584 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4585 break;
4586#endif
4587 default:
ab39ee45 4588 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4589 case OPC_AUIPC:
4590 if (rs != 0) {
ab39ee45
YK
4591 offset = sextract32(ctx->opcode, 0, 16) << 16;
4592 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4593 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4594 }
4595 break;
4596 case OPC_ALUIPC:
4597 if (rs != 0) {
ab39ee45
YK
4598 offset = sextract32(ctx->opcode, 0, 16) << 16;
4599 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4600 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4601 }
4602 break;
4603#if defined(TARGET_MIPS64)
4604 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4605 case R6_OPC_LDPC + (1 << 16):
4606 case R6_OPC_LDPC + (2 << 16):
4607 case R6_OPC_LDPC + (3 << 16):
4608 check_mips_64(ctx);
4609 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4610 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4611 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4612 break;
4613#endif
4614 default:
4615 MIPS_INVAL("OPC_PCREL");
9c708c7f 4616 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4617 break;
4618 }
4619 break;
4620 }
4621}
4622
b42ee5e1
LA
4623static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4624{
b42ee5e1
LA
4625 TCGv t0, t1;
4626
4627 if (rd == 0) {
4628 /* Treat as NOP. */
b42ee5e1
LA
4629 return;
4630 }
4631
4632 t0 = tcg_temp_new();
4633 t1 = tcg_temp_new();
4634
4635 gen_load_gpr(t0, rs);
4636 gen_load_gpr(t1, rt);
4637
4638 switch (opc) {
4639 case R6_OPC_DIV:
4640 {
4641 TCGv t2 = tcg_temp_new();
4642 TCGv t3 = tcg_temp_new();
4643 tcg_gen_ext32s_tl(t0, t0);
4644 tcg_gen_ext32s_tl(t1, t1);
4645 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4646 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4647 tcg_gen_and_tl(t2, t2, t3);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4649 tcg_gen_or_tl(t2, t2, t3);
4650 tcg_gen_movi_tl(t3, 0);
4651 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4652 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4653 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4654 tcg_temp_free(t3);
4655 tcg_temp_free(t2);
4656 }
b42ee5e1
LA
4657 break;
4658 case R6_OPC_MOD:
4659 {
4660 TCGv t2 = tcg_temp_new();
4661 TCGv t3 = tcg_temp_new();
4662 tcg_gen_ext32s_tl(t0, t0);
4663 tcg_gen_ext32s_tl(t1, t1);
4664 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4665 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4666 tcg_gen_and_tl(t2, t2, t3);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4668 tcg_gen_or_tl(t2, t2, t3);
4669 tcg_gen_movi_tl(t3, 0);
4670 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4671 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4672 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4673 tcg_temp_free(t3);
4674 tcg_temp_free(t2);
4675 }
b42ee5e1
LA
4676 break;
4677 case R6_OPC_DIVU:
4678 {
4679 TCGv t2 = tcg_const_tl(0);
4680 TCGv t3 = tcg_const_tl(1);
4681 tcg_gen_ext32u_tl(t0, t0);
4682 tcg_gen_ext32u_tl(t1, t1);
4683 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4684 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4685 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4686 tcg_temp_free(t3);
4687 tcg_temp_free(t2);
4688 }
b42ee5e1
LA
4689 break;
4690 case R6_OPC_MODU:
4691 {
4692 TCGv t2 = tcg_const_tl(0);
4693 TCGv t3 = tcg_const_tl(1);
4694 tcg_gen_ext32u_tl(t0, t0);
4695 tcg_gen_ext32u_tl(t1, t1);
4696 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4697 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4698 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4699 tcg_temp_free(t3);
4700 tcg_temp_free(t2);
4701 }
b42ee5e1
LA
4702 break;
4703 case R6_OPC_MUL:
4704 {
4705 TCGv_i32 t2 = tcg_temp_new_i32();
4706 TCGv_i32 t3 = tcg_temp_new_i32();
4707 tcg_gen_trunc_tl_i32(t2, t0);
4708 tcg_gen_trunc_tl_i32(t3, t1);
4709 tcg_gen_mul_i32(t2, t2, t3);
4710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4711 tcg_temp_free_i32(t2);
4712 tcg_temp_free_i32(t3);
4713 }
b42ee5e1
LA
4714 break;
4715 case R6_OPC_MUH:
4716 {
4717 TCGv_i32 t2 = tcg_temp_new_i32();
4718 TCGv_i32 t3 = tcg_temp_new_i32();
4719 tcg_gen_trunc_tl_i32(t2, t0);
4720 tcg_gen_trunc_tl_i32(t3, t1);
4721 tcg_gen_muls2_i32(t2, t3, t2, t3);
4722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4725 }
b42ee5e1
LA
4726 break;
4727 case R6_OPC_MULU:
4728 {
4729 TCGv_i32 t2 = tcg_temp_new_i32();
4730 TCGv_i32 t3 = tcg_temp_new_i32();
4731 tcg_gen_trunc_tl_i32(t2, t0);
4732 tcg_gen_trunc_tl_i32(t3, t1);
4733 tcg_gen_mul_i32(t2, t2, t3);
4734 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4735 tcg_temp_free_i32(t2);
4736 tcg_temp_free_i32(t3);
4737 }
b42ee5e1
LA
4738 break;
4739 case R6_OPC_MUHU:
4740 {
4741 TCGv_i32 t2 = tcg_temp_new_i32();
4742 TCGv_i32 t3 = tcg_temp_new_i32();
4743 tcg_gen_trunc_tl_i32(t2, t0);
4744 tcg_gen_trunc_tl_i32(t3, t1);
4745 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4746 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4747 tcg_temp_free_i32(t2);
4748 tcg_temp_free_i32(t3);
4749 }
b42ee5e1
LA
4750 break;
4751#if defined(TARGET_MIPS64)
4752 case R6_OPC_DDIV:
4753 {
4754 TCGv t2 = tcg_temp_new();
4755 TCGv t3 = tcg_temp_new();
4756 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4757 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4758 tcg_gen_and_tl(t2, t2, t3);
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4760 tcg_gen_or_tl(t2, t2, t3);
4761 tcg_gen_movi_tl(t3, 0);
4762 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4763 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4764 tcg_temp_free(t3);
4765 tcg_temp_free(t2);
4766 }
b42ee5e1
LA
4767 break;
4768 case R6_OPC_DMOD:
4769 {
4770 TCGv t2 = tcg_temp_new();
4771 TCGv t3 = tcg_temp_new();
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4774 tcg_gen_and_tl(t2, t2, t3);
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4776 tcg_gen_or_tl(t2, t2, t3);
4777 tcg_gen_movi_tl(t3, 0);
4778 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4779 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4782 }
b42ee5e1
LA
4783 break;
4784 case R6_OPC_DDIVU:
4785 {
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4789 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4790 tcg_temp_free(t3);
4791 tcg_temp_free(t2);
4792 }
b42ee5e1
LA
4793 break;
4794 case R6_OPC_DMODU:
4795 {
4796 TCGv t2 = tcg_const_tl(0);
4797 TCGv t3 = tcg_const_tl(1);
4798 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4799 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4800 tcg_temp_free(t3);
4801 tcg_temp_free(t2);
4802 }
b42ee5e1
LA
4803 break;
4804 case R6_OPC_DMUL:
4805 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4806 break;
4807 case R6_OPC_DMUH:
4808 {
4809 TCGv t2 = tcg_temp_new();
4810 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4811 tcg_temp_free(t2);
4812 }
b42ee5e1
LA
4813 break;
4814 case R6_OPC_DMULU:
4815 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4816 break;
4817 case R6_OPC_DMUHU:
4818 {
4819 TCGv t2 = tcg_temp_new();
4820 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4821 tcg_temp_free(t2);
4822 }
b42ee5e1
LA
4823 break;
4824#endif
4825 default:
9d68ac14 4826 MIPS_INVAL("r6 mul/div");
9c708c7f 4827 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4828 goto out;
4829 }
b42ee5e1
LA
4830 out:
4831 tcg_temp_free(t0);
4832 tcg_temp_free(t1);
4833}
4834
37b9aae2 4835#if defined(TARGET_MIPS64)
c42171c3
FN
4836static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4837{
4838 TCGv t0, t1;
4839
4840 t0 = tcg_temp_new();
4841 t1 = tcg_temp_new();
4842
4843 gen_load_gpr(t0, rs);
4844 gen_load_gpr(t1, rt);
4845
4846 switch (opc) {
baa609db 4847 case MMI_OPC_DIV1:
c42171c3
FN
4848 {
4849 TCGv t2 = tcg_temp_new();
4850 TCGv t3 = tcg_temp_new();
4851 tcg_gen_ext32s_tl(t0, t0);
4852 tcg_gen_ext32s_tl(t1, t1);
4853 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4854 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4855 tcg_gen_and_tl(t2, t2, t3);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4857 tcg_gen_or_tl(t2, t2, t3);
4858 tcg_gen_movi_tl(t3, 0);
4859 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4860 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4861 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4862 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4863 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4864 tcg_temp_free(t3);
4865 tcg_temp_free(t2);
4866 }
4867 break;
baa609db 4868 case MMI_OPC_DIVU1:
c42171c3
FN
4869 {
4870 TCGv t2 = tcg_const_tl(0);
4871 TCGv t3 = tcg_const_tl(1);
4872 tcg_gen_ext32u_tl(t0, t0);
4873 tcg_gen_ext32u_tl(t1, t1);
4874 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4875 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4876 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4877 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4878 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4879 tcg_temp_free(t3);
4880 tcg_temp_free(t2);
4881 }
4882 break;
4883 default:
4884 MIPS_INVAL("div1 TX79");
4885 generate_exception_end(ctx, EXCP_RI);
4886 goto out;
4887 }
4888 out:
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4891}
37b9aae2 4892#endif
c42171c3 4893
26135ead
RS
4894static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4895 int acc, int rs, int rt)
6af0bf9c 4896{
d45f89f4
AJ
4897 TCGv t0, t1;
4898
51127181
AJ
4899 t0 = tcg_temp_new();
4900 t1 = tcg_temp_new();
6af0bf9c 4901
78723684
TS
4902 gen_load_gpr(t0, rs);
4903 gen_load_gpr(t1, rt);
51127181 4904
26135ead 4905 if (acc != 0) {
c42171c3 4906 check_dsp(ctx);
26135ead
RS
4907 }
4908
6af0bf9c
FB
4909 switch (opc) {
4910 case OPC_DIV:
48d38ca5 4911 {
51127181
AJ
4912 TCGv t2 = tcg_temp_new();
4913 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4914 tcg_gen_ext32s_tl(t0, t0);
4915 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4916 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4917 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4918 tcg_gen_and_tl(t2, t2, t3);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4920 tcg_gen_or_tl(t2, t2, t3);
4921 tcg_gen_movi_tl(t3, 0);
4922 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4923 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4924 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4925 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4926 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4927 tcg_temp_free(t3);
4928 tcg_temp_free(t2);
48d38ca5 4929 }
6af0bf9c
FB
4930 break;
4931 case OPC_DIVU:
48d38ca5 4932 {
51127181
AJ
4933 TCGv t2 = tcg_const_tl(0);
4934 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4935 tcg_gen_ext32u_tl(t0, t0);
4936 tcg_gen_ext32u_tl(t1, t1);
51127181 4937 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4938 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4939 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4940 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4941 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4942 tcg_temp_free(t3);
4943 tcg_temp_free(t2);
48d38ca5 4944 }
6af0bf9c
FB
4945 break;
4946 case OPC_MULT:
214c465f 4947 {
ce1dd5d1
RH
4948 TCGv_i32 t2 = tcg_temp_new_i32();
4949 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4950 tcg_gen_trunc_tl_i32(t2, t0);
4951 tcg_gen_trunc_tl_i32(t3, t1);
4952 tcg_gen_muls2_i32(t2, t3, t2, t3);
4953 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4954 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4955 tcg_temp_free_i32(t2);
4956 tcg_temp_free_i32(t3);
214c465f 4957 }
6af0bf9c
FB
4958 break;
4959 case OPC_MULTU:
214c465f 4960 {
ce1dd5d1
RH
4961 TCGv_i32 t2 = tcg_temp_new_i32();
4962 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4963 tcg_gen_trunc_tl_i32(t2, t0);
4964 tcg_gen_trunc_tl_i32(t3, t1);
4965 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4966 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4967 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4968 tcg_temp_free_i32(t2);
4969 tcg_temp_free_i32(t3);
214c465f 4970 }
6af0bf9c 4971 break;
d26bc211 4972#if defined(TARGET_MIPS64)
7a387fff 4973 case OPC_DDIV:
48d38ca5 4974 {
51127181
AJ
4975 TCGv t2 = tcg_temp_new();
4976 TCGv t3 = tcg_temp_new();
4977 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4978 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4979 tcg_gen_and_tl(t2, t2, t3);
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4981 tcg_gen_or_tl(t2, t2, t3);
4982 tcg_gen_movi_tl(t3, 0);
4983 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4984 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4985 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4986 tcg_temp_free(t3);
4987 tcg_temp_free(t2);
48d38ca5 4988 }
7a387fff
TS
4989 break;
4990 case OPC_DDIVU:
48d38ca5 4991 {
51127181
AJ
4992 TCGv t2 = tcg_const_tl(0);
4993 TCGv t3 = tcg_const_tl(1);
4994 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4995 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4996 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
4997 tcg_temp_free(t3);
4998 tcg_temp_free(t2);
48d38ca5 4999 }
7a387fff
TS
5000 break;
5001 case OPC_DMULT:
26135ead 5002 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5003 break;
5004 case OPC_DMULTU:
26135ead 5005 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5006 break;
5007#endif
6af0bf9c 5008 case OPC_MADD:
214c465f 5009 {
d45f89f4
AJ
5010 TCGv_i64 t2 = tcg_temp_new_i64();
5011 TCGv_i64 t3 = tcg_temp_new_i64();
5012
5013 tcg_gen_ext_tl_i64(t2, t0);
5014 tcg_gen_ext_tl_i64(t3, t1);
5015 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5016 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5017 tcg_gen_add_i64(t2, t2, t3);
5018 tcg_temp_free_i64(t3);
71f303cd
RH
5019 gen_move_low32(cpu_LO[acc], t2);
5020 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5021 tcg_temp_free_i64(t2);
214c465f 5022 }
6af0bf9c
FB
5023 break;
5024 case OPC_MADDU:
4133498f 5025 {
d45f89f4
AJ
5026 TCGv_i64 t2 = tcg_temp_new_i64();
5027 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5028
78723684
TS
5029 tcg_gen_ext32u_tl(t0, t0);
5030 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5031 tcg_gen_extu_tl_i64(t2, t0);
5032 tcg_gen_extu_tl_i64(t3, t1);
5033 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5034 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5035 tcg_gen_add_i64(t2, t2, t3);
5036 tcg_temp_free_i64(t3);
71f303cd
RH
5037 gen_move_low32(cpu_LO[acc], t2);
5038 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5039 tcg_temp_free_i64(t2);
214c465f 5040 }
6af0bf9c
FB
5041 break;
5042 case OPC_MSUB:
214c465f 5043 {
d45f89f4
AJ
5044 TCGv_i64 t2 = tcg_temp_new_i64();
5045 TCGv_i64 t3 = tcg_temp_new_i64();
5046
5047 tcg_gen_ext_tl_i64(t2, t0);
5048 tcg_gen_ext_tl_i64(t3, t1);
5049 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5050 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5051 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5052 tcg_temp_free_i64(t3);
71f303cd
RH
5053 gen_move_low32(cpu_LO[acc], t2);
5054 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5055 tcg_temp_free_i64(t2);
214c465f 5056 }
6af0bf9c
FB
5057 break;
5058 case OPC_MSUBU:
214c465f 5059 {
d45f89f4
AJ
5060 TCGv_i64 t2 = tcg_temp_new_i64();
5061 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5062
78723684
TS
5063 tcg_gen_ext32u_tl(t0, t0);
5064 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5065 tcg_gen_extu_tl_i64(t2, t0);
5066 tcg_gen_extu_tl_i64(t3, t1);
5067 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5068 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5069 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5070 tcg_temp_free_i64(t3);
71f303cd
RH
5071 gen_move_low32(cpu_LO[acc], t2);
5072 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5073 tcg_temp_free_i64(t2);
214c465f 5074 }
6af0bf9c
FB
5075 break;
5076 default:
9d68ac14 5077 MIPS_INVAL("mul/div");
9c708c7f 5078 generate_exception_end(ctx, EXCP_RI);
78723684 5079 goto out;
6af0bf9c 5080 }
78723684
TS
5081 out:
5082 tcg_temp_free(t0);
5083 tcg_temp_free(t1);
6af0bf9c
FB
5084}
5085
21e8e8b2 5086/*
3b948f05
PMD
5087 * These MULT[U] and MADD[U] instructions implemented in for example
5088 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5089 * architectures are special three-operand variants with the syntax
5090 *
06de726b 5091 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5092 *
5093 * such that
5094 *
5095 * (rd, LO, HI) <- rs * rt
5096 *
3b948f05
PMD
5097 * and
5098 *
a95c4c26 5099 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5100 *
5101 * such that
5102 *
5103 * (rd, LO, HI) <- (LO, HI) + rs * rt
5104 *
21e8e8b2
FN
5105 * where the low-order 32-bits of the result is placed into both the
5106 * GPR rd and the special register LO. The high-order 32-bits of the
5107 * result is placed into the special register HI.
5108 *
5109 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5110 * which is the zero register that always reads as 0.
5111 */
5112static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5113 int rd, int rs, int rt)
5114{
5115 TCGv t0 = tcg_temp_new();
5116 TCGv t1 = tcg_temp_new();
5117 int acc = 0;
5118
5119 gen_load_gpr(t0, rs);
5120 gen_load_gpr(t1, rt);
5121
5122 switch (opc) {
baa609db 5123 case MMI_OPC_MULT1:
06de726b
FN
5124 acc = 1;
5125 /* Fall through */
21e8e8b2
FN
5126 case OPC_MULT:
5127 {
5128 TCGv_i32 t2 = tcg_temp_new_i32();
5129 TCGv_i32 t3 = tcg_temp_new_i32();
5130 tcg_gen_trunc_tl_i32(t2, t0);
5131 tcg_gen_trunc_tl_i32(t3, t1);
5132 tcg_gen_muls2_i32(t2, t3, t2, t3);
5133 if (rd) {
5134 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5135 }
5136 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5137 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5138 tcg_temp_free_i32(t2);
5139 tcg_temp_free_i32(t3);
5140 }
5141 break;
baa609db 5142 case MMI_OPC_MULTU1:
06de726b
FN
5143 acc = 1;
5144 /* Fall through */
21e8e8b2
FN
5145 case OPC_MULTU:
5146 {
5147 TCGv_i32 t2 = tcg_temp_new_i32();
5148 TCGv_i32 t3 = tcg_temp_new_i32();
5149 tcg_gen_trunc_tl_i32(t2, t0);
5150 tcg_gen_trunc_tl_i32(t3, t1);
5151 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5152 if (rd) {
5153 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5154 }
5155 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5156 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5157 tcg_temp_free_i32(t2);
5158 tcg_temp_free_i32(t3);
5159 }
5160 break;
a95c4c26
FN
5161 case MMI_OPC_MADD1:
5162 acc = 1;
5163 /* Fall through */
3b948f05
PMD
5164 case MMI_OPC_MADD:
5165 {
5166 TCGv_i64 t2 = tcg_temp_new_i64();
5167 TCGv_i64 t3 = tcg_temp_new_i64();
5168
5169 tcg_gen_ext_tl_i64(t2, t0);
5170 tcg_gen_ext_tl_i64(t3, t1);
5171 tcg_gen_mul_i64(t2, t2, t3);
5172 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5173 tcg_gen_add_i64(t2, t2, t3);
5174 tcg_temp_free_i64(t3);
5175 gen_move_low32(cpu_LO[acc], t2);
5176 gen_move_high32(cpu_HI[acc], t2);
5177 if (rd) {
5178 gen_move_low32(cpu_gpr[rd], t2);
5179 }
5180 tcg_temp_free_i64(t2);
5181 }
5182 break;
a95c4c26
FN
5183 case MMI_OPC_MADDU1:
5184 acc = 1;
5185 /* Fall through */
3b948f05
PMD
5186 case MMI_OPC_MADDU:
5187 {
5188 TCGv_i64 t2 = tcg_temp_new_i64();
5189 TCGv_i64 t3 = tcg_temp_new_i64();
5190
5191 tcg_gen_ext32u_tl(t0, t0);
5192 tcg_gen_ext32u_tl(t1, t1);
5193 tcg_gen_extu_tl_i64(t2, t0);
5194 tcg_gen_extu_tl_i64(t3, t1);
5195 tcg_gen_mul_i64(t2, t2, t3);
5196 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5197 tcg_gen_add_i64(t2, t2, t3);
5198 tcg_temp_free_i64(t3);
5199 gen_move_low32(cpu_LO[acc], t2);
5200 gen_move_high32(cpu_HI[acc], t2);
5201 if (rd) {
5202 gen_move_low32(cpu_gpr[rd], t2);
5203 }
5204 tcg_temp_free_i64(t2);
5205 }
5206 break;
21e8e8b2 5207 default:
3b948f05 5208 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5209 generate_exception_end(ctx, EXCP_RI);
5210 goto out;
5211 }
5212
5213 out:
5214 tcg_temp_free(t0);
5215 tcg_temp_free(t1);
5216}
5217
235785e8
AM
5218static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5219 int rd, int rs, int rt)
e9c71dd1 5220{
f157bfe1
AJ
5221 TCGv t0 = tcg_temp_new();
5222 TCGv t1 = tcg_temp_new();
e9c71dd1 5223
6c5c1e20
TS
5224 gen_load_gpr(t0, rs);
5225 gen_load_gpr(t1, rt);
e9c71dd1
TS
5226
5227 switch (opc) {
5228 case OPC_VR54XX_MULS:
895c2d04 5229 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5230 break;
e9c71dd1 5231 case OPC_VR54XX_MULSU:
895c2d04 5232 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5233 break;
e9c71dd1 5234 case OPC_VR54XX_MACC:
895c2d04 5235 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5236 break;
e9c71dd1 5237 case OPC_VR54XX_MACCU:
895c2d04 5238 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5239 break;
e9c71dd1 5240 case OPC_VR54XX_MSAC:
895c2d04 5241 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5242 break;
e9c71dd1 5243 case OPC_VR54XX_MSACU:
895c2d04 5244 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5245 break;
e9c71dd1 5246 case OPC_VR54XX_MULHI:
895c2d04 5247 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5248 break;
e9c71dd1 5249 case OPC_VR54XX_MULHIU:
895c2d04 5250 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5251 break;
e9c71dd1 5252 case OPC_VR54XX_MULSHI:
895c2d04 5253 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5254 break;
e9c71dd1 5255 case OPC_VR54XX_MULSHIU:
895c2d04 5256 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5257 break;
e9c71dd1 5258 case OPC_VR54XX_MACCHI:
895c2d04 5259 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5260 break;
e9c71dd1 5261 case OPC_VR54XX_MACCHIU:
895c2d04 5262 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5263 break;
e9c71dd1 5264 case OPC_VR54XX_MSACHI:
895c2d04 5265 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5266 break;
e9c71dd1 5267 case OPC_VR54XX_MSACHIU:
895c2d04 5268 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5269 break;
e9c71dd1
TS
5270 default:
5271 MIPS_INVAL("mul vr54xx");
9c708c7f 5272 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5273 goto out;
e9c71dd1 5274 }
6c5c1e20 5275 gen_store_gpr(t0, rd);
6c5c1e20
TS
5276
5277 out:
5278 tcg_temp_free(t0);
5279 tcg_temp_free(t1);
e9c71dd1
TS
5280}
5281
235785e8
AM
5282static void gen_cl(DisasContext *ctx, uint32_t opc,
5283 int rd, int rs)
6af0bf9c 5284{
20e1fb52 5285 TCGv t0;
6c5c1e20 5286
6af0bf9c 5287 if (rd == 0) {
ead9360e 5288 /* Treat as NOP. */
20e1fb52 5289 return;
6af0bf9c 5290 }
1a0196c5 5291 t0 = cpu_gpr[rd];
6c5c1e20 5292 gen_load_gpr(t0, rs);
1a0196c5 5293
6af0bf9c
FB
5294 switch (opc) {
5295 case OPC_CLO:
4267d3e6 5296 case R6_OPC_CLO:
1a0196c5
RH
5297#if defined(TARGET_MIPS64)
5298 case OPC_DCLO:
5299 case R6_OPC_DCLO:
5300#endif
5301 tcg_gen_not_tl(t0, t0);
6af0bf9c 5302 break;
1a0196c5
RH
5303 }
5304
5305 switch (opc) {
5306 case OPC_CLO:
5307 case R6_OPC_CLO:
6af0bf9c 5308 case OPC_CLZ:
4267d3e6 5309 case R6_OPC_CLZ:
1a0196c5
RH
5310 tcg_gen_ext32u_tl(t0, t0);
5311 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5312 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5313 break;
d26bc211 5314#if defined(TARGET_MIPS64)
7a387fff 5315 case OPC_DCLO:
4267d3e6 5316 case R6_OPC_DCLO:
7a387fff 5317 case OPC_DCLZ:
4267d3e6 5318 case R6_OPC_DCLZ:
1a0196c5 5319 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5320 break;
5321#endif
6af0bf9c 5322 }
6af0bf9c
FB
5323}
5324
161f85e6 5325/* Godson integer instructions */
bd277fa1
RH
5326static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5327 int rd, int rs, int rt)
161f85e6 5328{
161f85e6
AJ
5329 TCGv t0, t1;
5330
5331 if (rd == 0) {
5332 /* Treat as NOP. */
161f85e6
AJ
5333 return;
5334 }
5335
5336 switch (opc) {
5337 case OPC_MULT_G_2E:
5338 case OPC_MULT_G_2F:
5339 case OPC_MULTU_G_2E:
5340 case OPC_MULTU_G_2F:
5341#if defined(TARGET_MIPS64)
5342 case OPC_DMULT_G_2E:
5343 case OPC_DMULT_G_2F:
5344 case OPC_DMULTU_G_2E:
5345 case OPC_DMULTU_G_2F:
5346#endif
5347 t0 = tcg_temp_new();
5348 t1 = tcg_temp_new();
5349 break;
5350 default:
5351 t0 = tcg_temp_local_new();
5352 t1 = tcg_temp_local_new();
5353 break;
5354 }
5355
5356 gen_load_gpr(t0, rs);
5357 gen_load_gpr(t1, rt);
5358
5359 switch (opc) {
5360 case OPC_MULT_G_2E:
5361 case OPC_MULT_G_2F:
5362 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5363 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5364 break;
5365 case OPC_MULTU_G_2E:
5366 case OPC_MULTU_G_2F:
5367 tcg_gen_ext32u_tl(t0, t0);
5368 tcg_gen_ext32u_tl(t1, t1);
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5371 break;
5372 case OPC_DIV_G_2E:
5373 case OPC_DIV_G_2F:
5374 {
42a268c2
RH
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5378 tcg_gen_ext32s_tl(t0, t0);
5379 tcg_gen_ext32s_tl(t1, t1);
5380 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5381 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5382 tcg_gen_br(l3);
5383 gen_set_label(l1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5385 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5386 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5387 tcg_gen_br(l3);
5388 gen_set_label(l2);
5389 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5390 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5391 gen_set_label(l3);
5392 }
161f85e6
AJ
5393 break;
5394 case OPC_DIVU_G_2E:
5395 case OPC_DIVU_G_2F:
5396 {
42a268c2
RH
5397 TCGLabel *l1 = gen_new_label();
5398 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5399 tcg_gen_ext32u_tl(t0, t0);
5400 tcg_gen_ext32u_tl(t1, t1);
5401 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5402 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5403 tcg_gen_br(l2);
5404 gen_set_label(l1);
5405 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5406 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5407 gen_set_label(l2);
5408 }
161f85e6
AJ
5409 break;
5410 case OPC_MOD_G_2E:
5411 case OPC_MOD_G_2F:
5412 {
42a268c2
RH
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5416 tcg_gen_ext32u_tl(t0, t0);
5417 tcg_gen_ext32u_tl(t1, t1);
5418 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5419 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5421 gen_set_label(l1);
5422 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5426 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5427 gen_set_label(l3);
5428 }
161f85e6
AJ
5429 break;
5430 case OPC_MODU_G_2E:
5431 case OPC_MODU_G_2F:
5432 {
42a268c2
RH
5433 TCGLabel *l1 = gen_new_label();
5434 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5435 tcg_gen_ext32u_tl(t0, t0);
5436 tcg_gen_ext32u_tl(t1, t1);
5437 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5439 tcg_gen_br(l2);
5440 gen_set_label(l1);
5441 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5442 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5443 gen_set_label(l2);
5444 }
161f85e6
AJ
5445 break;
5446#if defined(TARGET_MIPS64)
5447 case OPC_DMULT_G_2E:
5448 case OPC_DMULT_G_2F:
5449 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5450 break;
5451 case OPC_DMULTU_G_2E:
5452 case OPC_DMULTU_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5454 break;
5455 case OPC_DDIV_G_2E:
5456 case OPC_DDIV_G_2F:
5457 {
42a268c2
RH
5458 TCGLabel *l1 = gen_new_label();
5459 TCGLabel *l2 = gen_new_label();
5460 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5462 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5463 tcg_gen_br(l3);
5464 gen_set_label(l1);
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5467 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5468 tcg_gen_br(l3);
5469 gen_set_label(l2);
5470 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5471 gen_set_label(l3);
5472 }
161f85e6
AJ
5473 break;
5474 case OPC_DDIVU_G_2E:
5475 case OPC_DDIVU_G_2F:
5476 {
42a268c2
RH
5477 TCGLabel *l1 = gen_new_label();
5478 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5479 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5480 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5481 tcg_gen_br(l2);
5482 gen_set_label(l1);
5483 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5484 gen_set_label(l2);
5485 }
161f85e6
AJ
5486 break;
5487 case OPC_DMOD_G_2E:
5488 case OPC_DMOD_G_2F:
5489 {
42a268c2
RH
5490 TCGLabel *l1 = gen_new_label();
5491 TCGLabel *l2 = gen_new_label();
5492 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5493 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5494 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5495 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5496 gen_set_label(l1);
5497 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5498 tcg_gen_br(l3);
5499 gen_set_label(l2);
5500 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5501 gen_set_label(l3);
5502 }
161f85e6
AJ
5503 break;
5504 case OPC_DMODU_G_2E:
5505 case OPC_DMODU_G_2F:
5506 {
42a268c2
RH
5507 TCGLabel *l1 = gen_new_label();
5508 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5509 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5510 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5511 tcg_gen_br(l2);
5512 gen_set_label(l1);
5513 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5514 gen_set_label(l2);
5515 }
161f85e6
AJ
5516 break;
5517#endif
5518 }
5519
161f85e6
AJ
5520 tcg_temp_free(t0);
5521 tcg_temp_free(t1);
5522}
5523
bd277fa1
RH
5524/* Loongson multimedia instructions */
5525static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5526{
bd277fa1
RH
5527 uint32_t opc, shift_max;
5528 TCGv_i64 t0, t1;
5529
5530 opc = MASK_LMI(ctx->opcode);
5531 switch (opc) {
5532 case OPC_ADD_CP2:
5533 case OPC_SUB_CP2:
5534 case OPC_DADD_CP2:
5535 case OPC_DSUB_CP2:
5536 t0 = tcg_temp_local_new_i64();
5537 t1 = tcg_temp_local_new_i64();
5538 break;
5539 default:
5540 t0 = tcg_temp_new_i64();
5541 t1 = tcg_temp_new_i64();
5542 break;
5543 }
5544
b5a587b6 5545 check_cp1_enabled(ctx);
bd277fa1
RH
5546 gen_load_fpr64(ctx, t0, rs);
5547 gen_load_fpr64(ctx, t1, rt);
5548
5549#define LMI_HELPER(UP, LO) \
9d68ac14 5550 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 5551#define LMI_HELPER_1(UP, LO) \
9d68ac14 5552 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 5553#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 5554 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
5555
5556 switch (opc) {
5557 LMI_HELPER(PADDSH, paddsh);
5558 LMI_HELPER(PADDUSH, paddush);
5559 LMI_HELPER(PADDH, paddh);
5560 LMI_HELPER(PADDW, paddw);
5561 LMI_HELPER(PADDSB, paddsb);
5562 LMI_HELPER(PADDUSB, paddusb);
5563 LMI_HELPER(PADDB, paddb);
5564
5565 LMI_HELPER(PSUBSH, psubsh);
5566 LMI_HELPER(PSUBUSH, psubush);
5567 LMI_HELPER(PSUBH, psubh);
5568 LMI_HELPER(PSUBW, psubw);
5569 LMI_HELPER(PSUBSB, psubsb);
5570 LMI_HELPER(PSUBUSB, psubusb);
5571 LMI_HELPER(PSUBB, psubb);
5572
5573 LMI_HELPER(PSHUFH, pshufh);
5574 LMI_HELPER(PACKSSWH, packsswh);
5575 LMI_HELPER(PACKSSHB, packsshb);
5576 LMI_HELPER(PACKUSHB, packushb);
5577
5578 LMI_HELPER(PUNPCKLHW, punpcklhw);
5579 LMI_HELPER(PUNPCKHHW, punpckhhw);
5580 LMI_HELPER(PUNPCKLBH, punpcklbh);
5581 LMI_HELPER(PUNPCKHBH, punpckhbh);
5582 LMI_HELPER(PUNPCKLWD, punpcklwd);
5583 LMI_HELPER(PUNPCKHWD, punpckhwd);
5584
5585 LMI_HELPER(PAVGH, pavgh);
5586 LMI_HELPER(PAVGB, pavgb);
5587 LMI_HELPER(PMAXSH, pmaxsh);
5588 LMI_HELPER(PMINSH, pminsh);
5589 LMI_HELPER(PMAXUB, pmaxub);
5590 LMI_HELPER(PMINUB, pminub);
5591
5592 LMI_HELPER(PCMPEQW, pcmpeqw);
5593 LMI_HELPER(PCMPGTW, pcmpgtw);
5594 LMI_HELPER(PCMPEQH, pcmpeqh);
5595 LMI_HELPER(PCMPGTH, pcmpgth);
5596 LMI_HELPER(PCMPEQB, pcmpeqb);
5597 LMI_HELPER(PCMPGTB, pcmpgtb);
5598
5599 LMI_HELPER(PSLLW, psllw);
5600 LMI_HELPER(PSLLH, psllh);
5601 LMI_HELPER(PSRLW, psrlw);
5602 LMI_HELPER(PSRLH, psrlh);
5603 LMI_HELPER(PSRAW, psraw);
5604 LMI_HELPER(PSRAH, psrah);
5605
5606 LMI_HELPER(PMULLH, pmullh);
5607 LMI_HELPER(PMULHH, pmulhh);
5608 LMI_HELPER(PMULHUH, pmulhuh);
5609 LMI_HELPER(PMADDHW, pmaddhw);
5610
5611 LMI_HELPER(PASUBUB, pasubub);
5612 LMI_HELPER_1(BIADD, biadd);
5613 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5614
5615 LMI_DIRECT(PADDD, paddd, add);
5616 LMI_DIRECT(PSUBD, psubd, sub);
5617 LMI_DIRECT(XOR_CP2, xor, xor);
5618 LMI_DIRECT(NOR_CP2, nor, nor);
5619 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 5620 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 5621
9099a36b
H
5622 case OPC_PANDN:
5623 tcg_gen_andc_i64(t0, t1, t0);
5624 break;
5625
bd277fa1
RH
5626 case OPC_PINSRH_0:
5627 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5628 break;
5629 case OPC_PINSRH_1:
5630 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5631 break;
5632 case OPC_PINSRH_2:
5633 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5634 break;
5635 case OPC_PINSRH_3:
5636 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5637 break;
5638
5639 case OPC_PEXTRH:
5640 tcg_gen_andi_i64(t1, t1, 3);
5641 tcg_gen_shli_i64(t1, t1, 4);
5642 tcg_gen_shr_i64(t0, t0, t1);
5643 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5644 break;
5645
5646 case OPC_ADDU_CP2:
5647 tcg_gen_add_i64(t0, t0, t1);
5648 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5649 break;
5650 case OPC_SUBU_CP2:
5651 tcg_gen_sub_i64(t0, t0, t1);
5652 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5653 break;
5654
5655 case OPC_SLL_CP2:
bd277fa1
RH
5656 shift_max = 32;
5657 goto do_shift;
5658 case OPC_SRL_CP2:
bd277fa1
RH
5659 shift_max = 32;
5660 goto do_shift;
5661 case OPC_SRA_CP2:
bd277fa1
RH
5662 shift_max = 32;
5663 goto do_shift;
5664 case OPC_DSLL_CP2:
bd277fa1
RH
5665 shift_max = 64;
5666 goto do_shift;
5667 case OPC_DSRL_CP2:
bd277fa1
RH
5668 shift_max = 64;
5669 goto do_shift;
5670 case OPC_DSRA_CP2:
bd277fa1
RH
5671 shift_max = 64;
5672 goto do_shift;
5673 do_shift:
5674 /* Make sure shift count isn't TCG undefined behaviour. */
5675 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5676
5677 switch (opc) {
5678 case OPC_SLL_CP2:
5679 case OPC_DSLL_CP2:
5680 tcg_gen_shl_i64(t0, t0, t1);
5681 break;
5682 case OPC_SRA_CP2:
5683 case OPC_DSRA_CP2:
7480515f
AM
5684 /*
5685 * Since SRA is UndefinedResult without sign-extended inputs,
5686 * we can treat SRA and DSRA the same.
5687 */
bd277fa1
RH
5688 tcg_gen_sar_i64(t0, t0, t1);
5689 break;
5690 case OPC_SRL_CP2:
5691 /* We want to shift in zeros for SRL; zero-extend first. */
5692 tcg_gen_ext32u_i64(t0, t0);
5693 /* FALLTHRU */
5694 case OPC_DSRL_CP2:
5695 tcg_gen_shr_i64(t0, t0, t1);
5696 break;
5697 }
5698
5699 if (shift_max == 32) {
5700 tcg_gen_ext32s_i64(t0, t0);
5701 }
5702
5703 /* Shifts larger than MAX produce zero. */
5704 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5705 tcg_gen_neg_i64(t1, t1);
5706 tcg_gen_and_i64(t0, t0, t1);
5707 break;
5708
5709 case OPC_ADD_CP2:
5710 case OPC_DADD_CP2:
5711 {
5712 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5713 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5714
5715 tcg_gen_mov_i64(t2, t0);
5716 tcg_gen_add_i64(t0, t1, t2);
5717 if (opc == OPC_ADD_CP2) {
5718 tcg_gen_ext32s_i64(t0, t0);
5719 }
5720 tcg_gen_xor_i64(t1, t1, t2);
5721 tcg_gen_xor_i64(t2, t2, t0);
5722 tcg_gen_andc_i64(t1, t2, t1);
5723 tcg_temp_free_i64(t2);
5724 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5725 generate_exception(ctx, EXCP_OVERFLOW);
5726 gen_set_label(lab);
bd277fa1
RH
5727 break;
5728 }
5729
5730 case OPC_SUB_CP2:
5731 case OPC_DSUB_CP2:
5732 {
5733 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5734 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5735
5736 tcg_gen_mov_i64(t2, t0);
5737 tcg_gen_sub_i64(t0, t1, t2);
5738 if (opc == OPC_SUB_CP2) {
5739 tcg_gen_ext32s_i64(t0, t0);
5740 }
5741 tcg_gen_xor_i64(t1, t1, t2);
5742 tcg_gen_xor_i64(t2, t2, t0);
5743 tcg_gen_and_i64(t1, t1, t2);
5744 tcg_temp_free_i64(t2);
5745 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5746 generate_exception(ctx, EXCP_OVERFLOW);
5747 gen_set_label(lab);
bd277fa1
RH
5748 break;
5749 }
5750
5751 case OPC_PMULUW:
5752 tcg_gen_ext32u_i64(t0, t0);
5753 tcg_gen_ext32u_i64(t1, t1);
5754 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5755 break;
5756
5757 case OPC_SEQU_CP2:
5758 case OPC_SEQ_CP2:
5759 case OPC_SLTU_CP2:
5760 case OPC_SLT_CP2:
5761 case OPC_SLEU_CP2:
5762 case OPC_SLE_CP2:
7480515f
AM
5763 /*
5764 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5765 * FD field is the CC field?
5766 */
bd277fa1 5767 default:
9d68ac14 5768 MIPS_INVAL("loongson_cp2");
9c708c7f 5769 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5770 return;
5771 }
5772
5773#undef LMI_HELPER
5774#undef LMI_DIRECT
5775
5776 gen_store_fpr64(ctx, t0, rd);
5777
bd277fa1
RH
5778 tcg_temp_free_i64(t0);
5779 tcg_temp_free_i64(t1);
5780}
5781
6af0bf9c 5782/* Traps */
71375b59
AM
5783static void gen_trap(DisasContext *ctx, uint32_t opc,
5784 int rs, int rt, int16_t imm)
6af0bf9c
FB
5785{
5786 int cond;
cdc0faa6 5787 TCGv t0 = tcg_temp_new();
1ba74fb8 5788 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5789
5790 cond = 0;
5791 /* Load needed operands */
5792 switch (opc) {
5793 case OPC_TEQ:
5794 case OPC_TGE:
5795 case OPC_TGEU:
5796 case OPC_TLT:
5797 case OPC_TLTU:
5798 case OPC_TNE:
5799 /* Compare two registers */
5800 if (rs != rt) {
be24bb4f
TS
5801 gen_load_gpr(t0, rs);
5802 gen_load_gpr(t1, rt);
6af0bf9c
FB
5803 cond = 1;
5804 }
179e32bb 5805 break;
6af0bf9c
FB
5806 case OPC_TEQI:
5807 case OPC_TGEI:
5808 case OPC_TGEIU:
5809 case OPC_TLTI:
5810 case OPC_TLTIU:
5811 case OPC_TNEI:
5812 /* Compare register to immediate */
5813 if (rs != 0 || imm != 0) {
be24bb4f
TS
5814 gen_load_gpr(t0, rs);
5815 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5816 cond = 1;
5817 }
5818 break;
5819 }
5820 if (cond == 0) {
5821 switch (opc) {
5822 case OPC_TEQ: /* rs == rs */
5823 case OPC_TEQI: /* r0 == 0 */
5824 case OPC_TGE: /* rs >= rs */
5825 case OPC_TGEI: /* r0 >= 0 */
5826 case OPC_TGEU: /* rs >= rs unsigned */
5827 case OPC_TGEIU: /* r0 >= 0 unsigned */
5828 /* Always trap */
9c708c7f 5829 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5830 break;
5831 case OPC_TLT: /* rs < rs */
5832 case OPC_TLTI: /* r0 < 0 */
5833 case OPC_TLTU: /* rs < rs unsigned */
5834 case OPC_TLTIU: /* r0 < 0 unsigned */
5835 case OPC_TNE: /* rs != rs */
5836 case OPC_TNEI: /* r0 != 0 */
ead9360e 5837 /* Never trap: treat as NOP. */
cdc0faa6 5838 break;
6af0bf9c
FB
5839 }
5840 } else {
42a268c2 5841 TCGLabel *l1 = gen_new_label();
cdc0faa6 5842
6af0bf9c
FB
5843 switch (opc) {
5844 case OPC_TEQ:
5845 case OPC_TEQI:
cdc0faa6 5846 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5847 break;
5848 case OPC_TGE:
5849 case OPC_TGEI:
cdc0faa6 5850 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5851 break;
5852 case OPC_TGEU:
5853 case OPC_TGEIU:
cdc0faa6 5854 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5855 break;
5856 case OPC_TLT:
5857 case OPC_TLTI:
cdc0faa6 5858 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5859 break;
5860 case OPC_TLTU:
5861 case OPC_TLTIU:
cdc0faa6 5862 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5863 break;
5864 case OPC_TNE:
5865 case OPC_TNEI:
cdc0faa6 5866 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5867 break;
6af0bf9c 5868 }
cdc0faa6 5869 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5870 gen_set_label(l1);
5871 }
be24bb4f
TS
5872 tcg_temp_free(t0);
5873 tcg_temp_free(t1);
6af0bf9c
FB
5874}
5875
90aa39a1
SF
5876static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5877{
eeb3bba8 5878 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5879 return false;
5880 }
5881
5882#ifndef CONFIG_USER_ONLY
eeb3bba8 5883 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5884#else
5885 return true;
5886#endif
5887}
5888
356265ae 5889static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5890{
90aa39a1 5891 if (use_goto_tb(ctx, dest)) {
57fec1fe 5892 tcg_gen_goto_tb(n);
9b9e4393 5893 gen_save_pc(dest);
07ea28b4 5894 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5895 } else {
9b9e4393 5896 gen_save_pc(dest);
eeb3bba8 5897 if (ctx->base.singlestep_enabled) {
7b270ef2 5898 save_cpu_state(ctx, 0);
9c708c7f 5899 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5900 }
7f11636d 5901 tcg_gen_lookup_and_goto_ptr();
6e256c93 5902 }
c53be334
FB
5903}
5904
6af0bf9c 5905/* Branches (before delay slot) */
71375b59
AM
5906static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5907 int insn_bytes,
5908 int rs, int rt, int32_t offset,
5909 int delayslot_size)
6af0bf9c 5910{
d077b6f7 5911 target_ulong btgt = -1;
3ad4bb2d 5912 int blink = 0;
2fdbad25 5913 int bcond_compute = 0;
1ba74fb8
AJ
5914 TCGv t0 = tcg_temp_new();
5915 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5916
5917 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5918#ifdef MIPS_DEBUG_DISAS
339cd2a8 5919 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5920 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5921#endif
9c708c7f 5922 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5923 goto out;
3ad4bb2d 5924 }
6af0bf9c 5925
6af0bf9c
FB
5926 /* Load needed operands */
5927 switch (opc) {
5928 case OPC_BEQ:
5929 case OPC_BEQL:
5930 case OPC_BNE:
5931 case OPC_BNEL:
5932 /* Compare two registers */
5933 if (rs != rt) {
6c5c1e20
TS
5934 gen_load_gpr(t0, rs);
5935 gen_load_gpr(t1, rt);
2fdbad25 5936 bcond_compute = 1;
6af0bf9c 5937 }
eeb3bba8 5938 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5939 break;
5940 case OPC_BGEZ:
5941 case OPC_BGEZAL:
5942 case OPC_BGEZALL:
5943 case OPC_BGEZL:
5944 case OPC_BGTZ:
5945 case OPC_BGTZL:
5946 case OPC_BLEZ:
5947 case OPC_BLEZL:
5948 case OPC_BLTZ:
5949 case OPC_BLTZAL:
5950 case OPC_BLTZALL:
5951 case OPC_BLTZL:
5952 /* Compare to zero */
5953 if (rs != 0) {
6c5c1e20 5954 gen_load_gpr(t0, rs);
2fdbad25 5955 bcond_compute = 1;
6af0bf9c 5956 }
eeb3bba8 5957 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5958 break;
e45a93e2
JL
5959 case OPC_BPOSGE32:
5960#if defined(TARGET_MIPS64)
5961 case OPC_BPOSGE64:
5962 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5963#else
5964 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5965#endif
5966 bcond_compute = 1;
eeb3bba8 5967 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5968 break;
6af0bf9c
FB
5969 case OPC_J:
5970 case OPC_JAL:
364d4831 5971 case OPC_JALX:
6af0bf9c 5972 /* Jump to immediate */
eeb3bba8
EC
5973 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5974 (uint32_t)offset;
6af0bf9c
FB
5975 break;
5976 case OPC_JR:
5977 case OPC_JALR:
5978 /* Jump to register */
7a387fff 5979 if (offset != 0 && offset != 16) {
7480515f
AM
5980 /*
5981 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5982 * others are reserved.
5983 */
923617a3 5984 MIPS_INVAL("jump hint");
9c708c7f 5985 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5986 goto out;
6af0bf9c 5987 }
d077b6f7 5988 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5989 break;
5990 default:
5991 MIPS_INVAL("branch/jump");
9c708c7f 5992 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5993 goto out;
6af0bf9c 5994 }
2fdbad25 5995 if (bcond_compute == 0) {
6af0bf9c
FB
5996 /* No condition to be computed */
5997 switch (opc) {
5998 case OPC_BEQ: /* rx == rx */
5999 case OPC_BEQL: /* rx == rx likely */
6000 case OPC_BGEZ: /* 0 >= 0 */
6001 case OPC_BGEZL: /* 0 >= 0 likely */
6002 case OPC_BLEZ: /* 0 <= 0 */
6003 case OPC_BLEZL: /* 0 <= 0 likely */
6004 /* Always take */
4ad40f36 6005 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6006 break;
6007 case OPC_BGEZAL: /* 0 >= 0 */
6008 case OPC_BGEZALL: /* 0 >= 0 likely */
6009 /* Always take and link */
6010 blink = 31;
4ad40f36 6011 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6012 break;
6013 case OPC_BNE: /* rx != rx */
6014 case OPC_BGTZ: /* 0 > 0 */
6015 case OPC_BLTZ: /* 0 < 0 */
ead9360e 6016 /* Treat as NOP. */
6c5c1e20 6017 goto out;
eeef26cd 6018 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
6019 /*
6020 * Handle as an unconditional branch to get correct delay
6021 * slot checking.
6022 */
3c824109 6023 blink = 31;
eeb3bba8 6024 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 6025 ctx->hflags |= MIPS_HFLAG_B;
3c824109 6026 break;
eeef26cd 6027 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 6028 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 6029 /* Skip the instruction in the delay slot */
eeb3bba8 6030 ctx->base.pc_next += 4;
6c5c1e20 6031 goto out;
6af0bf9c
FB
6032 case OPC_BNEL: /* rx != rx likely */
6033 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
6034 case OPC_BLTZL: /* 0 < 0 likely */
6035 /* Skip the instruction in the delay slot */
eeb3bba8 6036 ctx->base.pc_next += 4;
6c5c1e20 6037 goto out;
6af0bf9c 6038 case OPC_J:
4ad40f36 6039 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 6040 break;
364d4831
NF
6041 case OPC_JALX:
6042 ctx->hflags |= MIPS_HFLAG_BX;
6043 /* Fallthrough */
6af0bf9c
FB
6044 case OPC_JAL:
6045 blink = 31;
4ad40f36 6046 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6047 break;
6048 case OPC_JR:
4ad40f36 6049 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6050 break;
6051 case OPC_JALR:
6052 blink = rt;
4ad40f36 6053 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6054 break;
6055 default:
6056 MIPS_INVAL("branch/jump");
9c708c7f 6057 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6058 goto out;
6af0bf9c
FB
6059 }
6060 } else {
6061 switch (opc) {
6062 case OPC_BEQ:
e68dd28f 6063 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6064 goto not_likely;
6065 case OPC_BEQL:
e68dd28f 6066 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6067 goto likely;
6068 case OPC_BNE:
e68dd28f 6069 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6070 goto not_likely;
6071 case OPC_BNEL:
e68dd28f 6072 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6073 goto likely;
6074 case OPC_BGEZ:
e68dd28f 6075 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6076 goto not_likely;
6077 case OPC_BGEZL:
e68dd28f 6078 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6079 goto likely;
6080 case OPC_BGEZAL:
e68dd28f 6081 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6082 blink = 31;
6083 goto not_likely;
6084 case OPC_BGEZALL:
e68dd28f 6085 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6086 blink = 31;
6af0bf9c
FB
6087 goto likely;
6088 case OPC_BGTZ:
e68dd28f 6089 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6090 goto not_likely;
6091 case OPC_BGTZL:
e68dd28f 6092 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6093 goto likely;
6094 case OPC_BLEZ:
e68dd28f 6095 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6096 goto not_likely;
6097 case OPC_BLEZL:
e68dd28f 6098 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6099 goto likely;
6100 case OPC_BLTZ:
e68dd28f 6101 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6102 goto not_likely;
6103 case OPC_BLTZL:
e68dd28f 6104 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6105 goto likely;
e45a93e2
JL
6106 case OPC_BPOSGE32:
6107 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6108 goto not_likely;
6109#if defined(TARGET_MIPS64)
6110 case OPC_BPOSGE64:
6111 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6112 goto not_likely;
6113#endif
6af0bf9c 6114 case OPC_BLTZAL:
e68dd28f 6115 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6116 blink = 31;
6af0bf9c 6117 not_likely:
4ad40f36 6118 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6119 break;
6120 case OPC_BLTZALL:
e68dd28f 6121 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6122 blink = 31;
6af0bf9c 6123 likely:
4ad40f36 6124 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6125 break;
c53f4a62
TS
6126 default:
6127 MIPS_INVAL("conditional branch/jump");
9c708c7f 6128 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6129 goto out;
6af0bf9c 6130 }
6af0bf9c 6131 }
9b9e4393 6132
d077b6f7 6133 ctx->btarget = btgt;
b231c103
YK
6134
6135 switch (delayslot_size) {
6136 case 2:
6137 ctx->hflags |= MIPS_HFLAG_BDS16;
6138 break;
6139 case 4:
6140 ctx->hflags |= MIPS_HFLAG_BDS32;
6141 break;
6142 }
6143
6af0bf9c 6144 if (blink > 0) {
b231c103 6145 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6146 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6147
eeb3bba8
EC
6148 tcg_gen_movi_tl(cpu_gpr[blink],
6149 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6150 }
6c5c1e20
TS
6151
6152 out:
1f8929d2 6153 if (insn_bytes == 2) {
364d4831 6154 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 6155 }
6c5c1e20
TS
6156 tcg_temp_free(t0);
6157 tcg_temp_free(t1);
6af0bf9c
FB
6158}
6159
764371d2
SM
6160
6161/* nanoMIPS Branches */
6162static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6163 int insn_bytes,
6164 int rs, int rt, int32_t offset)
6165{
6166 target_ulong btgt = -1;
6167 int bcond_compute = 0;
6168 TCGv t0 = tcg_temp_new();
6169 TCGv t1 = tcg_temp_new();
6170
6171 /* Load needed operands */
6172 switch (opc) {
6173 case OPC_BEQ:
6174 case OPC_BNE:
6175 /* Compare two registers */
6176 if (rs != rt) {
6177 gen_load_gpr(t0, rs);
6178 gen_load_gpr(t1, rt);
6179 bcond_compute = 1;
6180 }
6181 btgt = ctx->base.pc_next + insn_bytes + offset;
6182 break;
6183 case OPC_BGEZAL:
6184 /* Compare to zero */
6185 if (rs != 0) {
6186 gen_load_gpr(t0, rs);
6187 bcond_compute = 1;
6188 }
6189 btgt = ctx->base.pc_next + insn_bytes + offset;
6190 break;
6191 case OPC_BPOSGE32:
6192 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6193 bcond_compute = 1;
6194 btgt = ctx->base.pc_next + insn_bytes + offset;
6195 break;
6196 case OPC_JR:
6197 case OPC_JALR:
6198 /* Jump to register */
6199 if (offset != 0 && offset != 16) {
7480515f
AM
6200 /*
6201 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6202 * others are reserved.
6203 */
764371d2
SM
6204 MIPS_INVAL("jump hint");
6205 generate_exception_end(ctx, EXCP_RI);
6206 goto out;
6207 }
6208 gen_load_gpr(btarget, rs);
6209 break;
6210 default:
6211 MIPS_INVAL("branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6214 }
6215 if (bcond_compute == 0) {
6216 /* No condition to be computed */
6217 switch (opc) {
6218 case OPC_BEQ: /* rx == rx */
6219 /* Always take */
6220 ctx->hflags |= MIPS_HFLAG_B;
6221 break;
6222 case OPC_BGEZAL: /* 0 >= 0 */
6223 /* Always take and link */
6224 tcg_gen_movi_tl(cpu_gpr[31],
6225 ctx->base.pc_next + insn_bytes);
6226 ctx->hflags |= MIPS_HFLAG_B;
6227 break;
6228 case OPC_BNE: /* rx != rx */
6229 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6230 /* Skip the instruction in the delay slot */
6231 ctx->base.pc_next += 4;
6232 goto out;
6233 case OPC_JR:
6234 ctx->hflags |= MIPS_HFLAG_BR;
6235 break;
6236 case OPC_JALR:
6237 if (rt > 0) {
6238 tcg_gen_movi_tl(cpu_gpr[rt],
6239 ctx->base.pc_next + insn_bytes);
6240 }
6241 ctx->hflags |= MIPS_HFLAG_BR;
6242 break;
6243 default:
6244 MIPS_INVAL("branch/jump");
6245 generate_exception_end(ctx, EXCP_RI);
6246 goto out;
6247 }
6248 } else {
6249 switch (opc) {
6250 case OPC_BEQ:
6251 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6252 goto not_likely;
6253 case OPC_BNE:
6254 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6255 goto not_likely;
6256 case OPC_BGEZAL:
6257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6258 tcg_gen_movi_tl(cpu_gpr[31],
6259 ctx->base.pc_next + insn_bytes);
6260 goto not_likely;
6261 case OPC_BPOSGE32:
6262 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6263 not_likely:
6264 ctx->hflags |= MIPS_HFLAG_BC;
6265 break;
6266 default:
6267 MIPS_INVAL("conditional branch/jump");
6268 generate_exception_end(ctx, EXCP_RI);
6269 goto out;
6270 }
6271 }
6272
6273 ctx->btarget = btgt;
6274
6275 out:
6276 if (insn_bytes == 2) {
6277 ctx->hflags |= MIPS_HFLAG_B16;
6278 }
6279 tcg_temp_free(t0);
6280 tcg_temp_free(t1);
6281}
6282
6283
7a387fff 6284/* special3 bitfield operations */
235785e8
AM
6285static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6286 int rs, int lsb, int msb)
7a387fff 6287{
a7812ae4
PB
6288 TCGv t0 = tcg_temp_new();
6289 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6290
6291 gen_load_gpr(t1, rs);
7a387fff
TS
6292 switch (opc) {
6293 case OPC_EXT:
b7f26e52 6294 if (lsb + msb > 31) {
7a387fff 6295 goto fail;
b7f26e52 6296 }
505ad7c2 6297 if (msb != 31) {
6eebb7a4 6298 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6299 } else {
7480515f
AM
6300 /*
6301 * The two checks together imply that lsb == 0,
6302 * so this is a simple sign-extension.
6303 */
6eebb7a4 6304 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6305 }
7a387fff 6306 break;
c6d6dd7c 6307#if defined(TARGET_MIPS64)
7a387fff 6308 case OPC_DEXTU:
b7f26e52
RH
6309 lsb += 32;
6310 goto do_dext;
6311 case OPC_DEXTM:
6312 msb += 32;
6313 goto do_dext;
7a387fff 6314 case OPC_DEXT:
b7f26e52
RH
6315 do_dext:
6316 if (lsb + msb > 63) {
6317 goto fail;
6318 }
6eebb7a4 6319 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6320 break;
c6d6dd7c 6321#endif
7a387fff 6322 case OPC_INS:
b7f26e52 6323 if (lsb > msb) {
7a387fff 6324 goto fail;
b7f26e52 6325 }
6c5c1e20 6326 gen_load_gpr(t0, rt);
e0d002f1 6327 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6328 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6329 break;
c6d6dd7c 6330#if defined(TARGET_MIPS64)
7a387fff 6331 case OPC_DINSU:
b7f26e52
RH
6332 lsb += 32;
6333 /* FALLTHRU */
6334 case OPC_DINSM:
6335 msb += 32;
6336 /* FALLTHRU */
7a387fff 6337 case OPC_DINS:
b7f26e52
RH
6338 if (lsb > msb) {
6339 goto fail;
6340 }
6c5c1e20 6341 gen_load_gpr(t0, rt);
e0d002f1 6342 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6343 break;
c6d6dd7c 6344#endif
7a387fff
TS
6345 default:
6346fail:
6347 MIPS_INVAL("bitops");
9c708c7f 6348 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6349 tcg_temp_free(t0);
6350 tcg_temp_free(t1);
7a387fff
TS
6351 return;
6352 }
6c5c1e20
TS
6353 gen_store_gpr(t0, rt);
6354 tcg_temp_free(t0);
6355 tcg_temp_free(t1);
7a387fff
TS
6356}
6357
235785e8 6358static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 6359{
3a55fa47 6360 TCGv t0;
49bcf33c 6361
3a55fa47
AJ
6362 if (rd == 0) {
6363 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6364 return;
6365 }
6366
6367 t0 = tcg_temp_new();
6368 gen_load_gpr(t0, rt);
49bcf33c
AJ
6369 switch (op2) {
6370 case OPC_WSBH:
3a55fa47
AJ
6371 {
6372 TCGv t1 = tcg_temp_new();
06a57e5c 6373 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6374
6375 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6376 tcg_gen_and_tl(t1, t1, t2);
6377 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6378 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6379 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6380 tcg_temp_free(t2);
3a55fa47
AJ
6381 tcg_temp_free(t1);
6382 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6383 }
49bcf33c
AJ
6384 break;
6385 case OPC_SEB:
3a55fa47 6386 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6387 break;
6388 case OPC_SEH:
3a55fa47 6389 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6390 break;
6391#if defined(TARGET_MIPS64)
6392 case OPC_DSBH:
3a55fa47
AJ
6393 {
6394 TCGv t1 = tcg_temp_new();
06a57e5c 6395 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6396
6397 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6398 tcg_gen_and_tl(t1, t1, t2);
6399 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6400 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6401 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6402 tcg_temp_free(t2);
3a55fa47
AJ
6403 tcg_temp_free(t1);
6404 }
49bcf33c
AJ
6405 break;
6406 case OPC_DSHD:
3a55fa47
AJ
6407 {
6408 TCGv t1 = tcg_temp_new();
06a57e5c 6409 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6410
6411 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6412 tcg_gen_and_tl(t1, t1, t2);
6413 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6414 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6415 tcg_gen_or_tl(t0, t0, t1);
6416 tcg_gen_shri_tl(t1, t0, 32);
6417 tcg_gen_shli_tl(t0, t0, 32);
6418 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6419 tcg_temp_free(t2);
3a55fa47
AJ
6420 tcg_temp_free(t1);
6421 }
49bcf33c
AJ
6422 break;
6423#endif
6424 default:
6425 MIPS_INVAL("bsfhl");
9c708c7f 6426 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6427 tcg_temp_free(t0);
49bcf33c
AJ
6428 return;
6429 }
49bcf33c 6430 tcg_temp_free(t0);
49bcf33c
AJ
6431}
6432
1f1b4c00
YK
6433static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6434 int imm2)
6435{
6436 TCGv t0;
6437 TCGv t1;
6438 if (rd == 0) {
6439 /* Treat as NOP. */
6440 return;
6441 }
6442 t0 = tcg_temp_new();
6443 t1 = tcg_temp_new();
6444 gen_load_gpr(t0, rs);
6445 gen_load_gpr(t1, rt);
6446 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6447 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6448 if (opc == OPC_LSA) {
6449 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6450 }
6451
6452 tcg_temp_free(t1);
6453 tcg_temp_free(t0);
6454
6455 return;
6456}
6457
821f2008
JH
6458static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6459 int rt, int bits)
284b731a 6460{
1f1b4c00
YK
6461 TCGv t0;
6462 if (rd == 0) {
6463 /* Treat as NOP. */
6464 return;
6465 }
6466 t0 = tcg_temp_new();
821f2008
JH
6467 if (bits == 0 || bits == wordsz) {
6468 if (bits == 0) {
6469 gen_load_gpr(t0, rt);
6470 } else {
6471 gen_load_gpr(t0, rs);
6472 }
6473 switch (wordsz) {
6474 case 32:
51243852
MD
6475 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6476 break;
6477#if defined(TARGET_MIPS64)
821f2008 6478 case 64:
51243852
MD
6479 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6480 break;
6481#endif
6482 }
1f1b4c00
YK
6483 } else {
6484 TCGv t1 = tcg_temp_new();
821f2008 6485 gen_load_gpr(t0, rt);
1f1b4c00 6486 gen_load_gpr(t1, rs);
821f2008
JH
6487 switch (wordsz) {
6488 case 32:
1f1b4c00
YK
6489 {
6490 TCGv_i64 t2 = tcg_temp_new_i64();
6491 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6492 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6493 gen_move_low32(cpu_gpr[rd], t2);
6494 tcg_temp_free_i64(t2);
6495 }
6496 break;
284b731a 6497#if defined(TARGET_MIPS64)
821f2008
JH
6498 case 64:
6499 tcg_gen_shli_tl(t0, t0, bits);
6500 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6501 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6502 break;
284b731a 6503#endif
1f1b4c00
YK
6504 }
6505 tcg_temp_free(t1);
6506 }
6507
6508 tcg_temp_free(t0);
6509}
6510
821f2008
JH
6511static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6512 int bp)
6513{
6514 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6515}
6516
6517static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6518 int shift)
6519{
6520 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6521}
6522
1f1b4c00
YK
6523static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6524{
6525 TCGv t0;
6526 if (rd == 0) {
6527 /* Treat as NOP. */
6528 return;
6529 }
6530 t0 = tcg_temp_new();
6531 gen_load_gpr(t0, rt);
6532 switch (opc) {
6533 case OPC_BITSWAP:
6534 gen_helper_bitswap(cpu_gpr[rd], t0);
6535 break;
6536#if defined(TARGET_MIPS64)
6537 case OPC_DBITSWAP:
6538 gen_helper_dbitswap(cpu_gpr[rd], t0);
6539 break;
6540#endif
6541 }
6542 tcg_temp_free(t0);
284b731a
LA
6543}
6544
1f1b4c00
YK
6545#ifndef CONFIG_USER_ONLY
6546/* CP0 (MMU and control) */
5204ea79
LA
6547static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6548{
6549 TCGv_i64 t0 = tcg_temp_new_i64();
6550 TCGv_i64 t1 = tcg_temp_new_i64();
6551
6552 tcg_gen_ext_tl_i64(t0, arg);
6553 tcg_gen_ld_i64(t1, cpu_env, off);
6554#if defined(TARGET_MIPS64)
6555 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6556#else
6557 tcg_gen_concat32_i64(t1, t1, t0);
6558#endif
6559 tcg_gen_st_i64(t1, cpu_env, off);
6560 tcg_temp_free_i64(t1);
6561 tcg_temp_free_i64(t0);
6562}
6563
6564static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6565{
6566 TCGv_i64 t0 = tcg_temp_new_i64();
6567 TCGv_i64 t1 = tcg_temp_new_i64();
6568
6569 tcg_gen_ext_tl_i64(t0, arg);
6570 tcg_gen_ld_i64(t1, cpu_env, off);
6571 tcg_gen_concat32_i64(t1, t1, t0);
6572 tcg_gen_st_i64(t1, cpu_env, off);
6573 tcg_temp_free_i64(t1);
6574 tcg_temp_free_i64(t0);
6575}
6576
6577static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6578{
6579 TCGv_i64 t0 = tcg_temp_new_i64();
6580
6581 tcg_gen_ld_i64(t0, cpu_env, off);
6582#if defined(TARGET_MIPS64)
6583 tcg_gen_shri_i64(t0, t0, 30);
6584#else
6585 tcg_gen_shri_i64(t0, t0, 32);
6586#endif
6587 gen_move_low32(arg, t0);
6588 tcg_temp_free_i64(t0);
6589}
6590
6591static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6592{
6593 TCGv_i64 t0 = tcg_temp_new_i64();
6594
6595 tcg_gen_ld_i64(t0, cpu_env, off);
6596 tcg_gen_shri_i64(t0, t0, 32 + shift);
6597 gen_move_low32(arg, t0);
6598 tcg_temp_free_i64(t0);
6599}
6600
235785e8 6601static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 6602{
d9bea114 6603 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6604
d9bea114
AJ
6605 tcg_gen_ld_i32(t0, cpu_env, off);
6606 tcg_gen_ext_i32_tl(arg, t0);
6607 tcg_temp_free_i32(t0);
4f57689a
TS
6608}
6609
235785e8 6610static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 6611{
d9bea114
AJ
6612 tcg_gen_ld_tl(arg, cpu_env, off);
6613 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6614}
6615
235785e8 6616static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 6617{
d9bea114 6618 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6619
d9bea114
AJ
6620 tcg_gen_trunc_tl_i32(t0, arg);
6621 tcg_gen_st_i32(t0, cpu_env, off);
6622 tcg_temp_free_i32(t0);
f1aa6320
TS
6623}
6624
c98d3d79
YK
6625#define CP0_CHECK(c) \
6626 do { \
6627 if (!(c)) { \
6628 goto cp0_unimplemented; \
6629 } \
6630 } while (0)
6631
5204ea79
LA
6632static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6633{
294fc2ea 6634 const char *register_name = "invalid";
5204ea79 6635
5204ea79 6636 switch (reg) {
04992c8c 6637 case CP0_REGISTER_02:
5204ea79
LA
6638 switch (sel) {
6639 case 0:
59488dda 6640 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6641 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6642 register_name = "EntryLo0";
5204ea79
LA
6643 break;
6644 default:
c98d3d79 6645 goto cp0_unimplemented;
5204ea79
LA
6646 }
6647 break;
04992c8c 6648 case CP0_REGISTER_03:
5204ea79 6649 switch (sel) {
acd37316 6650 case CP0_REG03__ENTRYLO1:
59488dda 6651 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6652 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6653 register_name = "EntryLo1";
5204ea79
LA
6654 break;
6655 default:
c98d3d79 6656 goto cp0_unimplemented;
5204ea79
LA
6657 }
6658 break;
04992c8c 6659 case CP0_REGISTER_09:
5fb2dcd1 6660 switch (sel) {
e5a98a72 6661 case CP0_REG09__SAAR:
5fb2dcd1
YK
6662 CP0_CHECK(ctx->saar);
6663 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 6664 register_name = "SAAR";
5fb2dcd1
YK
6665 break;
6666 default:
6667 goto cp0_unimplemented;
6668 }
6669 break;
04992c8c 6670 case CP0_REGISTER_17:
5204ea79 6671 switch (sel) {
706ce142 6672 case CP0_REG17__LLADDR:
c7c7e1e9 6673 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 6674 ctx->CP0_LLAddr_shift);
294fc2ea 6675 register_name = "LLAddr";
5204ea79 6676 break;
706ce142 6677 case CP0_REG17__MAAR:
f6d4dd81
YK
6678 CP0_CHECK(ctx->mrp);
6679 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 6680 register_name = "MAAR";
f6d4dd81 6681 break;
5204ea79 6682 default:
c98d3d79 6683 goto cp0_unimplemented;
5204ea79
LA
6684 }
6685 break;
04992c8c 6686 case CP0_REGISTER_28:
5204ea79
LA
6687 switch (sel) {
6688 case 0:
6689 case 2:
6690 case 4:
6691 case 6:
6692 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 6693 register_name = "TagLo";
5204ea79
LA
6694 break;
6695 default:
c98d3d79 6696 goto cp0_unimplemented;
5204ea79
LA
6697 }
6698 break;
6699 default:
c98d3d79 6700 goto cp0_unimplemented;
5204ea79 6701 }
294fc2ea 6702 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
6703 return;
6704
c98d3d79 6705cp0_unimplemented:
294fc2ea
AM
6706 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6707 register_name, reg, sel);
5204ea79
LA
6708 tcg_gen_movi_tl(arg, 0);
6709}
6710
6711static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6712{
294fc2ea 6713 const char *register_name = "invalid";
5204ea79
LA
6714 uint64_t mask = ctx->PAMask >> 36;
6715
5204ea79 6716 switch (reg) {
04992c8c 6717 case CP0_REGISTER_02:
5204ea79
LA
6718 switch (sel) {
6719 case 0:
59488dda 6720 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6721 tcg_gen_andi_tl(arg, arg, mask);
6722 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6723 register_name = "EntryLo0";
5204ea79
LA
6724 break;
6725 default:
c98d3d79 6726 goto cp0_unimplemented;
5204ea79
LA
6727 }
6728 break;
04992c8c 6729 case CP0_REGISTER_03:
5204ea79 6730 switch (sel) {
acd37316 6731 case CP0_REG03__ENTRYLO1:
59488dda 6732 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6733 tcg_gen_andi_tl(arg, arg, mask);
6734 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6735 register_name = "EntryLo1";
5204ea79
LA
6736 break;
6737 default:
c98d3d79 6738 goto cp0_unimplemented;
5204ea79
LA
6739 }
6740 break;
04992c8c 6741 case CP0_REGISTER_09:
5fb2dcd1 6742 switch (sel) {
e5a98a72 6743 case CP0_REG09__SAAR:
5fb2dcd1
YK
6744 CP0_CHECK(ctx->saar);
6745 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 6746 register_name = "SAAR";
5fb2dcd1
YK
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6750 }
ab8c3410 6751 break;
04992c8c 6752 case CP0_REGISTER_17:
5204ea79 6753 switch (sel) {
706ce142 6754 case CP0_REG17__LLADDR:
7480515f
AM
6755 /*
6756 * LLAddr is read-only (the only exception is bit 0 if LLB is
6757 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6758 * relevant for modern MIPS cores supporting MTHC0, therefore
6759 * treating MTHC0 to LLAddr as NOP.
6760 */
294fc2ea 6761 register_name = "LLAddr";
5204ea79 6762 break;
706ce142 6763 case CP0_REG17__MAAR:
f6d4dd81
YK
6764 CP0_CHECK(ctx->mrp);
6765 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 6766 register_name = "MAAR";
f6d4dd81 6767 break;
5204ea79 6768 default:
c98d3d79 6769 goto cp0_unimplemented;
5204ea79
LA
6770 }
6771 break;
04992c8c 6772 case CP0_REGISTER_28:
5204ea79
LA
6773 switch (sel) {
6774 case 0:
6775 case 2:
6776 case 4:
6777 case 6:
6778 tcg_gen_andi_tl(arg, arg, mask);
6779 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 6780 register_name = "TagLo";
5204ea79
LA
6781 break;
6782 default:
c98d3d79 6783 goto cp0_unimplemented;
5204ea79
LA
6784 }
6785 break;
6786 default:
c98d3d79 6787 goto cp0_unimplemented;
5204ea79 6788 }
294fc2ea 6789 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 6790
c98d3d79 6791cp0_unimplemented:
294fc2ea
AM
6792 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6793 register_name, reg, sel);
5204ea79
LA
6794}
6795
e98c0d17
LA
6796static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6797{
6798 if (ctx->insn_flags & ISA_MIPS32R6) {
6799 tcg_gen_movi_tl(arg, 0);
6800 } else {
6801 tcg_gen_movi_tl(arg, ~0);
6802 }
6803}
6804
d75c135e 6805static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6806{
294fc2ea 6807 const char *register_name = "invalid";
873eb012 6808
1f8929d2 6809 if (sel != 0) {
d75c135e 6810 check_insn(ctx, ISA_MIPS32);
1f8929d2 6811 }
e189e748 6812
873eb012 6813 switch (reg) {
04992c8c 6814 case CP0_REGISTER_00:
7a387fff 6815 switch (sel) {
1b142da5 6816 case CP0_REG00__INDEX:
7db13fae 6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6818 register_name = "Index";
7a387fff 6819 break;
1b142da5 6820 case CP0_REG00__MVPCONTROL:
f31b035a 6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6822 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 6823 register_name = "MVPControl";
ead9360e 6824 break;
1b142da5 6825 case CP0_REG00__MVPCONF0:
f31b035a 6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6827 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 6828 register_name = "MVPConf0";
ead9360e 6829 break;
1b142da5 6830 case CP0_REG00__MVPCONF1:
f31b035a 6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6832 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 6833 register_name = "MVPConf1";
ead9360e 6834 break;
1b142da5 6835 case CP0_REG00__VPCONTROL:
01bc435b
YK
6836 CP0_CHECK(ctx->vp);
6837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 6838 register_name = "VPControl";
01bc435b 6839 break;
7a387fff 6840 default:
f31b035a 6841 goto cp0_unimplemented;
7a387fff 6842 }
873eb012 6843 break;
04992c8c 6844 case CP0_REGISTER_01:
7a387fff 6845 switch (sel) {
30deb460 6846 case CP0_REG01__RANDOM:
f31b035a 6847 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6848 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6849 register_name = "Random";
2423f660 6850 break;
30deb460 6851 case CP0_REG01__VPECONTROL:
f31b035a 6852 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6854 register_name = "VPEControl";
ead9360e 6855 break;
30deb460 6856 case CP0_REG01__VPECONF0:
f31b035a 6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6859 register_name = "VPEConf0";
ead9360e 6860 break;
30deb460 6861 case CP0_REG01__VPECONF1:
f31b035a 6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6864 register_name = "VPEConf1";
ead9360e 6865 break;
30deb460 6866 case CP0_REG01__YQMASK:
f31b035a 6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6868 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6869 register_name = "YQMask";
ead9360e 6870 break;
30deb460 6871 case CP0_REG01__VPESCHEDULE:
f31b035a 6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6873 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6874 register_name = "VPESchedule";
ead9360e 6875 break;
30deb460 6876 case CP0_REG01__VPESCHEFBACK:
f31b035a 6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6878 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6879 register_name = "VPEScheFBack";
ead9360e 6880 break;
30deb460 6881 case CP0_REG01__VPEOPT:
f31b035a 6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6884 register_name = "VPEOpt";
ead9360e 6885 break;
7a387fff 6886 default:
f31b035a 6887 goto cp0_unimplemented;
7a387fff 6888 }
873eb012 6889 break;
04992c8c 6890 case CP0_REGISTER_02:
7a387fff 6891 switch (sel) {
6d27d5bd 6892 case CP0_REG02__ENTRYLO0:
284b731a
LA
6893 {
6894 TCGv_i64 tmp = tcg_temp_new_i64();
6895 tcg_gen_ld_i64(tmp, cpu_env,
6896 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6897#if defined(TARGET_MIPS64)
284b731a
LA
6898 if (ctx->rxi) {
6899 /* Move RI/XI fields to bits 31:30 */
6900 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6901 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6902 }
7207c7f9 6903#endif
284b731a
LA
6904 gen_move_low32(arg, tmp);
6905 tcg_temp_free_i64(tmp);
6906 }
294fc2ea 6907 register_name = "EntryLo0";
2423f660 6908 break;
6d27d5bd 6909 case CP0_REG02__TCSTATUS:
f31b035a 6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6911 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 6912 register_name = "TCStatus";
ead9360e 6913 break;
6d27d5bd 6914 case CP0_REG02__TCBIND:
f31b035a 6915 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6916 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 6917 register_name = "TCBind";
ead9360e 6918 break;
6d27d5bd 6919 case CP0_REG02__TCRESTART:
f31b035a 6920 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6921 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 6922 register_name = "TCRestart";
ead9360e 6923 break;
6d27d5bd 6924 case CP0_REG02__TCHALT:
f31b035a 6925 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6926 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 6927 register_name = "TCHalt";
ead9360e 6928 break;
6d27d5bd 6929 case CP0_REG02__TCCONTEXT:
f31b035a 6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6931 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 6932 register_name = "TCContext";
ead9360e 6933 break;
6d27d5bd 6934 case CP0_REG02__TCSCHEDULE:
f31b035a 6935 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6936 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 6937 register_name = "TCSchedule";
ead9360e 6938 break;
6d27d5bd 6939 case CP0_REG02__TCSCHEFBACK:
f31b035a 6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6941 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 6942 register_name = "TCScheFBack";
ead9360e 6943 break;
7a387fff 6944 default:
f31b035a 6945 goto cp0_unimplemented;
7a387fff 6946 }
873eb012 6947 break;
04992c8c 6948 case CP0_REGISTER_03:
7a387fff 6949 switch (sel) {
acd37316 6950 case CP0_REG03__ENTRYLO1:
284b731a
LA
6951 {
6952 TCGv_i64 tmp = tcg_temp_new_i64();
6953 tcg_gen_ld_i64(tmp, cpu_env,
6954 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6955#if defined(TARGET_MIPS64)
284b731a
LA
6956 if (ctx->rxi) {
6957 /* Move RI/XI fields to bits 31:30 */
6958 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6959 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6960 }
7207c7f9 6961#endif
284b731a
LA
6962 gen_move_low32(arg, tmp);
6963 tcg_temp_free_i64(tmp);
6964 }
294fc2ea 6965 register_name = "EntryLo1";
2423f660 6966 break;
acd37316 6967 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6968 CP0_CHECK(ctx->vp);
6969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 6970 register_name = "GlobalNumber";
01bc435b 6971 break;
7a387fff 6972 default:
f31b035a 6973 goto cp0_unimplemented;
1579a72e 6974 }
873eb012 6975 break;
04992c8c 6976 case CP0_REGISTER_04:
7a387fff 6977 switch (sel) {
020fe379 6978 case CP0_REG04__CONTEXT:
7db13fae 6979 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6980 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6981 register_name = "Context";
2423f660 6982 break;
020fe379
AM
6983 case CP0_REG04__CONTEXTCONFIG:
6984 /* SmartMIPS ASE */
6985 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 6986 register_name = "ContextConfig";
f31b035a 6987 goto cp0_unimplemented;
020fe379 6988 case CP0_REG04__USERLOCAL:
f31b035a 6989 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6990 tcg_gen_ld_tl(arg, cpu_env,
6991 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6992 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6993 register_name = "UserLocal";
d279279e 6994 break;
7a387fff 6995 default:
f31b035a 6996 goto cp0_unimplemented;
1579a72e 6997 }
873eb012 6998 break;
04992c8c 6999 case CP0_REGISTER_05:
7a387fff 7000 switch (sel) {
a1e76353 7001 case CP0_REG05__PAGEMASK:
7db13fae 7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7003 register_name = "PageMask";
2423f660 7004 break;
a1e76353 7005 case CP0_REG05__PAGEGRAIN:
d75c135e 7006 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7008 register_name = "PageGrain";
2423f660 7009 break;
a1e76353 7010 case CP0_REG05__SEGCTL0:
cec56a73
JH
7011 CP0_CHECK(ctx->sc);
7012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7013 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7014 register_name = "SegCtl0";
cec56a73 7015 break;
a1e76353 7016 case CP0_REG05__SEGCTL1:
cec56a73
JH
7017 CP0_CHECK(ctx->sc);
7018 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7019 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7020 register_name = "SegCtl1";
cec56a73 7021 break;
a1e76353 7022 case CP0_REG05__SEGCTL2:
cec56a73
JH
7023 CP0_CHECK(ctx->sc);
7024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7025 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7026 register_name = "SegCtl2";
cec56a73 7027 break;
a1e76353 7028 case CP0_REG05__PWBASE:
5e31fdd5
YK
7029 check_pw(ctx);
7030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7031 register_name = "PWBase";
5e31fdd5 7032 break;
a1e76353 7033 case CP0_REG05__PWFIELD:
fa75ad14
YK
7034 check_pw(ctx);
7035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7036 register_name = "PWField";
fa75ad14 7037 break;
a1e76353 7038 case CP0_REG05__PWSIZE:
20b28ebc
YK
7039 check_pw(ctx);
7040 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7041 register_name = "PWSize";
20b28ebc 7042 break;
7a387fff 7043 default:
f31b035a 7044 goto cp0_unimplemented;
1579a72e 7045 }
873eb012 7046 break;
04992c8c 7047 case CP0_REGISTER_06:
7a387fff 7048 switch (sel) {
9023594b 7049 case CP0_REG06__WIRED:
7db13fae 7050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7051 register_name = "Wired";
2423f660 7052 break;
9023594b 7053 case CP0_REG06__SRSCONF0:
d75c135e 7054 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7056 register_name = "SRSConf0";
ead9360e 7057 break;
9023594b 7058 case CP0_REG06__SRSCONF1:
d75c135e 7059 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7061 register_name = "SRSConf1";
ead9360e 7062 break;
9023594b 7063 case CP0_REG06__SRSCONF2:
d75c135e 7064 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7066 register_name = "SRSConf2";
ead9360e 7067 break;
9023594b 7068 case CP0_REG06__SRSCONF3:
d75c135e 7069 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7071 register_name = "SRSConf3";
ead9360e 7072 break;
9023594b 7073 case CP0_REG06__SRSCONF4:
d75c135e 7074 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7075 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7076 register_name = "SRSConf4";
ead9360e 7077 break;
9023594b 7078 case CP0_REG06__PWCTL:
103be64c
YK
7079 check_pw(ctx);
7080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7081 register_name = "PWCtl";
103be64c 7082 break;
7a387fff 7083 default:
f31b035a 7084 goto cp0_unimplemented;
1579a72e 7085 }
873eb012 7086 break;
04992c8c 7087 case CP0_REGISTER_07:
7a387fff 7088 switch (sel) {
143a9875 7089 case CP0_REG07__HWRENA:
d75c135e 7090 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7092 register_name = "HWREna";
2423f660 7093 break;
7a387fff 7094 default:
f31b035a 7095 goto cp0_unimplemented;
1579a72e 7096 }
8c0fdd85 7097 break;
04992c8c 7098 case CP0_REGISTER_08:
7a387fff 7099 switch (sel) {
67d167d2 7100 case CP0_REG08__BADVADDR:
7db13fae 7101 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7102 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7103 register_name = "BadVAddr";
2423f660 7104 break;
67d167d2 7105 case CP0_REG08__BADINSTR:
f31b035a
LA
7106 CP0_CHECK(ctx->bi);
7107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7108 register_name = "BadInstr";
aea14095 7109 break;
67d167d2 7110 case CP0_REG08__BADINSTRP:
f31b035a
LA
7111 CP0_CHECK(ctx->bp);
7112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7113 register_name = "BadInstrP";
aea14095 7114 break;
67d167d2 7115 case CP0_REG08__BADINSTRX:
25beba9b
SM
7116 CP0_CHECK(ctx->bi);
7117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7118 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7119 register_name = "BadInstrX";
25beba9b
SM
7120 break;
7121 default:
f31b035a 7122 goto cp0_unimplemented;
aea14095 7123 }
873eb012 7124 break;
04992c8c 7125 case CP0_REGISTER_09:
7a387fff 7126 switch (sel) {
e5a98a72 7127 case CP0_REG09__COUNT:
2e70f6ef 7128 /* Mark as an IO operation because we read the time. */
eeb3bba8 7129 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7130 gen_io_start();
7d37435b 7131 }
895c2d04 7132 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7133 /*
7134 * Break the TB to be able to take timer interrupts immediately
7135 * after reading count. DISAS_STOP isn't sufficient, we need to
7136 * ensure we break completely out of translated code.
7137 */
eeb3bba8
EC
7138 gen_save_pc(ctx->base.pc_next + 4);
7139 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7140 register_name = "Count";
2423f660 7141 break;
e5a98a72 7142 case CP0_REG09__SAARI:
5fb2dcd1
YK
7143 CP0_CHECK(ctx->saar);
7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7145 register_name = "SAARI";
5fb2dcd1 7146 break;
e5a98a72 7147 case CP0_REG09__SAAR:
5fb2dcd1
YK
7148 CP0_CHECK(ctx->saar);
7149 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7150 register_name = "SAAR";
5fb2dcd1 7151 break;
7a387fff 7152 default:
f31b035a 7153 goto cp0_unimplemented;
2423f660 7154 }
873eb012 7155 break;
04992c8c 7156 case CP0_REGISTER_10:
7a387fff 7157 switch (sel) {
860ffef0 7158 case CP0_REG10__ENTRYHI:
7db13fae 7159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7160 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7161 register_name = "EntryHi";
2423f660 7162 break;
7a387fff 7163 default:
f31b035a 7164 goto cp0_unimplemented;
1579a72e 7165 }
873eb012 7166 break;
04992c8c 7167 case CP0_REGISTER_11:
7a387fff 7168 switch (sel) {
f5f3834f 7169 case CP0_REG11__COMPARE:
7db13fae 7170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7171 register_name = "Compare";
2423f660
TS
7172 break;
7173 /* 6,7 are implementation dependent */
7a387fff 7174 default:
f31b035a 7175 goto cp0_unimplemented;
2423f660 7176 }
873eb012 7177 break;
04992c8c 7178 case CP0_REGISTER_12:
7a387fff 7179 switch (sel) {
2b084867 7180 case CP0_REG12__STATUS:
7db13fae 7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7182 register_name = "Status";
2423f660 7183 break;
2b084867 7184 case CP0_REG12__INTCTL:
d75c135e 7185 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7187 register_name = "IntCtl";
2423f660 7188 break;
2b084867 7189 case CP0_REG12__SRSCTL:
d75c135e 7190 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7192 register_name = "SRSCtl";
2423f660 7193 break;
2b084867 7194 case CP0_REG12__SRSMAP:
d75c135e 7195 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7197 register_name = "SRSMap";
fd88b6ab 7198 break;
7a387fff 7199 default:
f31b035a 7200 goto cp0_unimplemented;
7a387fff 7201 }
873eb012 7202 break;
04992c8c 7203 case CP0_REGISTER_13:
7a387fff 7204 switch (sel) {
e3c7559d 7205 case CP0_REG13__CAUSE:
7db13fae 7206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7207 register_name = "Cause";
2423f660 7208 break;
7a387fff 7209 default:
f31b035a 7210 goto cp0_unimplemented;
7a387fff 7211 }
873eb012 7212 break;
04992c8c 7213 case CP0_REGISTER_14:
7a387fff 7214 switch (sel) {
35e4b54d 7215 case CP0_REG14__EPC:
7db13fae 7216 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7217 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7218 register_name = "EPC";
2423f660 7219 break;
7a387fff 7220 default:
f31b035a 7221 goto cp0_unimplemented;
1579a72e 7222 }
873eb012 7223 break;
04992c8c 7224 case CP0_REGISTER_15:
7a387fff 7225 switch (sel) {
4466cd49 7226 case CP0_REG15__PRID:
7db13fae 7227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7228 register_name = "PRid";
2423f660 7229 break;
4466cd49 7230 case CP0_REG15__EBASE:
d75c135e 7231 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
7232 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7233 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7234 register_name = "EBase";
2423f660 7235 break;
4466cd49 7236 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
7237 check_insn(ctx, ISA_MIPS32R2);
7238 CP0_CHECK(ctx->cmgcr);
7239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7240 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7241 register_name = "CMGCRBase";
c870e3f5 7242 break;
7a387fff 7243 default:
f31b035a 7244 goto cp0_unimplemented;
7a387fff 7245 }
873eb012 7246 break;
04992c8c 7247 case CP0_REGISTER_16:
873eb012 7248 switch (sel) {
433efb4c 7249 case CP0_REG16__CONFIG:
7db13fae 7250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7251 register_name = "Config";
873eb012 7252 break;
433efb4c 7253 case CP0_REG16__CONFIG1:
7db13fae 7254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7255 register_name = "Config1";
873eb012 7256 break;
433efb4c 7257 case CP0_REG16__CONFIG2:
7db13fae 7258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7259 register_name = "Config2";
7a387fff 7260 break;
433efb4c 7261 case CP0_REG16__CONFIG3:
7db13fae 7262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7263 register_name = "Config3";
7a387fff 7264 break;
433efb4c 7265 case CP0_REG16__CONFIG4:
b4160af1 7266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7267 register_name = "Config4";
b4160af1 7268 break;
433efb4c 7269 case CP0_REG16__CONFIG5:
b4dd99a3 7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7271 register_name = "Config5";
b4dd99a3 7272 break;
e397ee33 7273 /* 6,7 are implementation dependent */
433efb4c 7274 case CP0_REG16__CONFIG6:
7db13fae 7275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7276 register_name = "Config6";
e397ee33 7277 break;
433efb4c 7278 case CP0_REG16__CONFIG7:
7db13fae 7279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7280 register_name = "Config7";
e397ee33 7281 break;
873eb012 7282 default:
f31b035a 7283 goto cp0_unimplemented;
873eb012
TS
7284 }
7285 break;
04992c8c 7286 case CP0_REGISTER_17:
7a387fff 7287 switch (sel) {
706ce142 7288 case CP0_REG17__LLADDR:
895c2d04 7289 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7290 register_name = "LLAddr";
2423f660 7291 break;
706ce142 7292 case CP0_REG17__MAAR:
f6d4dd81
YK
7293 CP0_CHECK(ctx->mrp);
7294 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7295 register_name = "MAAR";
f6d4dd81 7296 break;
706ce142 7297 case CP0_REG17__MAARI:
f6d4dd81
YK
7298 CP0_CHECK(ctx->mrp);
7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7300 register_name = "MAARI";
f6d4dd81 7301 break;
7a387fff 7302 default:
f31b035a 7303 goto cp0_unimplemented;
7a387fff 7304 }
873eb012 7305 break;
04992c8c 7306 case CP0_REGISTER_18:
7a387fff 7307 switch (sel) {
e8dcfe82
AM
7308 case CP0_REG18__WATCHLO0:
7309 case CP0_REG18__WATCHLO1:
7310 case CP0_REG18__WATCHLO2:
7311 case CP0_REG18__WATCHLO3:
7312 case CP0_REG18__WATCHLO4:
7313 case CP0_REG18__WATCHLO5:
7314 case CP0_REG18__WATCHLO6:
7315 case CP0_REG18__WATCHLO7:
fa192d49 7316 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7317 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7318 register_name = "WatchLo";
2423f660 7319 break;
7a387fff 7320 default:
f31b035a 7321 goto cp0_unimplemented;
7a387fff 7322 }
873eb012 7323 break;
04992c8c 7324 case CP0_REGISTER_19:
7a387fff 7325 switch (sel) {
be274dc1
AM
7326 case CP0_REG19__WATCHHI0:
7327 case CP0_REG19__WATCHHI1:
7328 case CP0_REG19__WATCHHI2:
7329 case CP0_REG19__WATCHHI3:
7330 case CP0_REG19__WATCHHI4:
7331 case CP0_REG19__WATCHHI5:
7332 case CP0_REG19__WATCHHI6:
7333 case CP0_REG19__WATCHHI7:
fa192d49 7334 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7335 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7336 register_name = "WatchHi";
2423f660 7337 break;
7a387fff 7338 default:
f31b035a 7339 goto cp0_unimplemented;
7a387fff 7340 }
873eb012 7341 break;
04992c8c 7342 case CP0_REGISTER_20:
7a387fff 7343 switch (sel) {
14f92b0b 7344 case CP0_REG20__XCONTEXT:
d26bc211 7345#if defined(TARGET_MIPS64)
d75c135e 7346 check_insn(ctx, ISA_MIPS3);
7db13fae 7347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7348 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7349 register_name = "XContext";
2423f660 7350 break;
703eaf37 7351#endif
7a387fff 7352 default:
f31b035a 7353 goto cp0_unimplemented;
7a387fff 7354 }
8c0fdd85 7355 break;
04992c8c 7356 case CP0_REGISTER_21:
7a387fff 7357 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7358 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7359 switch (sel) {
7360 case 0:
7db13fae 7361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7362 register_name = "Framemask";
2423f660 7363 break;
7a387fff 7364 default:
f31b035a 7365 goto cp0_unimplemented;
7a387fff 7366 }
8c0fdd85 7367 break;
04992c8c 7368 case CP0_REGISTER_22:
d9bea114 7369 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7370 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7371 break;
04992c8c 7372 case CP0_REGISTER_23:
7a387fff 7373 switch (sel) {
4cbf4b6d 7374 case CP0_REG23__DEBUG:
895c2d04 7375 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7376 register_name = "Debug";
2423f660 7377 break;
4cbf4b6d
AM
7378 case CP0_REG23__TRACECONTROL:
7379 /* PDtrace support */
7380 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 7381 register_name = "TraceControl";
3570d7f6 7382 goto cp0_unimplemented;
4cbf4b6d
AM
7383 case CP0_REG23__TRACECONTROL2:
7384 /* PDtrace support */
7385 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 7386 register_name = "TraceControl2";
3570d7f6 7387 goto cp0_unimplemented;
4cbf4b6d
AM
7388 case CP0_REG23__USERTRACEDATA1:
7389 /* PDtrace support */
7390 /* gen_helper_mfc0_usertracedata1(arg);*/
7391 register_name = "UserTraceData1";
3570d7f6 7392 goto cp0_unimplemented;
4cbf4b6d
AM
7393 case CP0_REG23__TRACEIBPC:
7394 /* PDtrace support */
7395 /* gen_helper_mfc0_traceibpc(arg); */
7396 register_name = "TraceIBPC";
7397 goto cp0_unimplemented;
7398 case CP0_REG23__TRACEDBPC:
7399 /* PDtrace support */
7400 /* gen_helper_mfc0_tracedbpc(arg); */
7401 register_name = "TraceDBPC";
3570d7f6 7402 goto cp0_unimplemented;
7a387fff 7403 default:
f31b035a 7404 goto cp0_unimplemented;
7a387fff 7405 }
873eb012 7406 break;
04992c8c 7407 case CP0_REGISTER_24:
7a387fff 7408 switch (sel) {
8d7b4b6e 7409 case CP0_REG24__DEPC:
f0b3f3ae 7410 /* EJTAG support */
7db13fae 7411 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7412 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7413 register_name = "DEPC";
2423f660 7414 break;
7a387fff 7415 default:
f31b035a 7416 goto cp0_unimplemented;
7a387fff 7417 }
873eb012 7418 break;
04992c8c 7419 case CP0_REGISTER_25:
7a387fff 7420 switch (sel) {
1176b328 7421 case CP0_REG25__PERFCTL0:
7db13fae 7422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7423 register_name = "Performance0";
7a387fff 7424 break;
1176b328 7425 case CP0_REG25__PERFCNT0:
7480515f 7426 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 7427 register_name = "Performance1";
3570d7f6 7428 goto cp0_unimplemented;
1176b328 7429 case CP0_REG25__PERFCTL1:
7480515f 7430 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 7431 register_name = "Performance2";
3570d7f6 7432 goto cp0_unimplemented;
1176b328 7433 case CP0_REG25__PERFCNT1:
7480515f 7434 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 7435 register_name = "Performance3";
3570d7f6 7436 goto cp0_unimplemented;
1176b328 7437 case CP0_REG25__PERFCTL2:
7480515f 7438 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 7439 register_name = "Performance4";
3570d7f6 7440 goto cp0_unimplemented;
1176b328 7441 case CP0_REG25__PERFCNT2:
7480515f 7442 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 7443 register_name = "Performance5";
3570d7f6 7444 goto cp0_unimplemented;
1176b328 7445 case CP0_REG25__PERFCTL3:
7480515f 7446 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 7447 register_name = "Performance6";
3570d7f6 7448 goto cp0_unimplemented;
1176b328 7449 case CP0_REG25__PERFCNT3:
7480515f 7450 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 7451 register_name = "Performance7";
3570d7f6 7452 goto cp0_unimplemented;
7a387fff 7453 default:
f31b035a 7454 goto cp0_unimplemented;
7a387fff 7455 }
8c0fdd85 7456 break;
04992c8c 7457 case CP0_REGISTER_26:
0d74a222 7458 switch (sel) {
dbbf08b2 7459 case CP0_REG26__ERRCTL:
0d74a222 7460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7461 register_name = "ErrCtl";
0d74a222
LA
7462 break;
7463 default:
7464 goto cp0_unimplemented;
7465 }
da80682b 7466 break;
04992c8c 7467 case CP0_REGISTER_27:
7a387fff 7468 switch (sel) {
5a10873d 7469 case CP0_REG27__CACHERR:
d9bea114 7470 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7471 register_name = "CacheErr";
2423f660 7472 break;
7a387fff 7473 default:
f31b035a 7474 goto cp0_unimplemented;
7a387fff 7475 }
8c0fdd85 7476 break;
04992c8c 7477 case CP0_REGISTER_28:
873eb012 7478 switch (sel) {
a30e2f21
AM
7479 case CP0_REG28__TAGLO:
7480 case CP0_REG28__TAGLO1:
7481 case CP0_REG28__TAGLO2:
7482 case CP0_REG28__TAGLO3:
284b731a
LA
7483 {
7484 TCGv_i64 tmp = tcg_temp_new_i64();
7485 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7486 gen_move_low32(arg, tmp);
7487 tcg_temp_free_i64(tmp);
7488 }
294fc2ea 7489 register_name = "TagLo";
873eb012 7490 break;
a30e2f21
AM
7491 case CP0_REG28__DATALO:
7492 case CP0_REG28__DATALO1:
7493 case CP0_REG28__DATALO2:
7494 case CP0_REG28__DATALO3:
7db13fae 7495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7496 register_name = "DataLo";
873eb012
TS
7497 break;
7498 default:
f31b035a 7499 goto cp0_unimplemented;
873eb012
TS
7500 }
7501 break;
04992c8c 7502 case CP0_REGISTER_29:
7a387fff 7503 switch (sel) {
af4bb6da
AM
7504 case CP0_REG29__TAGHI:
7505 case CP0_REG29__TAGHI1:
7506 case CP0_REG29__TAGHI2:
7507 case CP0_REG29__TAGHI3:
7db13fae 7508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7509 register_name = "TagHi";
7a387fff 7510 break;
af4bb6da
AM
7511 case CP0_REG29__DATAHI:
7512 case CP0_REG29__DATAHI1:
7513 case CP0_REG29__DATAHI2:
7514 case CP0_REG29__DATAHI3:
7db13fae 7515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7516 register_name = "DataHi";
7a387fff
TS
7517 break;
7518 default:
f31b035a 7519 goto cp0_unimplemented;
7a387fff 7520 }
8c0fdd85 7521 break;
04992c8c 7522 case CP0_REGISTER_30:
7a387fff 7523 switch (sel) {
4bcf121e 7524 case CP0_REG30__ERROREPC:
7db13fae 7525 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7526 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7527 register_name = "ErrorEPC";
2423f660 7528 break;
7a387fff 7529 default:
f31b035a 7530 goto cp0_unimplemented;
7a387fff 7531 }
873eb012 7532 break;
04992c8c 7533 case CP0_REGISTER_31:
7a387fff 7534 switch (sel) {
14d92efd 7535 case CP0_REG31__DESAVE:
f0b3f3ae 7536 /* EJTAG support */
7db13fae 7537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7538 register_name = "DESAVE";
2423f660 7539 break;
14d92efd
AM
7540 case CP0_REG31__KSCRATCH1:
7541 case CP0_REG31__KSCRATCH2:
7542 case CP0_REG31__KSCRATCH3:
7543 case CP0_REG31__KSCRATCH4:
7544 case CP0_REG31__KSCRATCH5:
7545 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7546 CP0_CHECK(ctx->kscrexist & (1 << sel));
7547 tcg_gen_ld_tl(arg, cpu_env,
7548 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7549 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7550 register_name = "KScratch";
e98c0d17 7551 break;
7a387fff 7552 default:
f31b035a 7553 goto cp0_unimplemented;
7a387fff 7554 }
873eb012
TS
7555 break;
7556 default:
f31b035a 7557 goto cp0_unimplemented;
873eb012 7558 }
294fc2ea 7559 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
7560 return;
7561
f31b035a 7562cp0_unimplemented:
294fc2ea
AM
7563 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7564 register_name, reg, sel);
f31b035a 7565 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7566}
7567
d75c135e 7568static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7569{
294fc2ea 7570 const char *register_name = "invalid";
7a387fff 7571
1f8929d2 7572 if (sel != 0) {
d75c135e 7573 check_insn(ctx, ISA_MIPS32);
1f8929d2 7574 }
e189e748 7575
eeb3bba8 7576 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7577 gen_io_start();
bd79255d 7578 }
2e70f6ef 7579
8c0fdd85 7580 switch (reg) {
04992c8c 7581 case CP0_REGISTER_00:
7a387fff 7582 switch (sel) {
1b142da5 7583 case CP0_REG00__INDEX:
895c2d04 7584 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 7585 register_name = "Index";
7a387fff 7586 break;
1b142da5 7587 case CP0_REG00__MVPCONTROL:
f31b035a 7588 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7589 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 7590 register_name = "MVPControl";
ead9360e 7591 break;
1b142da5 7592 case CP0_REG00__MVPCONF0:
f31b035a 7593 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7594 /* ignored */
294fc2ea 7595 register_name = "MVPConf0";
ead9360e 7596 break;
1b142da5 7597 case CP0_REG00__MVPCONF1:
f31b035a 7598 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7599 /* ignored */
294fc2ea 7600 register_name = "MVPConf1";
ead9360e 7601 break;
1b142da5 7602 case CP0_REG00__VPCONTROL:
01bc435b
YK
7603 CP0_CHECK(ctx->vp);
7604 /* ignored */
294fc2ea 7605 register_name = "VPControl";
01bc435b 7606 break;
7a387fff 7607 default:
f31b035a 7608 goto cp0_unimplemented;
7a387fff 7609 }
8c0fdd85 7610 break;
04992c8c 7611 case CP0_REGISTER_01:
7a387fff 7612 switch (sel) {
30deb460 7613 case CP0_REG01__RANDOM:
2423f660 7614 /* ignored */
294fc2ea 7615 register_name = "Random";
2423f660 7616 break;
30deb460 7617 case CP0_REG01__VPECONTROL:
f31b035a 7618 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7619 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 7620 register_name = "VPEControl";
ead9360e 7621 break;
30deb460 7622 case CP0_REG01__VPECONF0:
f31b035a 7623 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7624 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 7625 register_name = "VPEConf0";
ead9360e 7626 break;
30deb460 7627 case CP0_REG01__VPECONF1:
f31b035a 7628 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7629 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 7630 register_name = "VPEConf1";
ead9360e 7631 break;
30deb460 7632 case CP0_REG01__YQMASK:
f31b035a 7633 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7634 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 7635 register_name = "YQMask";
ead9360e 7636 break;
30deb460 7637 case CP0_REG01__VPESCHEDULE:
f31b035a 7638 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7639 tcg_gen_st_tl(arg, cpu_env,
7640 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7641 register_name = "VPESchedule";
ead9360e 7642 break;
30deb460 7643 case CP0_REG01__VPESCHEFBACK:
f31b035a 7644 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7645 tcg_gen_st_tl(arg, cpu_env,
7646 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7647 register_name = "VPEScheFBack";
ead9360e 7648 break;
30deb460 7649 case CP0_REG01__VPEOPT:
f31b035a 7650 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7651 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 7652 register_name = "VPEOpt";
ead9360e 7653 break;
7a387fff 7654 default:
f31b035a 7655 goto cp0_unimplemented;
7a387fff 7656 }
8c0fdd85 7657 break;
04992c8c 7658 case CP0_REGISTER_02:
7a387fff 7659 switch (sel) {
6d27d5bd 7660 case CP0_REG02__ENTRYLO0:
895c2d04 7661 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 7662 register_name = "EntryLo0";
2423f660 7663 break;
6d27d5bd 7664 case CP0_REG02__TCSTATUS:
f31b035a 7665 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7666 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 7667 register_name = "TCStatus";
ead9360e 7668 break;
6d27d5bd 7669 case CP0_REG02__TCBIND:
f31b035a 7670 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7671 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 7672 register_name = "TCBind";
ead9360e 7673 break;
6d27d5bd 7674 case CP0_REG02__TCRESTART:
f31b035a 7675 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7676 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 7677 register_name = "TCRestart";
ead9360e 7678 break;
6d27d5bd 7679 case CP0_REG02__TCHALT:
f31b035a 7680 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7681 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 7682 register_name = "TCHalt";
ead9360e 7683 break;
6d27d5bd 7684 case CP0_REG02__TCCONTEXT:
f31b035a 7685 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7686 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 7687 register_name = "TCContext";
ead9360e 7688 break;
6d27d5bd 7689 case CP0_REG02__TCSCHEDULE:
f31b035a 7690 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7691 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 7692 register_name = "TCSchedule";
ead9360e 7693 break;
6d27d5bd 7694 case CP0_REG02__TCSCHEFBACK:
f31b035a 7695 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7696 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 7697 register_name = "TCScheFBack";
ead9360e 7698 break;
7a387fff 7699 default:
f31b035a 7700 goto cp0_unimplemented;
7a387fff 7701 }
8c0fdd85 7702 break;
04992c8c 7703 case CP0_REGISTER_03:
7a387fff 7704 switch (sel) {
acd37316 7705 case CP0_REG03__ENTRYLO1:
895c2d04 7706 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 7707 register_name = "EntryLo1";
2423f660 7708 break;
acd37316 7709 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7710 CP0_CHECK(ctx->vp);
7711 /* ignored */
294fc2ea 7712 register_name = "GlobalNumber";
01bc435b 7713 break;
7a387fff 7714 default:
f31b035a 7715 goto cp0_unimplemented;
876d4b07 7716 }
8c0fdd85 7717 break;
04992c8c 7718 case CP0_REGISTER_04:
7a387fff 7719 switch (sel) {
020fe379 7720 case CP0_REG04__CONTEXT:
895c2d04 7721 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 7722 register_name = "Context";
2423f660 7723 break;
020fe379
AM
7724 case CP0_REG04__CONTEXTCONFIG:
7725 /* SmartMIPS ASE */
7726 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 7727 register_name = "ContextConfig";
f31b035a 7728 goto cp0_unimplemented;
020fe379 7729 case CP0_REG04__USERLOCAL:
f31b035a
LA
7730 CP0_CHECK(ctx->ulri);
7731 tcg_gen_st_tl(arg, cpu_env,
7732 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7733 register_name = "UserLocal";
d279279e 7734 break;
7a387fff 7735 default:
f31b035a 7736 goto cp0_unimplemented;
876d4b07 7737 }
8c0fdd85 7738 break;
04992c8c 7739 case CP0_REGISTER_05:
7a387fff 7740 switch (sel) {
a1e76353 7741 case CP0_REG05__PAGEMASK:
895c2d04 7742 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 7743 register_name = "PageMask";
2423f660 7744 break;
a1e76353 7745 case CP0_REG05__PAGEGRAIN:
d75c135e 7746 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7747 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 7748 register_name = "PageGrain";
eeb3bba8 7749 ctx->base.is_jmp = DISAS_STOP;
2423f660 7750 break;
a1e76353 7751 case CP0_REG05__SEGCTL0:
cec56a73
JH
7752 CP0_CHECK(ctx->sc);
7753 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 7754 register_name = "SegCtl0";
cec56a73 7755 break;
a1e76353 7756 case CP0_REG05__SEGCTL1:
cec56a73
JH
7757 CP0_CHECK(ctx->sc);
7758 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 7759 register_name = "SegCtl1";
cec56a73 7760 break;
a1e76353 7761 case CP0_REG05__SEGCTL2:
cec56a73
JH
7762 CP0_CHECK(ctx->sc);
7763 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 7764 register_name = "SegCtl2";
cec56a73 7765 break;
a1e76353 7766 case CP0_REG05__PWBASE:
5e31fdd5
YK
7767 check_pw(ctx);
7768 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7769 register_name = "PWBase";
5e31fdd5 7770 break;
a1e76353 7771 case CP0_REG05__PWFIELD:
fa75ad14
YK
7772 check_pw(ctx);
7773 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 7774 register_name = "PWField";
fa75ad14 7775 break;
a1e76353 7776 case CP0_REG05__PWSIZE:
20b28ebc
YK
7777 check_pw(ctx);
7778 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 7779 register_name = "PWSize";
20b28ebc 7780 break;
7a387fff 7781 default:
f31b035a 7782 goto cp0_unimplemented;
876d4b07 7783 }
8c0fdd85 7784 break;
04992c8c 7785 case CP0_REGISTER_06:
7a387fff 7786 switch (sel) {
9023594b 7787 case CP0_REG06__WIRED:
895c2d04 7788 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 7789 register_name = "Wired";
2423f660 7790 break;
9023594b 7791 case CP0_REG06__SRSCONF0:
d75c135e 7792 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7793 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 7794 register_name = "SRSConf0";
ead9360e 7795 break;
9023594b 7796 case CP0_REG06__SRSCONF1:
d75c135e 7797 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7798 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 7799 register_name = "SRSConf1";
ead9360e 7800 break;
9023594b 7801 case CP0_REG06__SRSCONF2:
d75c135e 7802 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7803 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 7804 register_name = "SRSConf2";
ead9360e 7805 break;
9023594b 7806 case CP0_REG06__SRSCONF3:
d75c135e 7807 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7808 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 7809 register_name = "SRSConf3";
ead9360e 7810 break;
9023594b 7811 case CP0_REG06__SRSCONF4:
d75c135e 7812 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7813 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 7814 register_name = "SRSConf4";
ead9360e 7815 break;
9023594b 7816 case CP0_REG06__PWCTL:
103be64c
YK
7817 check_pw(ctx);
7818 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 7819 register_name = "PWCtl";
103be64c 7820 break;
7a387fff 7821 default:
f31b035a 7822 goto cp0_unimplemented;
876d4b07 7823 }
8c0fdd85 7824 break;
04992c8c 7825 case CP0_REGISTER_07:
7a387fff 7826 switch (sel) {
143a9875 7827 case CP0_REG07__HWRENA:
d75c135e 7828 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7829 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7830 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7831 register_name = "HWREna";
2423f660 7832 break;
7a387fff 7833 default:
f31b035a 7834 goto cp0_unimplemented;
876d4b07 7835 }
8c0fdd85 7836 break;
04992c8c 7837 case CP0_REGISTER_08:
aea14095 7838 switch (sel) {
67d167d2 7839 case CP0_REG08__BADVADDR:
aea14095 7840 /* ignored */
294fc2ea 7841 register_name = "BadVAddr";
aea14095 7842 break;
67d167d2 7843 case CP0_REG08__BADINSTR:
aea14095 7844 /* ignored */
294fc2ea 7845 register_name = "BadInstr";
aea14095 7846 break;
67d167d2 7847 case CP0_REG08__BADINSTRP:
aea14095 7848 /* ignored */
294fc2ea 7849 register_name = "BadInstrP";
aea14095 7850 break;
67d167d2 7851 case CP0_REG08__BADINSTRX:
25beba9b 7852 /* ignored */
294fc2ea 7853 register_name = "BadInstrX";
25beba9b 7854 break;
aea14095 7855 default:
f31b035a 7856 goto cp0_unimplemented;
aea14095 7857 }
8c0fdd85 7858 break;
04992c8c 7859 case CP0_REGISTER_09:
7a387fff 7860 switch (sel) {
e5a98a72 7861 case CP0_REG09__COUNT:
895c2d04 7862 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 7863 register_name = "Count";
2423f660 7864 break;
e5a98a72 7865 case CP0_REG09__SAARI:
5fb2dcd1
YK
7866 CP0_CHECK(ctx->saar);
7867 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 7868 register_name = "SAARI";
5fb2dcd1 7869 break;
e5a98a72 7870 case CP0_REG09__SAAR:
5fb2dcd1
YK
7871 CP0_CHECK(ctx->saar);
7872 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 7873 register_name = "SAAR";
5fb2dcd1 7874 break;
7a387fff 7875 default:
f31b035a 7876 goto cp0_unimplemented;
876d4b07 7877 }
8c0fdd85 7878 break;
04992c8c 7879 case CP0_REGISTER_10:
7a387fff 7880 switch (sel) {
860ffef0 7881 case CP0_REG10__ENTRYHI:
895c2d04 7882 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 7883 register_name = "EntryHi";
2423f660 7884 break;
7a387fff 7885 default:
f31b035a 7886 goto cp0_unimplemented;
876d4b07 7887 }
8c0fdd85 7888 break;
04992c8c 7889 case CP0_REGISTER_11:
7a387fff 7890 switch (sel) {
f5f3834f 7891 case CP0_REG11__COMPARE:
895c2d04 7892 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 7893 register_name = "Compare";
2423f660
TS
7894 break;
7895 /* 6,7 are implementation dependent */
7a387fff 7896 default:
f31b035a 7897 goto cp0_unimplemented;
876d4b07 7898 }
8c0fdd85 7899 break;
04992c8c 7900 case CP0_REGISTER_12:
7a387fff 7901 switch (sel) {
2b084867 7902 case CP0_REG12__STATUS:
867abc7e 7903 save_cpu_state(ctx, 1);
895c2d04 7904 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7905 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7906 gen_save_pc(ctx->base.pc_next + 4);
7907 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7908 register_name = "Status";
2423f660 7909 break;
2b084867 7910 case CP0_REG12__INTCTL:
d75c135e 7911 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7912 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7913 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7914 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7915 register_name = "IntCtl";
2423f660 7916 break;
2b084867 7917 case CP0_REG12__SRSCTL:
d75c135e 7918 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7919 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7920 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7921 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7922 register_name = "SRSCtl";
2423f660 7923 break;
2b084867 7924 case CP0_REG12__SRSMAP:
d75c135e 7925 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7926 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7927 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7928 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7929 register_name = "SRSMap";
fd88b6ab 7930 break;
7a387fff 7931 default:
f31b035a 7932 goto cp0_unimplemented;
876d4b07 7933 }
8c0fdd85 7934 break;
04992c8c 7935 case CP0_REGISTER_13:
7a387fff 7936 switch (sel) {
e3c7559d 7937 case CP0_REG13__CAUSE:
867abc7e 7938 save_cpu_state(ctx, 1);
895c2d04 7939 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
7940 /*
7941 * Stop translation as we may have triggered an interrupt.
b28425ba 7942 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
7943 * translated code to check for pending interrupts.
7944 */
eeb3bba8
EC
7945 gen_save_pc(ctx->base.pc_next + 4);
7946 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7947 register_name = "Cause";
2423f660 7948 break;
7a387fff 7949 default:
f31b035a 7950 goto cp0_unimplemented;
876d4b07 7951 }
8c0fdd85 7952 break;
04992c8c 7953 case CP0_REGISTER_14:
7a387fff 7954 switch (sel) {
35e4b54d 7955 case CP0_REG14__EPC:
d54a299b 7956 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7957 register_name = "EPC";
2423f660 7958 break;
7a387fff 7959 default:
f31b035a 7960 goto cp0_unimplemented;
876d4b07 7961 }
8c0fdd85 7962 break;
04992c8c 7963 case CP0_REGISTER_15:
7a387fff 7964 switch (sel) {
4466cd49 7965 case CP0_REG15__PRID:
2423f660 7966 /* ignored */
294fc2ea 7967 register_name = "PRid";
2423f660 7968 break;
4466cd49 7969 case CP0_REG15__EBASE:
d75c135e 7970 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7971 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 7972 register_name = "EBase";
2423f660 7973 break;
7a387fff 7974 default:
f31b035a 7975 goto cp0_unimplemented;
1579a72e 7976 }
8c0fdd85 7977 break;
04992c8c 7978 case CP0_REGISTER_16:
8c0fdd85 7979 switch (sel) {
433efb4c 7980 case CP0_REG16__CONFIG:
895c2d04 7981 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 7982 register_name = "Config";
2423f660 7983 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7984 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7985 break;
433efb4c 7986 case CP0_REG16__CONFIG1:
e397ee33 7987 /* ignored, read only */
294fc2ea 7988 register_name = "Config1";
7a387fff 7989 break;
433efb4c 7990 case CP0_REG16__CONFIG2:
895c2d04 7991 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 7992 register_name = "Config2";
2423f660 7993 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7994 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7995 break;
433efb4c 7996 case CP0_REG16__CONFIG3:
90f12d73 7997 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 7998 register_name = "Config3";
90f12d73 7999 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8000 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8001 break;
433efb4c 8002 case CP0_REG16__CONFIG4:
b4160af1 8003 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 8004 register_name = "Config4";
eeb3bba8 8005 ctx->base.is_jmp = DISAS_STOP;
b4160af1 8006 break;
433efb4c 8007 case CP0_REG16__CONFIG5:
b4dd99a3 8008 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8009 register_name = "Config5";
b4dd99a3 8010 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8011 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 8012 break;
e397ee33 8013 /* 6,7 are implementation dependent */
433efb4c 8014 case CP0_REG16__CONFIG6:
e397ee33 8015 /* ignored */
294fc2ea 8016 register_name = "Config6";
e397ee33 8017 break;
433efb4c 8018 case CP0_REG16__CONFIG7:
e397ee33 8019 /* ignored */
294fc2ea 8020 register_name = "Config7";
e397ee33 8021 break;
8c0fdd85 8022 default:
294fc2ea 8023 register_name = "Invalid config selector";
f31b035a 8024 goto cp0_unimplemented;
8c0fdd85
TS
8025 }
8026 break;
04992c8c 8027 case CP0_REGISTER_17:
7a387fff 8028 switch (sel) {
706ce142 8029 case CP0_REG17__LLADDR:
895c2d04 8030 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8031 register_name = "LLAddr";
2423f660 8032 break;
706ce142 8033 case CP0_REG17__MAAR:
f6d4dd81
YK
8034 CP0_CHECK(ctx->mrp);
8035 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8036 register_name = "MAAR";
f6d4dd81 8037 break;
706ce142 8038 case CP0_REG17__MAARI:
f6d4dd81
YK
8039 CP0_CHECK(ctx->mrp);
8040 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8041 register_name = "MAARI";
f6d4dd81 8042 break;
7a387fff 8043 default:
f31b035a 8044 goto cp0_unimplemented;
7a387fff 8045 }
8c0fdd85 8046 break;
04992c8c 8047 case CP0_REGISTER_18:
7a387fff 8048 switch (sel) {
e8dcfe82
AM
8049 case CP0_REG18__WATCHLO0:
8050 case CP0_REG18__WATCHLO1:
8051 case CP0_REG18__WATCHLO2:
8052 case CP0_REG18__WATCHLO3:
8053 case CP0_REG18__WATCHLO4:
8054 case CP0_REG18__WATCHLO5:
8055 case CP0_REG18__WATCHLO6:
8056 case CP0_REG18__WATCHLO7:
fa192d49 8057 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8058 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8059 register_name = "WatchLo";
2423f660 8060 break;
7a387fff 8061 default:
f31b035a 8062 goto cp0_unimplemented;
7a387fff 8063 }
8c0fdd85 8064 break;
04992c8c 8065 case CP0_REGISTER_19:
7a387fff 8066 switch (sel) {
be274dc1
AM
8067 case CP0_REG19__WATCHHI0:
8068 case CP0_REG19__WATCHHI1:
8069 case CP0_REG19__WATCHHI2:
8070 case CP0_REG19__WATCHHI3:
8071 case CP0_REG19__WATCHHI4:
8072 case CP0_REG19__WATCHHI5:
8073 case CP0_REG19__WATCHHI6:
8074 case CP0_REG19__WATCHHI7:
fa192d49 8075 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8076 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8077 register_name = "WatchHi";
2423f660 8078 break;
7a387fff 8079 default:
f31b035a 8080 goto cp0_unimplemented;
7a387fff 8081 }
8c0fdd85 8082 break;
04992c8c 8083 case CP0_REGISTER_20:
7a387fff 8084 switch (sel) {
14f92b0b 8085 case CP0_REG20__XCONTEXT:
d26bc211 8086#if defined(TARGET_MIPS64)
d75c135e 8087 check_insn(ctx, ISA_MIPS3);
895c2d04 8088 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8089 register_name = "XContext";
2423f660 8090 break;
703eaf37 8091#endif
7a387fff 8092 default:
f31b035a 8093 goto cp0_unimplemented;
7a387fff 8094 }
8c0fdd85 8095 break;
04992c8c 8096 case CP0_REGISTER_21:
7a387fff 8097 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8098 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
8099 switch (sel) {
8100 case 0:
895c2d04 8101 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8102 register_name = "Framemask";
2423f660 8103 break;
7a387fff 8104 default:
f31b035a 8105 goto cp0_unimplemented;
7a387fff
TS
8106 }
8107 break;
04992c8c 8108 case CP0_REGISTER_22:
7a387fff 8109 /* ignored */
294fc2ea 8110 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8111 break;
04992c8c 8112 case CP0_REGISTER_23:
7a387fff 8113 switch (sel) {
4cbf4b6d 8114 case CP0_REG23__DEBUG:
895c2d04 8115 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8116 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8117 gen_save_pc(ctx->base.pc_next + 4);
8118 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8119 register_name = "Debug";
2423f660 8120 break;
4cbf4b6d
AM
8121 case CP0_REG23__TRACECONTROL:
8122 /* PDtrace support */
8123 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 8124 register_name = "TraceControl";
8487327a 8125 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8126 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8127 goto cp0_unimplemented;
4cbf4b6d
AM
8128 case CP0_REG23__TRACECONTROL2:
8129 /* PDtrace support */
8130 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 8131 register_name = "TraceControl2";
8487327a 8132 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8133 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8134 goto cp0_unimplemented;
4cbf4b6d 8135 case CP0_REG23__USERTRACEDATA1:
8487327a 8136 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8137 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8138 /* PDtrace support */
8139 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 8140 register_name = "UserTraceData";
8487327a 8141 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8142 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8143 goto cp0_unimplemented;
4cbf4b6d
AM
8144 case CP0_REG23__TRACEIBPC:
8145 /* PDtrace support */
8146 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 8147 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8148 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8149 register_name = "TraceIBPC";
8150 goto cp0_unimplemented;
8151 case CP0_REG23__TRACEDBPC:
8152 /* PDtrace support */
8153 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8154 /* Stop translation as we may have switched the execution mode */
8155 ctx->base.is_jmp = DISAS_STOP;
8156 register_name = "TraceDBPC";
3570d7f6 8157 goto cp0_unimplemented;
7a387fff 8158 default:
f31b035a 8159 goto cp0_unimplemented;
7a387fff 8160 }
8c0fdd85 8161 break;
04992c8c 8162 case CP0_REGISTER_24:
7a387fff 8163 switch (sel) {
8d7b4b6e 8164 case CP0_REG24__DEPC:
f1aa6320 8165 /* EJTAG support */
d54a299b 8166 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8167 register_name = "DEPC";
2423f660 8168 break;
7a387fff 8169 default:
f31b035a 8170 goto cp0_unimplemented;
7a387fff 8171 }
8c0fdd85 8172 break;
04992c8c 8173 case CP0_REGISTER_25:
7a387fff 8174 switch (sel) {
1176b328 8175 case CP0_REG25__PERFCTL0:
895c2d04 8176 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8177 register_name = "Performance0";
2423f660 8178 break;
1176b328 8179 case CP0_REG25__PERFCNT0:
7480515f 8180 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 8181 register_name = "Performance1";
3570d7f6 8182 goto cp0_unimplemented;
1176b328 8183 case CP0_REG25__PERFCTL1:
7480515f 8184 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 8185 register_name = "Performance2";
3570d7f6 8186 goto cp0_unimplemented;
1176b328 8187 case CP0_REG25__PERFCNT1:
7480515f 8188 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 8189 register_name = "Performance3";
3570d7f6 8190 goto cp0_unimplemented;
1176b328 8191 case CP0_REG25__PERFCTL2:
7480515f 8192 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 8193 register_name = "Performance4";
3570d7f6 8194 goto cp0_unimplemented;
1176b328 8195 case CP0_REG25__PERFCNT2:
7480515f 8196 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 8197 register_name = "Performance5";
3570d7f6 8198 goto cp0_unimplemented;
1176b328 8199 case CP0_REG25__PERFCTL3:
7480515f 8200 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 8201 register_name = "Performance6";
3570d7f6 8202 goto cp0_unimplemented;
1176b328 8203 case CP0_REG25__PERFCNT3:
7480515f 8204 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 8205 register_name = "Performance7";
3570d7f6 8206 goto cp0_unimplemented;
7a387fff 8207 default:
f31b035a 8208 goto cp0_unimplemented;
7a387fff 8209 }
8c0fdd85 8210 break;
04992c8c 8211 case CP0_REGISTER_26:
0d74a222 8212 switch (sel) {
dbbf08b2 8213 case CP0_REG26__ERRCTL:
0d74a222 8214 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8215 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8216 register_name = "ErrCtl";
0d74a222
LA
8217 break;
8218 default:
8219 goto cp0_unimplemented;
8220 }
2423f660 8221 break;
04992c8c 8222 case CP0_REGISTER_27:
7a387fff 8223 switch (sel) {
5a10873d 8224 case CP0_REG27__CACHERR:
2423f660 8225 /* ignored */
294fc2ea 8226 register_name = "CacheErr";
2423f660 8227 break;
7a387fff 8228 default:
f31b035a 8229 goto cp0_unimplemented;
7a387fff 8230 }
8c0fdd85 8231 break;
04992c8c 8232 case CP0_REGISTER_28:
8c0fdd85 8233 switch (sel) {
a30e2f21
AM
8234 case CP0_REG28__TAGLO:
8235 case CP0_REG28__TAGLO1:
8236 case CP0_REG28__TAGLO2:
8237 case CP0_REG28__TAGLO3:
895c2d04 8238 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8239 register_name = "TagLo";
8c0fdd85 8240 break;
a30e2f21
AM
8241 case CP0_REG28__DATALO:
8242 case CP0_REG28__DATALO1:
8243 case CP0_REG28__DATALO2:
8244 case CP0_REG28__DATALO3:
895c2d04 8245 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8246 register_name = "DataLo";
7a387fff 8247 break;
8c0fdd85 8248 default:
f31b035a 8249 goto cp0_unimplemented;
8c0fdd85
TS
8250 }
8251 break;
04992c8c 8252 case CP0_REGISTER_29:
7a387fff 8253 switch (sel) {
af4bb6da
AM
8254 case CP0_REG29__TAGHI:
8255 case CP0_REG29__TAGHI1:
8256 case CP0_REG29__TAGHI2:
8257 case CP0_REG29__TAGHI3:
895c2d04 8258 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8259 register_name = "TagHi";
7a387fff 8260 break;
af4bb6da
AM
8261 case CP0_REG29__DATAHI:
8262 case CP0_REG29__DATAHI1:
8263 case CP0_REG29__DATAHI2:
8264 case CP0_REG29__DATAHI3:
895c2d04 8265 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8266 register_name = "DataHi";
7a387fff
TS
8267 break;
8268 default:
294fc2ea 8269 register_name = "invalid sel";
f31b035a 8270 goto cp0_unimplemented;
7a387fff 8271 }
8c0fdd85 8272 break;
04992c8c 8273 case CP0_REGISTER_30:
7a387fff 8274 switch (sel) {
4bcf121e 8275 case CP0_REG30__ERROREPC:
d54a299b 8276 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8277 register_name = "ErrorEPC";
2423f660 8278 break;
7a387fff 8279 default:
f31b035a 8280 goto cp0_unimplemented;
7a387fff 8281 }
8c0fdd85 8282 break;
04992c8c 8283 case CP0_REGISTER_31:
7a387fff 8284 switch (sel) {
14d92efd 8285 case CP0_REG31__DESAVE:
f1aa6320 8286 /* EJTAG support */
7db13fae 8287 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8288 register_name = "DESAVE";
2423f660 8289 break;
14d92efd
AM
8290 case CP0_REG31__KSCRATCH1:
8291 case CP0_REG31__KSCRATCH2:
8292 case CP0_REG31__KSCRATCH3:
8293 case CP0_REG31__KSCRATCH4:
8294 case CP0_REG31__KSCRATCH5:
8295 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8296 CP0_CHECK(ctx->kscrexist & (1 << sel));
8297 tcg_gen_st_tl(arg, cpu_env,
8298 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
294fc2ea 8299 register_name = "KScratch";
e98c0d17 8300 break;
7a387fff 8301 default:
f31b035a 8302 goto cp0_unimplemented;
7a387fff 8303 }
8c0fdd85
TS
8304 break;
8305 default:
f31b035a 8306 goto cp0_unimplemented;
8c0fdd85 8307 }
294fc2ea 8308 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8309
bf20dc07 8310 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8311 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8312 /*
8313 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8314 * translated code to check for pending interrupts.
8315 */
eeb3bba8
EC
8316 gen_save_pc(ctx->base.pc_next + 4);
8317 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8318 }
8c0fdd85
TS
8319 return;
8320
f31b035a 8321cp0_unimplemented:
294fc2ea
AM
8322 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8323 register_name, reg, sel);
8c0fdd85
TS
8324}
8325
d26bc211 8326#if defined(TARGET_MIPS64)
d75c135e 8327static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8328{
294fc2ea 8329 const char *register_name = "invalid";
9c2149c8 8330
1f8929d2 8331 if (sel != 0) {
d75c135e 8332 check_insn(ctx, ISA_MIPS64);
1f8929d2 8333 }
e189e748 8334
9c2149c8 8335 switch (reg) {
04992c8c 8336 case CP0_REGISTER_00:
9c2149c8 8337 switch (sel) {
1b142da5 8338 case CP0_REG00__INDEX:
7db13fae 8339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8340 register_name = "Index";
9c2149c8 8341 break;
1b142da5 8342 case CP0_REG00__MVPCONTROL:
f31b035a 8343 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8344 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8345 register_name = "MVPControl";
ead9360e 8346 break;
1b142da5 8347 case CP0_REG00__MVPCONF0:
f31b035a 8348 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8349 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8350 register_name = "MVPConf0";
ead9360e 8351 break;
1b142da5 8352 case CP0_REG00__MVPCONF1:
f31b035a 8353 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8354 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8355 register_name = "MVPConf1";
ead9360e 8356 break;
1b142da5 8357 case CP0_REG00__VPCONTROL:
01bc435b
YK
8358 CP0_CHECK(ctx->vp);
8359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8360 register_name = "VPControl";
01bc435b 8361 break;
9c2149c8 8362 default:
f31b035a 8363 goto cp0_unimplemented;
9c2149c8
TS
8364 }
8365 break;
04992c8c 8366 case CP0_REGISTER_01:
9c2149c8 8367 switch (sel) {
30deb460 8368 case CP0_REG01__RANDOM:
f31b035a 8369 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 8370 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8371 register_name = "Random";
2423f660 8372 break;
30deb460 8373 case CP0_REG01__VPECONTROL:
f31b035a 8374 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8376 register_name = "VPEControl";
ead9360e 8377 break;
30deb460 8378 case CP0_REG01__VPECONF0:
f31b035a 8379 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8381 register_name = "VPEConf0";
ead9360e 8382 break;
30deb460 8383 case CP0_REG01__VPECONF1:
f31b035a 8384 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 8386 register_name = "VPEConf1";
ead9360e 8387 break;
30deb460 8388 case CP0_REG01__YQMASK:
f31b035a 8389 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 8391 register_name = "YQMask";
ead9360e 8392 break;
30deb460 8393 case CP0_REG01__VPESCHEDULE:
f31b035a 8394 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8395 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8396 register_name = "VPESchedule";
ead9360e 8397 break;
30deb460 8398 case CP0_REG01__VPESCHEFBACK:
f31b035a 8399 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8400 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8401 register_name = "VPEScheFBack";
ead9360e 8402 break;
30deb460 8403 case CP0_REG01__VPEOPT:
f31b035a 8404 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 8406 register_name = "VPEOpt";
ead9360e 8407 break;
9c2149c8 8408 default:
f31b035a 8409 goto cp0_unimplemented;
9c2149c8
TS
8410 }
8411 break;
04992c8c 8412 case CP0_REGISTER_02:
9c2149c8 8413 switch (sel) {
6d27d5bd 8414 case CP0_REG02__ENTRYLO0:
7db13fae 8415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 8416 register_name = "EntryLo0";
2423f660 8417 break;
6d27d5bd 8418 case CP0_REG02__TCSTATUS:
f31b035a 8419 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8420 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 8421 register_name = "TCStatus";
ead9360e 8422 break;
6d27d5bd 8423 case CP0_REG02__TCBIND:
f31b035a 8424 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8425 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 8426 register_name = "TCBind";
ead9360e 8427 break;
6d27d5bd 8428 case CP0_REG02__TCRESTART:
f31b035a 8429 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8430 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 8431 register_name = "TCRestart";
ead9360e 8432 break;
6d27d5bd 8433 case CP0_REG02__TCHALT:
f31b035a 8434 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8435 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 8436 register_name = "TCHalt";
ead9360e 8437 break;
6d27d5bd 8438 case CP0_REG02__TCCONTEXT:
f31b035a 8439 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8440 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 8441 register_name = "TCContext";
ead9360e 8442 break;
6d27d5bd 8443 case CP0_REG02__TCSCHEDULE:
f31b035a 8444 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8445 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 8446 register_name = "TCSchedule";
ead9360e 8447 break;
6d27d5bd 8448 case CP0_REG02__TCSCHEFBACK:
f31b035a 8449 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8450 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 8451 register_name = "TCScheFBack";
ead9360e 8452 break;
9c2149c8 8453 default:
f31b035a 8454 goto cp0_unimplemented;
9c2149c8
TS
8455 }
8456 break;
04992c8c 8457 case CP0_REGISTER_03:
9c2149c8 8458 switch (sel) {
acd37316 8459 case CP0_REG03__ENTRYLO1:
7db13fae 8460 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 8461 register_name = "EntryLo1";
2423f660 8462 break;
acd37316 8463 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8464 CP0_CHECK(ctx->vp);
8465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 8466 register_name = "GlobalNumber";
01bc435b 8467 break;
9c2149c8 8468 default:
f31b035a 8469 goto cp0_unimplemented;
1579a72e 8470 }
9c2149c8 8471 break;
04992c8c 8472 case CP0_REGISTER_04:
9c2149c8 8473 switch (sel) {
020fe379 8474 case CP0_REG04__CONTEXT:
7db13fae 8475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 8476 register_name = "Context";
2423f660 8477 break;
020fe379
AM
8478 case CP0_REG04__CONTEXTCONFIG:
8479 /* SmartMIPS ASE */
8480 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 8481 register_name = "ContextConfig";
f31b035a 8482 goto cp0_unimplemented;
020fe379 8483 case CP0_REG04__USERLOCAL:
f31b035a
LA
8484 CP0_CHECK(ctx->ulri);
8485 tcg_gen_ld_tl(arg, cpu_env,
8486 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8487 register_name = "UserLocal";
d279279e 8488 break;
9c2149c8 8489 default:
f31b035a 8490 goto cp0_unimplemented;
876d4b07 8491 }
9c2149c8 8492 break;
04992c8c 8493 case CP0_REGISTER_05:
9c2149c8 8494 switch (sel) {
a1e76353 8495 case CP0_REG05__PAGEMASK:
7db13fae 8496 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 8497 register_name = "PageMask";
2423f660 8498 break;
a1e76353 8499 case CP0_REG05__PAGEGRAIN:
d75c135e 8500 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 8502 register_name = "PageGrain";
2423f660 8503 break;
a1e76353 8504 case CP0_REG05__SEGCTL0:
cec56a73
JH
8505 CP0_CHECK(ctx->sc);
8506 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 8507 register_name = "SegCtl0";
cec56a73 8508 break;
a1e76353 8509 case CP0_REG05__SEGCTL1:
cec56a73
JH
8510 CP0_CHECK(ctx->sc);
8511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 8512 register_name = "SegCtl1";
cec56a73 8513 break;
a1e76353 8514 case CP0_REG05__SEGCTL2:
cec56a73
JH
8515 CP0_CHECK(ctx->sc);
8516 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 8517 register_name = "SegCtl2";
cec56a73 8518 break;
a1e76353 8519 case CP0_REG05__PWBASE:
5e31fdd5
YK
8520 check_pw(ctx);
8521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8522 register_name = "PWBase";
5e31fdd5 8523 break;
a1e76353 8524 case CP0_REG05__PWFIELD:
fa75ad14
YK
8525 check_pw(ctx);
8526 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 8527 register_name = "PWField";
fa75ad14 8528 break;
a1e76353 8529 case CP0_REG05__PWSIZE:
20b28ebc
YK
8530 check_pw(ctx);
8531 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 8532 register_name = "PWSize";
20b28ebc 8533 break;
9c2149c8 8534 default:
f31b035a 8535 goto cp0_unimplemented;
876d4b07 8536 }
9c2149c8 8537 break;
04992c8c 8538 case CP0_REGISTER_06:
9c2149c8 8539 switch (sel) {
9023594b 8540 case CP0_REG06__WIRED:
7db13fae 8541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 8542 register_name = "Wired";
2423f660 8543 break;
9023594b 8544 case CP0_REG06__SRSCONF0:
d75c135e 8545 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 8547 register_name = "SRSConf0";
ead9360e 8548 break;
9023594b 8549 case CP0_REG06__SRSCONF1:
d75c135e 8550 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 8552 register_name = "SRSConf1";
ead9360e 8553 break;
9023594b 8554 case CP0_REG06__SRSCONF2:
d75c135e 8555 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 8557 register_name = "SRSConf2";
ead9360e 8558 break;
9023594b 8559 case CP0_REG06__SRSCONF3:
d75c135e 8560 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 8562 register_name = "SRSConf3";
ead9360e 8563 break;
9023594b 8564 case CP0_REG06__SRSCONF4:
d75c135e 8565 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 8567 register_name = "SRSConf4";
ead9360e 8568 break;
9023594b 8569 case CP0_REG06__PWCTL:
103be64c
YK
8570 check_pw(ctx);
8571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 8572 register_name = "PWCtl";
103be64c 8573 break;
9c2149c8 8574 default:
f31b035a 8575 goto cp0_unimplemented;
876d4b07 8576 }
9c2149c8 8577 break;
04992c8c 8578 case CP0_REGISTER_07:
9c2149c8 8579 switch (sel) {
143a9875 8580 case CP0_REG07__HWRENA:
d75c135e 8581 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 8583 register_name = "HWREna";
2423f660 8584 break;
9c2149c8 8585 default:
f31b035a 8586 goto cp0_unimplemented;
876d4b07 8587 }
9c2149c8 8588 break;
04992c8c 8589 case CP0_REGISTER_08:
9c2149c8 8590 switch (sel) {
67d167d2 8591 case CP0_REG08__BADVADDR:
7db13fae 8592 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 8593 register_name = "BadVAddr";
2423f660 8594 break;
67d167d2 8595 case CP0_REG08__BADINSTR:
f31b035a
LA
8596 CP0_CHECK(ctx->bi);
8597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 8598 register_name = "BadInstr";
aea14095 8599 break;
67d167d2 8600 case CP0_REG08__BADINSTRP:
f31b035a
LA
8601 CP0_CHECK(ctx->bp);
8602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 8603 register_name = "BadInstrP";
aea14095 8604 break;
67d167d2 8605 case CP0_REG08__BADINSTRX:
25beba9b
SM
8606 CP0_CHECK(ctx->bi);
8607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8608 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 8609 register_name = "BadInstrX";
25beba9b 8610 break;
9c2149c8 8611 default:
f31b035a 8612 goto cp0_unimplemented;
876d4b07 8613 }
9c2149c8 8614 break;
04992c8c 8615 case CP0_REGISTER_09:
9c2149c8 8616 switch (sel) {
e5a98a72 8617 case CP0_REG09__COUNT:
2e70f6ef 8618 /* Mark as an IO operation because we read the time. */
eeb3bba8 8619 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8620 gen_io_start();
bd79255d 8621 }
895c2d04 8622 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
8623 /*
8624 * Break the TB to be able to take timer interrupts immediately
8625 * after reading count. DISAS_STOP isn't sufficient, we need to
8626 * ensure we break completely out of translated code.
8627 */
eeb3bba8
EC
8628 gen_save_pc(ctx->base.pc_next + 4);
8629 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8630 register_name = "Count";
2423f660 8631 break;
e5a98a72 8632 case CP0_REG09__SAARI:
5fb2dcd1
YK
8633 CP0_CHECK(ctx->saar);
8634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 8635 register_name = "SAARI";
5fb2dcd1 8636 break;
e5a98a72 8637 case CP0_REG09__SAAR:
5fb2dcd1
YK
8638 CP0_CHECK(ctx->saar);
8639 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 8640 register_name = "SAAR";
5fb2dcd1 8641 break;
9c2149c8 8642 default:
f31b035a 8643 goto cp0_unimplemented;
876d4b07 8644 }
9c2149c8 8645 break;
04992c8c 8646 case CP0_REGISTER_10:
9c2149c8 8647 switch (sel) {
860ffef0 8648 case CP0_REG10__ENTRYHI:
7db13fae 8649 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 8650 register_name = "EntryHi";
2423f660 8651 break;
9c2149c8 8652 default:
f31b035a 8653 goto cp0_unimplemented;
876d4b07 8654 }
9c2149c8 8655 break;
04992c8c 8656 case CP0_REGISTER_11:
9c2149c8 8657 switch (sel) {
f5f3834f 8658 case CP0_REG11__COMPARE:
7db13fae 8659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 8660 register_name = "Compare";
2423f660 8661 break;
876d4b07 8662 /* 6,7 are implementation dependent */
9c2149c8 8663 default:
f31b035a 8664 goto cp0_unimplemented;
876d4b07 8665 }
9c2149c8 8666 break;
04992c8c 8667 case CP0_REGISTER_12:
9c2149c8 8668 switch (sel) {
2b084867 8669 case CP0_REG12__STATUS:
7db13fae 8670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 8671 register_name = "Status";
2423f660 8672 break;
2b084867 8673 case CP0_REG12__INTCTL:
d75c135e 8674 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 8676 register_name = "IntCtl";
2423f660 8677 break;
2b084867 8678 case CP0_REG12__SRSCTL:
d75c135e 8679 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 8681 register_name = "SRSCtl";
2423f660 8682 break;
2b084867 8683 case CP0_REG12__SRSMAP:
d75c135e 8684 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 8686 register_name = "SRSMap";
2423f660 8687 break;
9c2149c8 8688 default:
f31b035a 8689 goto cp0_unimplemented;
876d4b07 8690 }
9c2149c8 8691 break;
04992c8c 8692 case CP0_REGISTER_13:
9c2149c8 8693 switch (sel) {
e3c7559d 8694 case CP0_REG13__CAUSE:
7db13fae 8695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 8696 register_name = "Cause";
2423f660 8697 break;
9c2149c8 8698 default:
f31b035a 8699 goto cp0_unimplemented;
876d4b07 8700 }
9c2149c8 8701 break;
04992c8c 8702 case CP0_REGISTER_14:
9c2149c8 8703 switch (sel) {
35e4b54d 8704 case CP0_REG14__EPC:
7db13fae 8705 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8706 register_name = "EPC";
2423f660 8707 break;
9c2149c8 8708 default:
f31b035a 8709 goto cp0_unimplemented;
876d4b07 8710 }
9c2149c8 8711 break;
04992c8c 8712 case CP0_REGISTER_15:
9c2149c8 8713 switch (sel) {
4466cd49 8714 case CP0_REG15__PRID:
7db13fae 8715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 8716 register_name = "PRid";
2423f660 8717 break;
4466cd49 8718 case CP0_REG15__EBASE:
d75c135e 8719 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8720 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 8721 register_name = "EBase";
2423f660 8722 break;
4466cd49 8723 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
8724 check_insn(ctx, ISA_MIPS32R2);
8725 CP0_CHECK(ctx->cmgcr);
8726 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 8727 register_name = "CMGCRBase";
c870e3f5 8728 break;
9c2149c8 8729 default:
f31b035a 8730 goto cp0_unimplemented;
876d4b07 8731 }
9c2149c8 8732 break;
04992c8c 8733 case CP0_REGISTER_16:
9c2149c8 8734 switch (sel) {
433efb4c 8735 case CP0_REG16__CONFIG:
7db13fae 8736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 8737 register_name = "Config";
9c2149c8 8738 break;
433efb4c 8739 case CP0_REG16__CONFIG1:
7db13fae 8740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 8741 register_name = "Config1";
9c2149c8 8742 break;
433efb4c 8743 case CP0_REG16__CONFIG2:
7db13fae 8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 8745 register_name = "Config2";
9c2149c8 8746 break;
433efb4c 8747 case CP0_REG16__CONFIG3:
7db13fae 8748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 8749 register_name = "Config3";
9c2149c8 8750 break;
433efb4c 8751 case CP0_REG16__CONFIG4:
faf1f68b 8752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 8753 register_name = "Config4";
faf1f68b 8754 break;
433efb4c 8755 case CP0_REG16__CONFIG5:
faf1f68b 8756 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 8757 register_name = "Config5";
faf1f68b 8758 break;
9c2149c8 8759 /* 6,7 are implementation dependent */
433efb4c 8760 case CP0_REG16__CONFIG6:
7db13fae 8761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 8762 register_name = "Config6";
f0b3f3ae 8763 break;
433efb4c 8764 case CP0_REG16__CONFIG7:
7db13fae 8765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 8766 register_name = "Config7";
f0b3f3ae 8767 break;
9c2149c8 8768 default:
f31b035a 8769 goto cp0_unimplemented;
9c2149c8
TS
8770 }
8771 break;
04992c8c 8772 case CP0_REGISTER_17:
9c2149c8 8773 switch (sel) {
706ce142 8774 case CP0_REG17__LLADDR:
895c2d04 8775 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 8776 register_name = "LLAddr";
2423f660 8777 break;
706ce142 8778 case CP0_REG17__MAAR:
f6d4dd81
YK
8779 CP0_CHECK(ctx->mrp);
8780 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 8781 register_name = "MAAR";
f6d4dd81 8782 break;
706ce142 8783 case CP0_REG17__MAARI:
f6d4dd81
YK
8784 CP0_CHECK(ctx->mrp);
8785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 8786 register_name = "MAARI";
f6d4dd81 8787 break;
9c2149c8 8788 default:
f31b035a 8789 goto cp0_unimplemented;
9c2149c8
TS
8790 }
8791 break;
04992c8c 8792 case CP0_REGISTER_18:
9c2149c8 8793 switch (sel) {
e8dcfe82
AM
8794 case CP0_REG18__WATCHLO0:
8795 case CP0_REG18__WATCHLO1:
8796 case CP0_REG18__WATCHLO2:
8797 case CP0_REG18__WATCHLO3:
8798 case CP0_REG18__WATCHLO4:
8799 case CP0_REG18__WATCHLO5:
8800 case CP0_REG18__WATCHLO6:
8801 case CP0_REG18__WATCHLO7:
fa192d49 8802 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8803 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 8804 register_name = "WatchLo";
2423f660 8805 break;
9c2149c8 8806 default:
f31b035a 8807 goto cp0_unimplemented;
9c2149c8
TS
8808 }
8809 break;
04992c8c 8810 case CP0_REGISTER_19:
9c2149c8 8811 switch (sel) {
be274dc1
AM
8812 case CP0_REG19__WATCHHI0:
8813 case CP0_REG19__WATCHHI1:
8814 case CP0_REG19__WATCHHI2:
8815 case CP0_REG19__WATCHHI3:
8816 case CP0_REG19__WATCHHI4:
8817 case CP0_REG19__WATCHHI5:
8818 case CP0_REG19__WATCHHI6:
8819 case CP0_REG19__WATCHHI7:
fa192d49 8820 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8821 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 8822 register_name = "WatchHi";
2423f660 8823 break;
9c2149c8 8824 default:
f31b035a 8825 goto cp0_unimplemented;
9c2149c8
TS
8826 }
8827 break;
04992c8c 8828 case CP0_REGISTER_20:
9c2149c8 8829 switch (sel) {
14f92b0b 8830 case CP0_REG20__XCONTEXT:
d75c135e 8831 check_insn(ctx, ISA_MIPS3);
7db13fae 8832 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8833 register_name = "XContext";
2423f660 8834 break;
9c2149c8 8835 default:
f31b035a 8836 goto cp0_unimplemented;
9c2149c8
TS
8837 }
8838 break;
04992c8c 8839 case CP0_REGISTER_21:
9c2149c8 8840 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8841 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8842 switch (sel) {
8843 case 0:
7db13fae 8844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8845 register_name = "Framemask";
2423f660 8846 break;
9c2149c8 8847 default:
f31b035a 8848 goto cp0_unimplemented;
9c2149c8
TS
8849 }
8850 break;
04992c8c 8851 case CP0_REGISTER_22:
d9bea114 8852 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8853 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8854 break;
04992c8c 8855 case CP0_REGISTER_23:
9c2149c8 8856 switch (sel) {
4cbf4b6d 8857 case CP0_REG23__DEBUG:
895c2d04 8858 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 8859 register_name = "Debug";
2423f660 8860 break;
4cbf4b6d
AM
8861 case CP0_REG23__TRACECONTROL:
8862 /* PDtrace support */
8863 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 8864 register_name = "TraceControl";
3570d7f6 8865 goto cp0_unimplemented;
4cbf4b6d
AM
8866 case CP0_REG23__TRACECONTROL2:
8867 /* PDtrace support */
8868 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 8869 register_name = "TraceControl2";
3570d7f6 8870 goto cp0_unimplemented;
4cbf4b6d
AM
8871 case CP0_REG23__USERTRACEDATA1:
8872 /* PDtrace support */
8873 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8874 register_name = "UserTraceData1";
3570d7f6 8875 goto cp0_unimplemented;
4cbf4b6d
AM
8876 case CP0_REG23__TRACEIBPC:
8877 /* PDtrace support */
8878 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8879 register_name = "TraceIBPC";
8880 goto cp0_unimplemented;
8881 case CP0_REG23__TRACEDBPC:
8882 /* PDtrace support */
8883 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8884 register_name = "TraceDBPC";
3570d7f6 8885 goto cp0_unimplemented;
9c2149c8 8886 default:
f31b035a 8887 goto cp0_unimplemented;
9c2149c8
TS
8888 }
8889 break;
04992c8c 8890 case CP0_REGISTER_24:
9c2149c8 8891 switch (sel) {
8d7b4b6e 8892 case CP0_REG24__DEPC:
f0b3f3ae 8893 /* EJTAG support */
7db13fae 8894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8895 register_name = "DEPC";
2423f660 8896 break;
9c2149c8 8897 default:
f31b035a 8898 goto cp0_unimplemented;
9c2149c8
TS
8899 }
8900 break;
04992c8c 8901 case CP0_REGISTER_25:
9c2149c8 8902 switch (sel) {
1176b328 8903 case CP0_REG25__PERFCTL0:
7db13fae 8904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8905 register_name = "Performance0";
9c2149c8 8906 break;
1176b328 8907 case CP0_REG25__PERFCNT0:
7480515f 8908 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 8909 register_name = "Performance1";
3570d7f6 8910 goto cp0_unimplemented;
1176b328 8911 case CP0_REG25__PERFCTL1:
7480515f 8912 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 8913 register_name = "Performance2";
3570d7f6 8914 goto cp0_unimplemented;
1176b328 8915 case CP0_REG25__PERFCNT1:
7480515f 8916 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 8917 register_name = "Performance3";
3570d7f6 8918 goto cp0_unimplemented;
1176b328 8919 case CP0_REG25__PERFCTL2:
7480515f 8920 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 8921 register_name = "Performance4";
3570d7f6 8922 goto cp0_unimplemented;
1176b328 8923 case CP0_REG25__PERFCNT2:
7480515f 8924 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 8925 register_name = "Performance5";
3570d7f6 8926 goto cp0_unimplemented;
1176b328 8927 case CP0_REG25__PERFCTL3:
7480515f 8928 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 8929 register_name = "Performance6";
3570d7f6 8930 goto cp0_unimplemented;
1176b328 8931 case CP0_REG25__PERFCNT3:
7480515f 8932 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 8933 register_name = "Performance7";
3570d7f6 8934 goto cp0_unimplemented;
9c2149c8 8935 default:
f31b035a 8936 goto cp0_unimplemented;
9c2149c8
TS
8937 }
8938 break;
04992c8c 8939 case CP0_REGISTER_26:
0d74a222 8940 switch (sel) {
dbbf08b2 8941 case CP0_REG26__ERRCTL:
0d74a222 8942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8943 register_name = "ErrCtl";
0d74a222
LA
8944 break;
8945 default:
8946 goto cp0_unimplemented;
8947 }
da80682b 8948 break;
04992c8c 8949 case CP0_REGISTER_27:
9c2149c8
TS
8950 switch (sel) {
8951 /* ignored */
5a10873d 8952 case CP0_REG27__CACHERR:
d9bea114 8953 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8954 register_name = "CacheErr";
2423f660 8955 break;
9c2149c8 8956 default:
f31b035a 8957 goto cp0_unimplemented;
9c2149c8
TS
8958 }
8959 break;
04992c8c 8960 case CP0_REGISTER_28:
9c2149c8 8961 switch (sel) {
a30e2f21
AM
8962 case CP0_REG28__TAGLO:
8963 case CP0_REG28__TAGLO1:
8964 case CP0_REG28__TAGLO2:
8965 case CP0_REG28__TAGLO3:
7db13fae 8966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 8967 register_name = "TagLo";
9c2149c8 8968 break;
a30e2f21
AM
8969 case CP0_REG28__DATALO:
8970 case CP0_REG28__DATALO1:
8971 case CP0_REG28__DATALO2:
8972 case CP0_REG28__DATALO3:
7db13fae 8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8974 register_name = "DataLo";
9c2149c8
TS
8975 break;
8976 default:
f31b035a 8977 goto cp0_unimplemented;
9c2149c8
TS
8978 }
8979 break;
04992c8c 8980 case CP0_REGISTER_29:
9c2149c8 8981 switch (sel) {
af4bb6da
AM
8982 case CP0_REG29__TAGHI:
8983 case CP0_REG29__TAGHI1:
8984 case CP0_REG29__TAGHI2:
8985 case CP0_REG29__TAGHI3:
7db13fae 8986 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8987 register_name = "TagHi";
9c2149c8 8988 break;
af4bb6da
AM
8989 case CP0_REG29__DATAHI:
8990 case CP0_REG29__DATAHI1:
8991 case CP0_REG29__DATAHI2:
8992 case CP0_REG29__DATAHI3:
7db13fae 8993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8994 register_name = "DataHi";
9c2149c8
TS
8995 break;
8996 default:
f31b035a 8997 goto cp0_unimplemented;
9c2149c8
TS
8998 }
8999 break;
04992c8c 9000 case CP0_REGISTER_30:
9c2149c8 9001 switch (sel) {
4bcf121e 9002 case CP0_REG30__ERROREPC:
7db13fae 9003 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9004 register_name = "ErrorEPC";
2423f660 9005 break;
9c2149c8 9006 default:
f31b035a 9007 goto cp0_unimplemented;
9c2149c8
TS
9008 }
9009 break;
04992c8c 9010 case CP0_REGISTER_31:
9c2149c8 9011 switch (sel) {
14d92efd 9012 case CP0_REG31__DESAVE:
f0b3f3ae 9013 /* EJTAG support */
7db13fae 9014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9015 register_name = "DESAVE";
2423f660 9016 break;
14d92efd
AM
9017 case CP0_REG31__KSCRATCH1:
9018 case CP0_REG31__KSCRATCH2:
9019 case CP0_REG31__KSCRATCH3:
9020 case CP0_REG31__KSCRATCH4:
9021 case CP0_REG31__KSCRATCH5:
9022 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9023 CP0_CHECK(ctx->kscrexist & (1 << sel));
9024 tcg_gen_ld_tl(arg, cpu_env,
9025 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
294fc2ea 9026 register_name = "KScratch";
e98c0d17 9027 break;
9c2149c8 9028 default:
f31b035a 9029 goto cp0_unimplemented;
9c2149c8
TS
9030 }
9031 break;
9032 default:
f31b035a 9033 goto cp0_unimplemented;
9c2149c8 9034 }
294fc2ea 9035 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
9036 return;
9037
f31b035a 9038cp0_unimplemented:
294fc2ea
AM
9039 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9040 register_name, reg, sel);
f31b035a 9041 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
9042}
9043
d75c135e 9044static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 9045{
294fc2ea 9046 const char *register_name = "invalid";
9c2149c8 9047
1f8929d2 9048 if (sel != 0) {
d75c135e 9049 check_insn(ctx, ISA_MIPS64);
1f8929d2 9050 }
e189e748 9051
eeb3bba8 9052 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9053 gen_io_start();
bd79255d 9054 }
2e70f6ef 9055
9c2149c8 9056 switch (reg) {
04992c8c 9057 case CP0_REGISTER_00:
9c2149c8 9058 switch (sel) {
1b142da5 9059 case CP0_REG00__INDEX:
895c2d04 9060 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 9061 register_name = "Index";
9c2149c8 9062 break;
1b142da5 9063 case CP0_REG00__MVPCONTROL:
f31b035a 9064 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9065 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 9066 register_name = "MVPControl";
ead9360e 9067 break;
1b142da5 9068 case CP0_REG00__MVPCONF0:
f31b035a 9069 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9070 /* ignored */
294fc2ea 9071 register_name = "MVPConf0";
ead9360e 9072 break;
1b142da5 9073 case CP0_REG00__MVPCONF1:
f31b035a 9074 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9075 /* ignored */
294fc2ea 9076 register_name = "MVPConf1";
ead9360e 9077 break;
1b142da5 9078 case CP0_REG00__VPCONTROL:
01bc435b
YK
9079 CP0_CHECK(ctx->vp);
9080 /* ignored */
294fc2ea 9081 register_name = "VPControl";
01bc435b 9082 break;
9c2149c8 9083 default:
f31b035a 9084 goto cp0_unimplemented;
9c2149c8
TS
9085 }
9086 break;
04992c8c 9087 case CP0_REGISTER_01:
9c2149c8 9088 switch (sel) {
30deb460 9089 case CP0_REG01__RANDOM:
2423f660 9090 /* ignored */
294fc2ea 9091 register_name = "Random";
2423f660 9092 break;
30deb460 9093 case CP0_REG01__VPECONTROL:
f31b035a 9094 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9095 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9096 register_name = "VPEControl";
ead9360e 9097 break;
30deb460 9098 case CP0_REG01__VPECONF0:
f31b035a 9099 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9100 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9101 register_name = "VPEConf0";
ead9360e 9102 break;
30deb460 9103 case CP0_REG01__VPECONF1:
f31b035a 9104 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9105 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9106 register_name = "VPEConf1";
ead9360e 9107 break;
30deb460 9108 case CP0_REG01__YQMASK:
f31b035a 9109 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9110 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9111 register_name = "YQMask";
ead9360e 9112 break;
30deb460 9113 case CP0_REG01__VPESCHEDULE:
f31b035a 9114 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 9115 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9116 register_name = "VPESchedule";
ead9360e 9117 break;
30deb460 9118 case CP0_REG01__VPESCHEFBACK:
f31b035a 9119 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 9120 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9121 register_name = "VPEScheFBack";
ead9360e 9122 break;
30deb460 9123 case CP0_REG01__VPEOPT:
f31b035a 9124 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9125 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9126 register_name = "VPEOpt";
ead9360e 9127 break;
9c2149c8 9128 default:
f31b035a 9129 goto cp0_unimplemented;
9c2149c8
TS
9130 }
9131 break;
04992c8c 9132 case CP0_REGISTER_02:
9c2149c8 9133 switch (sel) {
6d27d5bd 9134 case CP0_REG02__ENTRYLO0:
7207c7f9 9135 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9136 register_name = "EntryLo0";
2423f660 9137 break;
6d27d5bd 9138 case CP0_REG02__TCSTATUS:
f31b035a 9139 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9140 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9141 register_name = "TCStatus";
ead9360e 9142 break;
6d27d5bd 9143 case CP0_REG02__TCBIND:
f31b035a 9144 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9145 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9146 register_name = "TCBind";
ead9360e 9147 break;
6d27d5bd 9148 case CP0_REG02__TCRESTART:
f31b035a 9149 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9150 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9151 register_name = "TCRestart";
ead9360e 9152 break;
6d27d5bd 9153 case CP0_REG02__TCHALT:
f31b035a 9154 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9155 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9156 register_name = "TCHalt";
ead9360e 9157 break;
6d27d5bd 9158 case CP0_REG02__TCCONTEXT:
f31b035a 9159 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9160 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9161 register_name = "TCContext";
ead9360e 9162 break;
6d27d5bd 9163 case CP0_REG02__TCSCHEDULE:
f31b035a 9164 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9165 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9166 register_name = "TCSchedule";
ead9360e 9167 break;
6d27d5bd 9168 case CP0_REG02__TCSCHEFBACK:
f31b035a 9169 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9170 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9171 register_name = "TCScheFBack";
ead9360e 9172 break;
9c2149c8 9173 default:
f31b035a 9174 goto cp0_unimplemented;
9c2149c8
TS
9175 }
9176 break;
04992c8c 9177 case CP0_REGISTER_03:
9c2149c8 9178 switch (sel) {
acd37316 9179 case CP0_REG03__ENTRYLO1:
7207c7f9 9180 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9181 register_name = "EntryLo1";
2423f660 9182 break;
acd37316 9183 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9184 CP0_CHECK(ctx->vp);
9185 /* ignored */
294fc2ea 9186 register_name = "GlobalNumber";
01bc435b 9187 break;
9c2149c8 9188 default:
f31b035a 9189 goto cp0_unimplemented;
876d4b07 9190 }
9c2149c8 9191 break;
04992c8c 9192 case CP0_REGISTER_04:
9c2149c8 9193 switch (sel) {
020fe379 9194 case CP0_REG04__CONTEXT:
895c2d04 9195 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9196 register_name = "Context";
2423f660 9197 break;
020fe379
AM
9198 case CP0_REG04__CONTEXTCONFIG:
9199 /* SmartMIPS ASE */
9200 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 9201 register_name = "ContextConfig";
f31b035a 9202 goto cp0_unimplemented;
020fe379 9203 case CP0_REG04__USERLOCAL:
f31b035a
LA
9204 CP0_CHECK(ctx->ulri);
9205 tcg_gen_st_tl(arg, cpu_env,
9206 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9207 register_name = "UserLocal";
d279279e 9208 break;
9c2149c8 9209 default:
f31b035a 9210 goto cp0_unimplemented;
876d4b07 9211 }
9c2149c8 9212 break;
04992c8c 9213 case CP0_REGISTER_05:
9c2149c8 9214 switch (sel) {
a1e76353 9215 case CP0_REG05__PAGEMASK:
895c2d04 9216 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9217 register_name = "PageMask";
2423f660 9218 break;
a1e76353 9219 case CP0_REG05__PAGEGRAIN:
d75c135e 9220 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9221 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9222 register_name = "PageGrain";
2423f660 9223 break;
a1e76353 9224 case CP0_REG05__SEGCTL0:
cec56a73
JH
9225 CP0_CHECK(ctx->sc);
9226 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9227 register_name = "SegCtl0";
cec56a73 9228 break;
a1e76353 9229 case CP0_REG05__SEGCTL1:
cec56a73
JH
9230 CP0_CHECK(ctx->sc);
9231 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9232 register_name = "SegCtl1";
cec56a73 9233 break;
a1e76353 9234 case CP0_REG05__SEGCTL2:
cec56a73
JH
9235 CP0_CHECK(ctx->sc);
9236 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9237 register_name = "SegCtl2";
cec56a73 9238 break;
a1e76353 9239 case CP0_REG05__PWBASE:
5e31fdd5
YK
9240 check_pw(ctx);
9241 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9242 register_name = "PWBase";
5e31fdd5 9243 break;
a1e76353 9244 case CP0_REG05__PWFIELD:
fa75ad14
YK
9245 check_pw(ctx);
9246 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9247 register_name = "PWField";
fa75ad14 9248 break;
a1e76353 9249 case CP0_REG05__PWSIZE:
20b28ebc
YK
9250 check_pw(ctx);
9251 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9252 register_name = "PWSize";
20b28ebc 9253 break;
9c2149c8 9254 default:
f31b035a 9255 goto cp0_unimplemented;
876d4b07 9256 }
9c2149c8 9257 break;
04992c8c 9258 case CP0_REGISTER_06:
9c2149c8 9259 switch (sel) {
9023594b 9260 case CP0_REG06__WIRED:
895c2d04 9261 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9262 register_name = "Wired";
2423f660 9263 break;
9023594b 9264 case CP0_REG06__SRSCONF0:
d75c135e 9265 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9266 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9267 register_name = "SRSConf0";
ead9360e 9268 break;
9023594b 9269 case CP0_REG06__SRSCONF1:
d75c135e 9270 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9271 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9272 register_name = "SRSConf1";
ead9360e 9273 break;
9023594b 9274 case CP0_REG06__SRSCONF2:
d75c135e 9275 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9276 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9277 register_name = "SRSConf2";
ead9360e 9278 break;
9023594b 9279 case CP0_REG06__SRSCONF3:
d75c135e 9280 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9281 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9282 register_name = "SRSConf3";
ead9360e 9283 break;
9023594b 9284 case CP0_REG06__SRSCONF4:
d75c135e 9285 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9286 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9287 register_name = "SRSConf4";
ead9360e 9288 break;
9023594b 9289 case CP0_REG06__PWCTL:
103be64c
YK
9290 check_pw(ctx);
9291 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9292 register_name = "PWCtl";
103be64c 9293 break;
9c2149c8 9294 default:
f31b035a 9295 goto cp0_unimplemented;
876d4b07 9296 }
9c2149c8 9297 break;
04992c8c 9298 case CP0_REGISTER_07:
9c2149c8 9299 switch (sel) {
143a9875 9300 case CP0_REG07__HWRENA:
d75c135e 9301 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9302 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9303 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9304 register_name = "HWREna";
2423f660 9305 break;
9c2149c8 9306 default:
f31b035a 9307 goto cp0_unimplemented;
876d4b07 9308 }
9c2149c8 9309 break;
04992c8c 9310 case CP0_REGISTER_08:
aea14095 9311 switch (sel) {
67d167d2 9312 case CP0_REG08__BADVADDR:
aea14095 9313 /* ignored */
294fc2ea 9314 register_name = "BadVAddr";
aea14095 9315 break;
67d167d2 9316 case CP0_REG08__BADINSTR:
aea14095 9317 /* ignored */
294fc2ea 9318 register_name = "BadInstr";
aea14095 9319 break;
67d167d2 9320 case CP0_REG08__BADINSTRP:
aea14095 9321 /* ignored */
294fc2ea 9322 register_name = "BadInstrP";
aea14095 9323 break;
67d167d2 9324 case CP0_REG08__BADINSTRX:
25beba9b 9325 /* ignored */
294fc2ea 9326 register_name = "BadInstrX";
25beba9b 9327 break;
aea14095 9328 default:
f31b035a 9329 goto cp0_unimplemented;
aea14095 9330 }
9c2149c8 9331 break;
04992c8c 9332 case CP0_REGISTER_09:
9c2149c8 9333 switch (sel) {
e5a98a72 9334 case CP0_REG09__COUNT:
895c2d04 9335 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9336 register_name = "Count";
2423f660 9337 break;
e5a98a72 9338 case CP0_REG09__SAARI:
5fb2dcd1
YK
9339 CP0_CHECK(ctx->saar);
9340 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9341 register_name = "SAARI";
5fb2dcd1 9342 break;
e5a98a72 9343 case CP0_REG09__SAAR:
5fb2dcd1
YK
9344 CP0_CHECK(ctx->saar);
9345 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9346 register_name = "SAAR";
5fb2dcd1 9347 break;
9c2149c8 9348 default:
f31b035a 9349 goto cp0_unimplemented;
876d4b07
TS
9350 }
9351 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9352 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9353 break;
04992c8c 9354 case CP0_REGISTER_10:
9c2149c8 9355 switch (sel) {
860ffef0 9356 case CP0_REG10__ENTRYHI:
895c2d04 9357 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9358 register_name = "EntryHi";
2423f660 9359 break;
9c2149c8 9360 default:
f31b035a 9361 goto cp0_unimplemented;
876d4b07 9362 }
9c2149c8 9363 break;
04992c8c 9364 case CP0_REGISTER_11:
9c2149c8 9365 switch (sel) {
f5f3834f 9366 case CP0_REG11__COMPARE:
895c2d04 9367 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9368 register_name = "Compare";
2423f660 9369 break;
876d4b07 9370 /* 6,7 are implementation dependent */
9c2149c8 9371 default:
f31b035a 9372 goto cp0_unimplemented;
876d4b07 9373 }
de9a95f0 9374 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9375 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9376 break;
04992c8c 9377 case CP0_REGISTER_12:
9c2149c8 9378 switch (sel) {
2b084867 9379 case CP0_REG12__STATUS:
867abc7e 9380 save_cpu_state(ctx, 1);
895c2d04 9381 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 9382 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9383 gen_save_pc(ctx->base.pc_next + 4);
9384 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9385 register_name = "Status";
2423f660 9386 break;
2b084867 9387 case CP0_REG12__INTCTL:
d75c135e 9388 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9389 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 9390 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9391 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9392 register_name = "IntCtl";
2423f660 9393 break;
2b084867 9394 case CP0_REG12__SRSCTL:
d75c135e 9395 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9396 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 9397 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9398 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9399 register_name = "SRSCtl";
2423f660 9400 break;
2b084867 9401 case CP0_REG12__SRSMAP:
d75c135e 9402 check_insn(ctx, ISA_MIPS32R2);
7db13fae 9403 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 9404 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9405 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9406 register_name = "SRSMap";
2423f660
TS
9407 break;
9408 default:
f31b035a 9409 goto cp0_unimplemented;
876d4b07 9410 }
9c2149c8 9411 break;
04992c8c 9412 case CP0_REGISTER_13:
9c2149c8 9413 switch (sel) {
e3c7559d 9414 case CP0_REG13__CAUSE:
867abc7e 9415 save_cpu_state(ctx, 1);
895c2d04 9416 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
9417 /*
9418 * Stop translation as we may have triggered an interrupt.
b28425ba 9419 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
9420 * translated code to check for pending interrupts.
9421 */
eeb3bba8
EC
9422 gen_save_pc(ctx->base.pc_next + 4);
9423 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9424 register_name = "Cause";
2423f660 9425 break;
9c2149c8 9426 default:
f31b035a 9427 goto cp0_unimplemented;
876d4b07 9428 }
9c2149c8 9429 break;
04992c8c 9430 case CP0_REGISTER_14:
9c2149c8 9431 switch (sel) {
35e4b54d 9432 case CP0_REG14__EPC:
7db13fae 9433 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9434 register_name = "EPC";
2423f660 9435 break;
9c2149c8 9436 default:
f31b035a 9437 goto cp0_unimplemented;
876d4b07 9438 }
9c2149c8 9439 break;
04992c8c 9440 case CP0_REGISTER_15:
9c2149c8 9441 switch (sel) {
4466cd49 9442 case CP0_REG15__PRID:
2423f660 9443 /* ignored */
294fc2ea 9444 register_name = "PRid";
2423f660 9445 break;
4466cd49 9446 case CP0_REG15__EBASE:
d75c135e 9447 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9448 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 9449 register_name = "EBase";
2423f660 9450 break;
9c2149c8 9451 default:
f31b035a 9452 goto cp0_unimplemented;
876d4b07 9453 }
9c2149c8 9454 break;
04992c8c 9455 case CP0_REGISTER_16:
9c2149c8 9456 switch (sel) {
433efb4c 9457 case CP0_REG16__CONFIG:
895c2d04 9458 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 9459 register_name = "Config";
2423f660 9460 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9461 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9462 break;
433efb4c 9463 case CP0_REG16__CONFIG1:
1fc7bf6e 9464 /* ignored, read only */
294fc2ea 9465 register_name = "Config1";
9c2149c8 9466 break;
433efb4c 9467 case CP0_REG16__CONFIG2:
895c2d04 9468 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 9469 register_name = "Config2";
2423f660 9470 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9471 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9472 break;
433efb4c 9473 case CP0_REG16__CONFIG3:
90f12d73 9474 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 9475 register_name = "Config3";
90f12d73 9476 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9477 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9478 break;
433efb4c 9479 case CP0_REG16__CONFIG4:
faf1f68b 9480 /* currently ignored */
294fc2ea 9481 register_name = "Config4";
faf1f68b 9482 break;
433efb4c 9483 case CP0_REG16__CONFIG5:
faf1f68b 9484 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 9485 register_name = "Config5";
faf1f68b 9486 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9487 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9488 break;
9c2149c8
TS
9489 /* 6,7 are implementation dependent */
9490 default:
294fc2ea 9491 register_name = "Invalid config selector";
f31b035a 9492 goto cp0_unimplemented;
9c2149c8 9493 }
9c2149c8 9494 break;
04992c8c 9495 case CP0_REGISTER_17:
9c2149c8 9496 switch (sel) {
706ce142 9497 case CP0_REG17__LLADDR:
895c2d04 9498 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 9499 register_name = "LLAddr";
2423f660 9500 break;
706ce142 9501 case CP0_REG17__MAAR:
f6d4dd81
YK
9502 CP0_CHECK(ctx->mrp);
9503 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 9504 register_name = "MAAR";
f6d4dd81 9505 break;
706ce142 9506 case CP0_REG17__MAARI:
f6d4dd81
YK
9507 CP0_CHECK(ctx->mrp);
9508 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 9509 register_name = "MAARI";
f6d4dd81 9510 break;
9c2149c8 9511 default:
f31b035a 9512 goto cp0_unimplemented;
9c2149c8
TS
9513 }
9514 break;
04992c8c 9515 case CP0_REGISTER_18:
9c2149c8 9516 switch (sel) {
e8dcfe82
AM
9517 case CP0_REG18__WATCHLO0:
9518 case CP0_REG18__WATCHLO1:
9519 case CP0_REG18__WATCHLO2:
9520 case CP0_REG18__WATCHLO3:
9521 case CP0_REG18__WATCHLO4:
9522 case CP0_REG18__WATCHLO5:
9523 case CP0_REG18__WATCHLO6:
9524 case CP0_REG18__WATCHLO7:
fa192d49 9525 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9526 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 9527 register_name = "WatchLo";
2423f660 9528 break;
9c2149c8 9529 default:
f31b035a 9530 goto cp0_unimplemented;
9c2149c8
TS
9531 }
9532 break;
04992c8c 9533 case CP0_REGISTER_19:
9c2149c8 9534 switch (sel) {
be274dc1
AM
9535 case CP0_REG19__WATCHHI0:
9536 case CP0_REG19__WATCHHI1:
9537 case CP0_REG19__WATCHHI2:
9538 case CP0_REG19__WATCHHI3:
9539 case CP0_REG19__WATCHHI4:
9540 case CP0_REG19__WATCHHI5:
9541 case CP0_REG19__WATCHHI6:
9542 case CP0_REG19__WATCHHI7:
fa192d49 9543 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9544 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 9545 register_name = "WatchHi";
2423f660 9546 break;
9c2149c8 9547 default:
f31b035a 9548 goto cp0_unimplemented;
9c2149c8
TS
9549 }
9550 break;
04992c8c 9551 case CP0_REGISTER_20:
9c2149c8 9552 switch (sel) {
14f92b0b 9553 case CP0_REG20__XCONTEXT:
d75c135e 9554 check_insn(ctx, ISA_MIPS3);
895c2d04 9555 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 9556 register_name = "XContext";
2423f660 9557 break;
9c2149c8 9558 default:
f31b035a 9559 goto cp0_unimplemented;
9c2149c8
TS
9560 }
9561 break;
04992c8c 9562 case CP0_REGISTER_21:
9c2149c8 9563 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9564 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9565 switch (sel) {
9566 case 0:
895c2d04 9567 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 9568 register_name = "Framemask";
2423f660 9569 break;
9c2149c8 9570 default:
f31b035a 9571 goto cp0_unimplemented;
9c2149c8
TS
9572 }
9573 break;
04992c8c 9574 case CP0_REGISTER_22:
9c2149c8 9575 /* ignored */
294fc2ea 9576 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 9577 break;
04992c8c 9578 case CP0_REGISTER_23:
9c2149c8 9579 switch (sel) {
4cbf4b6d 9580 case CP0_REG23__DEBUG:
895c2d04 9581 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9582 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9583 gen_save_pc(ctx->base.pc_next + 4);
9584 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9585 register_name = "Debug";
2423f660 9586 break;
4cbf4b6d
AM
9587 case CP0_REG23__TRACECONTROL:
9588 /* PDtrace support */
9589 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 9590 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9591 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9592 register_name = "TraceControl";
3570d7f6 9593 goto cp0_unimplemented;
4cbf4b6d
AM
9594 case CP0_REG23__TRACECONTROL2:
9595 /* PDtrace support */
9596 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 9597 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9598 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9599 register_name = "TraceControl2";
3570d7f6 9600 goto cp0_unimplemented;
4cbf4b6d
AM
9601 case CP0_REG23__USERTRACEDATA1:
9602 /* PDtrace support */
9603 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 9604 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9605 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9606 register_name = "UserTraceData1";
3570d7f6 9607 goto cp0_unimplemented;
4cbf4b6d
AM
9608 case CP0_REG23__TRACEIBPC:
9609 /* PDtrace support */
9610 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9611 /* Stop translation as we may have switched the execution mode */
9612 ctx->base.is_jmp = DISAS_STOP;
9613 register_name = "TraceIBPC";
9614 goto cp0_unimplemented;
9615 case CP0_REG23__TRACEDBPC:
9616 /* PDtrace support */
9617 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 9618 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9619 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9620 register_name = "TraceDBPC";
3570d7f6 9621 goto cp0_unimplemented;
9c2149c8 9622 default:
f31b035a 9623 goto cp0_unimplemented;
9c2149c8 9624 }
9c2149c8 9625 break;
04992c8c 9626 case CP0_REGISTER_24:
9c2149c8 9627 switch (sel) {
8d7b4b6e 9628 case CP0_REG24__DEPC:
f1aa6320 9629 /* EJTAG support */
7db13fae 9630 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9631 register_name = "DEPC";
2423f660 9632 break;
9c2149c8 9633 default:
f31b035a 9634 goto cp0_unimplemented;
9c2149c8
TS
9635 }
9636 break;
04992c8c 9637 case CP0_REGISTER_25:
9c2149c8 9638 switch (sel) {
1176b328 9639 case CP0_REG25__PERFCTL0:
895c2d04 9640 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 9641 register_name = "Performance0";
2423f660 9642 break;
1176b328 9643 case CP0_REG25__PERFCNT0:
7480515f 9644 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 9645 register_name = "Performance1";
3570d7f6 9646 goto cp0_unimplemented;
1176b328 9647 case CP0_REG25__PERFCTL1:
7480515f 9648 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 9649 register_name = "Performance2";
3570d7f6 9650 goto cp0_unimplemented;
1176b328 9651 case CP0_REG25__PERFCNT1:
7480515f 9652 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 9653 register_name = "Performance3";
3570d7f6 9654 goto cp0_unimplemented;
1176b328 9655 case CP0_REG25__PERFCTL2:
7480515f 9656 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 9657 register_name = "Performance4";
3570d7f6 9658 goto cp0_unimplemented;
1176b328 9659 case CP0_REG25__PERFCNT2:
7480515f 9660 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 9661 register_name = "Performance5";
3570d7f6 9662 goto cp0_unimplemented;
1176b328 9663 case CP0_REG25__PERFCTL3:
7480515f 9664 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 9665 register_name = "Performance6";
3570d7f6 9666 goto cp0_unimplemented;
1176b328 9667 case CP0_REG25__PERFCNT3:
7480515f 9668 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 9669 register_name = "Performance7";
3570d7f6 9670 goto cp0_unimplemented;
9c2149c8 9671 default:
f31b035a 9672 goto cp0_unimplemented;
9c2149c8 9673 }
876d4b07 9674 break;
04992c8c 9675 case CP0_REGISTER_26:
0d74a222 9676 switch (sel) {
dbbf08b2 9677 case CP0_REG26__ERRCTL:
0d74a222 9678 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9679 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9680 register_name = "ErrCtl";
0d74a222
LA
9681 break;
9682 default:
9683 goto cp0_unimplemented;
9684 }
876d4b07 9685 break;
04992c8c 9686 case CP0_REGISTER_27:
9c2149c8 9687 switch (sel) {
5a10873d 9688 case CP0_REG27__CACHERR:
2423f660 9689 /* ignored */
294fc2ea 9690 register_name = "CacheErr";
2423f660 9691 break;
9c2149c8 9692 default:
f31b035a 9693 goto cp0_unimplemented;
9c2149c8 9694 }
876d4b07 9695 break;
04992c8c 9696 case CP0_REGISTER_28:
9c2149c8 9697 switch (sel) {
a30e2f21
AM
9698 case CP0_REG28__TAGLO:
9699 case CP0_REG28__TAGLO1:
9700 case CP0_REG28__TAGLO2:
9701 case CP0_REG28__TAGLO3:
895c2d04 9702 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 9703 register_name = "TagLo";
9c2149c8 9704 break;
a30e2f21
AM
9705 case CP0_REG28__DATALO:
9706 case CP0_REG28__DATALO1:
9707 case CP0_REG28__DATALO2:
9708 case CP0_REG28__DATALO3:
895c2d04 9709 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 9710 register_name = "DataLo";
9c2149c8
TS
9711 break;
9712 default:
f31b035a 9713 goto cp0_unimplemented;
9c2149c8
TS
9714 }
9715 break;
04992c8c 9716 case CP0_REGISTER_29:
9c2149c8 9717 switch (sel) {
af4bb6da
AM
9718 case CP0_REG29__TAGHI:
9719 case CP0_REG29__TAGHI1:
9720 case CP0_REG29__TAGHI2:
9721 case CP0_REG29__TAGHI3:
895c2d04 9722 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 9723 register_name = "TagHi";
9c2149c8 9724 break;
af4bb6da
AM
9725 case CP0_REG29__DATAHI:
9726 case CP0_REG29__DATAHI1:
9727 case CP0_REG29__DATAHI2:
9728 case CP0_REG29__DATAHI3:
895c2d04 9729 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 9730 register_name = "DataHi";
9c2149c8
TS
9731 break;
9732 default:
294fc2ea 9733 register_name = "invalid sel";
f31b035a 9734 goto cp0_unimplemented;
9c2149c8 9735 }
876d4b07 9736 break;
04992c8c 9737 case CP0_REGISTER_30:
9c2149c8 9738 switch (sel) {
4bcf121e 9739 case CP0_REG30__ERROREPC:
7db13fae 9740 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9741 register_name = "ErrorEPC";
2423f660 9742 break;
9c2149c8 9743 default:
f31b035a 9744 goto cp0_unimplemented;
9c2149c8
TS
9745 }
9746 break;
04992c8c 9747 case CP0_REGISTER_31:
9c2149c8 9748 switch (sel) {
14d92efd 9749 case CP0_REG31__DESAVE:
f1aa6320 9750 /* EJTAG support */
7db13fae 9751 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9752 register_name = "DESAVE";
2423f660 9753 break;
14d92efd
AM
9754 case CP0_REG31__KSCRATCH1:
9755 case CP0_REG31__KSCRATCH2:
9756 case CP0_REG31__KSCRATCH3:
9757 case CP0_REG31__KSCRATCH4:
9758 case CP0_REG31__KSCRATCH5:
9759 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9760 CP0_CHECK(ctx->kscrexist & (1 << sel));
9761 tcg_gen_st_tl(arg, cpu_env,
71375b59 9762 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9763 register_name = "KScratch";
e98c0d17 9764 break;
9c2149c8 9765 default:
f31b035a 9766 goto cp0_unimplemented;
9c2149c8 9767 }
9c2149c8
TS
9768 break;
9769 default:
f31b035a 9770 goto cp0_unimplemented;
9c2149c8 9771 }
294fc2ea 9772 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 9773
bf20dc07 9774 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9775 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
9776 /*
9777 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9778 * translated code to check for pending interrupts.
9779 */
eeb3bba8
EC
9780 gen_save_pc(ctx->base.pc_next + 4);
9781 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9782 }
9c2149c8
TS
9783 return;
9784
f31b035a 9785cp0_unimplemented:
294fc2ea
AM
9786 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9787 register_name, reg, sel);
9c2149c8 9788}
d26bc211 9789#endif /* TARGET_MIPS64 */
9c2149c8 9790
7db13fae 9791static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9792 int u, int sel, int h)
9793{
9794 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9795 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9796
9797 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9798 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9799 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 9800 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
9801 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9802 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 9803 tcg_gen_movi_tl(t0, -1);
1f8929d2 9804 } else if (u == 0) {
ead9360e 9805 switch (rt) {
5a25ce94
EI
9806 case 1:
9807 switch (sel) {
9808 case 1:
895c2d04 9809 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
9810 break;
9811 case 2:
895c2d04 9812 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9813 break;
9814 default:
9815 goto die;
9816 break;
9817 }
9818 break;
ead9360e
TS
9819 case 2:
9820 switch (sel) {
9821 case 1:
895c2d04 9822 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9823 break;
9824 case 2:
895c2d04 9825 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9826 break;
9827 case 3:
895c2d04 9828 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9829 break;
9830 case 4:
895c2d04 9831 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9832 break;
9833 case 5:
895c2d04 9834 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9835 break;
9836 case 6:
895c2d04 9837 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9838 break;
9839 case 7:
895c2d04 9840 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9841 break;
9842 default:
d75c135e 9843 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9844 break;
9845 }
9846 break;
9847 case 10:
9848 switch (sel) {
9849 case 0:
895c2d04 9850 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9851 break;
9852 default:
d75c135e 9853 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9854 break;
9855 }
f1fadbb2 9856 break;
ead9360e
TS
9857 case 12:
9858 switch (sel) {
9859 case 0:
895c2d04 9860 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9861 break;
9862 default:
d75c135e 9863 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9864 break;
9865 }
f1fadbb2 9866 break;
5a25ce94
EI
9867 case 13:
9868 switch (sel) {
9869 case 0:
895c2d04 9870 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9871 break;
9872 default:
9873 goto die;
9874 break;
9875 }
9876 break;
9877 case 14:
9878 switch (sel) {
9879 case 0:
895c2d04 9880 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9881 break;
9882 default:
9883 goto die;
9884 break;
9885 }
9886 break;
9887 case 15:
9888 switch (sel) {
9889 case 1:
895c2d04 9890 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9891 break;
9892 default:
9893 goto die;
9894 break;
9895 }
9896 break;
9897 case 16:
9898 switch (sel) {
c2e19f3c
AM
9899 case 0:
9900 case 1:
9901 case 2:
9902 case 3:
9903 case 4:
9904 case 5:
9905 case 6:
9906 case 7:
895c2d04 9907 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9908 break;
9909 default:
9910 goto die;
9911 break;
9912 }
9913 break;
ead9360e
TS
9914 case 23:
9915 switch (sel) {
9916 case 0:
895c2d04 9917 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9918 break;
9919 default:
d75c135e 9920 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9921 break;
9922 }
9923 break;
9924 default:
d75c135e 9925 gen_mfc0(ctx, t0, rt, sel);
ead9360e 9926 }
71375b59
AM
9927 } else {
9928 switch (sel) {
9929 /* GPR registers. */
ead9360e 9930 case 0:
71375b59 9931 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 9932 break;
71375b59 9933 /* Auxiliary CPU registers */
ead9360e 9934 case 1:
71375b59
AM
9935 switch (rt) {
9936 case 0:
9937 gen_helper_1e0i(mftlo, t0, 0);
9938 break;
9939 case 1:
9940 gen_helper_1e0i(mfthi, t0, 0);
9941 break;
9942 case 2:
9943 gen_helper_1e0i(mftacx, t0, 0);
9944 break;
9945 case 4:
9946 gen_helper_1e0i(mftlo, t0, 1);
9947 break;
9948 case 5:
9949 gen_helper_1e0i(mfthi, t0, 1);
9950 break;
9951 case 6:
9952 gen_helper_1e0i(mftacx, t0, 1);
9953 break;
9954 case 8:
9955 gen_helper_1e0i(mftlo, t0, 2);
9956 break;
9957 case 9:
9958 gen_helper_1e0i(mfthi, t0, 2);
9959 break;
9960 case 10:
9961 gen_helper_1e0i(mftacx, t0, 2);
9962 break;
9963 case 12:
9964 gen_helper_1e0i(mftlo, t0, 3);
9965 break;
9966 case 13:
9967 gen_helper_1e0i(mfthi, t0, 3);
9968 break;
9969 case 14:
9970 gen_helper_1e0i(mftacx, t0, 3);
9971 break;
9972 case 16:
9973 gen_helper_mftdsp(t0, cpu_env);
9974 break;
9975 default:
9976 goto die;
9977 }
ead9360e 9978 break;
71375b59 9979 /* Floating point (COP1). */
ead9360e 9980 case 2:
71375b59
AM
9981 /* XXX: For now we support only a single FPU context. */
9982 if (h == 0) {
9983 TCGv_i32 fp0 = tcg_temp_new_i32();
9984
9985 gen_load_fpr32(ctx, fp0, rt);
9986 tcg_gen_ext_i32_tl(t0, fp0);
9987 tcg_temp_free_i32(fp0);
9988 } else {
9989 TCGv_i32 fp0 = tcg_temp_new_i32();
9990
9991 gen_load_fpr32h(ctx, fp0, rt);
9992 tcg_gen_ext_i32_tl(t0, fp0);
9993 tcg_temp_free_i32(fp0);
9994 }
ead9360e 9995 break;
71375b59
AM
9996 case 3:
9997 /* XXX: For now we support only a single FPU context. */
9998 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 9999 break;
71375b59
AM
10000 /* COP2: Not implemented. */
10001 case 4:
ead9360e 10002 case 5:
71375b59 10003 /* fall through */
ead9360e
TS
10004 default:
10005 goto die;
10006 }
ead9360e 10007 }
b44a7fb1 10008 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
10009 gen_store_gpr(t0, rd);
10010 tcg_temp_free(t0);
ead9360e
TS
10011 return;
10012
10013die:
1a3fd9c3 10014 tcg_temp_free(t0);
d12d51d5 10015 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 10016 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10017}
10018
7db13fae 10019static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
10020 int u, int sel, int h)
10021{
10022 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10023 TCGv t0 = tcg_temp_local_new();
ead9360e 10024
1a3fd9c3 10025 gen_load_gpr(t0, rt);
ead9360e 10026 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10027 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10028 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
10029 /* NOP */
10030 ;
1f8929d2
AM
10031 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10032 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
10033 /* NOP */
10034 ;
1f8929d2 10035 } else if (u == 0) {
ead9360e 10036 switch (rd) {
5a25ce94
EI
10037 case 1:
10038 switch (sel) {
10039 case 1:
895c2d04 10040 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
10041 break;
10042 case 2:
895c2d04 10043 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
10044 break;
10045 default:
10046 goto die;
10047 break;
10048 }
10049 break;
ead9360e
TS
10050 case 2:
10051 switch (sel) {
10052 case 1:
895c2d04 10053 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
10054 break;
10055 case 2:
895c2d04 10056 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
10057 break;
10058 case 3:
895c2d04 10059 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
10060 break;
10061 case 4:
895c2d04 10062 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
10063 break;
10064 case 5:
895c2d04 10065 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
10066 break;
10067 case 6:
895c2d04 10068 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
10069 break;
10070 case 7:
895c2d04 10071 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
10072 break;
10073 default:
d75c135e 10074 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10075 break;
10076 }
10077 break;
10078 case 10:
10079 switch (sel) {
10080 case 0:
895c2d04 10081 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
10082 break;
10083 default:
d75c135e 10084 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10085 break;
10086 }
0d0304f2 10087 break;
ead9360e
TS
10088 case 12:
10089 switch (sel) {
10090 case 0:
895c2d04 10091 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
10092 break;
10093 default:
d75c135e 10094 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10095 break;
10096 }
0d0304f2 10097 break;
5a25ce94
EI
10098 case 13:
10099 switch (sel) {
10100 case 0:
895c2d04 10101 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
10102 break;
10103 default:
10104 goto die;
10105 break;
10106 }
10107 break;
10108 case 15:
10109 switch (sel) {
10110 case 1:
895c2d04 10111 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10112 break;
10113 default:
10114 goto die;
10115 break;
10116 }
10117 break;
ead9360e
TS
10118 case 23:
10119 switch (sel) {
10120 case 0:
895c2d04 10121 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10122 break;
10123 default:
d75c135e 10124 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10125 break;
10126 }
10127 break;
10128 default:
d75c135e 10129 gen_mtc0(ctx, t0, rd, sel);
ead9360e 10130 }
71375b59
AM
10131 } else {
10132 switch (sel) {
10133 /* GPR registers. */
ead9360e 10134 case 0:
71375b59 10135 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 10136 break;
71375b59 10137 /* Auxiliary CPU registers */
ead9360e 10138 case 1:
71375b59
AM
10139 switch (rd) {
10140 case 0:
10141 gen_helper_0e1i(mttlo, t0, 0);
10142 break;
10143 case 1:
10144 gen_helper_0e1i(mtthi, t0, 0);
10145 break;
10146 case 2:
10147 gen_helper_0e1i(mttacx, t0, 0);
10148 break;
10149 case 4:
10150 gen_helper_0e1i(mttlo, t0, 1);
10151 break;
10152 case 5:
10153 gen_helper_0e1i(mtthi, t0, 1);
10154 break;
10155 case 6:
10156 gen_helper_0e1i(mttacx, t0, 1);
10157 break;
10158 case 8:
10159 gen_helper_0e1i(mttlo, t0, 2);
10160 break;
10161 case 9:
10162 gen_helper_0e1i(mtthi, t0, 2);
10163 break;
10164 case 10:
10165 gen_helper_0e1i(mttacx, t0, 2);
10166 break;
10167 case 12:
10168 gen_helper_0e1i(mttlo, t0, 3);
10169 break;
10170 case 13:
10171 gen_helper_0e1i(mtthi, t0, 3);
10172 break;
10173 case 14:
10174 gen_helper_0e1i(mttacx, t0, 3);
10175 break;
10176 case 16:
10177 gen_helper_mttdsp(cpu_env, t0);
10178 break;
10179 default:
10180 goto die;
10181 }
ead9360e 10182 break;
71375b59 10183 /* Floating point (COP1). */
ead9360e 10184 case 2:
71375b59
AM
10185 /* XXX: For now we support only a single FPU context. */
10186 if (h == 0) {
10187 TCGv_i32 fp0 = tcg_temp_new_i32();
10188
10189 tcg_gen_trunc_tl_i32(fp0, t0);
10190 gen_store_fpr32(ctx, fp0, rd);
10191 tcg_temp_free_i32(fp0);
10192 } else {
10193 TCGv_i32 fp0 = tcg_temp_new_i32();
10194
10195 tcg_gen_trunc_tl_i32(fp0, t0);
10196 gen_store_fpr32h(ctx, fp0, rd);
10197 tcg_temp_free_i32(fp0);
10198 }
ead9360e 10199 break;
71375b59
AM
10200 case 3:
10201 /* XXX: For now we support only a single FPU context. */
10202 {
10203 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10204
10205 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10206 tcg_temp_free_i32(fs_tmp);
10207 }
10208 /* Stop translation as we may have changed hflags */
10209 ctx->base.is_jmp = DISAS_STOP;
ead9360e 10210 break;
71375b59
AM
10211 /* COP2: Not implemented. */
10212 case 4:
ead9360e 10213 case 5:
71375b59 10214 /* fall through */
ead9360e
TS
10215 default:
10216 goto die;
10217 }
ead9360e 10218 }
b44a7fb1 10219 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10220 tcg_temp_free(t0);
ead9360e
TS
10221 return;
10222
10223die:
1a3fd9c3 10224 tcg_temp_free(t0);
d12d51d5 10225 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10226 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10227}
10228
235785e8
AM
10229static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10230 int rt, int rd)
6af0bf9c 10231{
287c4b84 10232 const char *opn = "ldst";
6af0bf9c 10233
2e15497c 10234 check_cp0_enabled(ctx);
6af0bf9c
FB
10235 switch (opc) {
10236 case OPC_MFC0:
10237 if (rt == 0) {
ead9360e 10238 /* Treat as NOP. */
6af0bf9c
FB
10239 return;
10240 }
d75c135e 10241 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10242 opn = "mfc0";
10243 break;
10244 case OPC_MTC0:
1a3fd9c3 10245 {
1fc7bf6e 10246 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10247
10248 gen_load_gpr(t0, rt);
d75c135e 10249 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10250 tcg_temp_free(t0);
10251 }
6af0bf9c
FB
10252 opn = "mtc0";
10253 break;
d26bc211 10254#if defined(TARGET_MIPS64)
9c2149c8 10255 case OPC_DMFC0:
d75c135e 10256 check_insn(ctx, ISA_MIPS3);
9c2149c8 10257 if (rt == 0) {
ead9360e 10258 /* Treat as NOP. */
9c2149c8
TS
10259 return;
10260 }
d75c135e 10261 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10262 opn = "dmfc0";
10263 break;
10264 case OPC_DMTC0:
d75c135e 10265 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10266 {
1fc7bf6e 10267 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10268
10269 gen_load_gpr(t0, rt);
d75c135e 10270 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10271 tcg_temp_free(t0);
10272 }
9c2149c8
TS
10273 opn = "dmtc0";
10274 break;
534ce69f 10275#endif
5204ea79
LA
10276 case OPC_MFHC0:
10277 check_mvh(ctx);
10278 if (rt == 0) {
10279 /* Treat as NOP. */
10280 return;
10281 }
10282 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10283 opn = "mfhc0";
10284 break;
10285 case OPC_MTHC0:
10286 check_mvh(ctx);
10287 {
10288 TCGv t0 = tcg_temp_new();
10289 gen_load_gpr(t0, rt);
10290 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10291 tcg_temp_free(t0);
10292 }
10293 opn = "mthc0";
10294 break;
ead9360e 10295 case OPC_MFTR:
9affc1c5 10296 check_cp0_enabled(ctx);
ead9360e
TS
10297 if (rd == 0) {
10298 /* Treat as NOP. */
10299 return;
10300 }
6c5c1e20 10301 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10302 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10303 opn = "mftr";
10304 break;
10305 case OPC_MTTR:
9affc1c5 10306 check_cp0_enabled(ctx);
6c5c1e20 10307 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10308 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10309 opn = "mttr";
10310 break;
6af0bf9c 10311 case OPC_TLBWI:
6af0bf9c 10312 opn = "tlbwi";
1f8929d2 10313 if (!env->tlb->helper_tlbwi) {
29929e34 10314 goto die;
1f8929d2 10315 }
895c2d04 10316 gen_helper_tlbwi(cpu_env);
6af0bf9c 10317 break;
9456c2fb
LA
10318 case OPC_TLBINV:
10319 opn = "tlbinv";
10320 if (ctx->ie >= 2) {
10321 if (!env->tlb->helper_tlbinv) {
10322 goto die;
10323 }
10324 gen_helper_tlbinv(cpu_env);
10325 } /* treat as nop if TLBINV not supported */
10326 break;
10327 case OPC_TLBINVF:
10328 opn = "tlbinvf";
10329 if (ctx->ie >= 2) {
10330 if (!env->tlb->helper_tlbinvf) {
10331 goto die;
10332 }
10333 gen_helper_tlbinvf(cpu_env);
10334 } /* treat as nop if TLBINV not supported */
10335 break;
6af0bf9c 10336 case OPC_TLBWR:
6af0bf9c 10337 opn = "tlbwr";
1f8929d2 10338 if (!env->tlb->helper_tlbwr) {
29929e34 10339 goto die;
1f8929d2 10340 }
895c2d04 10341 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10342 break;
10343 case OPC_TLBP:
6af0bf9c 10344 opn = "tlbp";
1f8929d2 10345 if (!env->tlb->helper_tlbp) {
29929e34 10346 goto die;
1f8929d2 10347 }
895c2d04 10348 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10349 break;
10350 case OPC_TLBR:
6af0bf9c 10351 opn = "tlbr";
1f8929d2 10352 if (!env->tlb->helper_tlbr) {
29929e34 10353 goto die;
1f8929d2 10354 }
895c2d04 10355 gen_helper_tlbr(cpu_env);
6af0bf9c 10356 break;
ce9782f4 10357 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
10358 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10359 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10360 goto die;
ce9782f4
LA
10361 } else {
10362 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10363 if (ctx->opcode & (1 << bit_shift)) {
10364 /* OPC_ERETNC */
10365 opn = "eretnc";
10366 check_insn(ctx, ISA_MIPS32R5);
10367 gen_helper_eretnc(cpu_env);
10368 } else {
10369 /* OPC_ERET */
10370 opn = "eret";
10371 check_insn(ctx, ISA_MIPS2);
10372 gen_helper_eret(cpu_env);
10373 }
eeb3bba8 10374 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 10375 }
6af0bf9c
FB
10376 break;
10377 case OPC_DERET:
10378 opn = "deret";
d75c135e 10379 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
10380 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10381 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10382 goto die;
10383 }
6af0bf9c 10384 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 10385 MIPS_INVAL(opn);
9c708c7f 10386 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 10387 } else {
895c2d04 10388 gen_helper_deret(cpu_env);
eeb3bba8 10389 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
10390 }
10391 break;
4ad40f36
FB
10392 case OPC_WAIT:
10393 opn = "wait";
d75c135e 10394 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
10395 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10396 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10397 goto die;
10398 }
4ad40f36 10399 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 10400 ctx->base.pc_next += 4;
4ad40f36 10401 save_cpu_state(ctx, 1);
eeb3bba8 10402 ctx->base.pc_next -= 4;
895c2d04 10403 gen_helper_wait(cpu_env);
eeb3bba8 10404 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 10405 break;
6af0bf9c 10406 default:
29929e34 10407 die:
923617a3 10408 MIPS_INVAL(opn);
9c708c7f 10409 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
10410 return;
10411 }
2abf314d 10412 (void)opn; /* avoid a compiler warning */
6af0bf9c 10413}
f1aa6320 10414#endif /* !CONFIG_USER_ONLY */
6af0bf9c 10415
6ea83fed 10416/* CP1 Branches (before delay slot) */
d75c135e
AJ
10417static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10418 int32_t cc, int32_t offset)
6ea83fed
FB
10419{
10420 target_ulong btarget;
a7812ae4 10421 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 10422
339cd2a8 10423 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 10424 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
10425 goto out;
10426 }
10427
1f8929d2 10428 if (cc != 0) {
d75c135e 10429 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
1f8929d2 10430 }
e189e748 10431
eeb3bba8 10432 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 10433
7a387fff
TS
10434 switch (op) {
10435 case OPC_BC1F:
d94536f4
AJ
10436 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10437 tcg_gen_not_i32(t0, t0);
10438 tcg_gen_andi_i32(t0, t0, 1);
10439 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10440 goto not_likely;
7a387fff 10441 case OPC_BC1FL:
d94536f4
AJ
10442 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10443 tcg_gen_not_i32(t0, t0);
10444 tcg_gen_andi_i32(t0, t0, 1);
10445 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10446 goto likely;
7a387fff 10447 case OPC_BC1T:
d94536f4
AJ
10448 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10449 tcg_gen_andi_i32(t0, t0, 1);
10450 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10451 goto not_likely;
7a387fff 10452 case OPC_BC1TL:
d94536f4
AJ
10453 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10454 tcg_gen_andi_i32(t0, t0, 1);
10455 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10456 likely:
10457 ctx->hflags |= MIPS_HFLAG_BL;
10458 break;
5a5012ec 10459 case OPC_BC1FANY2:
a16336e4 10460 {
d94536f4
AJ
10461 TCGv_i32 t1 = tcg_temp_new_i32();
10462 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10463 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10464 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10465 tcg_temp_free_i32(t1);
d94536f4
AJ
10466 tcg_gen_andi_i32(t0, t0, 1);
10467 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10468 }
5a5012ec
TS
10469 goto not_likely;
10470 case OPC_BC1TANY2:
a16336e4 10471 {
d94536f4
AJ
10472 TCGv_i32 t1 = tcg_temp_new_i32();
10473 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10474 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
10475 tcg_gen_or_i32(t0, t0, t1);
10476 tcg_temp_free_i32(t1);
10477 tcg_gen_andi_i32(t0, t0, 1);
10478 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10479 }
5a5012ec
TS
10480 goto not_likely;
10481 case OPC_BC1FANY4:
a16336e4 10482 {
d94536f4
AJ
10483 TCGv_i32 t1 = tcg_temp_new_i32();
10484 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10485 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10486 tcg_gen_and_i32(t0, t0, t1);
71375b59 10487 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 10488 tcg_gen_and_i32(t0, t0, t1);
71375b59 10489 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 10490 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10491 tcg_temp_free_i32(t1);
d94536f4
AJ
10492 tcg_gen_andi_i32(t0, t0, 1);
10493 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10494 }
5a5012ec
TS
10495 goto not_likely;
10496 case OPC_BC1TANY4:
a16336e4 10497 {
d94536f4
AJ
10498 TCGv_i32 t1 = tcg_temp_new_i32();
10499 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10500 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 10501 tcg_gen_or_i32(t0, t0, t1);
71375b59 10502 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 10503 tcg_gen_or_i32(t0, t0, t1);
71375b59 10504 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
10505 tcg_gen_or_i32(t0, t0, t1);
10506 tcg_temp_free_i32(t1);
10507 tcg_gen_andi_i32(t0, t0, 1);
10508 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10509 }
5a5012ec
TS
10510 not_likely:
10511 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10512 break;
10513 default:
9d68ac14 10514 MIPS_INVAL("cp1 cond branch");
9c708c7f 10515 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10516 goto out;
6ea83fed 10517 }
6ea83fed 10518 ctx->btarget = btarget;
b231c103 10519 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10520 out:
a7812ae4 10521 tcg_temp_free_i32(t0);
6ea83fed
FB
10522}
10523
31837be3
YK
10524/* R6 CP1 Branches */
10525static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10526 int32_t ft, int32_t offset,
10527 int delayslot_size)
31837be3
YK
10528{
10529 target_ulong btarget;
31837be3
YK
10530 TCGv_i64 t0 = tcg_temp_new_i64();
10531
10532 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10533#ifdef MIPS_DEBUG_DISAS
339cd2a8 10534 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10535 "\n", ctx->base.pc_next);
31837be3 10536#endif
9c708c7f 10537 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10538 goto out;
10539 }
10540
10541 gen_load_fpr64(ctx, t0, ft);
10542 tcg_gen_andi_i64(t0, t0, 1);
10543
eeb3bba8 10544 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10545
10546 switch (op) {
10547 case OPC_BC1EQZ:
10548 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10549 ctx->hflags |= MIPS_HFLAG_BC;
10550 break;
10551 case OPC_BC1NEZ:
10552 /* t0 already set */
31837be3
YK
10553 ctx->hflags |= MIPS_HFLAG_BC;
10554 break;
10555 default:
9d68ac14 10556 MIPS_INVAL("cp1 cond branch");
9c708c7f 10557 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10558 goto out;
10559 }
10560
10561 tcg_gen_trunc_i64_tl(bcond, t0);
10562
31837be3 10563 ctx->btarget = btarget;
65935f07
YK
10564
10565 switch (delayslot_size) {
10566 case 2:
10567 ctx->hflags |= MIPS_HFLAG_BDS16;
10568 break;
10569 case 4:
10570 ctx->hflags |= MIPS_HFLAG_BDS32;
10571 break;
10572 }
31837be3
YK
10573
10574out:
10575 tcg_temp_free_i64(t0);
10576}
10577
6af0bf9c 10578/* Coprocessor 1 (FPU) */
5a5012ec 10579
5a5012ec
TS
10580#define FOP(func, fmt) (((fmt) << 21) | (func))
10581
bf4120ad
NF
10582enum fopcode {
10583 OPC_ADD_S = FOP(0, FMT_S),
10584 OPC_SUB_S = FOP(1, FMT_S),
10585 OPC_MUL_S = FOP(2, FMT_S),
10586 OPC_DIV_S = FOP(3, FMT_S),
10587 OPC_SQRT_S = FOP(4, FMT_S),
10588 OPC_ABS_S = FOP(5, FMT_S),
10589 OPC_MOV_S = FOP(6, FMT_S),
10590 OPC_NEG_S = FOP(7, FMT_S),
10591 OPC_ROUND_L_S = FOP(8, FMT_S),
10592 OPC_TRUNC_L_S = FOP(9, FMT_S),
10593 OPC_CEIL_L_S = FOP(10, FMT_S),
10594 OPC_FLOOR_L_S = FOP(11, FMT_S),
10595 OPC_ROUND_W_S = FOP(12, FMT_S),
10596 OPC_TRUNC_W_S = FOP(13, FMT_S),
10597 OPC_CEIL_W_S = FOP(14, FMT_S),
10598 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10599 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10600 OPC_MOVCF_S = FOP(17, FMT_S),
10601 OPC_MOVZ_S = FOP(18, FMT_S),
10602 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10603 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10604 OPC_RECIP_S = FOP(21, FMT_S),
10605 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10606 OPC_SELNEZ_S = FOP(23, FMT_S),
10607 OPC_MADDF_S = FOP(24, FMT_S),
10608 OPC_MSUBF_S = FOP(25, FMT_S),
10609 OPC_RINT_S = FOP(26, FMT_S),
10610 OPC_CLASS_S = FOP(27, FMT_S),
10611 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10612 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10613 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10614 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10615 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10616 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10617 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10618 OPC_RSQRT2_S = FOP(31, FMT_S),
10619 OPC_CVT_D_S = FOP(33, FMT_S),
10620 OPC_CVT_W_S = FOP(36, FMT_S),
10621 OPC_CVT_L_S = FOP(37, FMT_S),
10622 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
10623 OPC_CMP_F_S = FOP(48, FMT_S),
10624 OPC_CMP_UN_S = FOP(49, FMT_S),
10625 OPC_CMP_EQ_S = FOP(50, FMT_S),
10626 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10627 OPC_CMP_OLT_S = FOP(52, FMT_S),
10628 OPC_CMP_ULT_S = FOP(53, FMT_S),
10629 OPC_CMP_OLE_S = FOP(54, FMT_S),
10630 OPC_CMP_ULE_S = FOP(55, FMT_S),
10631 OPC_CMP_SF_S = FOP(56, FMT_S),
10632 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10633 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10634 OPC_CMP_NGL_S = FOP(59, FMT_S),
10635 OPC_CMP_LT_S = FOP(60, FMT_S),
10636 OPC_CMP_NGE_S = FOP(61, FMT_S),
10637 OPC_CMP_LE_S = FOP(62, FMT_S),
10638 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
10639
10640 OPC_ADD_D = FOP(0, FMT_D),
10641 OPC_SUB_D = FOP(1, FMT_D),
10642 OPC_MUL_D = FOP(2, FMT_D),
10643 OPC_DIV_D = FOP(3, FMT_D),
10644 OPC_SQRT_D = FOP(4, FMT_D),
10645 OPC_ABS_D = FOP(5, FMT_D),
10646 OPC_MOV_D = FOP(6, FMT_D),
10647 OPC_NEG_D = FOP(7, FMT_D),
10648 OPC_ROUND_L_D = FOP(8, FMT_D),
10649 OPC_TRUNC_L_D = FOP(9, FMT_D),
10650 OPC_CEIL_L_D = FOP(10, FMT_D),
10651 OPC_FLOOR_L_D = FOP(11, FMT_D),
10652 OPC_ROUND_W_D = FOP(12, FMT_D),
10653 OPC_TRUNC_W_D = FOP(13, FMT_D),
10654 OPC_CEIL_W_D = FOP(14, FMT_D),
10655 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10656 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10657 OPC_MOVCF_D = FOP(17, FMT_D),
10658 OPC_MOVZ_D = FOP(18, FMT_D),
10659 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10660 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10661 OPC_RECIP_D = FOP(21, FMT_D),
10662 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10663 OPC_SELNEZ_D = FOP(23, FMT_D),
10664 OPC_MADDF_D = FOP(24, FMT_D),
10665 OPC_MSUBF_D = FOP(25, FMT_D),
10666 OPC_RINT_D = FOP(26, FMT_D),
10667 OPC_CLASS_D = FOP(27, FMT_D),
10668 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10669 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10670 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10671 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10672 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10673 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10674 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10675 OPC_RSQRT2_D = FOP(31, FMT_D),
10676 OPC_CVT_S_D = FOP(32, FMT_D),
10677 OPC_CVT_W_D = FOP(36, FMT_D),
10678 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
10679 OPC_CMP_F_D = FOP(48, FMT_D),
10680 OPC_CMP_UN_D = FOP(49, FMT_D),
10681 OPC_CMP_EQ_D = FOP(50, FMT_D),
10682 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10683 OPC_CMP_OLT_D = FOP(52, FMT_D),
10684 OPC_CMP_ULT_D = FOP(53, FMT_D),
10685 OPC_CMP_OLE_D = FOP(54, FMT_D),
10686 OPC_CMP_ULE_D = FOP(55, FMT_D),
10687 OPC_CMP_SF_D = FOP(56, FMT_D),
10688 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10689 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10690 OPC_CMP_NGL_D = FOP(59, FMT_D),
10691 OPC_CMP_LT_D = FOP(60, FMT_D),
10692 OPC_CMP_NGE_D = FOP(61, FMT_D),
10693 OPC_CMP_LE_D = FOP(62, FMT_D),
10694 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
10695
10696 OPC_CVT_S_W = FOP(32, FMT_W),
10697 OPC_CVT_D_W = FOP(33, FMT_W),
10698 OPC_CVT_S_L = FOP(32, FMT_L),
10699 OPC_CVT_D_L = FOP(33, FMT_L),
10700 OPC_CVT_PS_PW = FOP(38, FMT_W),
10701
10702 OPC_ADD_PS = FOP(0, FMT_PS),
10703 OPC_SUB_PS = FOP(1, FMT_PS),
10704 OPC_MUL_PS = FOP(2, FMT_PS),
10705 OPC_DIV_PS = FOP(3, FMT_PS),
10706 OPC_ABS_PS = FOP(5, FMT_PS),
10707 OPC_MOV_PS = FOP(6, FMT_PS),
10708 OPC_NEG_PS = FOP(7, FMT_PS),
10709 OPC_MOVCF_PS = FOP(17, FMT_PS),
10710 OPC_MOVZ_PS = FOP(18, FMT_PS),
10711 OPC_MOVN_PS = FOP(19, FMT_PS),
10712 OPC_ADDR_PS = FOP(24, FMT_PS),
10713 OPC_MULR_PS = FOP(26, FMT_PS),
10714 OPC_RECIP2_PS = FOP(28, FMT_PS),
10715 OPC_RECIP1_PS = FOP(29, FMT_PS),
10716 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10717 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10718
10719 OPC_CVT_S_PU = FOP(32, FMT_PS),
10720 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10721 OPC_CVT_S_PL = FOP(40, FMT_PS),
10722 OPC_PLL_PS = FOP(44, FMT_PS),
10723 OPC_PLU_PS = FOP(45, FMT_PS),
10724 OPC_PUL_PS = FOP(46, FMT_PS),
10725 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
10726 OPC_CMP_F_PS = FOP(48, FMT_PS),
10727 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10728 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10729 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10730 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10731 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10732 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10733 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10734 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10735 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10736 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10737 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10738 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10739 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10740 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10741 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
10742};
10743
3f493883
YK
10744enum r6_f_cmp_op {
10745 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10746 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10747 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10748 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10749 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10750 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10751 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10752 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10753 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10754 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10755 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10756 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10757 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10758 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10759 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10760 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10761 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10762 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10763 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10764 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10765 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10766 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10767
10768 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10769 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10770 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10771 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10772 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10773 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10774 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10775 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10776 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10777 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10778 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10779 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10780 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10781 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10782 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10783 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10784 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10785 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10786 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10787 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10788 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10789 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10790};
235785e8
AM
10791
10792static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10793{
72c3a3ee 10794 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10795
10796 switch (opc) {
10797 case OPC_MFC1:
b6d96bed 10798 {
a7812ae4 10799 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10800
7c979afd 10801 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10802 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10803 tcg_temp_free_i32(fp0);
6958549d 10804 }
6c5c1e20 10805 gen_store_gpr(t0, rt);
6ea83fed
FB
10806 break;
10807 case OPC_MTC1:
6c5c1e20 10808 gen_load_gpr(t0, rt);
b6d96bed 10809 {
a7812ae4 10810 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10811
10812 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10813 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10814 tcg_temp_free_i32(fp0);
6958549d 10815 }
6ea83fed
FB
10816 break;
10817 case OPC_CFC1:
895c2d04 10818 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10819 gen_store_gpr(t0, rt);
6ea83fed
FB
10820 break;
10821 case OPC_CTC1:
6c5c1e20 10822 gen_load_gpr(t0, rt);
9c708c7f 10823 save_cpu_state(ctx, 0);
736d120a
PJ
10824 {
10825 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10826
10827 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10828 tcg_temp_free_i32(fs_tmp);
10829 }
4cf8a45f 10830 /* Stop translation as we may have changed hflags */
eeb3bba8 10831 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10832 break;
72c3a3ee 10833#if defined(TARGET_MIPS64)
9c2149c8 10834 case OPC_DMFC1:
72c3a3ee 10835 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10836 gen_store_gpr(t0, rt);
5a5012ec 10837 break;
9c2149c8 10838 case OPC_DMTC1:
6c5c1e20 10839 gen_load_gpr(t0, rt);
72c3a3ee 10840 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10841 break;
72c3a3ee 10842#endif
5a5012ec 10843 case OPC_MFHC1:
b6d96bed 10844 {
a7812ae4 10845 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10846
7f6613ce 10847 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10848 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10849 tcg_temp_free_i32(fp0);
6958549d 10850 }
6c5c1e20 10851 gen_store_gpr(t0, rt);
5a5012ec
TS
10852 break;
10853 case OPC_MTHC1:
6c5c1e20 10854 gen_load_gpr(t0, rt);
b6d96bed 10855 {
a7812ae4 10856 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10857
10858 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10859 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10860 tcg_temp_free_i32(fp0);
6958549d 10861 }
5a5012ec 10862 break;
6ea83fed 10863 default:
9d68ac14 10864 MIPS_INVAL("cp1 move");
9c708c7f 10865 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10866 goto out;
6ea83fed 10867 }
6c5c1e20
TS
10868
10869 out:
10870 tcg_temp_free(t0);
6ea83fed
FB
10871}
10872
235785e8 10873static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 10874{
42a268c2 10875 TCGLabel *l1;
e214b9bb 10876 TCGCond cond;
af58f9ca
AJ
10877 TCGv_i32 t0;
10878
10879 if (rd == 0) {
10880 /* Treat as NOP. */
10881 return;
10882 }
6ea83fed 10883
1f8929d2 10884 if (tf) {
e214b9bb 10885 cond = TCG_COND_EQ;
1f8929d2 10886 } else {
27848470 10887 cond = TCG_COND_NE;
1f8929d2 10888 }
27848470 10889
af58f9ca
AJ
10890 l1 = gen_new_label();
10891 t0 = tcg_temp_new_i32();
fa31af0e 10892 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10893 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10894 tcg_temp_free_i32(t0);
af58f9ca
AJ
10895 if (rs == 0) {
10896 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10897 } else {
10898 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10899 }
e214b9bb 10900 gen_set_label(l1);
5a5012ec
TS
10901}
10902
7c979afd
LA
10903static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10904 int tf)
a16336e4 10905{
a16336e4 10906 int cond;
cbc37b28 10907 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10908 TCGLabel *l1 = gen_new_label();
a16336e4 10909
1f8929d2 10910 if (tf) {
a16336e4 10911 cond = TCG_COND_EQ;
1f8929d2 10912 } else {
a16336e4 10913 cond = TCG_COND_NE;
1f8929d2 10914 }
a16336e4 10915
fa31af0e 10916 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10917 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10918 gen_load_fpr32(ctx, t0, fs);
10919 gen_store_fpr32(ctx, t0, fd);
a16336e4 10920 gen_set_label(l1);
cbc37b28 10921 tcg_temp_free_i32(t0);
5a5012ec 10922}
a16336e4 10923
235785e8
AM
10924static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10925 int tf)
a16336e4 10926{
a16336e4 10927 int cond;
cbc37b28
AJ
10928 TCGv_i32 t0 = tcg_temp_new_i32();
10929 TCGv_i64 fp0;
42a268c2 10930 TCGLabel *l1 = gen_new_label();
a16336e4 10931
1f8929d2 10932 if (tf) {
a16336e4 10933 cond = TCG_COND_EQ;
1f8929d2 10934 } else {
a16336e4 10935 cond = TCG_COND_NE;
1f8929d2 10936 }
a16336e4 10937
fa31af0e 10938 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10939 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10940 tcg_temp_free_i32(t0);
11f94258 10941 fp0 = tcg_temp_new_i64();
9bf3eb2c 10942 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10943 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10944 tcg_temp_free_i64(fp0);
cbc37b28 10945 gen_set_label(l1);
a16336e4
TS
10946}
10947
7f6613ce
PJ
10948static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10949 int cc, int tf)
a16336e4
TS
10950{
10951 int cond;
cbc37b28 10952 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10953 TCGLabel *l1 = gen_new_label();
10954 TCGLabel *l2 = gen_new_label();
a16336e4 10955
1f8929d2 10956 if (tf) {
a16336e4 10957 cond = TCG_COND_EQ;
1f8929d2 10958 } else {
a16336e4 10959 cond = TCG_COND_NE;
1f8929d2 10960 }
a16336e4 10961
fa31af0e 10962 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10963 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10964 gen_load_fpr32(ctx, t0, fs);
10965 gen_store_fpr32(ctx, t0, fd);
a16336e4 10966 gen_set_label(l1);
9bf3eb2c 10967
71375b59 10968 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 10969 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10970 gen_load_fpr32h(ctx, t0, fs);
10971 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10972 tcg_temp_free_i32(t0);
a16336e4 10973 gen_set_label(l2);
a16336e4
TS
10974}
10975
e7f16abb
LA
10976static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10977 int fs)
10978{
10979 TCGv_i32 t1 = tcg_const_i32(0);
10980 TCGv_i32 fp0 = tcg_temp_new_i32();
10981 TCGv_i32 fp1 = tcg_temp_new_i32();
10982 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10983 gen_load_fpr32(ctx, fp0, fd);
10984 gen_load_fpr32(ctx, fp1, ft);
10985 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10986
10987 switch (op1) {
10988 case OPC_SEL_S:
10989 tcg_gen_andi_i32(fp0, fp0, 1);
10990 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10991 break;
10992 case OPC_SELEQZ_S:
10993 tcg_gen_andi_i32(fp1, fp1, 1);
10994 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10995 break;
10996 case OPC_SELNEZ_S:
10997 tcg_gen_andi_i32(fp1, fp1, 1);
10998 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10999 break;
11000 default:
11001 MIPS_INVAL("gen_sel_s");
9c708c7f 11002 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11003 break;
11004 }
11005
7c979afd 11006 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11007 tcg_temp_free_i32(fp2);
11008 tcg_temp_free_i32(fp1);
11009 tcg_temp_free_i32(fp0);
11010 tcg_temp_free_i32(t1);
11011}
11012
11013static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11014 int fs)
11015{
11016 TCGv_i64 t1 = tcg_const_i64(0);
11017 TCGv_i64 fp0 = tcg_temp_new_i64();
11018 TCGv_i64 fp1 = tcg_temp_new_i64();
11019 TCGv_i64 fp2 = tcg_temp_new_i64();
11020 gen_load_fpr64(ctx, fp0, fd);
11021 gen_load_fpr64(ctx, fp1, ft);
11022 gen_load_fpr64(ctx, fp2, fs);
11023
11024 switch (op1) {
11025 case OPC_SEL_D:
11026 tcg_gen_andi_i64(fp0, fp0, 1);
11027 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11028 break;
11029 case OPC_SELEQZ_D:
11030 tcg_gen_andi_i64(fp1, fp1, 1);
11031 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11032 break;
11033 case OPC_SELNEZ_D:
11034 tcg_gen_andi_i64(fp1, fp1, 1);
11035 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11036 break;
11037 default:
11038 MIPS_INVAL("gen_sel_d");
9c708c7f 11039 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11040 break;
11041 }
11042
11043 gen_store_fpr64(ctx, fp0, fd);
11044 tcg_temp_free_i64(fp2);
11045 tcg_temp_free_i64(fp1);
11046 tcg_temp_free_i64(fp0);
11047 tcg_temp_free_i64(t1);
11048}
6ea83fed 11049
235785e8
AM
11050static void gen_farith(DisasContext *ctx, enum fopcode op1,
11051 int ft, int fs, int fd, int cc)
6ea83fed 11052{
7a387fff 11053 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
11054 switch (op1) {
11055 case OPC_ADD_S:
b6d96bed 11056 {
a7812ae4
PB
11057 TCGv_i32 fp0 = tcg_temp_new_i32();
11058 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11059
7c979afd
LA
11060 gen_load_fpr32(ctx, fp0, fs);
11061 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11062 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11063 tcg_temp_free_i32(fp1);
7c979afd 11064 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11065 tcg_temp_free_i32(fp0);
b6d96bed 11066 }
5a5012ec 11067 break;
bf4120ad 11068 case OPC_SUB_S:
b6d96bed 11069 {
a7812ae4
PB
11070 TCGv_i32 fp0 = tcg_temp_new_i32();
11071 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11072
7c979afd
LA
11073 gen_load_fpr32(ctx, fp0, fs);
11074 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11075 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11076 tcg_temp_free_i32(fp1);
7c979afd 11077 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11078 tcg_temp_free_i32(fp0);
b6d96bed 11079 }
5a5012ec 11080 break;
bf4120ad 11081 case OPC_MUL_S:
b6d96bed 11082 {
a7812ae4
PB
11083 TCGv_i32 fp0 = tcg_temp_new_i32();
11084 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11085
7c979afd
LA
11086 gen_load_fpr32(ctx, fp0, fs);
11087 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11088 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11089 tcg_temp_free_i32(fp1);
7c979afd 11090 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11091 tcg_temp_free_i32(fp0);
b6d96bed 11092 }
5a5012ec 11093 break;
bf4120ad 11094 case OPC_DIV_S:
b6d96bed 11095 {
a7812ae4
PB
11096 TCGv_i32 fp0 = tcg_temp_new_i32();
11097 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11098
7c979afd
LA
11099 gen_load_fpr32(ctx, fp0, fs);
11100 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11101 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11102 tcg_temp_free_i32(fp1);
7c979afd 11103 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11104 tcg_temp_free_i32(fp0);
b6d96bed 11105 }
5a5012ec 11106 break;
bf4120ad 11107 case OPC_SQRT_S:
b6d96bed 11108 {
a7812ae4 11109 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11110
7c979afd 11111 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11112 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 11113 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11114 tcg_temp_free_i32(fp0);
b6d96bed 11115 }
5a5012ec 11116 break;
bf4120ad 11117 case OPC_ABS_S:
b6d96bed 11118 {
a7812ae4 11119 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11120
7c979afd 11121 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11122 if (ctx->abs2008) {
11123 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11124 } else {
11125 gen_helper_float_abs_s(fp0, fp0);
11126 }
7c979afd 11127 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11128 tcg_temp_free_i32(fp0);
b6d96bed 11129 }
5a5012ec 11130 break;
bf4120ad 11131 case OPC_MOV_S:
b6d96bed 11132 {
a7812ae4 11133 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11134
7c979afd
LA
11135 gen_load_fpr32(ctx, fp0, fs);
11136 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11137 tcg_temp_free_i32(fp0);
b6d96bed 11138 }
5a5012ec 11139 break;
bf4120ad 11140 case OPC_NEG_S:
b6d96bed 11141 {
a7812ae4 11142 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11143
7c979afd 11144 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11145 if (ctx->abs2008) {
11146 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11147 } else {
11148 gen_helper_float_chs_s(fp0, fp0);
11149 }
7c979afd 11150 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11151 tcg_temp_free_i32(fp0);
b6d96bed 11152 }
5a5012ec 11153 break;
bf4120ad 11154 case OPC_ROUND_L_S:
5e755519 11155 check_cp1_64bitmode(ctx);
b6d96bed 11156 {
a7812ae4
PB
11157 TCGv_i32 fp32 = tcg_temp_new_i32();
11158 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11159
7c979afd 11160 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11161 if (ctx->nan2008) {
11162 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11163 } else {
11164 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11165 }
a7812ae4 11166 tcg_temp_free_i32(fp32);
b6d96bed 11167 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11168 tcg_temp_free_i64(fp64);
b6d96bed 11169 }
5a5012ec 11170 break;
bf4120ad 11171 case OPC_TRUNC_L_S:
5e755519 11172 check_cp1_64bitmode(ctx);
b6d96bed 11173 {
a7812ae4
PB
11174 TCGv_i32 fp32 = tcg_temp_new_i32();
11175 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11176
7c979afd 11177 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11178 if (ctx->nan2008) {
11179 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11180 } else {
11181 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11182 }
a7812ae4 11183 tcg_temp_free_i32(fp32);
b6d96bed 11184 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11185 tcg_temp_free_i64(fp64);
b6d96bed 11186 }
5a5012ec 11187 break;
bf4120ad 11188 case OPC_CEIL_L_S:
5e755519 11189 check_cp1_64bitmode(ctx);
b6d96bed 11190 {
a7812ae4
PB
11191 TCGv_i32 fp32 = tcg_temp_new_i32();
11192 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11193
7c979afd 11194 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11195 if (ctx->nan2008) {
11196 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11197 } else {
11198 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11199 }
a7812ae4 11200 tcg_temp_free_i32(fp32);
b6d96bed 11201 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11202 tcg_temp_free_i64(fp64);
b6d96bed 11203 }
5a5012ec 11204 break;
bf4120ad 11205 case OPC_FLOOR_L_S:
5e755519 11206 check_cp1_64bitmode(ctx);
b6d96bed 11207 {
a7812ae4
PB
11208 TCGv_i32 fp32 = tcg_temp_new_i32();
11209 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11210
7c979afd 11211 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11212 if (ctx->nan2008) {
11213 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11214 } else {
11215 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11216 }
a7812ae4 11217 tcg_temp_free_i32(fp32);
b6d96bed 11218 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11219 tcg_temp_free_i64(fp64);
b6d96bed 11220 }
5a5012ec 11221 break;
bf4120ad 11222 case OPC_ROUND_W_S:
b6d96bed 11223 {
a7812ae4 11224 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11225
7c979afd 11226 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11227 if (ctx->nan2008) {
11228 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11229 } else {
11230 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11231 }
7c979afd 11232 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11233 tcg_temp_free_i32(fp0);
b6d96bed 11234 }
5a5012ec 11235 break;
bf4120ad 11236 case OPC_TRUNC_W_S:
b6d96bed 11237 {
a7812ae4 11238 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11239
7c979afd 11240 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11241 if (ctx->nan2008) {
11242 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11243 } else {
11244 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11245 }
7c979afd 11246 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11247 tcg_temp_free_i32(fp0);
b6d96bed 11248 }
5a5012ec 11249 break;
bf4120ad 11250 case OPC_CEIL_W_S:
b6d96bed 11251 {
a7812ae4 11252 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11253
7c979afd 11254 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11255 if (ctx->nan2008) {
11256 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11257 } else {
11258 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11259 }
7c979afd 11260 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11261 tcg_temp_free_i32(fp0);
b6d96bed 11262 }
5a5012ec 11263 break;
bf4120ad 11264 case OPC_FLOOR_W_S:
b6d96bed 11265 {
a7812ae4 11266 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11267
7c979afd 11268 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11269 if (ctx->nan2008) {
11270 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11271 } else {
11272 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11273 }
7c979afd 11274 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11275 tcg_temp_free_i32(fp0);
b6d96bed 11276 }
5a5012ec 11277 break;
e7f16abb
LA
11278 case OPC_SEL_S:
11279 check_insn(ctx, ISA_MIPS32R6);
11280 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11281 break;
11282 case OPC_SELEQZ_S:
11283 check_insn(ctx, ISA_MIPS32R6);
11284 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11285 break;
11286 case OPC_SELNEZ_S:
11287 check_insn(ctx, ISA_MIPS32R6);
11288 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11289 break;
bf4120ad 11290 case OPC_MOVCF_S:
fecd2646 11291 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 11292 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11293 break;
bf4120ad 11294 case OPC_MOVZ_S:
fecd2646 11295 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11296 {
42a268c2 11297 TCGLabel *l1 = gen_new_label();
c9297f4d 11298 TCGv_i32 fp0;
a16336e4 11299
c9297f4d
AJ
11300 if (ft != 0) {
11301 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11302 }
11303 fp0 = tcg_temp_new_i32();
7c979afd
LA
11304 gen_load_fpr32(ctx, fp0, fs);
11305 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11306 tcg_temp_free_i32(fp0);
a16336e4
TS
11307 gen_set_label(l1);
11308 }
5a5012ec 11309 break;
bf4120ad 11310 case OPC_MOVN_S:
fecd2646 11311 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11312 {
42a268c2 11313 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11314 TCGv_i32 fp0;
11315
11316 if (ft != 0) {
11317 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11318 fp0 = tcg_temp_new_i32();
7c979afd
LA
11319 gen_load_fpr32(ctx, fp0, fs);
11320 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11321 tcg_temp_free_i32(fp0);
11322 gen_set_label(l1);
11323 }
a16336e4 11324 }
5a5012ec 11325 break;
bf4120ad 11326 case OPC_RECIP_S:
b6d96bed 11327 {
a7812ae4 11328 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11329
7c979afd 11330 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11331 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11332 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11333 tcg_temp_free_i32(fp0);
b6d96bed 11334 }
57fa1fb3 11335 break;
bf4120ad 11336 case OPC_RSQRT_S:
b6d96bed 11337 {
a7812ae4 11338 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11339
7c979afd 11340 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11341 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11342 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11343 tcg_temp_free_i32(fp0);
b6d96bed 11344 }
57fa1fb3 11345 break;
e7f16abb
LA
11346 case OPC_MADDF_S:
11347 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11348 {
a7812ae4
PB
11349 TCGv_i32 fp0 = tcg_temp_new_i32();
11350 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11351 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11352 gen_load_fpr32(ctx, fp0, fs);
11353 gen_load_fpr32(ctx, fp1, ft);
11354 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11355 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11356 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11357 tcg_temp_free_i32(fp2);
a7812ae4 11358 tcg_temp_free_i32(fp1);
a7812ae4 11359 tcg_temp_free_i32(fp0);
b6d96bed 11360 }
57fa1fb3 11361 break;
e7f16abb
LA
11362 case OPC_MSUBF_S:
11363 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11364 {
a7812ae4 11365 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11366 TCGv_i32 fp1 = tcg_temp_new_i32();
11367 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11368 gen_load_fpr32(ctx, fp0, fs);
11369 gen_load_fpr32(ctx, fp1, ft);
11370 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11371 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11372 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11373 tcg_temp_free_i32(fp2);
11374 tcg_temp_free_i32(fp1);
a7812ae4 11375 tcg_temp_free_i32(fp0);
b6d96bed 11376 }
57fa1fb3 11377 break;
e7f16abb
LA
11378 case OPC_RINT_S:
11379 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11380 {
a7812ae4 11381 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11382 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11383 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 11384 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11385 tcg_temp_free_i32(fp0);
b6d96bed 11386 }
57fa1fb3 11387 break;
e7f16abb
LA
11388 case OPC_CLASS_S:
11389 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11390 {
e7f16abb 11391 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11392 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 11393 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 11394 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 11395 tcg_temp_free_i32(fp0);
e7f16abb
LA
11396 }
11397 break;
11398 case OPC_MIN_S: /* OPC_RECIP2_S */
11399 if (ctx->insn_flags & ISA_MIPS32R6) {
11400 /* OPC_MIN_S */
a7812ae4
PB
11401 TCGv_i32 fp0 = tcg_temp_new_i32();
11402 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11403 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11404 gen_load_fpr32(ctx, fp0, fs);
11405 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11406 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 11407 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11408 tcg_temp_free_i32(fp2);
11409 tcg_temp_free_i32(fp1);
11410 tcg_temp_free_i32(fp0);
e7f16abb
LA
11411 } else {
11412 /* OPC_RECIP2_S */
11413 check_cp1_64bitmode(ctx);
11414 {
11415 TCGv_i32 fp0 = tcg_temp_new_i32();
11416 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11417
7c979afd
LA
11418 gen_load_fpr32(ctx, fp0, fs);
11419 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11420 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11421 tcg_temp_free_i32(fp1);
7c979afd 11422 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11423 tcg_temp_free_i32(fp0);
11424 }
e7f16abb
LA
11425 }
11426 break;
11427 case OPC_MINA_S: /* OPC_RECIP1_S */
11428 if (ctx->insn_flags & ISA_MIPS32R6) {
11429 /* OPC_MINA_S */
11430 TCGv_i32 fp0 = tcg_temp_new_i32();
11431 TCGv_i32 fp1 = tcg_temp_new_i32();
11432 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11433 gen_load_fpr32(ctx, fp0, fs);
11434 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11435 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 11436 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11437 tcg_temp_free_i32(fp2);
11438 tcg_temp_free_i32(fp1);
11439 tcg_temp_free_i32(fp0);
e7f16abb
LA
11440 } else {
11441 /* OPC_RECIP1_S */
11442 check_cp1_64bitmode(ctx);
11443 {
11444 TCGv_i32 fp0 = tcg_temp_new_i32();
11445
7c979afd 11446 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11447 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 11448 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11449 tcg_temp_free_i32(fp0);
11450 }
e7f16abb
LA
11451 }
11452 break;
11453 case OPC_MAX_S: /* OPC_RSQRT1_S */
11454 if (ctx->insn_flags & ISA_MIPS32R6) {
11455 /* OPC_MAX_S */
11456 TCGv_i32 fp0 = tcg_temp_new_i32();
11457 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11458 gen_load_fpr32(ctx, fp0, fs);
11459 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11460 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11461 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11462 tcg_temp_free_i32(fp1);
11463 tcg_temp_free_i32(fp0);
e7f16abb
LA
11464 } else {
11465 /* OPC_RSQRT1_S */
11466 check_cp1_64bitmode(ctx);
11467 {
11468 TCGv_i32 fp0 = tcg_temp_new_i32();
11469
7c979afd 11470 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11471 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11472 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11473 tcg_temp_free_i32(fp0);
11474 }
e7f16abb
LA
11475 }
11476 break;
11477 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11478 if (ctx->insn_flags & ISA_MIPS32R6) {
11479 /* OPC_MAXA_S */
11480 TCGv_i32 fp0 = tcg_temp_new_i32();
11481 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11482 gen_load_fpr32(ctx, fp0, fs);
11483 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11484 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11485 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11486 tcg_temp_free_i32(fp1);
a7812ae4 11487 tcg_temp_free_i32(fp0);
e7f16abb
LA
11488 } else {
11489 /* OPC_RSQRT2_S */
11490 check_cp1_64bitmode(ctx);
11491 {
11492 TCGv_i32 fp0 = tcg_temp_new_i32();
11493 TCGv_i32 fp1 = tcg_temp_new_i32();
11494
7c979afd
LA
11495 gen_load_fpr32(ctx, fp0, fs);
11496 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11497 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11498 tcg_temp_free_i32(fp1);
7c979afd 11499 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11500 tcg_temp_free_i32(fp0);
11501 }
b6d96bed 11502 }
57fa1fb3 11503 break;
bf4120ad 11504 case OPC_CVT_D_S:
5e755519 11505 check_cp1_registers(ctx, fd);
b6d96bed 11506 {
a7812ae4
PB
11507 TCGv_i32 fp32 = tcg_temp_new_i32();
11508 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11509
7c979afd 11510 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11511 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11512 tcg_temp_free_i32(fp32);
b6d96bed 11513 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11514 tcg_temp_free_i64(fp64);
b6d96bed 11515 }
5a5012ec 11516 break;
bf4120ad 11517 case OPC_CVT_W_S:
b6d96bed 11518 {
a7812ae4 11519 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11520
7c979afd 11521 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11522 if (ctx->nan2008) {
11523 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11524 } else {
11525 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11526 }
7c979afd 11527 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11528 tcg_temp_free_i32(fp0);
b6d96bed 11529 }
5a5012ec 11530 break;
bf4120ad 11531 case OPC_CVT_L_S:
5e755519 11532 check_cp1_64bitmode(ctx);
b6d96bed 11533 {
a7812ae4
PB
11534 TCGv_i32 fp32 = tcg_temp_new_i32();
11535 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11536
7c979afd 11537 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11538 if (ctx->nan2008) {
11539 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11540 } else {
11541 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11542 }
a7812ae4 11543 tcg_temp_free_i32(fp32);
b6d96bed 11544 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11545 tcg_temp_free_i64(fp64);
b6d96bed 11546 }
5a5012ec 11547 break;
bf4120ad 11548 case OPC_CVT_PS_S:
e29c9628 11549 check_ps(ctx);
b6d96bed 11550 {
a7812ae4
PB
11551 TCGv_i64 fp64 = tcg_temp_new_i64();
11552 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11553 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11554
7c979afd
LA
11555 gen_load_fpr32(ctx, fp32_0, fs);
11556 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11557 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11558 tcg_temp_free_i32(fp32_1);
11559 tcg_temp_free_i32(fp32_0);
36aa55dc 11560 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11561 tcg_temp_free_i64(fp64);
b6d96bed 11562 }
5a5012ec 11563 break;
bf4120ad
NF
11564 case OPC_CMP_F_S:
11565 case OPC_CMP_UN_S:
11566 case OPC_CMP_EQ_S:
11567 case OPC_CMP_UEQ_S:
11568 case OPC_CMP_OLT_S:
11569 case OPC_CMP_ULT_S:
11570 case OPC_CMP_OLE_S:
11571 case OPC_CMP_ULE_S:
11572 case OPC_CMP_SF_S:
11573 case OPC_CMP_NGLE_S:
11574 case OPC_CMP_SEQ_S:
11575 case OPC_CMP_NGL_S:
11576 case OPC_CMP_LT_S:
11577 case OPC_CMP_NGE_S:
11578 case OPC_CMP_LE_S:
11579 case OPC_CMP_NGT_S:
fecd2646 11580 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 11581 if (ctx->opcode & (1 << 6)) {
71375b59 11582 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 11583 } else {
71375b59 11584 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11585 }
5a5012ec 11586 break;
bf4120ad 11587 case OPC_ADD_D:
5e755519 11588 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11589 {
a7812ae4
PB
11590 TCGv_i64 fp0 = tcg_temp_new_i64();
11591 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11592
11593 gen_load_fpr64(ctx, fp0, fs);
11594 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11595 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11596 tcg_temp_free_i64(fp1);
b6d96bed 11597 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11598 tcg_temp_free_i64(fp0);
b6d96bed 11599 }
6ea83fed 11600 break;
bf4120ad 11601 case OPC_SUB_D:
5e755519 11602 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11603 {
a7812ae4
PB
11604 TCGv_i64 fp0 = tcg_temp_new_i64();
11605 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11606
11607 gen_load_fpr64(ctx, fp0, fs);
11608 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11609 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11610 tcg_temp_free_i64(fp1);
b6d96bed 11611 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11612 tcg_temp_free_i64(fp0);
b6d96bed 11613 }
6ea83fed 11614 break;
bf4120ad 11615 case OPC_MUL_D:
5e755519 11616 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11617 {
a7812ae4
PB
11618 TCGv_i64 fp0 = tcg_temp_new_i64();
11619 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11620
11621 gen_load_fpr64(ctx, fp0, fs);
11622 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11623 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11624 tcg_temp_free_i64(fp1);
b6d96bed 11625 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11626 tcg_temp_free_i64(fp0);
b6d96bed 11627 }
6ea83fed 11628 break;
bf4120ad 11629 case OPC_DIV_D:
5e755519 11630 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11631 {
a7812ae4
PB
11632 TCGv_i64 fp0 = tcg_temp_new_i64();
11633 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11634
11635 gen_load_fpr64(ctx, fp0, fs);
11636 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11637 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11638 tcg_temp_free_i64(fp1);
b6d96bed 11639 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11640 tcg_temp_free_i64(fp0);
b6d96bed 11641 }
6ea83fed 11642 break;
bf4120ad 11643 case OPC_SQRT_D:
5e755519 11644 check_cp1_registers(ctx, fs | fd);
b6d96bed 11645 {
a7812ae4 11646 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11647
11648 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11649 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11650 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11651 tcg_temp_free_i64(fp0);
b6d96bed 11652 }
6ea83fed 11653 break;
bf4120ad 11654 case OPC_ABS_D:
5e755519 11655 check_cp1_registers(ctx, fs | fd);
b6d96bed 11656 {
a7812ae4 11657 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11658
11659 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11660 if (ctx->abs2008) {
11661 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11662 } else {
11663 gen_helper_float_abs_d(fp0, fp0);
11664 }
b6d96bed 11665 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11666 tcg_temp_free_i64(fp0);
b6d96bed 11667 }
6ea83fed 11668 break;
bf4120ad 11669 case OPC_MOV_D:
5e755519 11670 check_cp1_registers(ctx, fs | fd);
b6d96bed 11671 {
a7812ae4 11672 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11673
11674 gen_load_fpr64(ctx, fp0, fs);
11675 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11676 tcg_temp_free_i64(fp0);
b6d96bed 11677 }
6ea83fed 11678 break;
bf4120ad 11679 case OPC_NEG_D:
5e755519 11680 check_cp1_registers(ctx, fs | fd);
b6d96bed 11681 {
a7812ae4 11682 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11683
11684 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11685 if (ctx->abs2008) {
11686 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11687 } else {
11688 gen_helper_float_chs_d(fp0, fp0);
11689 }
b6d96bed 11690 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11691 tcg_temp_free_i64(fp0);
b6d96bed 11692 }
6ea83fed 11693 break;
bf4120ad 11694 case OPC_ROUND_L_D:
5e755519 11695 check_cp1_64bitmode(ctx);
b6d96bed 11696 {
a7812ae4 11697 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11698
11699 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11700 if (ctx->nan2008) {
11701 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11702 } else {
11703 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11704 }
b6d96bed 11705 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11706 tcg_temp_free_i64(fp0);
b6d96bed 11707 }
5a5012ec 11708 break;
bf4120ad 11709 case OPC_TRUNC_L_D:
5e755519 11710 check_cp1_64bitmode(ctx);
b6d96bed 11711 {
a7812ae4 11712 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11713
11714 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11715 if (ctx->nan2008) {
11716 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11717 } else {
11718 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11719 }
b6d96bed 11720 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11721 tcg_temp_free_i64(fp0);
b6d96bed 11722 }
5a5012ec 11723 break;
bf4120ad 11724 case OPC_CEIL_L_D:
5e755519 11725 check_cp1_64bitmode(ctx);
b6d96bed 11726 {
a7812ae4 11727 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11728
11729 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11730 if (ctx->nan2008) {
11731 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11732 } else {
11733 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11734 }
b6d96bed 11735 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11736 tcg_temp_free_i64(fp0);
b6d96bed 11737 }
5a5012ec 11738 break;
bf4120ad 11739 case OPC_FLOOR_L_D:
5e755519 11740 check_cp1_64bitmode(ctx);
b6d96bed 11741 {
a7812ae4 11742 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11743
11744 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11745 if (ctx->nan2008) {
11746 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11747 } else {
11748 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11749 }
b6d96bed 11750 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11751 tcg_temp_free_i64(fp0);
b6d96bed 11752 }
5a5012ec 11753 break;
bf4120ad 11754 case OPC_ROUND_W_D:
5e755519 11755 check_cp1_registers(ctx, fs);
b6d96bed 11756 {
a7812ae4
PB
11757 TCGv_i32 fp32 = tcg_temp_new_i32();
11758 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11759
11760 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11761 if (ctx->nan2008) {
11762 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11763 } else {
11764 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11765 }
a7812ae4 11766 tcg_temp_free_i64(fp64);
7c979afd 11767 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11768 tcg_temp_free_i32(fp32);
b6d96bed 11769 }
6ea83fed 11770 break;
bf4120ad 11771 case OPC_TRUNC_W_D:
5e755519 11772 check_cp1_registers(ctx, fs);
b6d96bed 11773 {
a7812ae4
PB
11774 TCGv_i32 fp32 = tcg_temp_new_i32();
11775 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11776
11777 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11778 if (ctx->nan2008) {
11779 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11780 } else {
11781 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11782 }
a7812ae4 11783 tcg_temp_free_i64(fp64);
7c979afd 11784 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11785 tcg_temp_free_i32(fp32);
b6d96bed 11786 }
6ea83fed 11787 break;
bf4120ad 11788 case OPC_CEIL_W_D:
5e755519 11789 check_cp1_registers(ctx, fs);
b6d96bed 11790 {
a7812ae4
PB
11791 TCGv_i32 fp32 = tcg_temp_new_i32();
11792 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11793
11794 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11795 if (ctx->nan2008) {
11796 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11797 } else {
11798 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11799 }
a7812ae4 11800 tcg_temp_free_i64(fp64);
7c979afd 11801 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11802 tcg_temp_free_i32(fp32);
b6d96bed 11803 }
6ea83fed 11804 break;
bf4120ad 11805 case OPC_FLOOR_W_D:
5e755519 11806 check_cp1_registers(ctx, fs);
b6d96bed 11807 {
a7812ae4
PB
11808 TCGv_i32 fp32 = tcg_temp_new_i32();
11809 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11810
11811 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11812 if (ctx->nan2008) {
11813 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11814 } else {
11815 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11816 }
a7812ae4 11817 tcg_temp_free_i64(fp64);
7c979afd 11818 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11819 tcg_temp_free_i32(fp32);
b6d96bed 11820 }
6ea83fed 11821 break;
e7f16abb
LA
11822 case OPC_SEL_D:
11823 check_insn(ctx, ISA_MIPS32R6);
11824 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11825 break;
11826 case OPC_SELEQZ_D:
11827 check_insn(ctx, ISA_MIPS32R6);
11828 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11829 break;
11830 case OPC_SELNEZ_D:
11831 check_insn(ctx, ISA_MIPS32R6);
11832 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11833 break;
bf4120ad 11834 case OPC_MOVCF_D:
fecd2646 11835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 11836 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11837 break;
bf4120ad 11838 case OPC_MOVZ_D:
fecd2646 11839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11840 {
42a268c2 11841 TCGLabel *l1 = gen_new_label();
c9297f4d 11842 TCGv_i64 fp0;
a16336e4 11843
c9297f4d
AJ
11844 if (ft != 0) {
11845 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11846 }
11847 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11848 gen_load_fpr64(ctx, fp0, fs);
11849 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11850 tcg_temp_free_i64(fp0);
a16336e4
TS
11851 gen_set_label(l1);
11852 }
5a5012ec 11853 break;
bf4120ad 11854 case OPC_MOVN_D:
fecd2646 11855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11856 {
42a268c2 11857 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11858 TCGv_i64 fp0;
11859
11860 if (ft != 0) {
11861 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11862 fp0 = tcg_temp_new_i64();
11863 gen_load_fpr64(ctx, fp0, fs);
11864 gen_store_fpr64(ctx, fp0, fd);
11865 tcg_temp_free_i64(fp0);
11866 gen_set_label(l1);
11867 }
a16336e4 11868 }
6ea83fed 11869 break;
bf4120ad 11870 case OPC_RECIP_D:
ca6c7803 11871 check_cp1_registers(ctx, fs | fd);
b6d96bed 11872 {
a7812ae4 11873 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11874
11875 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11876 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11877 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11878 tcg_temp_free_i64(fp0);
b6d96bed 11879 }
57fa1fb3 11880 break;
bf4120ad 11881 case OPC_RSQRT_D:
ca6c7803 11882 check_cp1_registers(ctx, fs | fd);
b6d96bed 11883 {
a7812ae4 11884 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11885
11886 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11887 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11888 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11889 tcg_temp_free_i64(fp0);
b6d96bed 11890 }
57fa1fb3 11891 break;
e7f16abb
LA
11892 case OPC_MADDF_D:
11893 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11894 {
a7812ae4
PB
11895 TCGv_i64 fp0 = tcg_temp_new_i64();
11896 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11897 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11898 gen_load_fpr64(ctx, fp0, fs);
11899 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11900 gen_load_fpr64(ctx, fp2, fd);
11901 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11902 gen_store_fpr64(ctx, fp2, fd);
11903 tcg_temp_free_i64(fp2);
a7812ae4 11904 tcg_temp_free_i64(fp1);
a7812ae4 11905 tcg_temp_free_i64(fp0);
b6d96bed 11906 }
57fa1fb3 11907 break;
e7f16abb
LA
11908 case OPC_MSUBF_D:
11909 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11910 {
a7812ae4 11911 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11912 TCGv_i64 fp1 = tcg_temp_new_i64();
11913 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11914 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11915 gen_load_fpr64(ctx, fp1, ft);
11916 gen_load_fpr64(ctx, fp2, fd);
11917 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11918 gen_store_fpr64(ctx, fp2, fd);
11919 tcg_temp_free_i64(fp2);
11920 tcg_temp_free_i64(fp1);
a7812ae4 11921 tcg_temp_free_i64(fp0);
b6d96bed 11922 }
57fa1fb3 11923 break;
e7f16abb
LA
11924 case OPC_RINT_D:
11925 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11926 {
a7812ae4 11927 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11928 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11929 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11930 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11931 tcg_temp_free_i64(fp0);
b6d96bed 11932 }
57fa1fb3 11933 break;
e7f16abb
LA
11934 case OPC_CLASS_D:
11935 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11936 {
e7f16abb
LA
11937 TCGv_i64 fp0 = tcg_temp_new_i64();
11938 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11939 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11940 gen_store_fpr64(ctx, fp0, fd);
11941 tcg_temp_free_i64(fp0);
e7f16abb
LA
11942 }
11943 break;
11944 case OPC_MIN_D: /* OPC_RECIP2_D */
11945 if (ctx->insn_flags & ISA_MIPS32R6) {
11946 /* OPC_MIN_D */
a7812ae4
PB
11947 TCGv_i64 fp0 = tcg_temp_new_i64();
11948 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11949 gen_load_fpr64(ctx, fp0, fs);
11950 gen_load_fpr64(ctx, fp1, ft);
11951 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11952 gen_store_fpr64(ctx, fp1, fd);
11953 tcg_temp_free_i64(fp1);
11954 tcg_temp_free_i64(fp0);
e7f16abb
LA
11955 } else {
11956 /* OPC_RECIP2_D */
11957 check_cp1_64bitmode(ctx);
11958 {
11959 TCGv_i64 fp0 = tcg_temp_new_i64();
11960 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11961
e7f16abb
LA
11962 gen_load_fpr64(ctx, fp0, fs);
11963 gen_load_fpr64(ctx, fp1, ft);
11964 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11965 tcg_temp_free_i64(fp1);
11966 gen_store_fpr64(ctx, fp0, fd);
11967 tcg_temp_free_i64(fp0);
11968 }
e7f16abb
LA
11969 }
11970 break;
11971 case OPC_MINA_D: /* OPC_RECIP1_D */
11972 if (ctx->insn_flags & ISA_MIPS32R6) {
11973 /* OPC_MINA_D */
11974 TCGv_i64 fp0 = tcg_temp_new_i64();
11975 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11976 gen_load_fpr64(ctx, fp0, fs);
11977 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11978 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11979 gen_store_fpr64(ctx, fp1, fd);
11980 tcg_temp_free_i64(fp1);
11981 tcg_temp_free_i64(fp0);
e7f16abb
LA
11982 } else {
11983 /* OPC_RECIP1_D */
11984 check_cp1_64bitmode(ctx);
11985 {
11986 TCGv_i64 fp0 = tcg_temp_new_i64();
11987
11988 gen_load_fpr64(ctx, fp0, fs);
11989 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11990 gen_store_fpr64(ctx, fp0, fd);
11991 tcg_temp_free_i64(fp0);
11992 }
e7f16abb
LA
11993 }
11994 break;
11995 case OPC_MAX_D: /* OPC_RSQRT1_D */
11996 if (ctx->insn_flags & ISA_MIPS32R6) {
11997 /* OPC_MAX_D */
11998 TCGv_i64 fp0 = tcg_temp_new_i64();
11999 TCGv_i64 fp1 = tcg_temp_new_i64();
12000 gen_load_fpr64(ctx, fp0, fs);
12001 gen_load_fpr64(ctx, fp1, ft);
12002 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12003 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 12004 tcg_temp_free_i64(fp1);
a7812ae4 12005 tcg_temp_free_i64(fp0);
e7f16abb
LA
12006 } else {
12007 /* OPC_RSQRT1_D */
12008 check_cp1_64bitmode(ctx);
12009 {
12010 TCGv_i64 fp0 = tcg_temp_new_i64();
12011
12012 gen_load_fpr64(ctx, fp0, fs);
12013 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12014 gen_store_fpr64(ctx, fp0, fd);
12015 tcg_temp_free_i64(fp0);
12016 }
e7f16abb
LA
12017 }
12018 break;
12019 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12020 if (ctx->insn_flags & ISA_MIPS32R6) {
12021 /* OPC_MAXA_D */
12022 TCGv_i64 fp0 = tcg_temp_new_i64();
12023 TCGv_i64 fp1 = tcg_temp_new_i64();
12024 gen_load_fpr64(ctx, fp0, fs);
12025 gen_load_fpr64(ctx, fp1, ft);
12026 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12027 gen_store_fpr64(ctx, fp1, fd);
12028 tcg_temp_free_i64(fp1);
12029 tcg_temp_free_i64(fp0);
e7f16abb
LA
12030 } else {
12031 /* OPC_RSQRT2_D */
12032 check_cp1_64bitmode(ctx);
12033 {
12034 TCGv_i64 fp0 = tcg_temp_new_i64();
12035 TCGv_i64 fp1 = tcg_temp_new_i64();
12036
12037 gen_load_fpr64(ctx, fp0, fs);
12038 gen_load_fpr64(ctx, fp1, ft);
12039 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12040 tcg_temp_free_i64(fp1);
12041 gen_store_fpr64(ctx, fp0, fd);
12042 tcg_temp_free_i64(fp0);
12043 }
b6d96bed 12044 }
57fa1fb3 12045 break;
bf4120ad
NF
12046 case OPC_CMP_F_D:
12047 case OPC_CMP_UN_D:
12048 case OPC_CMP_EQ_D:
12049 case OPC_CMP_UEQ_D:
12050 case OPC_CMP_OLT_D:
12051 case OPC_CMP_ULT_D:
12052 case OPC_CMP_OLE_D:
12053 case OPC_CMP_ULE_D:
12054 case OPC_CMP_SF_D:
12055 case OPC_CMP_NGLE_D:
12056 case OPC_CMP_SEQ_D:
12057 case OPC_CMP_NGL_D:
12058 case OPC_CMP_LT_D:
12059 case OPC_CMP_NGE_D:
12060 case OPC_CMP_LE_D:
12061 case OPC_CMP_NGT_D:
fecd2646 12062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 12063 if (ctx->opcode & (1 << 6)) {
71375b59 12064 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 12065 } else {
71375b59 12066 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12067 }
6ea83fed 12068 break;
bf4120ad 12069 case OPC_CVT_S_D:
5e755519 12070 check_cp1_registers(ctx, fs);
b6d96bed 12071 {
a7812ae4
PB
12072 TCGv_i32 fp32 = tcg_temp_new_i32();
12073 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12074
12075 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12076 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 12077 tcg_temp_free_i64(fp64);
7c979afd 12078 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12079 tcg_temp_free_i32(fp32);
b6d96bed 12080 }
5a5012ec 12081 break;
bf4120ad 12082 case OPC_CVT_W_D:
5e755519 12083 check_cp1_registers(ctx, fs);
b6d96bed 12084 {
a7812ae4
PB
12085 TCGv_i32 fp32 = tcg_temp_new_i32();
12086 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12087
12088 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12089 if (ctx->nan2008) {
12090 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12091 } else {
12092 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12093 }
a7812ae4 12094 tcg_temp_free_i64(fp64);
7c979afd 12095 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12096 tcg_temp_free_i32(fp32);
b6d96bed 12097 }
5a5012ec 12098 break;
bf4120ad 12099 case OPC_CVT_L_D:
5e755519 12100 check_cp1_64bitmode(ctx);
b6d96bed 12101 {
a7812ae4 12102 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12103
12104 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12105 if (ctx->nan2008) {
12106 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12107 } else {
12108 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12109 }
b6d96bed 12110 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12111 tcg_temp_free_i64(fp0);
b6d96bed 12112 }
5a5012ec 12113 break;
bf4120ad 12114 case OPC_CVT_S_W:
b6d96bed 12115 {
a7812ae4 12116 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12117
7c979afd 12118 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12119 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 12120 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12121 tcg_temp_free_i32(fp0);
b6d96bed 12122 }
6ea83fed 12123 break;
bf4120ad 12124 case OPC_CVT_D_W:
5e755519 12125 check_cp1_registers(ctx, fd);
b6d96bed 12126 {
a7812ae4
PB
12127 TCGv_i32 fp32 = tcg_temp_new_i32();
12128 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12129
7c979afd 12130 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12131 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12132 tcg_temp_free_i32(fp32);
b6d96bed 12133 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12134 tcg_temp_free_i64(fp64);
b6d96bed 12135 }
5a5012ec 12136 break;
bf4120ad 12137 case OPC_CVT_S_L:
5e755519 12138 check_cp1_64bitmode(ctx);
b6d96bed 12139 {
a7812ae4
PB
12140 TCGv_i32 fp32 = tcg_temp_new_i32();
12141 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12142
12143 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12144 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12145 tcg_temp_free_i64(fp64);
7c979afd 12146 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12147 tcg_temp_free_i32(fp32);
b6d96bed 12148 }
5a5012ec 12149 break;
bf4120ad 12150 case OPC_CVT_D_L:
5e755519 12151 check_cp1_64bitmode(ctx);
b6d96bed 12152 {
a7812ae4 12153 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12154
12155 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12156 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12157 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12158 tcg_temp_free_i64(fp0);
b6d96bed 12159 }
5a5012ec 12160 break;
bf4120ad 12161 case OPC_CVT_PS_PW:
e29c9628 12162 check_ps(ctx);
b6d96bed 12163 {
a7812ae4 12164 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12165
12166 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12167 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12168 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12169 tcg_temp_free_i64(fp0);
b6d96bed 12170 }
5a5012ec 12171 break;
bf4120ad 12172 case OPC_ADD_PS:
e29c9628 12173 check_ps(ctx);
b6d96bed 12174 {
a7812ae4
PB
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12177
12178 gen_load_fpr64(ctx, fp0, fs);
12179 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12180 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12181 tcg_temp_free_i64(fp1);
b6d96bed 12182 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12183 tcg_temp_free_i64(fp0);
b6d96bed 12184 }
6ea83fed 12185 break;
bf4120ad 12186 case OPC_SUB_PS:
e29c9628 12187 check_ps(ctx);
b6d96bed 12188 {
a7812ae4
PB
12189 TCGv_i64 fp0 = tcg_temp_new_i64();
12190 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12191
12192 gen_load_fpr64(ctx, fp0, fs);
12193 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12194 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12195 tcg_temp_free_i64(fp1);
b6d96bed 12196 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12197 tcg_temp_free_i64(fp0);
b6d96bed 12198 }
6ea83fed 12199 break;
bf4120ad 12200 case OPC_MUL_PS:
e29c9628 12201 check_ps(ctx);
b6d96bed 12202 {
a7812ae4
PB
12203 TCGv_i64 fp0 = tcg_temp_new_i64();
12204 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12205
12206 gen_load_fpr64(ctx, fp0, fs);
12207 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12208 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12209 tcg_temp_free_i64(fp1);
b6d96bed 12210 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12211 tcg_temp_free_i64(fp0);
b6d96bed 12212 }
6ea83fed 12213 break;
bf4120ad 12214 case OPC_ABS_PS:
e29c9628 12215 check_ps(ctx);
b6d96bed 12216 {
a7812ae4 12217 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12218
12219 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12220 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12221 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12222 tcg_temp_free_i64(fp0);
b6d96bed 12223 }
6ea83fed 12224 break;
bf4120ad 12225 case OPC_MOV_PS:
e29c9628 12226 check_ps(ctx);
b6d96bed 12227 {
a7812ae4 12228 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12229
12230 gen_load_fpr64(ctx, fp0, fs);
12231 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12232 tcg_temp_free_i64(fp0);
b6d96bed 12233 }
6ea83fed 12234 break;
bf4120ad 12235 case OPC_NEG_PS:
e29c9628 12236 check_ps(ctx);
b6d96bed 12237 {
a7812ae4 12238 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12239
12240 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12241 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12242 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12243 tcg_temp_free_i64(fp0);
b6d96bed 12244 }
6ea83fed 12245 break;
bf4120ad 12246 case OPC_MOVCF_PS:
e29c9628 12247 check_ps(ctx);
7f6613ce 12248 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12249 break;
bf4120ad 12250 case OPC_MOVZ_PS:
e29c9628 12251 check_ps(ctx);
a16336e4 12252 {
42a268c2 12253 TCGLabel *l1 = gen_new_label();
30a3848b 12254 TCGv_i64 fp0;
a16336e4 12255
1f8929d2 12256 if (ft != 0) {
c9297f4d 12257 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 12258 }
c9297f4d
AJ
12259 fp0 = tcg_temp_new_i64();
12260 gen_load_fpr64(ctx, fp0, fs);
12261 gen_store_fpr64(ctx, fp0, fd);
12262 tcg_temp_free_i64(fp0);
a16336e4
TS
12263 gen_set_label(l1);
12264 }
6ea83fed 12265 break;
bf4120ad 12266 case OPC_MOVN_PS:
e29c9628 12267 check_ps(ctx);
a16336e4 12268 {
42a268c2 12269 TCGLabel *l1 = gen_new_label();
30a3848b 12270 TCGv_i64 fp0;
c9297f4d
AJ
12271
12272 if (ft != 0) {
12273 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12274 fp0 = tcg_temp_new_i64();
12275 gen_load_fpr64(ctx, fp0, fs);
12276 gen_store_fpr64(ctx, fp0, fd);
12277 tcg_temp_free_i64(fp0);
12278 gen_set_label(l1);
12279 }
a16336e4 12280 }
6ea83fed 12281 break;
bf4120ad 12282 case OPC_ADDR_PS:
e29c9628 12283 check_ps(ctx);
b6d96bed 12284 {
a7812ae4
PB
12285 TCGv_i64 fp0 = tcg_temp_new_i64();
12286 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12287
12288 gen_load_fpr64(ctx, fp0, ft);
12289 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12290 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12291 tcg_temp_free_i64(fp1);
b6d96bed 12292 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12293 tcg_temp_free_i64(fp0);
b6d96bed 12294 }
fbcc6828 12295 break;
bf4120ad 12296 case OPC_MULR_PS:
e29c9628 12297 check_ps(ctx);
b6d96bed 12298 {
a7812ae4
PB
12299 TCGv_i64 fp0 = tcg_temp_new_i64();
12300 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12301
12302 gen_load_fpr64(ctx, fp0, ft);
12303 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12304 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12305 tcg_temp_free_i64(fp1);
b6d96bed 12306 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12307 tcg_temp_free_i64(fp0);
b6d96bed 12308 }
57fa1fb3 12309 break;
bf4120ad 12310 case OPC_RECIP2_PS:
e29c9628 12311 check_ps(ctx);
b6d96bed 12312 {
a7812ae4
PB
12313 TCGv_i64 fp0 = tcg_temp_new_i64();
12314 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12315
12316 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12317 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12318 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12319 tcg_temp_free_i64(fp1);
b6d96bed 12320 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12321 tcg_temp_free_i64(fp0);
b6d96bed 12322 }
57fa1fb3 12323 break;
bf4120ad 12324 case OPC_RECIP1_PS:
e29c9628 12325 check_ps(ctx);
b6d96bed 12326 {
a7812ae4 12327 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12328
12329 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12330 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12331 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12332 tcg_temp_free_i64(fp0);
b6d96bed 12333 }
57fa1fb3 12334 break;
bf4120ad 12335 case OPC_RSQRT1_PS:
e29c9628 12336 check_ps(ctx);
b6d96bed 12337 {
a7812ae4 12338 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12339
12340 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12341 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12342 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12343 tcg_temp_free_i64(fp0);
b6d96bed 12344 }
57fa1fb3 12345 break;
bf4120ad 12346 case OPC_RSQRT2_PS:
e29c9628 12347 check_ps(ctx);
b6d96bed 12348 {
a7812ae4
PB
12349 TCGv_i64 fp0 = tcg_temp_new_i64();
12350 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12351
12352 gen_load_fpr64(ctx, fp0, fs);
12353 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12354 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12355 tcg_temp_free_i64(fp1);
b6d96bed 12356 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12357 tcg_temp_free_i64(fp0);
b6d96bed 12358 }
57fa1fb3 12359 break;
bf4120ad 12360 case OPC_CVT_S_PU:
5e755519 12361 check_cp1_64bitmode(ctx);
b6d96bed 12362 {
a7812ae4 12363 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12364
7f6613ce 12365 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12366 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12367 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12368 tcg_temp_free_i32(fp0);
b6d96bed 12369 }
dd016883 12370 break;
bf4120ad 12371 case OPC_CVT_PW_PS:
e29c9628 12372 check_ps(ctx);
b6d96bed 12373 {
a7812ae4 12374 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12375
12376 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12377 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 12378 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12379 tcg_temp_free_i64(fp0);
b6d96bed 12380 }
6ea83fed 12381 break;
bf4120ad 12382 case OPC_CVT_S_PL:
5e755519 12383 check_cp1_64bitmode(ctx);
b6d96bed 12384 {
a7812ae4 12385 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12386
7c979afd 12387 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12388 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 12389 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12390 tcg_temp_free_i32(fp0);
b6d96bed 12391 }
6ea83fed 12392 break;
bf4120ad 12393 case OPC_PLL_PS:
e29c9628 12394 check_ps(ctx);
b6d96bed 12395 {
a7812ae4
PB
12396 TCGv_i32 fp0 = tcg_temp_new_i32();
12397 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12398
7c979afd
LA
12399 gen_load_fpr32(ctx, fp0, fs);
12400 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 12401 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 12402 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
12403 tcg_temp_free_i32(fp0);
12404 tcg_temp_free_i32(fp1);
b6d96bed 12405 }
6ea83fed 12406 break;
bf4120ad 12407 case OPC_PLU_PS:
e29c9628 12408 check_ps(ctx);
b6d96bed 12409 {
a7812ae4
PB
12410 TCGv_i32 fp0 = tcg_temp_new_i32();
12411 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12412
7c979afd 12413 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 12414 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12415 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12416 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12417 tcg_temp_free_i32(fp0);
12418 tcg_temp_free_i32(fp1);
b6d96bed 12419 }
5a5012ec 12420 break;
bf4120ad 12421 case OPC_PUL_PS:
e29c9628 12422 check_ps(ctx);
b6d96bed 12423 {
a7812ae4
PB
12424 TCGv_i32 fp0 = tcg_temp_new_i32();
12425 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12426
7f6613ce 12427 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
12428 gen_load_fpr32(ctx, fp1, ft);
12429 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12430 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12431 tcg_temp_free_i32(fp0);
12432 tcg_temp_free_i32(fp1);
b6d96bed 12433 }
5a5012ec 12434 break;
bf4120ad 12435 case OPC_PUU_PS:
e29c9628 12436 check_ps(ctx);
b6d96bed 12437 {
a7812ae4
PB
12438 TCGv_i32 fp0 = tcg_temp_new_i32();
12439 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12440
7f6613ce
PJ
12441 gen_load_fpr32h(ctx, fp0, fs);
12442 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12443 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12444 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12445 tcg_temp_free_i32(fp0);
12446 tcg_temp_free_i32(fp1);
b6d96bed 12447 }
5a5012ec 12448 break;
bf4120ad
NF
12449 case OPC_CMP_F_PS:
12450 case OPC_CMP_UN_PS:
12451 case OPC_CMP_EQ_PS:
12452 case OPC_CMP_UEQ_PS:
12453 case OPC_CMP_OLT_PS:
12454 case OPC_CMP_ULT_PS:
12455 case OPC_CMP_OLE_PS:
12456 case OPC_CMP_ULE_PS:
12457 case OPC_CMP_SF_PS:
12458 case OPC_CMP_NGLE_PS:
12459 case OPC_CMP_SEQ_PS:
12460 case OPC_CMP_NGL_PS:
12461 case OPC_CMP_LT_PS:
12462 case OPC_CMP_NGE_PS:
12463 case OPC_CMP_LE_PS:
12464 case OPC_CMP_NGT_PS:
8153667c 12465 if (ctx->opcode & (1 << 6)) {
71375b59 12466 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 12467 } else {
71375b59 12468 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12469 }
6ea83fed 12470 break;
5a5012ec 12471 default:
9d68ac14 12472 MIPS_INVAL("farith");
9c708c7f 12473 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12474 return;
12475 }
6ea83fed 12476}
6af0bf9c 12477
5a5012ec 12478/* Coprocessor 3 (FPU) */
235785e8
AM
12479static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12480 int fd, int fs, int base, int index)
7a387fff 12481{
4e2474d6 12482 TCGv t0 = tcg_temp_new();
7a387fff 12483
93b12ccc 12484 if (base == 0) {
6c5c1e20 12485 gen_load_gpr(t0, index);
93b12ccc 12486 } else if (index == 0) {
6c5c1e20 12487 gen_load_gpr(t0, base);
93b12ccc 12488 } else {
05168674 12489 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12490 }
7480515f
AM
12491 /*
12492 * Don't do NOP if destination is zero: we must perform the actual
12493 * memory access.
12494 */
5a5012ec
TS
12495 switch (opc) {
12496 case OPC_LWXC1:
8c0ab41f 12497 check_cop1x(ctx);
b6d96bed 12498 {
a7812ae4 12499 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12500
5f68f5ae 12501 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12502 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12503 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12504 tcg_temp_free_i32(fp0);
b6d96bed 12505 }
5a5012ec
TS
12506 break;
12507 case OPC_LDXC1:
8c0ab41f
AJ
12508 check_cop1x(ctx);
12509 check_cp1_registers(ctx, fd);
b6d96bed 12510 {
a7812ae4 12511 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12512 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12513 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12514 tcg_temp_free_i64(fp0);
b6d96bed 12515 }
5a5012ec
TS
12516 break;
12517 case OPC_LUXC1:
8c0ab41f 12518 check_cp1_64bitmode(ctx);
6c5c1e20 12519 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12520 {
a7812ae4 12521 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12522
5f68f5ae 12523 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12524 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12525 tcg_temp_free_i64(fp0);
b6d96bed 12526 }
5a5012ec
TS
12527 break;
12528 case OPC_SWXC1:
8c0ab41f 12529 check_cop1x(ctx);
b6d96bed 12530 {
a7812ae4 12531 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12532 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12533 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12534 tcg_temp_free_i32(fp0);
b6d96bed 12535 }
5a5012ec
TS
12536 break;
12537 case OPC_SDXC1:
8c0ab41f
AJ
12538 check_cop1x(ctx);
12539 check_cp1_registers(ctx, fs);
b6d96bed 12540 {
a7812ae4 12541 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12542 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12543 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12544 tcg_temp_free_i64(fp0);
b6d96bed 12545 }
5a5012ec
TS
12546 break;
12547 case OPC_SUXC1:
8c0ab41f 12548 check_cp1_64bitmode(ctx);
6c5c1e20 12549 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12550 {
a7812ae4 12551 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12552 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12553 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12554 tcg_temp_free_i64(fp0);
b6d96bed 12555 }
5a5012ec 12556 break;
5a5012ec 12557 }
6c5c1e20 12558 tcg_temp_free(t0);
5a5012ec
TS
12559}
12560
235785e8
AM
12561static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12562 int fd, int fr, int fs, int ft)
5a5012ec 12563{
5a5012ec
TS
12564 switch (opc) {
12565 case OPC_ALNV_PS:
e29c9628 12566 check_ps(ctx);
a16336e4 12567 {
a7812ae4 12568 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12569 TCGv_i32 fp = tcg_temp_new_i32();
12570 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12571 TCGLabel *l1 = gen_new_label();
12572 TCGLabel *l2 = gen_new_label();
a16336e4 12573
6c5c1e20
TS
12574 gen_load_gpr(t0, fr);
12575 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12576
12577 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12578 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12579 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12580 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12581 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12582 tcg_gen_br(l2);
12583 gen_set_label(l1);
6c5c1e20
TS
12584 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12585 tcg_temp_free(t0);
a16336e4 12586#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12587 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12588 gen_load_fpr32h(ctx, fph, ft);
12589 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12590 gen_store_fpr32(ctx, fph, fd);
a16336e4 12591#else
7f6613ce 12592 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12593 gen_load_fpr32(ctx, fp, ft);
12594 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12595 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12596#endif
12597 gen_set_label(l2);
c905fdac
AJ
12598 tcg_temp_free_i32(fp);
12599 tcg_temp_free_i32(fph);
a16336e4 12600 }
5a5012ec
TS
12601 break;
12602 case OPC_MADD_S:
b8aa4598 12603 check_cop1x(ctx);
b6d96bed 12604 {
a7812ae4
PB
12605 TCGv_i32 fp0 = tcg_temp_new_i32();
12606 TCGv_i32 fp1 = tcg_temp_new_i32();
12607 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12608
7c979afd
LA
12609 gen_load_fpr32(ctx, fp0, fs);
12610 gen_load_fpr32(ctx, fp1, ft);
12611 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12612 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12613 tcg_temp_free_i32(fp0);
12614 tcg_temp_free_i32(fp1);
7c979afd 12615 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12616 tcg_temp_free_i32(fp2);
b6d96bed 12617 }
5a5012ec
TS
12618 break;
12619 case OPC_MADD_D:
b8aa4598
TS
12620 check_cop1x(ctx);
12621 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12622 {
a7812ae4
PB
12623 TCGv_i64 fp0 = tcg_temp_new_i64();
12624 TCGv_i64 fp1 = tcg_temp_new_i64();
12625 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12626
12627 gen_load_fpr64(ctx, fp0, fs);
12628 gen_load_fpr64(ctx, fp1, ft);
12629 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12630 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12631 tcg_temp_free_i64(fp0);
12632 tcg_temp_free_i64(fp1);
b6d96bed 12633 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12634 tcg_temp_free_i64(fp2);
b6d96bed 12635 }
5a5012ec
TS
12636 break;
12637 case OPC_MADD_PS:
e29c9628 12638 check_ps(ctx);
b6d96bed 12639 {
a7812ae4
PB
12640 TCGv_i64 fp0 = tcg_temp_new_i64();
12641 TCGv_i64 fp1 = tcg_temp_new_i64();
12642 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12643
12644 gen_load_fpr64(ctx, fp0, fs);
12645 gen_load_fpr64(ctx, fp1, ft);
12646 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12647 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12648 tcg_temp_free_i64(fp0);
12649 tcg_temp_free_i64(fp1);
b6d96bed 12650 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12651 tcg_temp_free_i64(fp2);
b6d96bed 12652 }
5a5012ec
TS
12653 break;
12654 case OPC_MSUB_S:
b8aa4598 12655 check_cop1x(ctx);
b6d96bed 12656 {
a7812ae4
PB
12657 TCGv_i32 fp0 = tcg_temp_new_i32();
12658 TCGv_i32 fp1 = tcg_temp_new_i32();
12659 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12660
7c979afd
LA
12661 gen_load_fpr32(ctx, fp0, fs);
12662 gen_load_fpr32(ctx, fp1, ft);
12663 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12664 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12665 tcg_temp_free_i32(fp0);
12666 tcg_temp_free_i32(fp1);
7c979afd 12667 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12668 tcg_temp_free_i32(fp2);
b6d96bed 12669 }
5a5012ec
TS
12670 break;
12671 case OPC_MSUB_D:
b8aa4598
TS
12672 check_cop1x(ctx);
12673 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12674 {
a7812ae4
PB
12675 TCGv_i64 fp0 = tcg_temp_new_i64();
12676 TCGv_i64 fp1 = tcg_temp_new_i64();
12677 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12678
12679 gen_load_fpr64(ctx, fp0, fs);
12680 gen_load_fpr64(ctx, fp1, ft);
12681 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12682 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12683 tcg_temp_free_i64(fp0);
12684 tcg_temp_free_i64(fp1);
b6d96bed 12685 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12686 tcg_temp_free_i64(fp2);
b6d96bed 12687 }
5a5012ec
TS
12688 break;
12689 case OPC_MSUB_PS:
e29c9628 12690 check_ps(ctx);
b6d96bed 12691 {
a7812ae4
PB
12692 TCGv_i64 fp0 = tcg_temp_new_i64();
12693 TCGv_i64 fp1 = tcg_temp_new_i64();
12694 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12695
12696 gen_load_fpr64(ctx, fp0, fs);
12697 gen_load_fpr64(ctx, fp1, ft);
12698 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12699 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12700 tcg_temp_free_i64(fp0);
12701 tcg_temp_free_i64(fp1);
b6d96bed 12702 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12703 tcg_temp_free_i64(fp2);
b6d96bed 12704 }
5a5012ec
TS
12705 break;
12706 case OPC_NMADD_S:
b8aa4598 12707 check_cop1x(ctx);
b6d96bed 12708 {
a7812ae4
PB
12709 TCGv_i32 fp0 = tcg_temp_new_i32();
12710 TCGv_i32 fp1 = tcg_temp_new_i32();
12711 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12712
7c979afd
LA
12713 gen_load_fpr32(ctx, fp0, fs);
12714 gen_load_fpr32(ctx, fp1, ft);
12715 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12716 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12717 tcg_temp_free_i32(fp0);
12718 tcg_temp_free_i32(fp1);
7c979afd 12719 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12720 tcg_temp_free_i32(fp2);
b6d96bed 12721 }
5a5012ec
TS
12722 break;
12723 case OPC_NMADD_D:
b8aa4598
TS
12724 check_cop1x(ctx);
12725 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12726 {
a7812ae4
PB
12727 TCGv_i64 fp0 = tcg_temp_new_i64();
12728 TCGv_i64 fp1 = tcg_temp_new_i64();
12729 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12730
12731 gen_load_fpr64(ctx, fp0, fs);
12732 gen_load_fpr64(ctx, fp1, ft);
12733 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12734 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12735 tcg_temp_free_i64(fp0);
12736 tcg_temp_free_i64(fp1);
b6d96bed 12737 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12738 tcg_temp_free_i64(fp2);
b6d96bed 12739 }
5a5012ec
TS
12740 break;
12741 case OPC_NMADD_PS:
e29c9628 12742 check_ps(ctx);
b6d96bed 12743 {
a7812ae4
PB
12744 TCGv_i64 fp0 = tcg_temp_new_i64();
12745 TCGv_i64 fp1 = tcg_temp_new_i64();
12746 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12747
12748 gen_load_fpr64(ctx, fp0, fs);
12749 gen_load_fpr64(ctx, fp1, ft);
12750 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12751 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12752 tcg_temp_free_i64(fp0);
12753 tcg_temp_free_i64(fp1);
b6d96bed 12754 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12755 tcg_temp_free_i64(fp2);
b6d96bed 12756 }
5a5012ec
TS
12757 break;
12758 case OPC_NMSUB_S:
b8aa4598 12759 check_cop1x(ctx);
b6d96bed 12760 {
a7812ae4
PB
12761 TCGv_i32 fp0 = tcg_temp_new_i32();
12762 TCGv_i32 fp1 = tcg_temp_new_i32();
12763 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12764
7c979afd
LA
12765 gen_load_fpr32(ctx, fp0, fs);
12766 gen_load_fpr32(ctx, fp1, ft);
12767 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12768 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12769 tcg_temp_free_i32(fp0);
12770 tcg_temp_free_i32(fp1);
7c979afd 12771 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12772 tcg_temp_free_i32(fp2);
b6d96bed 12773 }
5a5012ec
TS
12774 break;
12775 case OPC_NMSUB_D:
b8aa4598
TS
12776 check_cop1x(ctx);
12777 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12778 {
a7812ae4
PB
12779 TCGv_i64 fp0 = tcg_temp_new_i64();
12780 TCGv_i64 fp1 = tcg_temp_new_i64();
12781 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12782
12783 gen_load_fpr64(ctx, fp0, fs);
12784 gen_load_fpr64(ctx, fp1, ft);
12785 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12786 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12787 tcg_temp_free_i64(fp0);
12788 tcg_temp_free_i64(fp1);
b6d96bed 12789 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12790 tcg_temp_free_i64(fp2);
b6d96bed 12791 }
5a5012ec
TS
12792 break;
12793 case OPC_NMSUB_PS:
e29c9628 12794 check_ps(ctx);
b6d96bed 12795 {
a7812ae4
PB
12796 TCGv_i64 fp0 = tcg_temp_new_i64();
12797 TCGv_i64 fp1 = tcg_temp_new_i64();
12798 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12799
12800 gen_load_fpr64(ctx, fp0, fs);
12801 gen_load_fpr64(ctx, fp1, ft);
12802 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12803 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12804 tcg_temp_free_i64(fp0);
12805 tcg_temp_free_i64(fp1);
b6d96bed 12806 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12807 tcg_temp_free_i64(fp2);
b6d96bed 12808 }
5a5012ec 12809 break;
923617a3 12810 default:
9d68ac14 12811 MIPS_INVAL("flt3_arith");
9c708c7f 12812 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
12813 return;
12814 }
7a387fff
TS
12815}
12816
b00c7218 12817static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12818{
12819 TCGv t0;
12820
b3167288 12821#if !defined(CONFIG_USER_ONLY)
7480515f
AM
12822 /*
12823 * The Linux kernel will emulate rdhwr if it's not supported natively.
12824 * Therefore only check the ISA in system mode.
12825 */
d75c135e 12826 check_insn(ctx, ISA_MIPS32R2);
b3167288 12827#endif
26ebe468
NF
12828 t0 = tcg_temp_new();
12829
12830 switch (rd) {
12831 case 0:
895c2d04 12832 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12833 gen_store_gpr(t0, rt);
12834 break;
12835 case 1:
895c2d04 12836 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12837 gen_store_gpr(t0, rt);
12838 break;
12839 case 2:
eeb3bba8 12840 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12841 gen_io_start();
12842 }
895c2d04 12843 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 12844 gen_store_gpr(t0, rt);
7480515f
AM
12845 /*
12846 * Break the TB to be able to take timer interrupts immediately
12847 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12848 * we break completely out of translated code.
12849 */
eeb3bba8
EC
12850 gen_save_pc(ctx->base.pc_next + 4);
12851 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12852 break;
12853 case 3:
895c2d04 12854 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12855 gen_store_gpr(t0, rt);
12856 break;
b00c7218
YK
12857 case 4:
12858 check_insn(ctx, ISA_MIPS32R6);
12859 if (sel != 0) {
7480515f
AM
12860 /*
12861 * Performance counter registers are not implemented other than
b00c7218
YK
12862 * control register 0.
12863 */
12864 generate_exception(ctx, EXCP_RI);
12865 }
12866 gen_helper_rdhwr_performance(t0, cpu_env);
12867 gen_store_gpr(t0, rt);
12868 break;
12869 case 5:
12870 check_insn(ctx, ISA_MIPS32R6);
12871 gen_helper_rdhwr_xnp(t0, cpu_env);
12872 gen_store_gpr(t0, rt);
12873 break;
26ebe468
NF
12874 case 29:
12875#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12876 tcg_gen_ld_tl(t0, cpu_env,
12877 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12878 gen_store_gpr(t0, rt);
12879 break;
12880#else
d279279e
PJ
12881 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12882 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12883 tcg_gen_ld_tl(t0, cpu_env,
12884 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12885 gen_store_gpr(t0, rt);
12886 } else {
9c708c7f 12887 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
12888 }
12889 break;
26ebe468
NF
12890#endif
12891 default: /* Invalid */
12892 MIPS_INVAL("rdhwr");
9c708c7f 12893 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
12894 break;
12895 }
12896 tcg_temp_free(t0);
12897}
12898
a5f53390
LA
12899static inline void clear_branch_hflags(DisasContext *ctx)
12900{
12901 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12902 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12903 save_cpu_state(ctx, 0);
12904 } else {
7480515f
AM
12905 /*
12906 * It is not safe to save ctx->hflags as hflags may be changed
12907 * in execution time by the instruction in delay / forbidden slot.
12908 */
a5f53390
LA
12909 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12910 }
12911}
12912
31837be3 12913static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12914{
12915 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12916 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12917 /* Branches completion */
a5f53390 12918 clear_branch_hflags(ctx);
eeb3bba8 12919 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12920 /* FIXME: Need to clear can_do_io. */
364d4831 12921 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12922 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12923 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12924 break;
c9602061
NF
12925 case MIPS_HFLAG_B:
12926 /* unconditional branch */
364d4831
NF
12927 if (proc_hflags & MIPS_HFLAG_BX) {
12928 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12929 }
c9602061
NF
12930 gen_goto_tb(ctx, 0, ctx->btarget);
12931 break;
12932 case MIPS_HFLAG_BL:
12933 /* blikely taken case */
c9602061
NF
12934 gen_goto_tb(ctx, 0, ctx->btarget);
12935 break;
12936 case MIPS_HFLAG_BC:
12937 /* Conditional branch */
c9602061 12938 {
42a268c2 12939 TCGLabel *l1 = gen_new_label();
c9602061
NF
12940
12941 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12942 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12943 gen_set_label(l1);
12944 gen_goto_tb(ctx, 0, ctx->btarget);
12945 }
12946 break;
12947 case MIPS_HFLAG_BR:
12948 /* unconditional branch to register */
d75c135e 12949 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12950 TCGv t0 = tcg_temp_new();
12951 TCGv_i32 t1 = tcg_temp_new_i32();
12952
12953 tcg_gen_andi_tl(t0, btarget, 0x1);
12954 tcg_gen_trunc_tl_i32(t1, t0);
12955 tcg_temp_free(t0);
12956 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12957 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12958 tcg_gen_or_i32(hflags, hflags, t1);
12959 tcg_temp_free_i32(t1);
12960
12961 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12962 } else {
12963 tcg_gen_mov_tl(cpu_PC, btarget);
12964 }
eeb3bba8 12965 if (ctx->base.singlestep_enabled) {
c9602061 12966 save_cpu_state(ctx, 0);
9c708c7f 12967 gen_helper_raise_exception_debug(cpu_env);
c9602061 12968 }
7f11636d 12969 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12970 break;
12971 default:
a5f53390
LA
12972 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12973 abort();
c9602061
NF
12974 }
12975 }
12976}
12977
6893f074
YK
12978/* Compact Branches */
12979static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12980 int rs, int rt, int32_t offset)
12981{
12982 int bcond_compute = 0;
12983 TCGv t0 = tcg_temp_new();
12984 TCGv t1 = tcg_temp_new();
65935f07 12985 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12986
12987 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12988#ifdef MIPS_DEBUG_DISAS
12989 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12990 "\n", ctx->base.pc_next);
6893f074 12991#endif
9c708c7f 12992 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12993 goto out;
12994 }
12995
12996 /* Load needed operands and calculate btarget */
12997 switch (opc) {
12998 /* compact branch */
12999 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13000 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13001 gen_load_gpr(t0, rs);
13002 gen_load_gpr(t1, rt);
13003 bcond_compute = 1;
eeb3bba8 13004 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13005 if (rs <= rt && rs == 0) {
13006 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 13007 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13008 }
13009 break;
13010 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13011 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13012 gen_load_gpr(t0, rs);
13013 gen_load_gpr(t1, rt);
13014 bcond_compute = 1;
eeb3bba8 13015 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13016 break;
13017 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13018 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13019 if (rs == 0 || rs == rt) {
13020 /* OPC_BLEZALC, OPC_BGEZALC */
13021 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 13022 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13023 }
13024 gen_load_gpr(t0, rs);
13025 gen_load_gpr(t1, rt);
13026 bcond_compute = 1;
eeb3bba8 13027 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13028 break;
13029 case OPC_BC:
13030 case OPC_BALC:
eeb3bba8 13031 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13032 break;
13033 case OPC_BEQZC:
13034 case OPC_BNEZC:
13035 if (rs != 0) {
13036 /* OPC_BEQZC, OPC_BNEZC */
13037 gen_load_gpr(t0, rs);
13038 bcond_compute = 1;
eeb3bba8 13039 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13040 } else {
13041 /* OPC_JIC, OPC_JIALC */
13042 TCGv tbase = tcg_temp_new();
13043 TCGv toffset = tcg_temp_new();
13044
13045 gen_load_gpr(tbase, rt);
13046 tcg_gen_movi_tl(toffset, offset);
13047 gen_op_addr_add(ctx, btarget, tbase, toffset);
13048 tcg_temp_free(tbase);
13049 tcg_temp_free(toffset);
13050 }
13051 break;
13052 default:
13053 MIPS_INVAL("Compact branch/jump");
9c708c7f 13054 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13055 goto out;
13056 }
13057
13058 if (bcond_compute == 0) {
13059 /* Uncoditional compact branch */
13060 switch (opc) {
13061 case OPC_JIALC:
eeb3bba8 13062 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13063 /* Fallthrough */
13064 case OPC_JIC:
13065 ctx->hflags |= MIPS_HFLAG_BR;
13066 break;
13067 case OPC_BALC:
eeb3bba8 13068 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13069 /* Fallthrough */
13070 case OPC_BC:
13071 ctx->hflags |= MIPS_HFLAG_B;
13072 break;
13073 default:
13074 MIPS_INVAL("Compact branch/jump");
9c708c7f 13075 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13076 goto out;
13077 }
13078
13079 /* Generating branch here as compact branches don't have delay slot */
13080 gen_branch(ctx, 4);
13081 } else {
13082 /* Conditional compact branch */
13083 TCGLabel *fs = gen_new_label();
13084 save_cpu_state(ctx, 0);
13085
13086 switch (opc) {
13087 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13088 if (rs == 0 && rt != 0) {
13089 /* OPC_BLEZALC */
13090 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13091 } else if (rs != 0 && rt != 0 && rs == rt) {
13092 /* OPC_BGEZALC */
13093 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13094 } else {
13095 /* OPC_BGEUC */
13096 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13097 }
13098 break;
13099 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13100 if (rs == 0 && rt != 0) {
13101 /* OPC_BGTZALC */
13102 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13103 } else if (rs != 0 && rt != 0 && rs == rt) {
13104 /* OPC_BLTZALC */
13105 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13106 } else {
13107 /* OPC_BLTUC */
13108 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13109 }
13110 break;
13111 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13112 if (rs == 0 && rt != 0) {
13113 /* OPC_BLEZC */
13114 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13115 } else if (rs != 0 && rt != 0 && rs == rt) {
13116 /* OPC_BGEZC */
13117 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13118 } else {
13119 /* OPC_BGEC */
13120 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13121 }
13122 break;
13123 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13124 if (rs == 0 && rt != 0) {
13125 /* OPC_BGTZC */
13126 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13127 } else if (rs != 0 && rt != 0 && rs == rt) {
13128 /* OPC_BLTZC */
13129 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13130 } else {
13131 /* OPC_BLTC */
13132 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13133 }
13134 break;
13135 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13136 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13137 if (rs >= rt) {
13138 /* OPC_BOVC, OPC_BNVC */
13139 TCGv t2 = tcg_temp_new();
13140 TCGv t3 = tcg_temp_new();
13141 TCGv t4 = tcg_temp_new();
13142 TCGv input_overflow = tcg_temp_new();
13143
13144 gen_load_gpr(t0, rs);
13145 gen_load_gpr(t1, rt);
13146 tcg_gen_ext32s_tl(t2, t0);
13147 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13148 tcg_gen_ext32s_tl(t3, t1);
13149 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13150 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13151
13152 tcg_gen_add_tl(t4, t2, t3);
13153 tcg_gen_ext32s_tl(t4, t4);
13154 tcg_gen_xor_tl(t2, t2, t3);
13155 tcg_gen_xor_tl(t3, t4, t3);
13156 tcg_gen_andc_tl(t2, t3, t2);
13157 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13158 tcg_gen_or_tl(t4, t4, input_overflow);
13159 if (opc == OPC_BOVC) {
13160 /* OPC_BOVC */
13161 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13162 } else {
13163 /* OPC_BNVC */
13164 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13165 }
13166 tcg_temp_free(input_overflow);
13167 tcg_temp_free(t4);
13168 tcg_temp_free(t3);
13169 tcg_temp_free(t2);
13170 } else if (rs < rt && rs == 0) {
13171 /* OPC_BEQZALC, OPC_BNEZALC */
13172 if (opc == OPC_BEQZALC) {
13173 /* OPC_BEQZALC */
13174 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13175 } else {
13176 /* OPC_BNEZALC */
13177 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13178 }
13179 } else {
13180 /* OPC_BEQC, OPC_BNEC */
13181 if (opc == OPC_BEQC) {
13182 /* OPC_BEQC */
13183 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13184 } else {
13185 /* OPC_BNEC */
13186 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13187 }
13188 }
13189 break;
13190 case OPC_BEQZC:
13191 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13192 break;
13193 case OPC_BNEZC:
13194 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13195 break;
13196 default:
13197 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13198 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13199 goto out;
13200 }
13201
13202 /* Generating branch here as compact branches don't have delay slot */
13203 gen_goto_tb(ctx, 1, ctx->btarget);
13204 gen_set_label(fs);
13205
13206 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13207 }
13208
13209out:
13210 tcg_temp_free(t0);
13211 tcg_temp_free(t1);
13212}
13213
7a387fff 13214/* ISA extensions (ASEs) */
6af0bf9c 13215/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13216
13217/* MIPS16 major opcodes */
13218enum {
13219 M16_OPC_ADDIUSP = 0x00,
13220 M16_OPC_ADDIUPC = 0x01,
13221 M16_OPC_B = 0x02,
13222 M16_OPC_JAL = 0x03,
13223 M16_OPC_BEQZ = 0x04,
13224 M16_OPC_BNEQZ = 0x05,
13225 M16_OPC_SHIFT = 0x06,
13226 M16_OPC_LD = 0x07,
13227 M16_OPC_RRIA = 0x08,
13228 M16_OPC_ADDIU8 = 0x09,
13229 M16_OPC_SLTI = 0x0a,
13230 M16_OPC_SLTIU = 0x0b,
13231 M16_OPC_I8 = 0x0c,
13232 M16_OPC_LI = 0x0d,
13233 M16_OPC_CMPI = 0x0e,
13234 M16_OPC_SD = 0x0f,
13235 M16_OPC_LB = 0x10,
13236 M16_OPC_LH = 0x11,
13237 M16_OPC_LWSP = 0x12,
13238 M16_OPC_LW = 0x13,
13239 M16_OPC_LBU = 0x14,
13240 M16_OPC_LHU = 0x15,
13241 M16_OPC_LWPC = 0x16,
13242 M16_OPC_LWU = 0x17,
13243 M16_OPC_SB = 0x18,
13244 M16_OPC_SH = 0x19,
13245 M16_OPC_SWSP = 0x1a,
13246 M16_OPC_SW = 0x1b,
13247 M16_OPC_RRR = 0x1c,
13248 M16_OPC_RR = 0x1d,
13249 M16_OPC_EXTEND = 0x1e,
13250 M16_OPC_I64 = 0x1f
13251};
13252
13253/* I8 funct field */
13254enum {
13255 I8_BTEQZ = 0x0,
13256 I8_BTNEZ = 0x1,
13257 I8_SWRASP = 0x2,
13258 I8_ADJSP = 0x3,
13259 I8_SVRS = 0x4,
13260 I8_MOV32R = 0x5,
13261 I8_MOVR32 = 0x7
13262};
13263
13264/* RRR f field */
13265enum {
13266 RRR_DADDU = 0x0,
13267 RRR_ADDU = 0x1,
13268 RRR_DSUBU = 0x2,
13269 RRR_SUBU = 0x3
13270};
13271
13272/* RR funct field */
13273enum {
13274 RR_JR = 0x00,
13275 RR_SDBBP = 0x01,
13276 RR_SLT = 0x02,
13277 RR_SLTU = 0x03,
13278 RR_SLLV = 0x04,
13279 RR_BREAK = 0x05,
13280 RR_SRLV = 0x06,
13281 RR_SRAV = 0x07,
13282 RR_DSRL = 0x08,
13283 RR_CMP = 0x0a,
13284 RR_NEG = 0x0b,
13285 RR_AND = 0x0c,
13286 RR_OR = 0x0d,
13287 RR_XOR = 0x0e,
13288 RR_NOT = 0x0f,
13289 RR_MFHI = 0x10,
13290 RR_CNVT = 0x11,
13291 RR_MFLO = 0x12,
13292 RR_DSRA = 0x13,
13293 RR_DSLLV = 0x14,
13294 RR_DSRLV = 0x16,
13295 RR_DSRAV = 0x17,
13296 RR_MULT = 0x18,
13297 RR_MULTU = 0x19,
13298 RR_DIV = 0x1a,
13299 RR_DIVU = 0x1b,
13300 RR_DMULT = 0x1c,
13301 RR_DMULTU = 0x1d,
13302 RR_DDIV = 0x1e,
13303 RR_DDIVU = 0x1f
13304};
13305
13306/* I64 funct field */
13307enum {
13308 I64_LDSP = 0x0,
13309 I64_SDSP = 0x1,
13310 I64_SDRASP = 0x2,
13311 I64_DADJSP = 0x3,
13312 I64_LDPC = 0x4,
364d4831 13313 I64_DADDIU5 = 0x5,
6ea219d0
NF
13314 I64_DADDIUPC = 0x6,
13315 I64_DADDIUSP = 0x7
13316};
13317
13318/* RR ry field for CNVT */
13319enum {
13320 RR_RY_CNVT_ZEB = 0x0,
13321 RR_RY_CNVT_ZEH = 0x1,
13322 RR_RY_CNVT_ZEW = 0x2,
13323 RR_RY_CNVT_SEB = 0x4,
13324 RR_RY_CNVT_SEH = 0x5,
13325 RR_RY_CNVT_SEW = 0x6,
13326};
13327
235785e8 13328static int xlat(int r)
364d4831
NF
13329{
13330 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13331
13332 return map[r];
13333}
13334
235785e8
AM
13335static void gen_mips16_save(DisasContext *ctx,
13336 int xsregs, int aregs,
13337 int do_ra, int do_s0, int do_s1,
13338 int framesize)
364d4831
NF
13339{
13340 TCGv t0 = tcg_temp_new();
13341 TCGv t1 = tcg_temp_new();
c48245f0 13342 TCGv t2 = tcg_temp_new();
364d4831
NF
13343 int args, astatic;
13344
13345 switch (aregs) {
13346 case 0:
13347 case 1:
13348 case 2:
13349 case 3:
13350 case 11:
13351 args = 0;
13352 break;
13353 case 4:
13354 case 5:
13355 case 6:
13356 case 7:
13357 args = 1;
13358 break;
13359 case 8:
13360 case 9:
13361 case 10:
13362 args = 2;
13363 break;
13364 case 12:
13365 case 13:
13366 args = 3;
13367 break;
13368 case 14:
13369 args = 4;
13370 break;
13371 default:
9c708c7f 13372 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13373 return;
13374 }
13375
13376 switch (args) {
13377 case 4:
13378 gen_base_offset_addr(ctx, t0, 29, 12);
13379 gen_load_gpr(t1, 7);
5f68f5ae 13380 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13381 /* Fall through */
13382 case 3:
13383 gen_base_offset_addr(ctx, t0, 29, 8);
13384 gen_load_gpr(t1, 6);
5f68f5ae 13385 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13386 /* Fall through */
13387 case 2:
13388 gen_base_offset_addr(ctx, t0, 29, 4);
13389 gen_load_gpr(t1, 5);
5f68f5ae 13390 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13391 /* Fall through */
13392 case 1:
13393 gen_base_offset_addr(ctx, t0, 29, 0);
13394 gen_load_gpr(t1, 4);
5f68f5ae 13395 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13396 }
13397
13398 gen_load_gpr(t0, 29);
13399
5f68f5ae 13400#define DECR_AND_STORE(reg) do { \
c48245f0
MR
13401 tcg_gen_movi_tl(t2, -4); \
13402 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13403 gen_load_gpr(t1, reg); \
13404 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
13405 } while (0)
13406
13407 if (do_ra) {
13408 DECR_AND_STORE(31);
13409 }
13410
13411 switch (xsregs) {
13412 case 7:
13413 DECR_AND_STORE(30);
13414 /* Fall through */
13415 case 6:
13416 DECR_AND_STORE(23);
13417 /* Fall through */
13418 case 5:
13419 DECR_AND_STORE(22);
13420 /* Fall through */
13421 case 4:
13422 DECR_AND_STORE(21);
13423 /* Fall through */
13424 case 3:
13425 DECR_AND_STORE(20);
13426 /* Fall through */
13427 case 2:
13428 DECR_AND_STORE(19);
13429 /* Fall through */
13430 case 1:
13431 DECR_AND_STORE(18);
13432 }
13433
13434 if (do_s1) {
13435 DECR_AND_STORE(17);
13436 }
13437 if (do_s0) {
13438 DECR_AND_STORE(16);
13439 }
13440
13441 switch (aregs) {
13442 case 0:
13443 case 4:
13444 case 8:
13445 case 12:
13446 case 14:
13447 astatic = 0;
13448 break;
13449 case 1:
13450 case 5:
13451 case 9:
13452 case 13:
13453 astatic = 1;
13454 break;
13455 case 2:
13456 case 6:
13457 case 10:
13458 astatic = 2;
13459 break;
13460 case 3:
13461 case 7:
13462 astatic = 3;
13463 break;
13464 case 11:
13465 astatic = 4;
13466 break;
13467 default:
9c708c7f 13468 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13469 return;
13470 }
13471
13472 if (astatic > 0) {
13473 DECR_AND_STORE(7);
13474 if (astatic > 1) {
13475 DECR_AND_STORE(6);
13476 if (astatic > 2) {
13477 DECR_AND_STORE(5);
13478 if (astatic > 3) {
13479 DECR_AND_STORE(4);
13480 }
13481 }
13482 }
13483 }
13484#undef DECR_AND_STORE
13485
c48245f0
MR
13486 tcg_gen_movi_tl(t2, -framesize);
13487 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13488 tcg_temp_free(t0);
13489 tcg_temp_free(t1);
c48245f0 13490 tcg_temp_free(t2);
364d4831
NF
13491}
13492
235785e8
AM
13493static void gen_mips16_restore(DisasContext *ctx,
13494 int xsregs, int aregs,
13495 int do_ra, int do_s0, int do_s1,
13496 int framesize)
364d4831
NF
13497{
13498 int astatic;
13499 TCGv t0 = tcg_temp_new();
13500 TCGv t1 = tcg_temp_new();
c48245f0 13501 TCGv t2 = tcg_temp_new();
364d4831 13502
c48245f0
MR
13503 tcg_gen_movi_tl(t2, framesize);
13504 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13505
5f68f5ae 13506#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13507 tcg_gen_movi_tl(t2, -4); \
13508 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13509 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13510 gen_store_gpr(t1, reg); \
364d4831
NF
13511 } while (0)
13512
13513 if (do_ra) {
13514 DECR_AND_LOAD(31);
13515 }
13516
13517 switch (xsregs) {
13518 case 7:
13519 DECR_AND_LOAD(30);
13520 /* Fall through */
13521 case 6:
13522 DECR_AND_LOAD(23);
13523 /* Fall through */
13524 case 5:
13525 DECR_AND_LOAD(22);
13526 /* Fall through */
13527 case 4:
13528 DECR_AND_LOAD(21);
13529 /* Fall through */
13530 case 3:
13531 DECR_AND_LOAD(20);
13532 /* Fall through */
13533 case 2:
13534 DECR_AND_LOAD(19);
13535 /* Fall through */
13536 case 1:
13537 DECR_AND_LOAD(18);
13538 }
13539
13540 if (do_s1) {
13541 DECR_AND_LOAD(17);
13542 }
13543 if (do_s0) {
13544 DECR_AND_LOAD(16);
13545 }
13546
13547 switch (aregs) {
13548 case 0:
13549 case 4:
13550 case 8:
13551 case 12:
13552 case 14:
13553 astatic = 0;
13554 break;
13555 case 1:
13556 case 5:
13557 case 9:
13558 case 13:
13559 astatic = 1;
13560 break;
13561 case 2:
13562 case 6:
13563 case 10:
13564 astatic = 2;
13565 break;
13566 case 3:
13567 case 7:
13568 astatic = 3;
13569 break;
13570 case 11:
13571 astatic = 4;
13572 break;
13573 default:
9c708c7f 13574 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13575 return;
13576 }
13577
13578 if (astatic > 0) {
13579 DECR_AND_LOAD(7);
13580 if (astatic > 1) {
13581 DECR_AND_LOAD(6);
13582 if (astatic > 2) {
13583 DECR_AND_LOAD(5);
13584 if (astatic > 3) {
13585 DECR_AND_LOAD(4);
13586 }
13587 }
13588 }
13589 }
13590#undef DECR_AND_LOAD
13591
c48245f0
MR
13592 tcg_gen_movi_tl(t2, framesize);
13593 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13594 tcg_temp_free(t0);
13595 tcg_temp_free(t1);
c48245f0 13596 tcg_temp_free(t2);
364d4831
NF
13597}
13598
235785e8
AM
13599static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13600 int is_64_bit, int extended)
364d4831
NF
13601{
13602 TCGv t0;
13603
13604 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13605 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13606 return;
13607 }
13608
13609 t0 = tcg_temp_new();
13610
13611 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13612 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13613 if (!is_64_bit) {
13614 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13615 }
13616
13617 tcg_temp_free(t0);
13618}
13619
0d74a222
LA
13620static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13621 int16_t offset)
13622{
13623 TCGv_i32 t0 = tcg_const_i32(op);
13624 TCGv t1 = tcg_temp_new();
13625 gen_base_offset_addr(ctx, t1, base, offset);
13626 gen_helper_cache(cpu_env, t1, t0);
13627}
13628
364d4831 13629#if defined(TARGET_MIPS64)
235785e8
AM
13630static void decode_i64_mips16(DisasContext *ctx,
13631 int ry, int funct, int16_t offset,
13632 int extended)
364d4831
NF
13633{
13634 switch (funct) {
13635 case I64_LDSP:
d9224450 13636 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13637 check_mips_64(ctx);
13638 offset = extended ? offset : offset << 3;
d75c135e 13639 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13640 break;
13641 case I64_SDSP:
d9224450 13642 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13643 check_mips_64(ctx);
13644 offset = extended ? offset : offset << 3;
5c13fdfd 13645 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13646 break;
13647 case I64_SDRASP:
d9224450 13648 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13649 check_mips_64(ctx);
13650 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13651 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13652 break;
13653 case I64_DADJSP:
d9224450 13654 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13655 check_mips_64(ctx);
13656 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13657 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13658 break;
13659 case I64_LDPC:
d9224450
MR
13660 check_insn(ctx, ISA_MIPS3);
13661 check_mips_64(ctx);
364d4831 13662 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13663 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13664 } else {
13665 offset = extended ? offset : offset << 3;
d75c135e 13666 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13667 }
13668 break;
13669 case I64_DADDIU5:
d9224450 13670 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13671 check_mips_64(ctx);
13672 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13673 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13674 break;
13675 case I64_DADDIUPC:
d9224450 13676 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13677 check_mips_64(ctx);
13678 offset = extended ? offset : offset << 2;
13679 gen_addiupc(ctx, ry, offset, 1, extended);
13680 break;
13681 case I64_DADDIUSP:
d9224450 13682 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13683 check_mips_64(ctx);
13684 offset = extended ? offset : offset << 2;
d75c135e 13685 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13686 break;
13687 }
13688}
13689#endif
13690
235785e8 13691static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 13692{
eeb3bba8 13693 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13694 int op, rx, ry, funct, sa;
13695 int16_t imm, offset;
13696
13697 ctx->opcode = (ctx->opcode << 16) | extend;
13698 op = (ctx->opcode >> 11) & 0x1f;
13699 sa = (ctx->opcode >> 22) & 0x1f;
13700 funct = (ctx->opcode >> 8) & 0x7;
13701 rx = xlat((ctx->opcode >> 8) & 0x7);
13702 ry = xlat((ctx->opcode >> 5) & 0x7);
13703 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13704 | ((ctx->opcode >> 21) & 0x3f) << 5
13705 | (ctx->opcode & 0x1f));
13706
7480515f
AM
13707 /*
13708 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13709 * counterparts.
13710 */
364d4831
NF
13711 switch (op) {
13712 case M16_OPC_ADDIUSP:
d75c135e 13713 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13714 break;
13715 case M16_OPC_ADDIUPC:
13716 gen_addiupc(ctx, rx, imm, 0, 1);
13717 break;
13718 case M16_OPC_B:
b231c103 13719 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13720 /* No delay slot, so just process as a normal instruction */
13721 break;
13722 case M16_OPC_BEQZ:
b231c103 13723 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13724 /* No delay slot, so just process as a normal instruction */
13725 break;
13726 case M16_OPC_BNEQZ:
b231c103 13727 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13728 /* No delay slot, so just process as a normal instruction */
13729 break;
13730 case M16_OPC_SHIFT:
13731 switch (ctx->opcode & 0x3) {
13732 case 0x0:
d75c135e 13733 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13734 break;
13735 case 0x1:
13736#if defined(TARGET_MIPS64)
13737 check_mips_64(ctx);
d75c135e 13738 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13739#else
9c708c7f 13740 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13741#endif
13742 break;
13743 case 0x2:
d75c135e 13744 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13745 break;
13746 case 0x3:
d75c135e 13747 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13748 break;
13749 }
13750 break;
13751#if defined(TARGET_MIPS64)
13752 case M16_OPC_LD:
d9224450 13753 check_insn(ctx, ISA_MIPS3);
d75de749 13754 check_mips_64(ctx);
d75c135e 13755 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13756 break;
13757#endif
13758 case M16_OPC_RRIA:
13759 imm = ctx->opcode & 0xf;
13760 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13761 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13762 imm = (int16_t) (imm << 1) >> 1;
13763 if ((ctx->opcode >> 4) & 0x1) {
13764#if defined(TARGET_MIPS64)
13765 check_mips_64(ctx);
d75c135e 13766 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13767#else
9c708c7f 13768 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13769#endif
13770 } else {
d75c135e 13771 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13772 }
13773 break;
13774 case M16_OPC_ADDIU8:
d75c135e 13775 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13776 break;
13777 case M16_OPC_SLTI:
d75c135e 13778 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13779 break;
13780 case M16_OPC_SLTIU:
d75c135e 13781 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13782 break;
13783 case M16_OPC_I8:
13784 switch (funct) {
13785 case I8_BTEQZ:
b231c103 13786 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13787 break;
13788 case I8_BTNEZ:
b231c103 13789 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13790 break;
13791 case I8_SWRASP:
5c13fdfd 13792 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13793 break;
13794 case I8_ADJSP:
d75c135e 13795 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13796 break;
13797 case I8_SVRS:
d9224450 13798 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13799 {
13800 int xsregs = (ctx->opcode >> 24) & 0x7;
13801 int aregs = (ctx->opcode >> 16) & 0xf;
13802 int do_ra = (ctx->opcode >> 6) & 0x1;
13803 int do_s0 = (ctx->opcode >> 5) & 0x1;
13804 int do_s1 = (ctx->opcode >> 4) & 0x1;
13805 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13806 | (ctx->opcode & 0xf)) << 3;
13807
13808 if (ctx->opcode & (1 << 7)) {
13809 gen_mips16_save(ctx, xsregs, aregs,
13810 do_ra, do_s0, do_s1,
13811 framesize);
13812 } else {
13813 gen_mips16_restore(ctx, xsregs, aregs,
13814 do_ra, do_s0, do_s1,
13815 framesize);
13816 }
13817 }
13818 break;
13819 default:
9c708c7f 13820 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13821 break;
13822 }
13823 break;
13824 case M16_OPC_LI:
13825 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13826 break;
13827 case M16_OPC_CMPI:
13828 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13829 break;
13830#if defined(TARGET_MIPS64)
13831 case M16_OPC_SD:
d9224450
MR
13832 check_insn(ctx, ISA_MIPS3);
13833 check_mips_64(ctx);
5c13fdfd 13834 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13835 break;
13836#endif
13837 case M16_OPC_LB:
d75c135e 13838 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13839 break;
13840 case M16_OPC_LH:
d75c135e 13841 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13842 break;
13843 case M16_OPC_LWSP:
d75c135e 13844 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13845 break;
13846 case M16_OPC_LW:
d75c135e 13847 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13848 break;
13849 case M16_OPC_LBU:
d75c135e 13850 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13851 break;
13852 case M16_OPC_LHU:
d75c135e 13853 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13854 break;
13855 case M16_OPC_LWPC:
d75c135e 13856 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13857 break;
13858#if defined(TARGET_MIPS64)
13859 case M16_OPC_LWU:
d9224450
MR
13860 check_insn(ctx, ISA_MIPS3);
13861 check_mips_64(ctx);
d75c135e 13862 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13863 break;
13864#endif
13865 case M16_OPC_SB:
5c13fdfd 13866 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13867 break;
13868 case M16_OPC_SH:
5c13fdfd 13869 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13870 break;
13871 case M16_OPC_SWSP:
5c13fdfd 13872 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13873 break;
13874 case M16_OPC_SW:
5c13fdfd 13875 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13876 break;
13877#if defined(TARGET_MIPS64)
13878 case M16_OPC_I64:
d75c135e 13879 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13880 break;
13881#endif
13882 default:
9c708c7f 13883 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13884 break;
13885 }
13886
13887 return 4;
13888}
13889
3b3c1694
LA
13890static inline bool is_uhi(int sdbbp_code)
13891{
13892#ifdef CONFIG_USER_ONLY
13893 return false;
13894#else
13895 return semihosting_enabled() && sdbbp_code == 1;
13896#endif
13897}
13898
82ba4266
AB
13899#ifdef CONFIG_USER_ONLY
13900/* The above should dead-code away any calls to this..*/
13901static inline void gen_helper_do_semihosting(void *env)
13902{
13903 g_assert_not_reached();
13904}
13905#endif
13906
235785e8 13907static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13908{
13909 int rx, ry;
13910 int sa;
13911 int op, cnvt_op, op1, offset;
13912 int funct;
13913 int n_bytes;
13914
13915 op = (ctx->opcode >> 11) & 0x1f;
13916 sa = (ctx->opcode >> 2) & 0x7;
13917 sa = sa == 0 ? 8 : sa;
13918 rx = xlat((ctx->opcode >> 8) & 0x7);
13919 cnvt_op = (ctx->opcode >> 5) & 0x7;
13920 ry = xlat((ctx->opcode >> 5) & 0x7);
13921 op1 = offset = ctx->opcode & 0x1f;
13922
13923 n_bytes = 2;
13924
13925 switch (op) {
13926 case M16_OPC_ADDIUSP:
13927 {
13928 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13929
d75c135e 13930 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13931 }
13932 break;
13933 case M16_OPC_ADDIUPC:
13934 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13935 break;
13936 case M16_OPC_B:
13937 offset = (ctx->opcode & 0x7ff) << 1;
13938 offset = (int16_t)(offset << 4) >> 4;
b231c103 13939 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13940 /* No delay slot, so just process as a normal instruction */
13941 break;
13942 case M16_OPC_JAL:
eeb3bba8 13943 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13944 offset = (((ctx->opcode & 0x1f) << 21)
13945 | ((ctx->opcode >> 5) & 0x1f) << 16
13946 | offset) << 2;
b231c103
YK
13947 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13948 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13949 n_bytes = 4;
364d4831
NF
13950 break;
13951 case M16_OPC_BEQZ:
b231c103
YK
13952 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13953 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13954 /* No delay slot, so just process as a normal instruction */
13955 break;
13956 case M16_OPC_BNEQZ:
b231c103
YK
13957 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13958 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13959 /* No delay slot, so just process as a normal instruction */
13960 break;
13961 case M16_OPC_SHIFT:
13962 switch (ctx->opcode & 0x3) {
13963 case 0x0:
d75c135e 13964 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13965 break;
13966 case 0x1:
13967#if defined(TARGET_MIPS64)
d9224450 13968 check_insn(ctx, ISA_MIPS3);
364d4831 13969 check_mips_64(ctx);
d75c135e 13970 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13971#else
9c708c7f 13972 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13973#endif
13974 break;
13975 case 0x2:
d75c135e 13976 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13977 break;
13978 case 0x3:
d75c135e 13979 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13980 break;
13981 }
13982 break;
13983#if defined(TARGET_MIPS64)
13984 case M16_OPC_LD:
d9224450 13985 check_insn(ctx, ISA_MIPS3);
364d4831 13986 check_mips_64(ctx);
d75c135e 13987 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13988 break;
13989#endif
13990 case M16_OPC_RRIA:
13991 {
13992 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13993
13994 if ((ctx->opcode >> 4) & 1) {
13995#if defined(TARGET_MIPS64)
d9224450 13996 check_insn(ctx, ISA_MIPS3);
364d4831 13997 check_mips_64(ctx);
d75c135e 13998 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13999#else
9c708c7f 14000 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14001#endif
14002 } else {
d75c135e 14003 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14004 }
14005 }
14006 break;
14007 case M16_OPC_ADDIU8:
14008 {
14009 int16_t imm = (int8_t) ctx->opcode;
14010
d75c135e 14011 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14012 }
14013 break;
14014 case M16_OPC_SLTI:
14015 {
14016 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14017 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14018 }
14019 break;
14020 case M16_OPC_SLTIU:
14021 {
14022 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14023 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14024 }
14025 break;
14026 case M16_OPC_I8:
14027 {
14028 int reg32;
14029
14030 funct = (ctx->opcode >> 8) & 0x7;
14031 switch (funct) {
14032 case I8_BTEQZ:
14033 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 14034 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14035 break;
14036 case I8_BTNEZ:
14037 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 14038 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14039 break;
14040 case I8_SWRASP:
5c13fdfd 14041 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
14042 break;
14043 case I8_ADJSP:
d75c135e 14044 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
14045 ((int8_t)ctx->opcode) << 3);
14046 break;
14047 case I8_SVRS:
d9224450 14048 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14049 {
14050 int do_ra = ctx->opcode & (1 << 6);
14051 int do_s0 = ctx->opcode & (1 << 5);
14052 int do_s1 = ctx->opcode & (1 << 4);
14053 int framesize = ctx->opcode & 0xf;
14054
14055 if (framesize == 0) {
14056 framesize = 128;
14057 } else {
14058 framesize = framesize << 3;
14059 }
14060
14061 if (ctx->opcode & (1 << 7)) {
14062 gen_mips16_save(ctx, 0, 0,
14063 do_ra, do_s0, do_s1, framesize);
14064 } else {
14065 gen_mips16_restore(ctx, 0, 0,
14066 do_ra, do_s0, do_s1, framesize);
14067 }
14068 }
14069 break;
14070 case I8_MOV32R:
14071 {
14072 int rz = xlat(ctx->opcode & 0x7);
14073
14074 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14075 ((ctx->opcode >> 5) & 0x7);
d75c135e 14076 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
14077 }
14078 break;
14079 case I8_MOVR32:
14080 reg32 = ctx->opcode & 0x1f;
d75c135e 14081 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
14082 break;
14083 default:
9c708c7f 14084 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14085 break;
14086 }
14087 }
14088 break;
14089 case M16_OPC_LI:
14090 {
14091 int16_t imm = (uint8_t) ctx->opcode;
14092
d75c135e 14093 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
14094 }
14095 break;
14096 case M16_OPC_CMPI:
14097 {
14098 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14099 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
14100 }
14101 break;
14102#if defined(TARGET_MIPS64)
14103 case M16_OPC_SD:
d9224450 14104 check_insn(ctx, ISA_MIPS3);
364d4831 14105 check_mips_64(ctx);
5c13fdfd 14106 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
14107 break;
14108#endif
14109 case M16_OPC_LB:
d75c135e 14110 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14111 break;
14112 case M16_OPC_LH:
d75c135e 14113 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
14114 break;
14115 case M16_OPC_LWSP:
d75c135e 14116 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14117 break;
14118 case M16_OPC_LW:
d75c135e 14119 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
14120 break;
14121 case M16_OPC_LBU:
d75c135e 14122 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14123 break;
14124 case M16_OPC_LHU:
d75c135e 14125 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
14126 break;
14127 case M16_OPC_LWPC:
d75c135e 14128 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 14129 break;
235785e8 14130#if defined(TARGET_MIPS64)
364d4831 14131 case M16_OPC_LWU:
d9224450 14132 check_insn(ctx, ISA_MIPS3);
364d4831 14133 check_mips_64(ctx);
d75c135e 14134 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
14135 break;
14136#endif
14137 case M16_OPC_SB:
5c13fdfd 14138 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14139 break;
14140 case M16_OPC_SH:
5c13fdfd 14141 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14142 break;
14143 case M16_OPC_SWSP:
5c13fdfd 14144 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14145 break;
14146 case M16_OPC_SW:
5c13fdfd 14147 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14148 break;
14149 case M16_OPC_RRR:
14150 {
14151 int rz = xlat((ctx->opcode >> 2) & 0x7);
14152 int mips32_op;
14153
14154 switch (ctx->opcode & 0x3) {
14155 case RRR_ADDU:
14156 mips32_op = OPC_ADDU;
14157 break;
14158 case RRR_SUBU:
14159 mips32_op = OPC_SUBU;
14160 break;
14161#if defined(TARGET_MIPS64)
14162 case RRR_DADDU:
14163 mips32_op = OPC_DADDU;
d9224450 14164 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14165 check_mips_64(ctx);
14166 break;
14167 case RRR_DSUBU:
14168 mips32_op = OPC_DSUBU;
d9224450 14169 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14170 check_mips_64(ctx);
14171 break;
14172#endif
14173 default:
9c708c7f 14174 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14175 goto done;
14176 }
14177
d75c135e 14178 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14179 done:
14180 ;
14181 }
14182 break;
14183 case M16_OPC_RR:
14184 switch (op1) {
14185 case RR_JR:
14186 {
14187 int nd = (ctx->opcode >> 7) & 0x1;
14188 int link = (ctx->opcode >> 6) & 0x1;
14189 int ra = (ctx->opcode >> 5) & 0x1;
14190
d9224450
MR
14191 if (nd) {
14192 check_insn(ctx, ISA_MIPS32);
14193 }
14194
364d4831 14195 if (link) {
b231c103 14196 op = OPC_JALR;
364d4831
NF
14197 } else {
14198 op = OPC_JR;
14199 }
14200
b231c103
YK
14201 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14202 (nd ? 0 : 2));
364d4831
NF
14203 }
14204 break;
14205 case RR_SDBBP:
3b3c1694
LA
14206 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14207 gen_helper_do_semihosting(cpu_env);
14208 } else {
7480515f
AM
14209 /*
14210 * XXX: not clear which exception should be raised
3b3c1694
LA
14211 * when in debug mode...
14212 */
14213 check_insn(ctx, ISA_MIPS32);
9c708c7f 14214 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14215 }
364d4831
NF
14216 break;
14217 case RR_SLT:
d75c135e 14218 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14219 break;
14220 case RR_SLTU:
d75c135e 14221 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14222 break;
14223 case RR_BREAK:
9c708c7f 14224 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14225 break;
14226 case RR_SLLV:
d75c135e 14227 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14228 break;
14229 case RR_SRLV:
d75c135e 14230 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14231 break;
14232 case RR_SRAV:
d75c135e 14233 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 14234 break;
235785e8 14235#if defined(TARGET_MIPS64)
364d4831 14236 case RR_DSRL:
d9224450 14237 check_insn(ctx, ISA_MIPS3);
364d4831 14238 check_mips_64(ctx);
d75c135e 14239 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14240 break;
14241#endif
14242 case RR_CMP:
d75c135e 14243 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14244 break;
14245 case RR_NEG:
d75c135e 14246 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14247 break;
14248 case RR_AND:
d75c135e 14249 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14250 break;
14251 case RR_OR:
d75c135e 14252 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14253 break;
14254 case RR_XOR:
d75c135e 14255 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14256 break;
14257 case RR_NOT:
d75c135e 14258 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14259 break;
14260 case RR_MFHI:
26135ead 14261 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14262 break;
14263 case RR_CNVT:
d9224450 14264 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14265 switch (cnvt_op) {
14266 case RR_RY_CNVT_ZEB:
14267 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14268 break;
14269 case RR_RY_CNVT_ZEH:
14270 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14271 break;
14272 case RR_RY_CNVT_SEB:
14273 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14274 break;
14275 case RR_RY_CNVT_SEH:
14276 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14277 break;
71375b59 14278#if defined(TARGET_MIPS64)
364d4831 14279 case RR_RY_CNVT_ZEW:
d9224450 14280 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14281 check_mips_64(ctx);
14282 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14283 break;
14284 case RR_RY_CNVT_SEW:
d9224450 14285 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14286 check_mips_64(ctx);
14287 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14288 break;
14289#endif
14290 default:
9c708c7f 14291 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14292 break;
14293 }
14294 break;
14295 case RR_MFLO:
26135ead 14296 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 14297 break;
235785e8 14298#if defined(TARGET_MIPS64)
364d4831 14299 case RR_DSRA:
d9224450 14300 check_insn(ctx, ISA_MIPS3);
364d4831 14301 check_mips_64(ctx);
d75c135e 14302 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14303 break;
14304 case RR_DSLLV:
d9224450 14305 check_insn(ctx, ISA_MIPS3);
364d4831 14306 check_mips_64(ctx);
d75c135e 14307 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14308 break;
14309 case RR_DSRLV:
d9224450 14310 check_insn(ctx, ISA_MIPS3);
364d4831 14311 check_mips_64(ctx);
d75c135e 14312 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14313 break;
14314 case RR_DSRAV:
d9224450 14315 check_insn(ctx, ISA_MIPS3);
364d4831 14316 check_mips_64(ctx);
d75c135e 14317 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14318 break;
14319#endif
14320 case RR_MULT:
26135ead 14321 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14322 break;
14323 case RR_MULTU:
26135ead 14324 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14325 break;
14326 case RR_DIV:
26135ead 14327 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14328 break;
14329 case RR_DIVU:
26135ead 14330 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 14331 break;
235785e8 14332#if defined(TARGET_MIPS64)
364d4831 14333 case RR_DMULT:
d9224450 14334 check_insn(ctx, ISA_MIPS3);
364d4831 14335 check_mips_64(ctx);
26135ead 14336 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14337 break;
14338 case RR_DMULTU:
d9224450 14339 check_insn(ctx, ISA_MIPS3);
364d4831 14340 check_mips_64(ctx);
26135ead 14341 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14342 break;
14343 case RR_DDIV:
d9224450 14344 check_insn(ctx, ISA_MIPS3);
364d4831 14345 check_mips_64(ctx);
26135ead 14346 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14347 break;
14348 case RR_DDIVU:
d9224450 14349 check_insn(ctx, ISA_MIPS3);
364d4831 14350 check_mips_64(ctx);
26135ead 14351 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14352 break;
14353#endif
14354 default:
9c708c7f 14355 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14356 break;
14357 }
14358 break;
14359 case M16_OPC_EXTEND:
240ce26a 14360 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14361 n_bytes = 4;
14362 break;
14363#if defined(TARGET_MIPS64)
14364 case M16_OPC_I64:
14365 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14366 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14367 break;
14368#endif
14369 default:
9c708c7f 14370 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14371 break;
14372 }
14373
14374 return n_bytes;
14375}
14376
211da992 14377/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 14378
211da992
CWR
14379/*
14380 * microMIPS32/microMIPS64 major opcodes
14381 *
14382 * 1. MIPS Architecture for Programmers Volume II-B:
14383 * The microMIPS32 Instruction Set (Revision 3.05)
14384 *
14385 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14386 *
14387 * 2. MIPS Architecture For Programmers Volume II-A:
14388 * The MIPS64 Instruction Set (Revision 3.51)
14389 */
6af0bf9c 14390
3c824109
NF
14391enum {
14392 POOL32A = 0x00,
14393 POOL16A = 0x01,
14394 LBU16 = 0x02,
14395 MOVE16 = 0x03,
14396 ADDI32 = 0x04,
3a1f4268
YK
14397 R6_LUI = 0x04,
14398 AUI = 0x04,
3c824109
NF
14399 LBU32 = 0x05,
14400 SB32 = 0x06,
14401 LB32 = 0x07,
14402
14403 POOL32B = 0x08,
14404 POOL16B = 0x09,
14405 LHU16 = 0x0a,
14406 ANDI16 = 0x0b,
14407 ADDIU32 = 0x0c,
14408 LHU32 = 0x0d,
14409 SH32 = 0x0e,
14410 LH32 = 0x0f,
14411
14412 POOL32I = 0x10,
14413 POOL16C = 0x11,
14414 LWSP16 = 0x12,
14415 POOL16D = 0x13,
14416 ORI32 = 0x14,
14417 POOL32F = 0x15,
211da992
CWR
14418 POOL32S = 0x16, /* MIPS64 */
14419 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
14420
14421 POOL32C = 0x18,
14422 LWGP16 = 0x19,
14423 LW16 = 0x1a,
14424 POOL16E = 0x1b,
14425 XORI32 = 0x1c,
14426 JALS32 = 0x1d,
3a1f4268
YK
14427 BOVC = 0x1d,
14428 BEQC = 0x1d,
14429 BEQZALC = 0x1d,
3c824109 14430 ADDIUPC = 0x1e,
3a1f4268
YK
14431 PCREL = 0x1e,
14432 BNVC = 0x1f,
14433 BNEC = 0x1f,
14434 BNEZALC = 0x1f,
3c824109 14435
3a1f4268
YK
14436 R6_BEQZC = 0x20,
14437 JIC = 0x20,
3c824109
NF
14438 POOL16F = 0x21,
14439 SB16 = 0x22,
14440 BEQZ16 = 0x23,
3a1f4268 14441 BEQZC16 = 0x23,
3c824109
NF
14442 SLTI32 = 0x24,
14443 BEQ32 = 0x25,
3a1f4268 14444 BC = 0x25,
3c824109
NF
14445 SWC132 = 0x26,
14446 LWC132 = 0x27,
14447
3a1f4268 14448 /* 0x29 is reserved */
3c824109 14449 RES_29 = 0x29,
3a1f4268
YK
14450 R6_BNEZC = 0x28,
14451 JIALC = 0x28,
3c824109
NF
14452 SH16 = 0x2a,
14453 BNEZ16 = 0x2b,
3a1f4268 14454 BNEZC16 = 0x2b,
3c824109
NF
14455 SLTIU32 = 0x2c,
14456 BNE32 = 0x2d,
3a1f4268 14457 BALC = 0x2d,
3c824109
NF
14458 SDC132 = 0x2e,
14459 LDC132 = 0x2f,
14460
3a1f4268 14461 /* 0x31 is reserved */
3c824109 14462 RES_31 = 0x31,
3a1f4268
YK
14463 BLEZALC = 0x30,
14464 BGEZALC = 0x30,
14465 BGEUC = 0x30,
3c824109
NF
14466 SWSP16 = 0x32,
14467 B16 = 0x33,
3a1f4268 14468 BC16 = 0x33,
3c824109
NF
14469 ANDI32 = 0x34,
14470 J32 = 0x35,
3a1f4268
YK
14471 BGTZC = 0x35,
14472 BLTZC = 0x35,
14473 BLTC = 0x35,
211da992
CWR
14474 SD32 = 0x36, /* MIPS64 */
14475 LD32 = 0x37, /* MIPS64 */
3c824109 14476
3a1f4268 14477 /* 0x39 is reserved */
3c824109 14478 RES_39 = 0x39,
3a1f4268
YK
14479 BGTZALC = 0x38,
14480 BLTZALC = 0x38,
14481 BLTUC = 0x38,
3c824109
NF
14482 SW16 = 0x3a,
14483 LI16 = 0x3b,
14484 JALX32 = 0x3c,
14485 JAL32 = 0x3d,
3a1f4268
YK
14486 BLEZC = 0x3d,
14487 BGEZC = 0x3d,
14488 BGEC = 0x3d,
3c824109
NF
14489 SW32 = 0x3e,
14490 LW32 = 0x3f
14491};
14492
3a1f4268
YK
14493/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14494enum {
14495 ADDIUPC_00 = 0x00,
c38a1d52
AR
14496 ADDIUPC_01 = 0x01,
14497 ADDIUPC_02 = 0x02,
14498 ADDIUPC_03 = 0x03,
14499 ADDIUPC_04 = 0x04,
14500 ADDIUPC_05 = 0x05,
14501 ADDIUPC_06 = 0x06,
3a1f4268
YK
14502 ADDIUPC_07 = 0x07,
14503 AUIPC = 0x1e,
14504 ALUIPC = 0x1f,
14505 LWPC_08 = 0x08,
c38a1d52
AR
14506 LWPC_09 = 0x09,
14507 LWPC_0A = 0x0A,
14508 LWPC_0B = 0x0B,
14509 LWPC_0C = 0x0C,
14510 LWPC_0D = 0x0D,
14511 LWPC_0E = 0x0E,
3a1f4268
YK
14512 LWPC_0F = 0x0F,
14513};
14514
3c824109
NF
14515/* POOL32A encoding of minor opcode field */
14516
14517enum {
7480515f
AM
14518 /*
14519 * These opcodes are distinguished only by bits 9..6; those bits are
14520 * what are recorded below.
14521 */
3c824109
NF
14522 SLL32 = 0x0,
14523 SRL32 = 0x1,
14524 SRA = 0x2,
14525 ROTR = 0x3,
3a1f4268
YK
14526 SELEQZ = 0x5,
14527 SELNEZ = 0x6,
b00c7218 14528 R6_RDHWR = 0x7,
3c824109
NF
14529
14530 SLLV = 0x0,
14531 SRLV = 0x1,
14532 SRAV = 0x2,
14533 ROTRV = 0x3,
14534 ADD = 0x4,
14535 ADDU32 = 0x5,
14536 SUB = 0x6,
14537 SUBU32 = 0x7,
14538 MUL = 0x8,
14539 AND = 0x9,
14540 OR32 = 0xa,
14541 NOR = 0xb,
14542 XOR32 = 0xc,
14543 SLT = 0xd,
14544 SLTU = 0xe,
14545
14546 MOVN = 0x0,
3a1f4268 14547 R6_MUL = 0x0,
3c824109 14548 MOVZ = 0x1,
3a1f4268
YK
14549 MUH = 0x1,
14550 MULU = 0x2,
14551 MUHU = 0x3,
3c824109 14552 LWXS = 0x4,
3a1f4268
YK
14553 R6_DIV = 0x4,
14554 MOD = 0x5,
14555 R6_DIVU = 0x6,
14556 MODU = 0x7,
3c824109
NF
14557
14558 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14559 BREAK32 = 0x07,
3c824109 14560 INS = 0x0c,
3a1f4268
YK
14561 LSA = 0x0f,
14562 ALIGN = 0x1f,
3c824109 14563 EXT = 0x2c,
bb238210
YK
14564 POOL32AXF = 0x3c,
14565 SIGRIE = 0x3f
3c824109
NF
14566};
14567
14568/* POOL32AXF encoding of minor opcode field extension */
14569
d132c79f
CWR
14570/*
14571 * 1. MIPS Architecture for Programmers Volume II-B:
14572 * The microMIPS32 Instruction Set (Revision 3.05)
14573 *
14574 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14575 *
14576 * 2. MIPS Architecture for Programmers VolumeIV-e:
14577 * The MIPS DSP Application-Specific Extension
14578 * to the microMIPS32 Architecture (Revision 2.34)
14579 *
14580 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14581 */
14582
3c824109
NF
14583enum {
14584 /* bits 11..6 */
14585 TEQ = 0x00,
14586 TGE = 0x08,
14587 TGEU = 0x10,
14588 TLT = 0x20,
14589 TLTU = 0x28,
14590 TNE = 0x30,
14591
14592 MFC0 = 0x03,
14593 MTC0 = 0x0b,
14594
d132c79f
CWR
14595 /* begin of microMIPS32 DSP */
14596
3c824109
NF
14597 /* bits 13..12 for 0x01 */
14598 MFHI_ACC = 0x0,
14599 MFLO_ACC = 0x1,
14600 MTHI_ACC = 0x2,
14601 MTLO_ACC = 0x3,
14602
14603 /* bits 13..12 for 0x2a */
14604 MADD_ACC = 0x0,
14605 MADDU_ACC = 0x1,
14606 MSUB_ACC = 0x2,
14607 MSUBU_ACC = 0x3,
14608
14609 /* bits 13..12 for 0x32 */
14610 MULT_ACC = 0x0,
6801038b 14611 MULTU_ACC = 0x1,
3c824109 14612
d132c79f
CWR
14613 /* end of microMIPS32 DSP */
14614
3c824109 14615 /* bits 15..12 for 0x2c */
3a1f4268 14616 BITSWAP = 0x0,
3c824109
NF
14617 SEB = 0x2,
14618 SEH = 0x3,
14619 CLO = 0x4,
14620 CLZ = 0x5,
14621 RDHWR = 0x6,
14622 WSBH = 0x7,
14623 MULT = 0x8,
14624 MULTU = 0x9,
14625 DIV = 0xa,
14626 DIVU = 0xb,
14627 MADD = 0xc,
14628 MADDU = 0xd,
14629 MSUB = 0xe,
14630 MSUBU = 0xf,
14631
14632 /* bits 15..12 for 0x34 */
14633 MFC2 = 0x4,
14634 MTC2 = 0x5,
14635 MFHC2 = 0x8,
14636 MTHC2 = 0x9,
14637 CFC2 = 0xc,
14638 CTC2 = 0xd,
14639
14640 /* bits 15..12 for 0x3c */
14641 JALR = 0x0,
14642 JR = 0x0, /* alias */
3a1f4268
YK
14643 JALRC = 0x0,
14644 JRC = 0x0,
3c824109 14645 JALR_HB = 0x1,
3a1f4268 14646 JALRC_HB = 0x1,
3c824109
NF
14647 JALRS = 0x4,
14648 JALRS_HB = 0x5,
14649
14650 /* bits 15..12 for 0x05 */
14651 RDPGPR = 0xe,
14652 WRPGPR = 0xf,
14653
14654 /* bits 15..12 for 0x0d */
14655 TLBP = 0x0,
14656 TLBR = 0x1,
14657 TLBWI = 0x2,
14658 TLBWR = 0x3,
e60ec063
YK
14659 TLBINV = 0x4,
14660 TLBINVF = 0x5,
3c824109
NF
14661 WAIT = 0x9,
14662 IRET = 0xd,
14663 DERET = 0xe,
14664 ERET = 0xf,
14665
14666 /* bits 15..12 for 0x15 */
14667 DMT = 0x0,
14668 DVPE = 0x1,
14669 EMT = 0x2,
14670 EVPE = 0x3,
14671
14672 /* bits 15..12 for 0x1d */
14673 DI = 0x4,
14674 EI = 0x5,
14675
14676 /* bits 15..12 for 0x2d */
14677 SYNC = 0x6,
14678 SYSCALL = 0x8,
14679 SDBBP = 0xd,
14680
14681 /* bits 15..12 for 0x35 */
14682 MFHI32 = 0x0,
14683 MFLO32 = 0x1,
14684 MTHI32 = 0x2,
14685 MTLO32 = 0x3,
14686};
14687
14688/* POOL32B encoding of minor opcode field (bits 15..12) */
14689
14690enum {
14691 LWC2 = 0x0,
14692 LWP = 0x1,
14693 LDP = 0x4,
14694 LWM32 = 0x5,
14695 CACHE = 0x6,
14696 LDM = 0x7,
14697 SWC2 = 0x8,
14698 SWP = 0x9,
14699 SDP = 0xc,
14700 SWM32 = 0xd,
14701 SDM = 0xf
14702};
14703
14704/* POOL32C encoding of minor opcode field (bits 15..12) */
14705
14706enum {
14707 LWL = 0x0,
14708 SWL = 0x8,
14709 LWR = 0x1,
14710 SWR = 0x9,
14711 PREF = 0x2,
8fffc646 14712 ST_EVA = 0xa,
3c824109
NF
14713 LL = 0x3,
14714 SC = 0xb,
14715 LDL = 0x4,
14716 SDL = 0xc,
14717 LDR = 0x5,
14718 SDR = 0xd,
8fffc646 14719 LD_EVA = 0x6,
3c824109
NF
14720 LWU = 0xe,
14721 LLD = 0x7,
14722 SCD = 0xf
14723};
14724
8fffc646
JH
14725/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14726
14727enum {
14728 LBUE = 0x0,
14729 LHUE = 0x1,
14730 LWLE = 0x2,
14731 LWRE = 0x3,
14732 LBE = 0x4,
14733 LHE = 0x5,
14734 LLE = 0x6,
14735 LWE = 0x7,
14736};
14737
14738/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14739
14740enum {
14741 SWLE = 0x0,
14742 SWRE = 0x1,
14743 PREFE = 0x2,
14744 CACHEE = 0x3,
14745 SBE = 0x4,
14746 SHE = 0x5,
14747 SCE = 0x6,
14748 SWE = 0x7,
14749};
14750
3c824109
NF
14751/* POOL32F encoding of minor opcode field (bits 5..0) */
14752
14753enum {
14754 /* These are the bit 7..6 values */
14755 ADD_FMT = 0x0,
3c824109
NF
14756
14757 SUB_FMT = 0x1,
3c824109
NF
14758
14759 MUL_FMT = 0x2,
14760
14761 DIV_FMT = 0x3,
14762
14763 /* These are the bit 8..6 values */
3a1f4268 14764 MOVN_FMT = 0x0,
3c824109
NF
14765 RSQRT2_FMT = 0x0,
14766 MOVF_FMT = 0x0,
3a1f4268
YK
14767 RINT_FMT = 0x0,
14768 SELNEZ_FMT = 0x0,
3c824109 14769
3a1f4268 14770 MOVZ_FMT = 0x1,
3c824109
NF
14771 LWXC1 = 0x1,
14772 MOVT_FMT = 0x1,
3a1f4268
YK
14773 CLASS_FMT = 0x1,
14774 SELEQZ_FMT = 0x1,
3c824109
NF
14775
14776 PLL_PS = 0x2,
14777 SWXC1 = 0x2,
3a1f4268 14778 SEL_FMT = 0x2,
3c824109
NF
14779
14780 PLU_PS = 0x3,
14781 LDXC1 = 0x3,
14782
3a1f4268 14783 MOVN_FMT_04 = 0x4,
3c824109
NF
14784 PUL_PS = 0x4,
14785 SDXC1 = 0x4,
14786 RECIP2_FMT = 0x4,
14787
3a1f4268 14788 MOVZ_FMT_05 = 0x05,
3c824109
NF
14789 PUU_PS = 0x5,
14790 LUXC1 = 0x5,
14791
14792 CVT_PS_S = 0x6,
14793 SUXC1 = 0x6,
14794 ADDR_PS = 0x6,
14795 PREFX = 0x6,
3a1f4268 14796 MADDF_FMT = 0x6,
3c824109
NF
14797
14798 MULR_PS = 0x7,
3a1f4268 14799 MSUBF_FMT = 0x7,
3c824109
NF
14800
14801 MADD_S = 0x01,
14802 MADD_D = 0x09,
14803 MADD_PS = 0x11,
14804 ALNV_PS = 0x19,
14805 MSUB_S = 0x21,
14806 MSUB_D = 0x29,
14807 MSUB_PS = 0x31,
14808
14809 NMADD_S = 0x02,
14810 NMADD_D = 0x0a,
14811 NMADD_PS = 0x12,
14812 NMSUB_S = 0x22,
14813 NMSUB_D = 0x2a,
14814 NMSUB_PS = 0x32,
14815
3a1f4268
YK
14816 MIN_FMT = 0x3,
14817 MAX_FMT = 0xb,
14818 MINA_FMT = 0x23,
14819 MAXA_FMT = 0x2b,
3c824109
NF
14820 POOL32FXF = 0x3b,
14821
14822 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14823 C_COND_FMT = 0x3c,
14824
14825 CMP_CONDN_S = 0x5,
14826 CMP_CONDN_D = 0x15
3c824109
NF
14827};
14828
14829/* POOL32Fxf encoding of minor opcode extension field */
14830
14831enum {
14832 CVT_L = 0x04,
14833 RSQRT_FMT = 0x08,
14834 FLOOR_L = 0x0c,
14835 CVT_PW_PS = 0x1c,
14836 CVT_W = 0x24,
14837 SQRT_FMT = 0x28,
14838 FLOOR_W = 0x2c,
14839 CVT_PS_PW = 0x3c,
14840 CFC1 = 0x40,
14841 RECIP_FMT = 0x48,
14842 CEIL_L = 0x4c,
14843 CTC1 = 0x60,
14844 CEIL_W = 0x6c,
14845 MFC1 = 0x80,
14846 CVT_S_PL = 0x84,
14847 TRUNC_L = 0x8c,
14848 MTC1 = 0xa0,
14849 CVT_S_PU = 0xa4,
14850 TRUNC_W = 0xac,
14851 MFHC1 = 0xc0,
14852 ROUND_L = 0xcc,
14853 MTHC1 = 0xe0,
14854 ROUND_W = 0xec,
14855
14856 MOV_FMT = 0x01,
14857 MOVF = 0x05,
14858 ABS_FMT = 0x0d,
14859 RSQRT1_FMT = 0x1d,
14860 MOVT = 0x25,
14861 NEG_FMT = 0x2d,
14862 CVT_D = 0x4d,
14863 RECIP1_FMT = 0x5d,
14864 CVT_S = 0x6d
14865};
14866
14867/* POOL32I encoding of minor opcode field (bits 25..21) */
14868
14869enum {
14870 BLTZ = 0x00,
14871 BLTZAL = 0x01,
14872 BGEZ = 0x02,
14873 BGEZAL = 0x03,
14874 BLEZ = 0x04,
14875 BNEZC = 0x05,
14876 BGTZ = 0x06,
14877 BEQZC = 0x07,
14878 TLTI = 0x08,
3a1f4268 14879 BC1EQZC = 0x08,
3c824109 14880 TGEI = 0x09,
3a1f4268 14881 BC1NEZC = 0x09,
3c824109 14882 TLTIU = 0x0a,
3a1f4268 14883 BC2EQZC = 0x0a,
3c824109 14884 TGEIU = 0x0b,
3a1f4268 14885 BC2NEZC = 0x0a,
3c824109 14886 TNEI = 0x0c,
3a1f4268 14887 R6_SYNCI = 0x0c,
3c824109
NF
14888 LUI = 0x0d,
14889 TEQI = 0x0e,
14890 SYNCI = 0x10,
14891 BLTZALS = 0x11,
14892 BGEZALS = 0x13,
14893 BC2F = 0x14,
14894 BC2T = 0x15,
14895 BPOSGE64 = 0x1a,
14896 BPOSGE32 = 0x1b,
14897 /* These overlap and are distinguished by bit16 of the instruction */
14898 BC1F = 0x1c,
14899 BC1T = 0x1d,
14900 BC1ANY2F = 0x1c,
14901 BC1ANY2T = 0x1d,
14902 BC1ANY4F = 0x1e,
14903 BC1ANY4T = 0x1f
14904};
14905
14906/* POOL16A encoding of minor opcode field */
14907
14908enum {
14909 ADDU16 = 0x0,
14910 SUBU16 = 0x1
14911};
14912
14913/* POOL16B encoding of minor opcode field */
14914
14915enum {
14916 SLL16 = 0x0,
14917 SRL16 = 0x1
14918};
14919
14920/* POOL16C encoding of minor opcode field */
14921
14922enum {
14923 NOT16 = 0x00,
14924 XOR16 = 0x04,
14925 AND16 = 0x08,
14926 OR16 = 0x0c,
14927 LWM16 = 0x10,
14928 SWM16 = 0x14,
14929 JR16 = 0x18,
14930 JRC16 = 0x1a,
14931 JALR16 = 0x1c,
14932 JALR16S = 0x1e,
14933 MFHI16 = 0x20,
14934 MFLO16 = 0x24,
14935 BREAK16 = 0x28,
14936 SDBBP16 = 0x2c,
14937 JRADDIUSP = 0x30
14938};
14939
3a1f4268
YK
14940/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14941
14942enum {
14943 R6_NOT16 = 0x00,
14944 R6_AND16 = 0x01,
14945 R6_LWM16 = 0x02,
14946 R6_JRC16 = 0x03,
14947 MOVEP = 0x04,
c38a1d52
AR
14948 MOVEP_05 = 0x05,
14949 MOVEP_06 = 0x06,
3a1f4268
YK
14950 MOVEP_07 = 0x07,
14951 R6_XOR16 = 0x08,
14952 R6_OR16 = 0x09,
14953 R6_SWM16 = 0x0a,
14954 JALRC16 = 0x0b,
14955 MOVEP_0C = 0x0c,
c38a1d52
AR
14956 MOVEP_0D = 0x0d,
14957 MOVEP_0E = 0x0e,
3a1f4268
YK
14958 MOVEP_0F = 0x0f,
14959 JRCADDIUSP = 0x13,
14960 R6_BREAK16 = 0x1b,
14961 R6_SDBBP16 = 0x3b
14962};
14963
3c824109
NF
14964/* POOL16D encoding of minor opcode field */
14965
14966enum {
14967 ADDIUS5 = 0x0,
14968 ADDIUSP = 0x1
14969};
14970
14971/* POOL16E encoding of minor opcode field */
14972
14973enum {
14974 ADDIUR2 = 0x0,
14975 ADDIUR1SP = 0x1
14976};
14977
235785e8 14978static int mmreg(int r)
3c824109
NF
14979{
14980 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14981
14982 return map[r];
14983}
14984
14985/* Used for 16-bit store instructions. */
235785e8 14986static int mmreg2(int r)
3c824109
NF
14987{
14988 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14989
14990 return map[r];
14991}
14992
14993#define uMIPS_RD(op) ((op >> 7) & 0x7)
14994#define uMIPS_RS(op) ((op >> 4) & 0x7)
14995#define uMIPS_RS2(op) uMIPS_RS(op)
14996#define uMIPS_RS1(op) ((op >> 1) & 0x7)
14997#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14998#define uMIPS_RS5(op) (op & 0x1f)
14999
15000/* Signed immediate */
15001#define SIMM(op, start, width) \
71375b59
AM
15002 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15003 << (32 - width)) \
15004 >> (32 - width))
3c824109 15005/* Zero-extended immediate */
71375b59 15006#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 15007
d75c135e 15008static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
15009{
15010 int rd = mmreg(uMIPS_RD(ctx->opcode));
15011
d75c135e 15012 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
15013}
15014
d75c135e 15015static void gen_addiur2(DisasContext *ctx)
3c824109
NF
15016{
15017 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15018 int rd = mmreg(uMIPS_RD(ctx->opcode));
15019 int rs = mmreg(uMIPS_RS(ctx->opcode));
15020
d75c135e 15021 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
15022}
15023
d75c135e 15024static void gen_addiusp(DisasContext *ctx)
3c824109
NF
15025{
15026 int encoded = ZIMM(ctx->opcode, 1, 9);
15027 int decoded;
15028
15029 if (encoded <= 1) {
15030 decoded = 256 + encoded;
15031 } else if (encoded <= 255) {
15032 decoded = encoded;
15033 } else if (encoded <= 509) {
15034 decoded = encoded - 512;
15035 } else {
15036 decoded = encoded - 768;
15037 }
15038
d75c135e 15039 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
15040}
15041
d75c135e 15042static void gen_addius5(DisasContext *ctx)
3c824109
NF
15043{
15044 int imm = SIMM(ctx->opcode, 1, 4);
15045 int rd = (ctx->opcode >> 5) & 0x1f;
15046
d75c135e 15047 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
15048}
15049
d75c135e 15050static void gen_andi16(DisasContext *ctx)
3c824109
NF
15051{
15052 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15053 31, 32, 63, 64, 255, 32768, 65535 };
15054 int rd = mmreg(uMIPS_RD(ctx->opcode));
15055 int rs = mmreg(uMIPS_RS(ctx->opcode));
15056 int encoded = ZIMM(ctx->opcode, 0, 4);
15057
d75c135e 15058 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
15059}
15060
235785e8
AM
15061static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15062 int base, int16_t offset)
3c824109
NF
15063{
15064 TCGv t0, t1;
15065 TCGv_i32 t2;
15066
15067 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 15068 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15069 return;
15070 }
15071
15072 t0 = tcg_temp_new();
15073
15074 gen_base_offset_addr(ctx, t0, base, offset);
15075
15076 t1 = tcg_const_tl(reglist);
15077 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 15078
3c824109
NF
15079 save_cpu_state(ctx, 1);
15080 switch (opc) {
15081 case LWM32:
895c2d04 15082 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
15083 break;
15084 case SWM32:
895c2d04 15085 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
15086 break;
15087#ifdef TARGET_MIPS64
15088 case LDM:
895c2d04 15089 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
15090 break;
15091 case SDM:
895c2d04 15092 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 15093 break;
6af0bf9c 15094#endif
3c824109 15095 }
3c824109 15096 tcg_temp_free(t0);
33087598 15097 tcg_temp_free(t1);
3c824109
NF
15098 tcg_temp_free_i32(t2);
15099}
6af0bf9c 15100
3c824109 15101
240ce26a 15102static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 15103{
3c824109
NF
15104 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15105 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 15106
3c824109
NF
15107 switch (((ctx->opcode) >> 4) & 0x3f) {
15108 case NOT16 + 0:
15109 case NOT16 + 1:
15110 case NOT16 + 2:
15111 case NOT16 + 3:
d75c135e 15112 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
15113 break;
15114 case XOR16 + 0:
15115 case XOR16 + 1:
15116 case XOR16 + 2:
15117 case XOR16 + 3:
d75c135e 15118 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
15119 break;
15120 case AND16 + 0:
15121 case AND16 + 1:
15122 case AND16 + 2:
15123 case AND16 + 3:
d75c135e 15124 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
15125 break;
15126 case OR16 + 0:
15127 case OR16 + 1:
15128 case OR16 + 2:
15129 case OR16 + 3:
d75c135e 15130 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
15131 break;
15132 case LWM16 + 0:
15133 case LWM16 + 1:
15134 case LWM16 + 2:
15135 case LWM16 + 3:
15136 {
15137 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15138 int offset = ZIMM(ctx->opcode, 0, 4);
15139
15140 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15141 29, offset << 2);
15142 }
15143 break;
15144 case SWM16 + 0:
15145 case SWM16 + 1:
15146 case SWM16 + 2:
15147 case SWM16 + 3:
15148 {
15149 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15150 int offset = ZIMM(ctx->opcode, 0, 4);
15151
15152 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15153 29, offset << 2);
15154 }
15155 break;
15156 case JR16 + 0:
15157 case JR16 + 1:
15158 {
15159 int reg = ctx->opcode & 0x1f;
15160
b231c103 15161 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15162 }
3c824109
NF
15163 break;
15164 case JRC16 + 0:
15165 case JRC16 + 1:
15166 {
15167 int reg = ctx->opcode & 0x1f;
b231c103 15168 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
15169 /*
15170 * Let normal delay slot handling in our caller take us
15171 * to the branch target.
15172 */
3c824109
NF
15173 }
15174 break;
15175 case JALR16 + 0:
15176 case JALR16 + 1:
b231c103
YK
15177 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15178 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15179 break;
3c824109
NF
15180 case JALR16S + 0:
15181 case JALR16S + 1:
b231c103
YK
15182 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15183 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15184 break;
15185 case MFHI16 + 0:
15186 case MFHI16 + 1:
26135ead 15187 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15188 break;
15189 case MFLO16 + 0:
15190 case MFLO16 + 1:
26135ead 15191 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15192 break;
15193 case BREAK16:
9c708c7f 15194 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15195 break;
15196 case SDBBP16:
3b3c1694
LA
15197 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15198 gen_helper_do_semihosting(cpu_env);
15199 } else {
7480515f
AM
15200 /*
15201 * XXX: not clear which exception should be raised
3b3c1694
LA
15202 * when in debug mode...
15203 */
15204 check_insn(ctx, ISA_MIPS32);
9c708c7f 15205 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15206 }
3c824109
NF
15207 break;
15208 case JRADDIUSP + 0:
15209 case JRADDIUSP + 1:
15210 {
15211 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15212 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15213 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
15214 /*
15215 * Let normal delay slot handling in our caller take us
15216 * to the branch target.
15217 */
3c824109
NF
15218 }
15219 break;
15220 default:
9c708c7f 15221 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15222 break;
15223 }
15224}
15225
ed7ce6c0
YK
15226static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15227 int enc_rs)
15228{
15229 int rd, rs, re, rt;
15230 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15231 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15232 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15233 rd = rd_enc[enc_dest];
15234 re = re_enc[enc_dest];
15235 rs = rs_rt_enc[enc_rs];
15236 rt = rs_rt_enc[enc_rt];
15237 if (rs) {
15238 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15239 } else {
15240 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15241 }
15242 if (rt) {
15243 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15244 } else {
15245 tcg_gen_movi_tl(cpu_gpr[re], 0);
15246 }
15247}
15248
15249static void gen_pool16c_r6_insn(DisasContext *ctx)
15250{
15251 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15252 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15253
15254 switch (ctx->opcode & 0xf) {
15255 case R6_NOT16:
15256 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15257 break;
15258 case R6_AND16:
15259 gen_logic(ctx, OPC_AND, rt, rt, rs);
15260 break;
15261 case R6_LWM16:
15262 {
15263 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15264 int offset = extract32(ctx->opcode, 4, 4);
15265 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15266 }
15267 break;
15268 case R6_JRC16: /* JRCADDIUSP */
15269 if ((ctx->opcode >> 4) & 1) {
15270 /* JRCADDIUSP */
15271 int imm = extract32(ctx->opcode, 5, 5);
15272 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15273 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15274 } else {
15275 /* JRC16 */
e1555d7d 15276 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15277 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15278 }
15279 break;
c38a1d52
AR
15280 case MOVEP:
15281 case MOVEP_05:
15282 case MOVEP_06:
15283 case MOVEP_07:
15284 case MOVEP_0C:
15285 case MOVEP_0D:
15286 case MOVEP_0E:
15287 case MOVEP_0F:
ed7ce6c0
YK
15288 {
15289 int enc_dest = uMIPS_RD(ctx->opcode);
15290 int enc_rt = uMIPS_RS2(ctx->opcode);
15291 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15292 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15293 }
15294 break;
15295 case R6_XOR16:
15296 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15297 break;
15298 case R6_OR16:
15299 gen_logic(ctx, OPC_OR, rt, rt, rs);
15300 break;
15301 case R6_SWM16:
15302 {
15303 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15304 int offset = extract32(ctx->opcode, 4, 4);
15305 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15306 }
15307 break;
15308 case JALRC16: /* BREAK16, SDBBP16 */
15309 switch (ctx->opcode & 0x3f) {
15310 case JALRC16:
15311 case JALRC16 + 0x20:
15312 /* JALRC16 */
15313 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15314 31, 0, 0);
15315 break;
15316 case R6_BREAK16:
15317 /* BREAK16 */
15318 generate_exception(ctx, EXCP_BREAK);
15319 break;
15320 case R6_SDBBP16:
15321 /* SDBBP16 */
060ebfef
LA
15322 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15323 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15324 } else {
060ebfef
LA
15325 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15326 generate_exception(ctx, EXCP_RI);
15327 } else {
15328 generate_exception(ctx, EXCP_DBp);
15329 }
ed7ce6c0
YK
15330 }
15331 break;
15332 }
15333 break;
15334 default:
15335 generate_exception(ctx, EXCP_RI);
15336 break;
15337 }
15338}
15339
235785e8 15340static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
15341{
15342 TCGv t0 = tcg_temp_new();
15343 TCGv t1 = tcg_temp_new();
15344
15345 gen_load_gpr(t0, base);
15346
15347 if (index != 0) {
15348 gen_load_gpr(t1, index);
15349 tcg_gen_shli_tl(t1, t1, 2);
15350 gen_op_addr_add(ctx, t0, t1, t0);
15351 }
15352
5f68f5ae 15353 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15354 gen_store_gpr(t1, rd);
15355
15356 tcg_temp_free(t0);
15357 tcg_temp_free(t1);
15358}
15359
235785e8
AM
15360static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15361 int base, int16_t offset)
3c824109 15362{
3c824109
NF
15363 TCGv t0, t1;
15364
36c6711b 15365 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15366 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15367 return;
15368 }
15369
3c824109
NF
15370 t0 = tcg_temp_new();
15371 t1 = tcg_temp_new();
8e9ade68 15372
3c824109
NF
15373 gen_base_offset_addr(ctx, t0, base, offset);
15374
15375 switch (opc) {
15376 case LWP:
36c6711b 15377 if (rd == base) {
9c708c7f 15378 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15379 return;
15380 }
5f68f5ae 15381 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15382 gen_store_gpr(t1, rd);
15383 tcg_gen_movi_tl(t1, 4);
15384 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15385 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 15386 gen_store_gpr(t1, rd + 1);
3c824109
NF
15387 break;
15388 case SWP:
3c824109 15389 gen_load_gpr(t1, rd);
5f68f5ae 15390 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15391 tcg_gen_movi_tl(t1, 4);
15392 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15393 gen_load_gpr(t1, rd + 1);
5f68f5ae 15394 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15395 break;
15396#ifdef TARGET_MIPS64
15397 case LDP:
36c6711b 15398 if (rd == base) {
9c708c7f 15399 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15400 return;
15401 }
5f68f5ae 15402 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15403 gen_store_gpr(t1, rd);
15404 tcg_gen_movi_tl(t1, 8);
15405 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15406 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 15407 gen_store_gpr(t1, rd + 1);
3c824109
NF
15408 break;
15409 case SDP:
3c824109 15410 gen_load_gpr(t1, rd);
5f68f5ae 15411 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15412 tcg_gen_movi_tl(t1, 8);
15413 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15414 gen_load_gpr(t1, rd + 1);
5f68f5ae 15415 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15416 break;
15417#endif
6af0bf9c 15418 }
3c824109
NF
15419 tcg_temp_free(t0);
15420 tcg_temp_free(t1);
15421}
618b0fe9 15422
d208ac0c
LA
15423static void gen_sync(int stype)
15424{
15425 TCGBar tcg_mo = TCG_BAR_SC;
15426
15427 switch (stype) {
15428 case 0x4: /* SYNC_WMB */
15429 tcg_mo |= TCG_MO_ST_ST;
15430 break;
15431 case 0x10: /* SYNC_MB */
15432 tcg_mo |= TCG_MO_ALL;
15433 break;
15434 case 0x11: /* SYNC_ACQUIRE */
15435 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15436 break;
15437 case 0x12: /* SYNC_RELEASE */
15438 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15439 break;
15440 case 0x13: /* SYNC_RMB */
15441 tcg_mo |= TCG_MO_LD_LD;
15442 break;
15443 default:
15444 tcg_mo |= TCG_MO_ALL;
15445 break;
15446 }
15447
15448 tcg_gen_mb(tcg_mo);
15449}
15450
235785e8 15451static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
15452{
15453 int extension = (ctx->opcode >> 6) & 0x3f;
15454 int minor = (ctx->opcode >> 12) & 0xf;
15455 uint32_t mips32_op;
15456
15457 switch (extension) {
15458 case TEQ:
15459 mips32_op = OPC_TEQ;
15460 goto do_trap;
15461 case TGE:
15462 mips32_op = OPC_TGE;
15463 goto do_trap;
15464 case TGEU:
15465 mips32_op = OPC_TGEU;
15466 goto do_trap;
15467 case TLT:
15468 mips32_op = OPC_TLT;
15469 goto do_trap;
15470 case TLTU:
15471 mips32_op = OPC_TLTU;
15472 goto do_trap;
15473 case TNE:
15474 mips32_op = OPC_TNE;
15475 do_trap:
15476 gen_trap(ctx, mips32_op, rs, rt, -1);
15477 break;
15478#ifndef CONFIG_USER_ONLY
15479 case MFC0:
15480 case MFC0 + 32:
2e15497c 15481 check_cp0_enabled(ctx);
3c824109
NF
15482 if (rt == 0) {
15483 /* Treat as NOP. */
15484 break;
15485 }
d75c135e 15486 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15487 break;
15488 case MTC0:
15489 case MTC0 + 32:
2e15497c 15490 check_cp0_enabled(ctx);
3c824109
NF
15491 {
15492 TCGv t0 = tcg_temp_new();
618b0fe9 15493
3c824109 15494 gen_load_gpr(t0, rt);
d75c135e 15495 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15496 tcg_temp_free(t0);
15497 }
15498 break;
15499#endif
a1fc6246
LA
15500 case 0x2a:
15501 switch (minor & 3) {
15502 case MADD_ACC:
15503 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15504 break;
15505 case MADDU_ACC:
15506 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15507 break;
15508 case MSUB_ACC:
15509 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15510 break;
15511 case MSUBU_ACC:
15512 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15513 break;
15514 default:
15515 goto pool32axf_invalid;
15516 }
15517 break;
15518 case 0x32:
15519 switch (minor & 3) {
15520 case MULT_ACC:
15521 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15522 break;
15523 case MULTU_ACC:
15524 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15525 break;
15526 default:
15527 goto pool32axf_invalid;
15528 }
15529 break;
3c824109
NF
15530 case 0x2c:
15531 switch (minor) {
e0332095
YK
15532 case BITSWAP:
15533 check_insn(ctx, ISA_MIPS32R6);
15534 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15535 break;
3c824109
NF
15536 case SEB:
15537 gen_bshfl(ctx, OPC_SEB, rs, rt);
15538 break;
15539 case SEH:
15540 gen_bshfl(ctx, OPC_SEH, rs, rt);
15541 break;
15542 case CLO:
15543 mips32_op = OPC_CLO;
15544 goto do_cl;
15545 case CLZ:
15546 mips32_op = OPC_CLZ;
15547 do_cl:
d75c135e 15548 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15549 gen_cl(ctx, mips32_op, rt, rs);
15550 break;
15551 case RDHWR:
b00c7218
YK
15552 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15553 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15554 break;
15555 case WSBH:
15556 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15557 break;
15558 case MULT:
9e8f441a 15559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15560 mips32_op = OPC_MULT;
26135ead 15561 goto do_mul;
3c824109 15562 case MULTU:
9e8f441a 15563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15564 mips32_op = OPC_MULTU;
26135ead 15565 goto do_mul;
3c824109 15566 case DIV:
9e8f441a 15567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15568 mips32_op = OPC_DIV;
26135ead 15569 goto do_div;
3c824109 15570 case DIVU:
9e8f441a 15571 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15572 mips32_op = OPC_DIVU;
26135ead
RS
15573 goto do_div;
15574 do_div:
15575 check_insn(ctx, ISA_MIPS32);
15576 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15577 break;
3c824109 15578 case MADD:
9e8f441a 15579 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15580 mips32_op = OPC_MADD;
26135ead 15581 goto do_mul;
3c824109 15582 case MADDU:
9e8f441a 15583 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15584 mips32_op = OPC_MADDU;
26135ead 15585 goto do_mul;
3c824109 15586 case MSUB:
9e8f441a 15587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15588 mips32_op = OPC_MSUB;
26135ead 15589 goto do_mul;
3c824109 15590 case MSUBU:
9e8f441a 15591 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15592 mips32_op = OPC_MSUBU;
26135ead 15593 do_mul:
d75c135e 15594 check_insn(ctx, ISA_MIPS32);
a1fc6246 15595 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15596 break;
15597 default:
15598 goto pool32axf_invalid;
15599 }
15600 break;
15601 case 0x34:
15602 switch (minor) {
15603 case MFC2:
15604 case MTC2:
15605 case MFHC2:
15606 case MTHC2:
15607 case CFC2:
15608 case CTC2:
15609 generate_exception_err(ctx, EXCP_CpU, 2);
15610 break;
15611 default:
15612 goto pool32axf_invalid;
15613 }
15614 break;
15615 case 0x3c:
15616 switch (minor) {
65935f07
YK
15617 case JALR: /* JALRC */
15618 case JALR_HB: /* JALRC_HB */
15619 if (ctx->insn_flags & ISA_MIPS32R6) {
15620 /* JALRC, JALRC_HB */
15621 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15622 } else {
15623 /* JALR, JALR_HB */
15624 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15625 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15626 }
3c824109
NF
15627 break;
15628 case JALRS:
15629 case JALRS_HB:
9e8f441a 15630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15631 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15632 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15633 break;
15634 default:
15635 goto pool32axf_invalid;
15636 }
15637 break;
15638 case 0x05:
15639 switch (minor) {
15640 case RDPGPR:
2e15497c 15641 check_cp0_enabled(ctx);
d75c135e 15642 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15643 gen_load_srsgpr(rs, rt);
3c824109
NF
15644 break;
15645 case WRPGPR:
2e15497c 15646 check_cp0_enabled(ctx);
d75c135e 15647 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15648 gen_store_srsgpr(rs, rt);
3c824109
NF
15649 break;
15650 default:
15651 goto pool32axf_invalid;
15652 }
15653 break;
15654#ifndef CONFIG_USER_ONLY
15655 case 0x0d:
15656 switch (minor) {
15657 case TLBP:
15658 mips32_op = OPC_TLBP;
15659 goto do_cp0;
15660 case TLBR:
15661 mips32_op = OPC_TLBR;
15662 goto do_cp0;
15663 case TLBWI:
15664 mips32_op = OPC_TLBWI;
15665 goto do_cp0;
15666 case TLBWR:
15667 mips32_op = OPC_TLBWR;
15668 goto do_cp0;
e60ec063
YK
15669 case TLBINV:
15670 mips32_op = OPC_TLBINV;
15671 goto do_cp0;
15672 case TLBINVF:
15673 mips32_op = OPC_TLBINVF;
15674 goto do_cp0;
3c824109
NF
15675 case WAIT:
15676 mips32_op = OPC_WAIT;
15677 goto do_cp0;
15678 case DERET:
15679 mips32_op = OPC_DERET;
15680 goto do_cp0;
15681 case ERET:
15682 mips32_op = OPC_ERET;
15683 do_cp0:
15684 gen_cp0(env, ctx, mips32_op, rt, rs);
15685 break;
15686 default:
15687 goto pool32axf_invalid;
15688 }
15689 break;
15690 case 0x1d:
15691 switch (minor) {
15692 case DI:
2e15497c 15693 check_cp0_enabled(ctx);
3c824109
NF
15694 {
15695 TCGv t0 = tcg_temp_new();
15696
15697 save_cpu_state(ctx, 1);
895c2d04 15698 gen_helper_di(t0, cpu_env);
3c824109 15699 gen_store_gpr(t0, rs);
71375b59
AM
15700 /*
15701 * Stop translation as we may have switched the execution
15702 * mode.
15703 */
eeb3bba8 15704 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15705 tcg_temp_free(t0);
15706 }
15707 break;
15708 case EI:
2e15497c 15709 check_cp0_enabled(ctx);
3c824109
NF
15710 {
15711 TCGv t0 = tcg_temp_new();
15712
15713 save_cpu_state(ctx, 1);
895c2d04 15714 gen_helper_ei(t0, cpu_env);
3c824109 15715 gen_store_gpr(t0, rs);
7480515f
AM
15716 /*
15717 * DISAS_STOP isn't sufficient, we need to ensure we break out
15718 * of translated code to check for pending interrupts.
15719 */
eeb3bba8
EC
15720 gen_save_pc(ctx->base.pc_next + 4);
15721 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15722 tcg_temp_free(t0);
15723 }
15724 break;
15725 default:
15726 goto pool32axf_invalid;
15727 }
15728 break;
15729#endif
15730 case 0x2d:
15731 switch (minor) {
15732 case SYNC:
d208ac0c 15733 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15734 break;
15735 case SYSCALL:
9c708c7f 15736 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15737 break;
15738 case SDBBP:
3b3c1694
LA
15739 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15740 gen_helper_do_semihosting(cpu_env);
15741 } else {
15742 check_insn(ctx, ISA_MIPS32);
e0332095 15743 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15744 generate_exception_end(ctx, EXCP_RI);
e0332095 15745 } else {
9c708c7f 15746 generate_exception_end(ctx, EXCP_DBp);
e0332095 15747 }
3b3c1694 15748 }
3c824109
NF
15749 break;
15750 default:
15751 goto pool32axf_invalid;
15752 }
15753 break;
a1fc6246 15754 case 0x01:
26135ead 15755 switch (minor & 3) {
a1fc6246 15756 case MFHI_ACC:
26135ead 15757 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15758 break;
a1fc6246 15759 case MFLO_ACC:
26135ead 15760 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15761 break;
a1fc6246 15762 case MTHI_ACC:
26135ead 15763 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15764 break;
a1fc6246 15765 case MTLO_ACC:
26135ead 15766 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15767 break;
15768 default:
15769 goto pool32axf_invalid;
15770 }
15771 break;
a1fc6246 15772 case 0x35:
9e8f441a 15773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15774 switch (minor) {
15775 case MFHI32:
15776 gen_HILO(ctx, OPC_MFHI, 0, rs);
15777 break;
15778 case MFLO32:
15779 gen_HILO(ctx, OPC_MFLO, 0, rs);
15780 break;
15781 case MTHI32:
15782 gen_HILO(ctx, OPC_MTHI, 0, rs);
15783 break;
15784 case MTLO32:
15785 gen_HILO(ctx, OPC_MTLO, 0, rs);
15786 break;
15787 default:
15788 goto pool32axf_invalid;
15789 }
15790 break;
3c824109
NF
15791 default:
15792 pool32axf_invalid:
15793 MIPS_INVAL("pool32axf");
9c708c7f 15794 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15795 break;
15796 }
15797}
15798
7480515f
AM
15799/*
15800 * Values for microMIPS fmt field. Variable-width, depending on which
15801 * formats the instruction supports.
15802 */
3c824109
NF
15803enum {
15804 FMT_SD_S = 0,
15805 FMT_SD_D = 1,
15806
15807 FMT_SDPS_S = 0,
15808 FMT_SDPS_D = 1,
15809 FMT_SDPS_PS = 2,
15810
15811 FMT_SWL_S = 0,
15812 FMT_SWL_W = 1,
15813 FMT_SWL_L = 2,
15814
15815 FMT_DWL_D = 0,
15816 FMT_DWL_W = 1,
15817 FMT_DWL_L = 2
15818};
15819
d75c135e 15820static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
15821{
15822 int extension = (ctx->opcode >> 6) & 0x3ff;
15823 uint32_t mips32_op;
15824
71375b59
AM
15825#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15826#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15827#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
15828
15829 switch (extension) {
15830 case FLOAT_1BIT_FMT(CFC1, 0):
15831 mips32_op = OPC_CFC1;
15832 goto do_cp1;
15833 case FLOAT_1BIT_FMT(CTC1, 0):
15834 mips32_op = OPC_CTC1;
15835 goto do_cp1;
15836 case FLOAT_1BIT_FMT(MFC1, 0):
15837 mips32_op = OPC_MFC1;
15838 goto do_cp1;
15839 case FLOAT_1BIT_FMT(MTC1, 0):
15840 mips32_op = OPC_MTC1;
15841 goto do_cp1;
15842 case FLOAT_1BIT_FMT(MFHC1, 0):
15843 mips32_op = OPC_MFHC1;
15844 goto do_cp1;
15845 case FLOAT_1BIT_FMT(MTHC1, 0):
15846 mips32_op = OPC_MTHC1;
15847 do_cp1:
15848 gen_cp1(ctx, mips32_op, rt, rs);
15849 break;
15850
15851 /* Reciprocal square root */
15852 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15853 mips32_op = OPC_RSQRT_S;
15854 goto do_unaryfp;
15855 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15856 mips32_op = OPC_RSQRT_D;
15857 goto do_unaryfp;
15858
15859 /* Square root */
15860 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15861 mips32_op = OPC_SQRT_S;
15862 goto do_unaryfp;
15863 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15864 mips32_op = OPC_SQRT_D;
15865 goto do_unaryfp;
15866
15867 /* Reciprocal */
15868 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15869 mips32_op = OPC_RECIP_S;
15870 goto do_unaryfp;
15871 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15872 mips32_op = OPC_RECIP_D;
15873 goto do_unaryfp;
15874
15875 /* Floor */
15876 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15877 mips32_op = OPC_FLOOR_L_S;
15878 goto do_unaryfp;
15879 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15880 mips32_op = OPC_FLOOR_L_D;
15881 goto do_unaryfp;
15882 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15883 mips32_op = OPC_FLOOR_W_S;
15884 goto do_unaryfp;
15885 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15886 mips32_op = OPC_FLOOR_W_D;
15887 goto do_unaryfp;
15888
15889 /* Ceiling */
15890 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15891 mips32_op = OPC_CEIL_L_S;
15892 goto do_unaryfp;
15893 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15894 mips32_op = OPC_CEIL_L_D;
15895 goto do_unaryfp;
15896 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15897 mips32_op = OPC_CEIL_W_S;
15898 goto do_unaryfp;
15899 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15900 mips32_op = OPC_CEIL_W_D;
15901 goto do_unaryfp;
15902
15903 /* Truncation */
15904 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15905 mips32_op = OPC_TRUNC_L_S;
15906 goto do_unaryfp;
15907 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15908 mips32_op = OPC_TRUNC_L_D;
15909 goto do_unaryfp;
15910 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15911 mips32_op = OPC_TRUNC_W_S;
15912 goto do_unaryfp;
15913 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15914 mips32_op = OPC_TRUNC_W_D;
15915 goto do_unaryfp;
15916
15917 /* Round */
15918 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15919 mips32_op = OPC_ROUND_L_S;
15920 goto do_unaryfp;
15921 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15922 mips32_op = OPC_ROUND_L_D;
15923 goto do_unaryfp;
15924 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15925 mips32_op = OPC_ROUND_W_S;
15926 goto do_unaryfp;
15927 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15928 mips32_op = OPC_ROUND_W_D;
15929 goto do_unaryfp;
15930
15931 /* Integer to floating-point conversion */
15932 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15933 mips32_op = OPC_CVT_L_S;
15934 goto do_unaryfp;
15935 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15936 mips32_op = OPC_CVT_L_D;
15937 goto do_unaryfp;
15938 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15939 mips32_op = OPC_CVT_W_S;
15940 goto do_unaryfp;
15941 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15942 mips32_op = OPC_CVT_W_D;
15943 goto do_unaryfp;
15944
15945 /* Paired-foo conversions */
15946 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15947 mips32_op = OPC_CVT_S_PL;
15948 goto do_unaryfp;
15949 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15950 mips32_op = OPC_CVT_S_PU;
15951 goto do_unaryfp;
15952 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15953 mips32_op = OPC_CVT_PW_PS;
15954 goto do_unaryfp;
15955 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15956 mips32_op = OPC_CVT_PS_PW;
15957 goto do_unaryfp;
15958
15959 /* Floating-point moves */
15960 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15961 mips32_op = OPC_MOV_S;
15962 goto do_unaryfp;
15963 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15964 mips32_op = OPC_MOV_D;
15965 goto do_unaryfp;
15966 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15967 mips32_op = OPC_MOV_PS;
15968 goto do_unaryfp;
15969
15970 /* Absolute value */
15971 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15972 mips32_op = OPC_ABS_S;
15973 goto do_unaryfp;
15974 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15975 mips32_op = OPC_ABS_D;
15976 goto do_unaryfp;
15977 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15978 mips32_op = OPC_ABS_PS;
15979 goto do_unaryfp;
15980
15981 /* Negation */
15982 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15983 mips32_op = OPC_NEG_S;
15984 goto do_unaryfp;
15985 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15986 mips32_op = OPC_NEG_D;
15987 goto do_unaryfp;
15988 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15989 mips32_op = OPC_NEG_PS;
15990 goto do_unaryfp;
15991
15992 /* Reciprocal square root step */
15993 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15994 mips32_op = OPC_RSQRT1_S;
15995 goto do_unaryfp;
15996 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15997 mips32_op = OPC_RSQRT1_D;
15998 goto do_unaryfp;
15999 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16000 mips32_op = OPC_RSQRT1_PS;
16001 goto do_unaryfp;
16002
16003 /* Reciprocal step */
16004 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16005 mips32_op = OPC_RECIP1_S;
16006 goto do_unaryfp;
16007 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16008 mips32_op = OPC_RECIP1_S;
16009 goto do_unaryfp;
16010 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16011 mips32_op = OPC_RECIP1_PS;
16012 goto do_unaryfp;
16013
16014 /* Conversions from double */
16015 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16016 mips32_op = OPC_CVT_D_S;
16017 goto do_unaryfp;
16018 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16019 mips32_op = OPC_CVT_D_W;
16020 goto do_unaryfp;
16021 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16022 mips32_op = OPC_CVT_D_L;
16023 goto do_unaryfp;
16024
16025 /* Conversions from single */
16026 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16027 mips32_op = OPC_CVT_S_D;
16028 goto do_unaryfp;
16029 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16030 mips32_op = OPC_CVT_S_W;
16031 goto do_unaryfp;
16032 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16033 mips32_op = OPC_CVT_S_L;
16034 do_unaryfp:
16035 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16036 break;
16037
16038 /* Conditional moves on floating-point codes */
16039 case COND_FLOAT_MOV(MOVT, 0):
16040 case COND_FLOAT_MOV(MOVT, 1):
16041 case COND_FLOAT_MOV(MOVT, 2):
16042 case COND_FLOAT_MOV(MOVT, 3):
16043 case COND_FLOAT_MOV(MOVT, 4):
16044 case COND_FLOAT_MOV(MOVT, 5):
16045 case COND_FLOAT_MOV(MOVT, 6):
16046 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 16047 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16048 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16049 break;
16050 case COND_FLOAT_MOV(MOVF, 0):
16051 case COND_FLOAT_MOV(MOVF, 1):
16052 case COND_FLOAT_MOV(MOVF, 2):
16053 case COND_FLOAT_MOV(MOVF, 3):
16054 case COND_FLOAT_MOV(MOVF, 4):
16055 case COND_FLOAT_MOV(MOVF, 5):
16056 case COND_FLOAT_MOV(MOVF, 6):
16057 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 16058 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16059 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16060 break;
16061 default:
16062 MIPS_INVAL("pool32fxf");
9c708c7f 16063 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16064 break;
16065 }
16066}
16067
f60eeb0c 16068static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16069{
16070 int32_t offset;
16071 uint16_t insn;
16072 int rt, rs, rd, rr;
16073 int16_t imm;
8fffc646 16074 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
16075 uint32_t cond, fmt, cc;
16076
eeb3bba8 16077 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
16078 ctx->opcode = (ctx->opcode << 16) | insn;
16079
16080 rt = (ctx->opcode >> 21) & 0x1f;
16081 rs = (ctx->opcode >> 16) & 0x1f;
16082 rd = (ctx->opcode >> 11) & 0x1f;
16083 rr = (ctx->opcode >> 6) & 0x1f;
16084 imm = (int16_t) ctx->opcode;
16085
16086 op = (ctx->opcode >> 26) & 0x3f;
16087 switch (op) {
16088 case POOL32A:
16089 minor = ctx->opcode & 0x3f;
16090 switch (minor) {
16091 case 0x00:
16092 minor = (ctx->opcode >> 6) & 0xf;
16093 switch (minor) {
16094 case SLL32:
16095 mips32_op = OPC_SLL;
16096 goto do_shifti;
16097 case SRA:
16098 mips32_op = OPC_SRA;
16099 goto do_shifti;
16100 case SRL32:
16101 mips32_op = OPC_SRL;
16102 goto do_shifti;
16103 case ROTR:
16104 mips32_op = OPC_ROTR;
16105 do_shifti:
d75c135e 16106 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 16107 break;
e0332095
YK
16108 case SELEQZ:
16109 check_insn(ctx, ISA_MIPS32R6);
16110 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16111 break;
16112 case SELNEZ:
16113 check_insn(ctx, ISA_MIPS32R6);
16114 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16115 break;
b00c7218
YK
16116 case R6_RDHWR:
16117 check_insn(ctx, ISA_MIPS32R6);
16118 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16119 break;
3c824109
NF
16120 default:
16121 goto pool32a_invalid;
16122 }
16123 break;
16124 case 0x10:
16125 minor = (ctx->opcode >> 6) & 0xf;
16126 switch (minor) {
16127 /* Arithmetic */
16128 case ADD:
16129 mips32_op = OPC_ADD;
16130 goto do_arith;
16131 case ADDU32:
16132 mips32_op = OPC_ADDU;
16133 goto do_arith;
16134 case SUB:
16135 mips32_op = OPC_SUB;
16136 goto do_arith;
16137 case SUBU32:
16138 mips32_op = OPC_SUBU;
16139 goto do_arith;
16140 case MUL:
9e8f441a 16141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16142 mips32_op = OPC_MUL;
16143 do_arith:
d75c135e 16144 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16145 break;
16146 /* Shifts */
16147 case SLLV:
16148 mips32_op = OPC_SLLV;
16149 goto do_shift;
16150 case SRLV:
16151 mips32_op = OPC_SRLV;
16152 goto do_shift;
16153 case SRAV:
16154 mips32_op = OPC_SRAV;
16155 goto do_shift;
16156 case ROTRV:
16157 mips32_op = OPC_ROTRV;
16158 do_shift:
d75c135e 16159 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16160 break;
16161 /* Logical operations */
16162 case AND:
16163 mips32_op = OPC_AND;
16164 goto do_logic;
16165 case OR32:
16166 mips32_op = OPC_OR;
16167 goto do_logic;
16168 case NOR:
16169 mips32_op = OPC_NOR;
16170 goto do_logic;
16171 case XOR32:
16172 mips32_op = OPC_XOR;
16173 do_logic:
d75c135e 16174 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16175 break;
16176 /* Set less than */
16177 case SLT:
16178 mips32_op = OPC_SLT;
16179 goto do_slt;
16180 case SLTU:
16181 mips32_op = OPC_SLTU;
16182 do_slt:
d75c135e 16183 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16184 break;
16185 default:
16186 goto pool32a_invalid;
16187 }
16188 break;
16189 case 0x18:
16190 minor = (ctx->opcode >> 6) & 0xf;
16191 switch (minor) {
16192 /* Conditional moves */
e0332095
YK
16193 case MOVN: /* MUL */
16194 if (ctx->insn_flags & ISA_MIPS32R6) {
16195 /* MUL */
16196 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16197 } else {
16198 /* MOVN */
16199 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16200 }
16201 break;
16202 case MOVZ: /* MUH */
16203 if (ctx->insn_flags & ISA_MIPS32R6) {
16204 /* MUH */
16205 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16206 } else {
16207 /* MOVZ */
16208 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16209 }
16210 break;
16211 case MULU:
16212 check_insn(ctx, ISA_MIPS32R6);
16213 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16214 break;
16215 case MUHU:
16216 check_insn(ctx, ISA_MIPS32R6);
16217 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16218 break;
16219 case LWXS: /* DIV */
16220 if (ctx->insn_flags & ISA_MIPS32R6) {
16221 /* DIV */
16222 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16223 } else {
16224 /* LWXS */
16225 gen_ldxs(ctx, rs, rt, rd);
16226 }
16227 break;
16228 case MOD:
16229 check_insn(ctx, ISA_MIPS32R6);
16230 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16231 break;
16232 case R6_DIVU:
16233 check_insn(ctx, ISA_MIPS32R6);
16234 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16235 break;
e0332095
YK
16236 case MODU:
16237 check_insn(ctx, ISA_MIPS32R6);
16238 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16239 break;
16240 default:
16241 goto pool32a_invalid;
16242 }
16243 break;
16244 case INS:
16245 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16246 return;
e0332095
YK
16247 case LSA:
16248 check_insn(ctx, ISA_MIPS32R6);
16249 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16250 extract32(ctx->opcode, 9, 2));
16251 break;
16252 case ALIGN:
16253 check_insn(ctx, ISA_MIPS32R6);
821f2008 16254 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16255 break;
3c824109
NF
16256 case EXT:
16257 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16258 return;
16259 case POOL32AXF:
240ce26a 16260 gen_pool32axf(env, ctx, rt, rs);
3c824109 16261 break;
dbd8af98 16262 case BREAK32:
9c708c7f 16263 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16264 break;
bb238210
YK
16265 case SIGRIE:
16266 check_insn(ctx, ISA_MIPS32R6);
16267 generate_exception_end(ctx, EXCP_RI);
16268 break;
3c824109
NF
16269 default:
16270 pool32a_invalid:
16271 MIPS_INVAL("pool32a");
9c708c7f 16272 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16273 break;
16274 }
16275 break;
16276 case POOL32B:
16277 minor = (ctx->opcode >> 12) & 0xf;
16278 switch (minor) {
16279 case CACHE:
2e15497c 16280 check_cp0_enabled(ctx);
0d74a222
LA
16281 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16282 gen_cache_operation(ctx, rt, rs, imm);
16283 }
3c824109
NF
16284 break;
16285 case LWC2:
16286 case SWC2:
16287 /* COP2: Not implemented. */
16288 generate_exception_err(ctx, EXCP_CpU, 2);
16289 break;
3c824109
NF
16290#ifdef TARGET_MIPS64
16291 case LDP:
16292 case SDP:
d9224450
MR
16293 check_insn(ctx, ISA_MIPS3);
16294 check_mips_64(ctx);
3c824109 16295#endif
146dd620 16296 /* fall through */
d9224450
MR
16297 case LWP:
16298 case SWP:
3c824109
NF
16299 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16300 break;
3c824109
NF
16301#ifdef TARGET_MIPS64
16302 case LDM:
16303 case SDM:
d9224450
MR
16304 check_insn(ctx, ISA_MIPS3);
16305 check_mips_64(ctx);
3c824109 16306#endif
146dd620 16307 /* fall through */
d9224450
MR
16308 case LWM32:
16309 case SWM32:
3c824109
NF
16310 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16311 break;
16312 default:
16313 MIPS_INVAL("pool32b");
9c708c7f 16314 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16315 break;
16316 }
16317 break;
16318 case POOL32F:
5ab5c041 16319 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16320 minor = ctx->opcode & 0x3f;
16321 check_cp1_enabled(ctx);
16322 switch (minor) {
16323 case ALNV_PS:
9e8f441a 16324 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16325 mips32_op = OPC_ALNV_PS;
16326 goto do_madd;
16327 case MADD_S:
9e8f441a 16328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16329 mips32_op = OPC_MADD_S;
16330 goto do_madd;
16331 case MADD_D:
9e8f441a 16332 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16333 mips32_op = OPC_MADD_D;
16334 goto do_madd;
16335 case MADD_PS:
9e8f441a 16336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16337 mips32_op = OPC_MADD_PS;
16338 goto do_madd;
16339 case MSUB_S:
9e8f441a 16340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16341 mips32_op = OPC_MSUB_S;
16342 goto do_madd;
16343 case MSUB_D:
9e8f441a 16344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16345 mips32_op = OPC_MSUB_D;
16346 goto do_madd;
16347 case MSUB_PS:
9e8f441a 16348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16349 mips32_op = OPC_MSUB_PS;
16350 goto do_madd;
16351 case NMADD_S:
9e8f441a 16352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16353 mips32_op = OPC_NMADD_S;
16354 goto do_madd;
16355 case NMADD_D:
9e8f441a 16356 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16357 mips32_op = OPC_NMADD_D;
16358 goto do_madd;
16359 case NMADD_PS:
9e8f441a 16360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16361 mips32_op = OPC_NMADD_PS;
16362 goto do_madd;
16363 case NMSUB_S:
9e8f441a 16364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16365 mips32_op = OPC_NMSUB_S;
16366 goto do_madd;
16367 case NMSUB_D:
9e8f441a 16368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16369 mips32_op = OPC_NMSUB_D;
16370 goto do_madd;
16371 case NMSUB_PS:
9e8f441a 16372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16373 mips32_op = OPC_NMSUB_PS;
16374 do_madd:
16375 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16376 break;
16377 case CABS_COND_FMT:
9e8f441a 16378 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16379 cond = (ctx->opcode >> 6) & 0xf;
16380 cc = (ctx->opcode >> 13) & 0x7;
16381 fmt = (ctx->opcode >> 10) & 0x3;
16382 switch (fmt) {
16383 case 0x0:
16384 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16385 break;
16386 case 0x1:
16387 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16388 break;
16389 case 0x2:
16390 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16391 break;
16392 default:
16393 goto pool32f_invalid;
16394 }
16395 break;
16396 case C_COND_FMT:
9e8f441a 16397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16398 cond = (ctx->opcode >> 6) & 0xf;
16399 cc = (ctx->opcode >> 13) & 0x7;
16400 fmt = (ctx->opcode >> 10) & 0x3;
16401 switch (fmt) {
16402 case 0x0:
16403 gen_cmp_s(ctx, cond, rt, rs, cc);
16404 break;
16405 case 0x1:
16406 gen_cmp_d(ctx, cond, rt, rs, cc);
16407 break;
16408 case 0x2:
16409 gen_cmp_ps(ctx, cond, rt, rs, cc);
16410 break;
16411 default:
16412 goto pool32f_invalid;
16413 }
16414 break;
2a24a7ba
YK
16415 case CMP_CONDN_S:
16416 check_insn(ctx, ISA_MIPS32R6);
16417 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16418 break;
16419 case CMP_CONDN_D:
16420 check_insn(ctx, ISA_MIPS32R6);
16421 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16422 break;
3c824109 16423 case POOL32FXF:
d75c135e 16424 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
16425 break;
16426 case 0x00:
16427 /* PLL foo */
16428 switch ((ctx->opcode >> 6) & 0x7) {
16429 case PLL_PS:
16430 mips32_op = OPC_PLL_PS;
16431 goto do_ps;
16432 case PLU_PS:
16433 mips32_op = OPC_PLU_PS;
16434 goto do_ps;
16435 case PUL_PS:
16436 mips32_op = OPC_PUL_PS;
16437 goto do_ps;
16438 case PUU_PS:
16439 mips32_op = OPC_PUU_PS;
16440 goto do_ps;
16441 case CVT_PS_S:
9e8f441a 16442 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16443 mips32_op = OPC_CVT_PS_S;
16444 do_ps:
16445 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16446 break;
16447 default:
16448 goto pool32f_invalid;
16449 }
16450 break;
2a24a7ba
YK
16451 case MIN_FMT:
16452 check_insn(ctx, ISA_MIPS32R6);
16453 switch ((ctx->opcode >> 9) & 0x3) {
16454 case FMT_SDPS_S:
16455 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16456 break;
16457 case FMT_SDPS_D:
16458 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16459 break;
16460 default:
16461 goto pool32f_invalid;
16462 }
16463 break;
3c824109
NF
16464 case 0x08:
16465 /* [LS][WDU]XC1 */
16466 switch ((ctx->opcode >> 6) & 0x7) {
16467 case LWXC1:
9e8f441a 16468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16469 mips32_op = OPC_LWXC1;
16470 goto do_ldst_cp1;
16471 case SWXC1:
9e8f441a 16472 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16473 mips32_op = OPC_SWXC1;
16474 goto do_ldst_cp1;
16475 case LDXC1:
9e8f441a 16476 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16477 mips32_op = OPC_LDXC1;
16478 goto do_ldst_cp1;
16479 case SDXC1:
9e8f441a 16480 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16481 mips32_op = OPC_SDXC1;
16482 goto do_ldst_cp1;
16483 case LUXC1:
9e8f441a 16484 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16485 mips32_op = OPC_LUXC1;
16486 goto do_ldst_cp1;
16487 case SUXC1:
9e8f441a 16488 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16489 mips32_op = OPC_SUXC1;
16490 do_ldst_cp1:
16491 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16492 break;
16493 default:
16494 goto pool32f_invalid;
16495 }
16496 break;
2a24a7ba
YK
16497 case MAX_FMT:
16498 check_insn(ctx, ISA_MIPS32R6);
16499 switch ((ctx->opcode >> 9) & 0x3) {
16500 case FMT_SDPS_S:
16501 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16502 break;
16503 case FMT_SDPS_D:
16504 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16505 break;
16506 default:
16507 goto pool32f_invalid;
16508 }
16509 break;
3c824109
NF
16510 case 0x18:
16511 /* 3D insns */
9e8f441a 16512 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16513 fmt = (ctx->opcode >> 9) & 0x3;
16514 switch ((ctx->opcode >> 6) & 0x7) {
16515 case RSQRT2_FMT:
16516 switch (fmt) {
16517 case FMT_SDPS_S:
16518 mips32_op = OPC_RSQRT2_S;
16519 goto do_3d;
16520 case FMT_SDPS_D:
16521 mips32_op = OPC_RSQRT2_D;
16522 goto do_3d;
16523 case FMT_SDPS_PS:
16524 mips32_op = OPC_RSQRT2_PS;
16525 goto do_3d;
16526 default:
16527 goto pool32f_invalid;
16528 }
16529 break;
16530 case RECIP2_FMT:
16531 switch (fmt) {
16532 case FMT_SDPS_S:
16533 mips32_op = OPC_RECIP2_S;
16534 goto do_3d;
16535 case FMT_SDPS_D:
16536 mips32_op = OPC_RECIP2_D;
16537 goto do_3d;
16538 case FMT_SDPS_PS:
16539 mips32_op = OPC_RECIP2_PS;
16540 goto do_3d;
16541 default:
16542 goto pool32f_invalid;
16543 }
16544 break;
16545 case ADDR_PS:
16546 mips32_op = OPC_ADDR_PS;
16547 goto do_3d;
16548 case MULR_PS:
16549 mips32_op = OPC_MULR_PS;
16550 do_3d:
16551 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16552 break;
16553 default:
16554 goto pool32f_invalid;
16555 }
16556 break;
16557 case 0x20:
2a24a7ba 16558 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16559 cc = (ctx->opcode >> 13) & 0x7;
16560 fmt = (ctx->opcode >> 9) & 0x3;
16561 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16562 case MOVF_FMT: /* RINT_FMT */
16563 if (ctx->insn_flags & ISA_MIPS32R6) {
16564 /* RINT_FMT */
16565 switch (fmt) {
16566 case FMT_SDPS_S:
16567 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16568 break;
16569 case FMT_SDPS_D:
16570 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16571 break;
16572 default:
16573 goto pool32f_invalid;
16574 }
16575 } else {
16576 /* MOVF_FMT */
16577 switch (fmt) {
16578 case FMT_SDPS_S:
16579 gen_movcf_s(ctx, rs, rt, cc, 0);
16580 break;
16581 case FMT_SDPS_D:
16582 gen_movcf_d(ctx, rs, rt, cc, 0);
16583 break;
16584 case FMT_SDPS_PS:
16585 check_ps(ctx);
16586 gen_movcf_ps(ctx, rs, rt, cc, 0);
16587 break;
16588 default:
16589 goto pool32f_invalid;
16590 }
3c824109
NF
16591 }
16592 break;
2a24a7ba
YK
16593 case MOVT_FMT: /* CLASS_FMT */
16594 if (ctx->insn_flags & ISA_MIPS32R6) {
16595 /* CLASS_FMT */
16596 switch (fmt) {
16597 case FMT_SDPS_S:
16598 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16599 break;
16600 case FMT_SDPS_D:
16601 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16602 break;
16603 default:
16604 goto pool32f_invalid;
16605 }
16606 } else {
16607 /* MOVT_FMT */
16608 switch (fmt) {
16609 case FMT_SDPS_S:
16610 gen_movcf_s(ctx, rs, rt, cc, 1);
16611 break;
16612 case FMT_SDPS_D:
16613 gen_movcf_d(ctx, rs, rt, cc, 1);
16614 break;
16615 case FMT_SDPS_PS:
16616 check_ps(ctx);
16617 gen_movcf_ps(ctx, rs, rt, cc, 1);
16618 break;
16619 default:
16620 goto pool32f_invalid;
16621 }
3c824109
NF
16622 }
16623 break;
16624 case PREFX:
9e8f441a 16625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16626 break;
16627 default:
16628 goto pool32f_invalid;
16629 }
16630 break;
16631#define FINSN_3ARG_SDPS(prfx) \
16632 switch ((ctx->opcode >> 8) & 0x3) { \
16633 case FMT_SDPS_S: \
16634 mips32_op = OPC_##prfx##_S; \
16635 goto do_fpop; \
16636 case FMT_SDPS_D: \
16637 mips32_op = OPC_##prfx##_D; \
16638 goto do_fpop; \
16639 case FMT_SDPS_PS: \
e29c9628 16640 check_ps(ctx); \
3c824109
NF
16641 mips32_op = OPC_##prfx##_PS; \
16642 goto do_fpop; \
16643 default: \
16644 goto pool32f_invalid; \
16645 }
2a24a7ba
YK
16646 case MINA_FMT:
16647 check_insn(ctx, ISA_MIPS32R6);
16648 switch ((ctx->opcode >> 9) & 0x3) {
16649 case FMT_SDPS_S:
16650 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16651 break;
16652 case FMT_SDPS_D:
16653 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16654 break;
16655 default:
16656 goto pool32f_invalid;
16657 }
16658 break;
16659 case MAXA_FMT:
16660 check_insn(ctx, ISA_MIPS32R6);
16661 switch ((ctx->opcode >> 9) & 0x3) {
16662 case FMT_SDPS_S:
16663 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16664 break;
16665 case FMT_SDPS_D:
16666 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16667 break;
16668 default:
16669 goto pool32f_invalid;
16670 }
16671 break;
3c824109
NF
16672 case 0x30:
16673 /* regular FP ops */
16674 switch ((ctx->opcode >> 6) & 0x3) {
16675 case ADD_FMT:
16676 FINSN_3ARG_SDPS(ADD);
16677 break;
16678 case SUB_FMT:
16679 FINSN_3ARG_SDPS(SUB);
16680 break;
16681 case MUL_FMT:
16682 FINSN_3ARG_SDPS(MUL);
16683 break;
16684 case DIV_FMT:
16685 fmt = (ctx->opcode >> 8) & 0x3;
16686 if (fmt == 1) {
16687 mips32_op = OPC_DIV_D;
16688 } else if (fmt == 0) {
16689 mips32_op = OPC_DIV_S;
16690 } else {
16691 goto pool32f_invalid;
16692 }
16693 goto do_fpop;
16694 default:
16695 goto pool32f_invalid;
16696 }
16697 break;
16698 case 0x38:
16699 /* cmovs */
2a24a7ba 16700 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16701 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16702 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16703 /* SELEQZ_FMT */
2a24a7ba
YK
16704 switch ((ctx->opcode >> 9) & 0x3) {
16705 case FMT_SDPS_S:
fdac60cd 16706 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16707 break;
16708 case FMT_SDPS_D:
fdac60cd 16709 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16710 break;
16711 default:
16712 goto pool32f_invalid;
16713 }
16714 } else {
16715 /* MOVN_FMT */
16716 FINSN_3ARG_SDPS(MOVN);
16717 }
16718 break;
16719 case MOVN_FMT_04:
16720 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16721 FINSN_3ARG_SDPS(MOVN);
16722 break;
fdac60cd 16723 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16724 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16725 /* SELNEZ_FMT */
2a24a7ba
YK
16726 switch ((ctx->opcode >> 9) & 0x3) {
16727 case FMT_SDPS_S:
fdac60cd 16728 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16729 break;
16730 case FMT_SDPS_D:
fdac60cd 16731 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16732 break;
16733 default:
16734 goto pool32f_invalid;
16735 }
16736 } else {
16737 /* MOVZ_FMT */
16738 FINSN_3ARG_SDPS(MOVZ);
16739 }
16740 break;
16741 case MOVZ_FMT_05:
16742 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16743 FINSN_3ARG_SDPS(MOVZ);
16744 break;
2a24a7ba
YK
16745 case SEL_FMT:
16746 check_insn(ctx, ISA_MIPS32R6);
16747 switch ((ctx->opcode >> 9) & 0x3) {
16748 case FMT_SDPS_S:
16749 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16750 break;
16751 case FMT_SDPS_D:
16752 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16753 break;
16754 default:
16755 goto pool32f_invalid;
16756 }
16757 break;
16758 case MADDF_FMT:
16759 check_insn(ctx, ISA_MIPS32R6);
16760 switch ((ctx->opcode >> 9) & 0x3) {
16761 case FMT_SDPS_S:
16762 mips32_op = OPC_MADDF_S;
16763 goto do_fpop;
16764 case FMT_SDPS_D:
16765 mips32_op = OPC_MADDF_D;
16766 goto do_fpop;
16767 default:
16768 goto pool32f_invalid;
16769 }
16770 break;
16771 case MSUBF_FMT:
16772 check_insn(ctx, ISA_MIPS32R6);
16773 switch ((ctx->opcode >> 9) & 0x3) {
16774 case FMT_SDPS_S:
16775 mips32_op = OPC_MSUBF_S;
16776 goto do_fpop;
16777 case FMT_SDPS_D:
16778 mips32_op = OPC_MSUBF_D;
16779 goto do_fpop;
16780 default:
16781 goto pool32f_invalid;
16782 }
16783 break;
3c824109
NF
16784 default:
16785 goto pool32f_invalid;
16786 }
16787 break;
16788 do_fpop:
16789 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16790 break;
16791 default:
16792 pool32f_invalid:
16793 MIPS_INVAL("pool32f");
9c708c7f 16794 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16795 break;
16796 }
16797 } else {
16798 generate_exception_err(ctx, EXCP_CpU, 1);
16799 }
16800 break;
16801 case POOL32I:
16802 minor = (ctx->opcode >> 21) & 0x1f;
16803 switch (minor) {
16804 case BLTZ:
9e8f441a 16805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16806 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16807 break;
3c824109 16808 case BLTZAL:
9e8f441a 16809 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16810 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16811 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16812 break;
3c824109 16813 case BLTZALS:
9e8f441a 16814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16815 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16816 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16817 break;
3c824109 16818 case BGEZ:
9e8f441a 16819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16820 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16821 break;
3c824109 16822 case BGEZAL:
9e8f441a 16823 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16824 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16825 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16826 break;
3c824109 16827 case BGEZALS:
9e8f441a 16828 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16829 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16830 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16831 break;
3c824109 16832 case BLEZ:
9e8f441a 16833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16834 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16835 break;
3c824109 16836 case BGTZ:
9e8f441a 16837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 16838 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16839 break;
16840
16841 /* Traps */
65935f07
YK
16842 case TLTI: /* BC1EQZC */
16843 if (ctx->insn_flags & ISA_MIPS32R6) {
16844 /* BC1EQZC */
16845 check_cp1_enabled(ctx);
16846 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16847 } else {
16848 /* TLTI */
16849 mips32_op = OPC_TLTI;
16850 goto do_trapi;
16851 }
16852 break;
16853 case TGEI: /* BC1NEZC */
16854 if (ctx->insn_flags & ISA_MIPS32R6) {
16855 /* BC1NEZC */
16856 check_cp1_enabled(ctx);
16857 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16858 } else {
16859 /* TGEI */
16860 mips32_op = OPC_TGEI;
16861 goto do_trapi;
16862 }
16863 break;
3c824109 16864 case TLTIU:
9e8f441a 16865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16866 mips32_op = OPC_TLTIU;
16867 goto do_trapi;
16868 case TGEIU:
9e8f441a 16869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16870 mips32_op = OPC_TGEIU;
16871 goto do_trapi;
3b4a5489
YK
16872 case TNEI: /* SYNCI */
16873 if (ctx->insn_flags & ISA_MIPS32R6) {
16874 /* SYNCI */
7480515f
AM
16875 /*
16876 * Break the TB to be able to sync copied instructions
16877 * immediately.
16878 */
eeb3bba8 16879 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16880 } else {
16881 /* TNEI */
16882 mips32_op = OPC_TNEI;
16883 goto do_trapi;
16884 }
16885 break;
3c824109 16886 case TEQI:
9e8f441a 16887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16888 mips32_op = OPC_TEQI;
16889 do_trapi:
16890 gen_trap(ctx, mips32_op, rs, -1, imm);
16891 break;
16892
16893 case BNEZC:
16894 case BEQZC:
9e8f441a 16895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16896 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16897 4, rs, 0, imm << 1, 0);
7480515f
AM
16898 /*
16899 * Compact branches don't have a delay slot, so just let
16900 * the normal delay slot handling take us to the branch
16901 * target.
16902 */
3c824109
NF
16903 break;
16904 case LUI:
9e8f441a 16905 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 16906 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16907 break;
16908 case SYNCI:
9e8f441a 16909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7480515f
AM
16910 /*
16911 * Break the TB to be able to sync copied instructions
16912 * immediately.
16913 */
eeb3bba8 16914 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16915 break;
16916 case BC2F:
16917 case BC2T:
9e8f441a 16918 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16919 /* COP2: Not implemented. */
16920 generate_exception_err(ctx, EXCP_CpU, 2);
16921 break;
16922 case BC1F:
9e8f441a 16923 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16924 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16925 goto do_cp1branch;
16926 case BC1T:
9e8f441a 16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16928 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16929 goto do_cp1branch;
16930 case BC1ANY4F:
9e8f441a 16931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16932 mips32_op = OPC_BC1FANY4;
16933 goto do_cp1mips3d;
16934 case BC1ANY4T:
9e8f441a 16935 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16936 mips32_op = OPC_BC1TANY4;
16937 do_cp1mips3d:
16938 check_cop1x(ctx);
d75c135e 16939 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16940 /* Fall through */
16941 do_cp1branch:
272f458d
MR
16942 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16943 check_cp1_enabled(ctx);
16944 gen_compute_branch1(ctx, mips32_op,
16945 (ctx->opcode >> 18) & 0x7, imm << 1);
16946 } else {
16947 generate_exception_err(ctx, EXCP_CpU, 1);
16948 }
3c824109
NF
16949 break;
16950 case BPOSGE64:
16951 case BPOSGE32:
16952 /* MIPS DSP: not implemented */
16953 /* Fall through */
16954 default:
16955 MIPS_INVAL("pool32i");
9c708c7f 16956 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16957 break;
16958 }
16959 break;
16960 case POOL32C:
16961 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
16962 offset = sextract32(ctx->opcode, 0,
16963 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
16964 switch (minor) {
16965 case LWL:
9e8f441a 16966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16967 mips32_op = OPC_LWL;
5c13fdfd 16968 goto do_ld_lr;
3c824109 16969 case SWL:
9e8f441a 16970 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16971 mips32_op = OPC_SWL;
5c13fdfd 16972 goto do_st_lr;
3c824109 16973 case LWR:
9e8f441a 16974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16975 mips32_op = OPC_LWR;
5c13fdfd 16976 goto do_ld_lr;
3c824109 16977 case SWR:
9e8f441a 16978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16979 mips32_op = OPC_SWR;
5c13fdfd 16980 goto do_st_lr;
3c824109
NF
16981#if defined(TARGET_MIPS64)
16982 case LDL:
d9224450
MR
16983 check_insn(ctx, ISA_MIPS3);
16984 check_mips_64(ctx);
9e8f441a 16985 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16986 mips32_op = OPC_LDL;
5c13fdfd 16987 goto do_ld_lr;
3c824109 16988 case SDL:
d9224450
MR
16989 check_insn(ctx, ISA_MIPS3);
16990 check_mips_64(ctx);
9e8f441a 16991 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16992 mips32_op = OPC_SDL;
5c13fdfd 16993 goto do_st_lr;
3c824109 16994 case LDR:
d9224450
MR
16995 check_insn(ctx, ISA_MIPS3);
16996 check_mips_64(ctx);
9e8f441a 16997 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16998 mips32_op = OPC_LDR;
5c13fdfd 16999 goto do_ld_lr;
3c824109 17000 case SDR:
d9224450
MR
17001 check_insn(ctx, ISA_MIPS3);
17002 check_mips_64(ctx);
9e8f441a 17003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17004 mips32_op = OPC_SDR;
5c13fdfd 17005 goto do_st_lr;
3c824109 17006 case LWU:
d9224450
MR
17007 check_insn(ctx, ISA_MIPS3);
17008 check_mips_64(ctx);
3c824109 17009 mips32_op = OPC_LWU;
5c13fdfd 17010 goto do_ld_lr;
3c824109 17011 case LLD:
d9224450
MR
17012 check_insn(ctx, ISA_MIPS3);
17013 check_mips_64(ctx);
3c824109 17014 mips32_op = OPC_LLD;
5c13fdfd 17015 goto do_ld_lr;
3c824109
NF
17016#endif
17017 case LL:
17018 mips32_op = OPC_LL;
5c13fdfd
AJ
17019 goto do_ld_lr;
17020 do_ld_lr:
3b4a5489 17021 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
17022 break;
17023 do_st_lr:
8fffc646 17024 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
17025 break;
17026 case SC:
33a07fa2 17027 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
17028 break;
17029#if defined(TARGET_MIPS64)
17030 case SCD:
d9224450
MR
17031 check_insn(ctx, ISA_MIPS3);
17032 check_mips_64(ctx);
33a07fa2 17033 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
17034 break;
17035#endif
8fffc646
JH
17036 case LD_EVA:
17037 if (!ctx->eva) {
17038 MIPS_INVAL("pool32c ld-eva");
17039 generate_exception_end(ctx, EXCP_RI);
17040 break;
17041 }
17042 check_cp0_enabled(ctx);
17043
17044 minor2 = (ctx->opcode >> 9) & 0x7;
17045 offset = sextract32(ctx->opcode, 0, 9);
17046 switch (minor2) {
17047 case LBUE:
17048 mips32_op = OPC_LBUE;
17049 goto do_ld_lr;
17050 case LHUE:
17051 mips32_op = OPC_LHUE;
17052 goto do_ld_lr;
17053 case LWLE:
17054 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17055 mips32_op = OPC_LWLE;
17056 goto do_ld_lr;
17057 case LWRE:
17058 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17059 mips32_op = OPC_LWRE;
17060 goto do_ld_lr;
17061 case LBE:
17062 mips32_op = OPC_LBE;
17063 goto do_ld_lr;
17064 case LHE:
17065 mips32_op = OPC_LHE;
17066 goto do_ld_lr;
17067 case LLE:
17068 mips32_op = OPC_LLE;
17069 goto do_ld_lr;
17070 case LWE:
17071 mips32_op = OPC_LWE;
17072 goto do_ld_lr;
17073 };
17074 break;
17075 case ST_EVA:
17076 if (!ctx->eva) {
17077 MIPS_INVAL("pool32c st-eva");
17078 generate_exception_end(ctx, EXCP_RI);
17079 break;
17080 }
17081 check_cp0_enabled(ctx);
17082
17083 minor2 = (ctx->opcode >> 9) & 0x7;
17084 offset = sextract32(ctx->opcode, 0, 9);
17085 switch (minor2) {
17086 case SWLE:
17087 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17088 mips32_op = OPC_SWLE;
17089 goto do_st_lr;
17090 case SWRE:
17091 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17092 mips32_op = OPC_SWRE;
17093 goto do_st_lr;
17094 case PREFE:
17095 /* Treat as no-op */
17096 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17097 /* hint codes 24-31 are reserved and signal RI */
17098 generate_exception(ctx, EXCP_RI);
17099 }
17100 break;
17101 case CACHEE:
17102 /* Treat as no-op */
17103 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17104 gen_cache_operation(ctx, rt, rs, offset);
17105 }
17106 break;
17107 case SBE:
17108 mips32_op = OPC_SBE;
17109 goto do_st_lr;
17110 case SHE:
17111 mips32_op = OPC_SHE;
17112 goto do_st_lr;
17113 case SCE:
33a07fa2 17114 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
17115 break;
17116 case SWE:
17117 mips32_op = OPC_SWE;
17118 goto do_st_lr;
17119 };
17120 break;
3c824109
NF
17121 case PREF:
17122 /* Treat as no-op */
3b4a5489
YK
17123 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17124 /* hint codes 24-31 are reserved and signal RI */
17125 generate_exception(ctx, EXCP_RI);
17126 }
3c824109
NF
17127 break;
17128 default:
17129 MIPS_INVAL("pool32c");
9c708c7f 17130 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17131 break;
17132 }
17133 break;
ab39ee45
YK
17134 case ADDI32: /* AUI, LUI */
17135 if (ctx->insn_flags & ISA_MIPS32R6) {
17136 /* AUI, LUI */
17137 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17138 } else {
17139 /* ADDI32 */
17140 mips32_op = OPC_ADDI;
17141 goto do_addi;
17142 }
17143 break;
3c824109
NF
17144 case ADDIU32:
17145 mips32_op = OPC_ADDIU;
17146 do_addi:
d75c135e 17147 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17148 break;
17149
17150 /* Logical operations */
17151 case ORI32:
17152 mips32_op = OPC_ORI;
17153 goto do_logici;
17154 case XORI32:
17155 mips32_op = OPC_XORI;
17156 goto do_logici;
17157 case ANDI32:
17158 mips32_op = OPC_ANDI;
17159 do_logici:
d75c135e 17160 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17161 break;
17162
17163 /* Set less than immediate */
17164 case SLTI32:
17165 mips32_op = OPC_SLTI;
17166 goto do_slti;
17167 case SLTIU32:
17168 mips32_op = OPC_SLTIU;
17169 do_slti:
d75c135e 17170 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17171 break;
17172 case JALX32:
9e8f441a 17173 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17174 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17175 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17176 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17177 break;
65935f07
YK
17178 case JALS32: /* BOVC, BEQC, BEQZALC */
17179 if (ctx->insn_flags & ISA_MIPS32R6) {
17180 if (rs >= rt) {
17181 /* BOVC */
17182 mips32_op = OPC_BOVC;
17183 } else if (rs < rt && rs == 0) {
17184 /* BEQZALC */
17185 mips32_op = OPC_BEQZALC;
17186 } else {
17187 /* BEQC */
17188 mips32_op = OPC_BEQC;
17189 }
17190 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17191 } else {
17192 /* JALS32 */
17193 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17194 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17195 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17196 }
3c824109 17197 break;
65935f07
YK
17198 case BEQ32: /* BC */
17199 if (ctx->insn_flags & ISA_MIPS32R6) {
17200 /* BC */
17201 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17202 sextract32(ctx->opcode << 1, 0, 27));
17203 } else {
17204 /* BEQ32 */
17205 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17206 }
3c824109 17207 break;
65935f07
YK
17208 case BNE32: /* BALC */
17209 if (ctx->insn_flags & ISA_MIPS32R6) {
17210 /* BALC */
17211 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17212 sextract32(ctx->opcode << 1, 0, 27));
17213 } else {
17214 /* BNE32 */
17215 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17216 }
3c824109 17217 break;
65935f07
YK
17218 case J32: /* BGTZC, BLTZC, BLTC */
17219 if (ctx->insn_flags & ISA_MIPS32R6) {
17220 if (rs == 0 && rt != 0) {
17221 /* BGTZC */
17222 mips32_op = OPC_BGTZC;
17223 } else if (rs != 0 && rt != 0 && rs == rt) {
17224 /* BLTZC */
17225 mips32_op = OPC_BLTZC;
17226 } else {
17227 /* BLTC */
17228 mips32_op = OPC_BLTC;
17229 }
17230 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17231 } else {
17232 /* J32 */
17233 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17234 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17235 }
3c824109 17236 break;
65935f07
YK
17237 case JAL32: /* BLEZC, BGEZC, BGEC */
17238 if (ctx->insn_flags & ISA_MIPS32R6) {
17239 if (rs == 0 && rt != 0) {
17240 /* BLEZC */
17241 mips32_op = OPC_BLEZC;
17242 } else if (rs != 0 && rt != 0 && rs == rt) {
17243 /* BGEZC */
17244 mips32_op = OPC_BGEZC;
17245 } else {
17246 /* BGEC */
17247 mips32_op = OPC_BGEC;
17248 }
17249 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17250 } else {
17251 /* JAL32 */
17252 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17253 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17254 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17255 }
3c824109
NF
17256 break;
17257 /* Floating point (COP1) */
17258 case LWC132:
17259 mips32_op = OPC_LWC1;
17260 goto do_cop1;
17261 case LDC132:
17262 mips32_op = OPC_LDC1;
17263 goto do_cop1;
17264 case SWC132:
17265 mips32_op = OPC_SWC1;
17266 goto do_cop1;
17267 case SDC132:
17268 mips32_op = OPC_SDC1;
17269 do_cop1:
5ab5c041 17270 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17271 break;
ab39ee45
YK
17272 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17273 if (ctx->insn_flags & ISA_MIPS32R6) {
17274 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17275 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17276 case ADDIUPC_00:
17277 case ADDIUPC_01:
17278 case ADDIUPC_02:
17279 case ADDIUPC_03:
17280 case ADDIUPC_04:
17281 case ADDIUPC_05:
17282 case ADDIUPC_06:
17283 case ADDIUPC_07:
eeb3bba8 17284 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17285 break;
17286 case AUIPC:
eeb3bba8 17287 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17288 break;
17289 case ALUIPC:
eeb3bba8 17290 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17291 break;
c38a1d52
AR
17292 case LWPC_08:
17293 case LWPC_09:
17294 case LWPC_0A:
17295 case LWPC_0B:
17296 case LWPC_0C:
17297 case LWPC_0D:
17298 case LWPC_0E:
17299 case LWPC_0F:
eeb3bba8 17300 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17301 break;
17302 default:
17303 generate_exception(ctx, EXCP_RI);
17304 break;
17305 }
17306 } else {
17307 /* ADDIUPC */
3c824109 17308 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17309 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17310
17311 gen_addiupc(ctx, reg, offset, 0, 0);
17312 }
17313 break;
65935f07
YK
17314 case BNVC: /* BNEC, BNEZALC */
17315 check_insn(ctx, ISA_MIPS32R6);
17316 if (rs >= rt) {
17317 /* BNVC */
17318 mips32_op = OPC_BNVC;
17319 } else if (rs < rt && rs == 0) {
17320 /* BNEZALC */
17321 mips32_op = OPC_BNEZALC;
17322 } else {
17323 /* BNEC */
17324 mips32_op = OPC_BNEC;
17325 }
17326 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17327 break;
17328 case R6_BNEZC: /* JIALC */
17329 check_insn(ctx, ISA_MIPS32R6);
17330 if (rt != 0) {
17331 /* BNEZC */
17332 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17333 sextract32(ctx->opcode << 1, 0, 22));
17334 } else {
17335 /* JIALC */
17336 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17337 }
17338 break;
17339 case R6_BEQZC: /* JIC */
17340 check_insn(ctx, ISA_MIPS32R6);
17341 if (rt != 0) {
17342 /* BEQZC */
17343 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17344 sextract32(ctx->opcode << 1, 0, 22));
17345 } else {
17346 /* JIC */
17347 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17348 }
17349 break;
17350 case BLEZALC: /* BGEZALC, BGEUC */
17351 check_insn(ctx, ISA_MIPS32R6);
17352 if (rs == 0 && rt != 0) {
17353 /* BLEZALC */
17354 mips32_op = OPC_BLEZALC;
17355 } else if (rs != 0 && rt != 0 && rs == rt) {
17356 /* BGEZALC */
17357 mips32_op = OPC_BGEZALC;
17358 } else {
17359 /* BGEUC */
17360 mips32_op = OPC_BGEUC;
17361 }
17362 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17363 break;
17364 case BGTZALC: /* BLTZALC, BLTUC */
17365 check_insn(ctx, ISA_MIPS32R6);
17366 if (rs == 0 && rt != 0) {
17367 /* BGTZALC */
17368 mips32_op = OPC_BGTZALC;
17369 } else if (rs != 0 && rt != 0 && rs == rt) {
17370 /* BLTZALC */
17371 mips32_op = OPC_BLTZALC;
17372 } else {
17373 /* BLTUC */
17374 mips32_op = OPC_BLTUC;
17375 }
17376 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17377 break;
3c824109
NF
17378 /* Loads and stores */
17379 case LB32:
17380 mips32_op = OPC_LB;
5c13fdfd 17381 goto do_ld;
3c824109
NF
17382 case LBU32:
17383 mips32_op = OPC_LBU;
5c13fdfd 17384 goto do_ld;
3c824109
NF
17385 case LH32:
17386 mips32_op = OPC_LH;
5c13fdfd 17387 goto do_ld;
3c824109
NF
17388 case LHU32:
17389 mips32_op = OPC_LHU;
5c13fdfd 17390 goto do_ld;
3c824109
NF
17391 case LW32:
17392 mips32_op = OPC_LW;
5c13fdfd 17393 goto do_ld;
3c824109
NF
17394#ifdef TARGET_MIPS64
17395 case LD32:
d9224450
MR
17396 check_insn(ctx, ISA_MIPS3);
17397 check_mips_64(ctx);
3c824109 17398 mips32_op = OPC_LD;
5c13fdfd 17399 goto do_ld;
3c824109 17400 case SD32:
d9224450
MR
17401 check_insn(ctx, ISA_MIPS3);
17402 check_mips_64(ctx);
3c824109 17403 mips32_op = OPC_SD;
5c13fdfd 17404 goto do_st;
3c824109
NF
17405#endif
17406 case SB32:
17407 mips32_op = OPC_SB;
5c13fdfd 17408 goto do_st;
3c824109
NF
17409 case SH32:
17410 mips32_op = OPC_SH;
5c13fdfd 17411 goto do_st;
3c824109
NF
17412 case SW32:
17413 mips32_op = OPC_SW;
5c13fdfd
AJ
17414 goto do_st;
17415 do_ld:
d75c135e 17416 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
17417 break;
17418 do_st:
17419 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17420 break;
17421 default:
9c708c7f 17422 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17423 break;
17424 }
17425}
17426
235785e8 17427static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
17428{
17429 uint32_t op;
17430
17431 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
17432 if (ctx->base.pc_next & 0x1) {
17433 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 17434 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
17435 return 2;
17436 }
17437
17438 op = (ctx->opcode >> 10) & 0x3f;
17439 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
17440 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17441 switch (op & 0x7) { /* MSB-3..MSB-5 */
17442 case 0:
17443 /* POOL32A, POOL32B, POOL32I, POOL32C */
17444 case 4:
17445 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17446 case 5:
17447 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17448 case 6:
17449 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17450 case 7:
17451 /* LB32, LH32, LWC132, LDC132, LW32 */
17452 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 17453 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17454 return 2;
17455 }
17456 break;
b231c103
YK
17457 case 1:
17458 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17459 case 2:
17460 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17461 case 3:
17462 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17463 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 17464 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17465 return 2;
17466 }
17467 break;
3c824109
NF
17468 }
17469 }
b231c103 17470
3c824109
NF
17471 switch (op) {
17472 case POOL16A:
17473 {
17474 int rd = mmreg(uMIPS_RD(ctx->opcode));
17475 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17476 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17477 uint32_t opc = 0;
17478
17479 switch (ctx->opcode & 0x1) {
17480 case ADDU16:
17481 opc = OPC_ADDU;
17482 break;
17483 case SUBU16:
17484 opc = OPC_SUBU;
17485 break;
17486 }
ed7ce6c0 17487 if (ctx->insn_flags & ISA_MIPS32R6) {
7480515f
AM
17488 /*
17489 * In the Release 6, the register number location in
ed7ce6c0
YK
17490 * the instruction encoding has changed.
17491 */
17492 gen_arith(ctx, opc, rs1, rd, rs2);
17493 } else {
17494 gen_arith(ctx, opc, rd, rs1, rs2);
17495 }
3c824109
NF
17496 }
17497 break;
17498 case POOL16B:
17499 {
17500 int rd = mmreg(uMIPS_RD(ctx->opcode));
17501 int rs = mmreg(uMIPS_RS(ctx->opcode));
17502 int amount = (ctx->opcode >> 1) & 0x7;
17503 uint32_t opc = 0;
17504 amount = amount == 0 ? 8 : amount;
17505
17506 switch (ctx->opcode & 0x1) {
17507 case SLL16:
17508 opc = OPC_SLL;
17509 break;
17510 case SRL16:
17511 opc = OPC_SRL;
17512 break;
17513 }
17514
d75c135e 17515 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17516 }
17517 break;
17518 case POOL16C:
ed7ce6c0
YK
17519 if (ctx->insn_flags & ISA_MIPS32R6) {
17520 gen_pool16c_r6_insn(ctx);
17521 } else {
17522 gen_pool16c_insn(ctx);
17523 }
3c824109
NF
17524 break;
17525 case LWGP16:
17526 {
17527 int rd = mmreg(uMIPS_RD(ctx->opcode));
17528 int rb = 28; /* GP */
17529 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17530
d75c135e 17531 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17532 }
17533 break;
17534 case POOL16F:
9e8f441a 17535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17536 if (ctx->opcode & 1) {
9c708c7f 17537 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17538 } else {
17539 /* MOVEP */
17540 int enc_dest = uMIPS_RD(ctx->opcode);
17541 int enc_rt = uMIPS_RS2(ctx->opcode);
17542 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17543 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17544 }
17545 break;
17546 case LBU16:
17547 {
17548 int rd = mmreg(uMIPS_RD(ctx->opcode));
17549 int rb = mmreg(uMIPS_RS(ctx->opcode));
17550 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17551 offset = (offset == 0xf ? -1 : offset);
17552
d75c135e 17553 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17554 }
17555 break;
17556 case LHU16:
17557 {
17558 int rd = mmreg(uMIPS_RD(ctx->opcode));
17559 int rb = mmreg(uMIPS_RS(ctx->opcode));
17560 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17561
d75c135e 17562 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17563 }
17564 break;
17565 case LWSP16:
17566 {
17567 int rd = (ctx->opcode >> 5) & 0x1f;
17568 int rb = 29; /* SP */
17569 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17570
d75c135e 17571 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17572 }
17573 break;
17574 case LW16:
17575 {
17576 int rd = mmreg(uMIPS_RD(ctx->opcode));
17577 int rb = mmreg(uMIPS_RS(ctx->opcode));
17578 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17579
d75c135e 17580 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17581 }
17582 break;
17583 case SB16:
17584 {
17585 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17586 int rb = mmreg(uMIPS_RS(ctx->opcode));
17587 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17588
5c13fdfd 17589 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17590 }
17591 break;
17592 case SH16:
17593 {
17594 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17595 int rb = mmreg(uMIPS_RS(ctx->opcode));
17596 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17597
5c13fdfd 17598 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17599 }
17600 break;
17601 case SWSP16:
17602 {
17603 int rd = (ctx->opcode >> 5) & 0x1f;
17604 int rb = 29; /* SP */
17605 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17606
5c13fdfd 17607 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17608 }
17609 break;
17610 case SW16:
17611 {
17612 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17613 int rb = mmreg(uMIPS_RS(ctx->opcode));
17614 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17615
5c13fdfd 17616 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17617 }
17618 break;
17619 case MOVE16:
17620 {
17621 int rd = uMIPS_RD5(ctx->opcode);
17622 int rs = uMIPS_RS5(ctx->opcode);
17623
7215d7e7 17624 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17625 }
17626 break;
17627 case ANDI16:
d75c135e 17628 gen_andi16(ctx);
3c824109
NF
17629 break;
17630 case POOL16D:
17631 switch (ctx->opcode & 0x1) {
17632 case ADDIUS5:
d75c135e 17633 gen_addius5(ctx);
3c824109
NF
17634 break;
17635 case ADDIUSP:
d75c135e 17636 gen_addiusp(ctx);
3c824109
NF
17637 break;
17638 }
17639 break;
17640 case POOL16E:
17641 switch (ctx->opcode & 0x1) {
17642 case ADDIUR2:
d75c135e 17643 gen_addiur2(ctx);
3c824109
NF
17644 break;
17645 case ADDIUR1SP:
d75c135e 17646 gen_addiur1sp(ctx);
3c824109
NF
17647 break;
17648 }
17649 break;
65935f07 17650 case B16: /* BC16 */
3c824109 17651 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17652 sextract32(ctx->opcode, 0, 10) << 1,
17653 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17654 break;
65935f07
YK
17655 case BNEZ16: /* BNEZC16 */
17656 case BEQZ16: /* BEQZC16 */
3c824109
NF
17657 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17658 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17659 0, sextract32(ctx->opcode, 0, 7) << 1,
17660 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17661
3c824109
NF
17662 break;
17663 case LI16:
17664 {
17665 int reg = mmreg(uMIPS_RD(ctx->opcode));
17666 int imm = ZIMM(ctx->opcode, 0, 7);
17667
17668 imm = (imm == 0x7f ? -1 : imm);
17669 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17670 }
17671 break;
3c824109 17672 case RES_29:
3c824109 17673 case RES_31:
3c824109 17674 case RES_39:
9c708c7f 17675 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17676 break;
17677 default:
f60eeb0c 17678 decode_micromips32_opc(env, ctx);
3c824109
NF
17679 return 4;
17680 }
17681
17682 return 2;
17683}
17684
261c95a0
YK
17685/*
17686 *
17687 * nanoMIPS opcodes
17688 *
17689 */
17690
17691/* MAJOR, P16, and P32 pools opcodes */
17692enum {
17693 NM_P_ADDIU = 0x00,
17694 NM_ADDIUPC = 0x01,
17695 NM_MOVE_BALC = 0x02,
17696 NM_P16_MV = 0x04,
17697 NM_LW16 = 0x05,
17698 NM_BC16 = 0x06,
17699 NM_P16_SR = 0x07,
17700
17701 NM_POOL32A = 0x08,
17702 NM_P_BAL = 0x0a,
17703 NM_P16_SHIFT = 0x0c,
17704 NM_LWSP16 = 0x0d,
17705 NM_BALC16 = 0x0e,
17706 NM_P16_4X4 = 0x0f,
17707
17708 NM_P_GP_W = 0x10,
17709 NM_P_GP_BH = 0x11,
17710 NM_P_J = 0x12,
17711 NM_P16C = 0x14,
17712 NM_LWGP16 = 0x15,
17713 NM_P16_LB = 0x17,
17714
17715 NM_P48I = 0x18,
17716 NM_P16_A1 = 0x1c,
17717 NM_LW4X4 = 0x1d,
17718 NM_P16_LH = 0x1f,
17719
17720 NM_P_U12 = 0x20,
17721 NM_P_LS_U12 = 0x21,
17722 NM_P_BR1 = 0x22,
17723 NM_P16_A2 = 0x24,
17724 NM_SW16 = 0x25,
17725 NM_BEQZC16 = 0x26,
17726
17727 NM_POOL32F = 0x28,
17728 NM_P_LS_S9 = 0x29,
17729 NM_P_BR2 = 0x2a,
17730
17731 NM_P16_ADDU = 0x2c,
17732 NM_SWSP16 = 0x2d,
17733 NM_BNEZC16 = 0x2e,
17734 NM_MOVEP = 0x2f,
17735
17736 NM_POOL32S = 0x30,
17737 NM_P_BRI = 0x32,
17738 NM_LI16 = 0x34,
17739 NM_SWGP16 = 0x35,
17740 NM_P16_BR = 0x36,
17741
17742 NM_P_LUI = 0x38,
17743 NM_ANDI16 = 0x3c,
17744 NM_SW4X4 = 0x3d,
17745 NM_MOVEPREV = 0x3f,
17746};
17747
17748/* POOL32A instruction pool */
17749enum {
17750 NM_POOL32A0 = 0x00,
17751 NM_SPECIAL2 = 0x01,
17752 NM_COP2_1 = 0x02,
17753 NM_UDI = 0x03,
17754 NM_POOL32A5 = 0x05,
17755 NM_POOL32A7 = 0x07,
17756};
17757
17758/* P.GP.W instruction pool */
17759enum {
17760 NM_ADDIUGP_W = 0x00,
17761 NM_LWGP = 0x02,
17762 NM_SWGP = 0x03,
17763};
17764
17765/* P48I instruction pool */
17766enum {
17767 NM_LI48 = 0x00,
17768 NM_ADDIU48 = 0x01,
17769 NM_ADDIUGP48 = 0x02,
17770 NM_ADDIUPC48 = 0x03,
17771 NM_LWPC48 = 0x0b,
17772 NM_SWPC48 = 0x0f,
17773};
17774
17775/* P.U12 instruction pool */
17776enum {
17777 NM_ORI = 0x00,
17778 NM_XORI = 0x01,
17779 NM_ANDI = 0x02,
17780 NM_P_SR = 0x03,
17781 NM_SLTI = 0x04,
17782 NM_SLTIU = 0x05,
17783 NM_SEQI = 0x06,
17784 NM_ADDIUNEG = 0x08,
17785 NM_P_SHIFT = 0x0c,
17786 NM_P_ROTX = 0x0d,
17787 NM_P_INS = 0x0e,
17788 NM_P_EXT = 0x0f,
17789};
17790
17791/* POOL32F instruction pool */
17792enum {
17793 NM_POOL32F_0 = 0x00,
17794 NM_POOL32F_3 = 0x03,
17795 NM_POOL32F_5 = 0x05,
17796};
17797
17798/* POOL32S instruction pool */
17799enum {
17800 NM_POOL32S_0 = 0x00,
17801 NM_POOL32S_4 = 0x04,
17802};
17803
17804/* P.LUI instruction pool */
17805enum {
17806 NM_LUI = 0x00,
17807 NM_ALUIPC = 0x01,
17808};
17809
17810/* P.GP.BH instruction pool */
17811enum {
17812 NM_LBGP = 0x00,
17813 NM_SBGP = 0x01,
17814 NM_LBUGP = 0x02,
17815 NM_ADDIUGP_B = 0x03,
17816 NM_P_GP_LH = 0x04,
17817 NM_P_GP_SH = 0x05,
17818 NM_P_GP_CP1 = 0x06,
17819};
17820
17821/* P.LS.U12 instruction pool */
17822enum {
17823 NM_LB = 0x00,
17824 NM_SB = 0x01,
17825 NM_LBU = 0x02,
17826 NM_P_PREFU12 = 0x03,
17827 NM_LH = 0x04,
17828 NM_SH = 0x05,
17829 NM_LHU = 0x06,
17830 NM_LWU = 0x07,
17831 NM_LW = 0x08,
17832 NM_SW = 0x09,
17833 NM_LWC1 = 0x0a,
17834 NM_SWC1 = 0x0b,
17835 NM_LDC1 = 0x0e,
17836 NM_SDC1 = 0x0f,
17837};
17838
17839/* P.LS.S9 instruction pool */
17840enum {
17841 NM_P_LS_S0 = 0x00,
17842 NM_P_LS_S1 = 0x01,
17843 NM_P_LS_E0 = 0x02,
17844 NM_P_LS_WM = 0x04,
17845 NM_P_LS_UAWM = 0x05,
17846};
17847
17848/* P.BAL instruction pool */
17849enum {
17850 NM_BC = 0x00,
17851 NM_BALC = 0x01,
17852};
17853
17854/* P.J instruction pool */
17855enum {
17856 NM_JALRC = 0x00,
17857 NM_JALRC_HB = 0x01,
17858 NM_P_BALRSC = 0x08,
17859};
17860
17861/* P.BR1 instruction pool */
17862enum {
17863 NM_BEQC = 0x00,
17864 NM_P_BR3A = 0x01,
17865 NM_BGEC = 0x02,
17866 NM_BGEUC = 0x03,
17867};
17868
17869/* P.BR2 instruction pool */
17870enum {
17871 NM_BNEC = 0x00,
17872 NM_BLTC = 0x02,
17873 NM_BLTUC = 0x03,
17874};
17875
17876/* P.BRI instruction pool */
17877enum {
17878 NM_BEQIC = 0x00,
17879 NM_BBEQZC = 0x01,
17880 NM_BGEIC = 0x02,
17881 NM_BGEIUC = 0x03,
17882 NM_BNEIC = 0x04,
17883 NM_BBNEZC = 0x05,
17884 NM_BLTIC = 0x06,
17885 NM_BLTIUC = 0x07,
17886};
17887
17888/* P16.SHIFT instruction pool */
17889enum {
17890 NM_SLL16 = 0x00,
17891 NM_SRL16 = 0x01,
17892};
17893
17894/* POOL16C instruction pool */
17895enum {
17896 NM_POOL16C_0 = 0x00,
17897 NM_LWXS16 = 0x01,
17898};
17899
17900/* P16.A1 instruction pool */
17901enum {
17902 NM_ADDIUR1SP = 0x01,
17903};
17904
17905/* P16.A2 instruction pool */
17906enum {
17907 NM_ADDIUR2 = 0x00,
17908 NM_P_ADDIURS5 = 0x01,
17909};
17910
17911/* P16.ADDU instruction pool */
17912enum {
17913 NM_ADDU16 = 0x00,
17914 NM_SUBU16 = 0x01,
17915};
17916
17917/* P16.SR instruction pool */
17918enum {
17919 NM_SAVE16 = 0x00,
17920 NM_RESTORE_JRC16 = 0x01,
17921};
17922
17923/* P16.4X4 instruction pool */
17924enum {
17925 NM_ADDU4X4 = 0x00,
17926 NM_MUL4X4 = 0x01,
17927};
17928
17929/* P16.LB instruction pool */
17930enum {
17931 NM_LB16 = 0x00,
17932 NM_SB16 = 0x01,
17933 NM_LBU16 = 0x02,
17934};
17935
17936/* P16.LH instruction pool */
17937enum {
17938 NM_LH16 = 0x00,
17939 NM_SH16 = 0x01,
17940 NM_LHU16 = 0x02,
17941};
17942
17943/* P.RI instruction pool */
17944enum {
17945 NM_SIGRIE = 0x00,
17946 NM_P_SYSCALL = 0x01,
17947 NM_BREAK = 0x02,
17948 NM_SDBBP = 0x03,
17949};
17950
17951/* POOL32A0 instruction pool */
17952enum {
17953 NM_P_TRAP = 0x00,
17954 NM_SEB = 0x01,
17955 NM_SLLV = 0x02,
17956 NM_MUL = 0x03,
17957 NM_MFC0 = 0x06,
17958 NM_MFHC0 = 0x07,
17959 NM_SEH = 0x09,
17960 NM_SRLV = 0x0a,
17961 NM_MUH = 0x0b,
17962 NM_MTC0 = 0x0e,
17963 NM_MTHC0 = 0x0f,
17964 NM_SRAV = 0x12,
17965 NM_MULU = 0x13,
17966 NM_ROTRV = 0x1a,
17967 NM_MUHU = 0x1b,
17968 NM_ADD = 0x22,
17969 NM_DIV = 0x23,
17970 NM_ADDU = 0x2a,
17971 NM_MOD = 0x2b,
17972 NM_SUB = 0x32,
17973 NM_DIVU = 0x33,
17974 NM_RDHWR = 0x38,
17975 NM_SUBU = 0x3a,
17976 NM_MODU = 0x3b,
17977 NM_P_CMOVE = 0x42,
17978 NM_FORK = 0x45,
17979 NM_MFTR = 0x46,
17980 NM_MFHTR = 0x47,
17981 NM_AND = 0x4a,
17982 NM_YIELD = 0x4d,
17983 NM_MTTR = 0x4e,
17984 NM_MTHTR = 0x4f,
17985 NM_OR = 0x52,
17986 NM_D_E_MT_VPE = 0x56,
17987 NM_NOR = 0x5a,
17988 NM_XOR = 0x62,
17989 NM_SLT = 0x6a,
17990 NM_P_SLTU = 0x72,
17991 NM_SOV = 0x7a,
17992};
17993
ba1e8117
AM
17994/* CRC32 instruction pool */
17995enum {
17996 NM_CRC32B = 0x00,
17997 NM_CRC32H = 0x01,
17998 NM_CRC32W = 0x02,
17999 NM_CRC32CB = 0x04,
18000 NM_CRC32CH = 0x05,
18001 NM_CRC32CW = 0x06,
18002};
18003
b3979b6f
SM
18004/* POOL32A5 instruction pool */
18005enum {
18006 NM_CMP_EQ_PH = 0x00,
18007 NM_CMP_LT_PH = 0x08,
18008 NM_CMP_LE_PH = 0x10,
18009 NM_CMPGU_EQ_QB = 0x18,
18010 NM_CMPGU_LT_QB = 0x20,
18011 NM_CMPGU_LE_QB = 0x28,
18012 NM_CMPGDU_EQ_QB = 0x30,
18013 NM_CMPGDU_LT_QB = 0x38,
18014 NM_CMPGDU_LE_QB = 0x40,
18015 NM_CMPU_EQ_QB = 0x48,
18016 NM_CMPU_LT_QB = 0x50,
18017 NM_CMPU_LE_QB = 0x58,
18018 NM_ADDQ_S_W = 0x60,
18019 NM_SUBQ_S_W = 0x68,
18020 NM_ADDSC = 0x70,
18021 NM_ADDWC = 0x78,
18022
18023 NM_ADDQ_S_PH = 0x01,
18024 NM_ADDQH_R_PH = 0x09,
18025 NM_ADDQH_R_W = 0x11,
18026 NM_ADDU_S_QB = 0x19,
18027 NM_ADDU_S_PH = 0x21,
18028 NM_ADDUH_R_QB = 0x29,
18029 NM_SHRAV_R_PH = 0x31,
18030 NM_SHRAV_R_QB = 0x39,
18031 NM_SUBQ_S_PH = 0x41,
18032 NM_SUBQH_R_PH = 0x49,
18033 NM_SUBQH_R_W = 0x51,
18034 NM_SUBU_S_QB = 0x59,
18035 NM_SUBU_S_PH = 0x61,
18036 NM_SUBUH_R_QB = 0x69,
18037 NM_SHLLV_S_PH = 0x71,
18038 NM_PRECR_SRA_R_PH_W = 0x79,
18039
18040 NM_MULEU_S_PH_QBL = 0x12,
18041 NM_MULEU_S_PH_QBR = 0x1a,
18042 NM_MULQ_RS_PH = 0x22,
18043 NM_MULQ_S_PH = 0x2a,
18044 NM_MULQ_RS_W = 0x32,
18045 NM_MULQ_S_W = 0x3a,
18046 NM_APPEND = 0x42,
18047 NM_MODSUB = 0x52,
18048 NM_SHRAV_R_W = 0x5a,
18049 NM_SHRLV_PH = 0x62,
18050 NM_SHRLV_QB = 0x6a,
18051 NM_SHLLV_QB = 0x72,
18052 NM_SHLLV_S_W = 0x7a,
18053
18054 NM_SHILO = 0x03,
18055
18056 NM_MULEQ_S_W_PHL = 0x04,
18057 NM_MULEQ_S_W_PHR = 0x0c,
18058
18059 NM_MUL_S_PH = 0x05,
18060 NM_PRECR_QB_PH = 0x0d,
18061 NM_PRECRQ_QB_PH = 0x15,
18062 NM_PRECRQ_PH_W = 0x1d,
18063 NM_PRECRQ_RS_PH_W = 0x25,
18064 NM_PRECRQU_S_QB_PH = 0x2d,
18065 NM_PACKRL_PH = 0x35,
18066 NM_PICK_QB = 0x3d,
18067 NM_PICK_PH = 0x45,
18068
18069 NM_SHRA_R_W = 0x5e,
18070 NM_SHRA_R_PH = 0x66,
18071 NM_SHLL_S_PH = 0x76,
18072 NM_SHLL_S_W = 0x7e,
18073
18074 NM_REPL_PH = 0x07
18075};
18076
261c95a0
YK
18077/* POOL32A7 instruction pool */
18078enum {
18079 NM_P_LSX = 0x00,
18080 NM_LSA = 0x01,
18081 NM_EXTW = 0x03,
18082 NM_POOL32AXF = 0x07,
18083};
18084
18085/* P.SR instruction pool */
18086enum {
18087 NM_PP_SR = 0x00,
18088 NM_P_SR_F = 0x01,
18089};
18090
18091/* P.SHIFT instruction pool */
18092enum {
18093 NM_P_SLL = 0x00,
18094 NM_SRL = 0x02,
18095 NM_SRA = 0x04,
18096 NM_ROTR = 0x06,
18097};
18098
18099/* P.ROTX instruction pool */
18100enum {
18101 NM_ROTX = 0x00,
18102};
18103
18104/* P.INS instruction pool */
18105enum {
18106 NM_INS = 0x00,
18107};
18108
18109/* P.EXT instruction pool */
18110enum {
18111 NM_EXT = 0x00,
18112};
18113
18114/* POOL32F_0 (fmt) instruction pool */
18115enum {
18116 NM_RINT_S = 0x04,
18117 NM_RINT_D = 0x44,
18118 NM_ADD_S = 0x06,
18119 NM_SELEQZ_S = 0x07,
18120 NM_SELEQZ_D = 0x47,
18121 NM_CLASS_S = 0x0c,
18122 NM_CLASS_D = 0x4c,
18123 NM_SUB_S = 0x0e,
18124 NM_SELNEZ_S = 0x0f,
18125 NM_SELNEZ_D = 0x4f,
18126 NM_MUL_S = 0x16,
18127 NM_SEL_S = 0x17,
18128 NM_SEL_D = 0x57,
18129 NM_DIV_S = 0x1e,
18130 NM_ADD_D = 0x26,
18131 NM_SUB_D = 0x2e,
18132 NM_MUL_D = 0x36,
18133 NM_MADDF_S = 0x37,
18134 NM_MADDF_D = 0x77,
18135 NM_DIV_D = 0x3e,
18136 NM_MSUBF_S = 0x3f,
18137 NM_MSUBF_D = 0x7f,
18138};
18139
18140/* POOL32F_3 instruction pool */
18141enum {
18142 NM_MIN_FMT = 0x00,
18143 NM_MAX_FMT = 0x01,
18144 NM_MINA_FMT = 0x04,
18145 NM_MAXA_FMT = 0x05,
18146 NM_POOL32FXF = 0x07,
18147};
18148
18149/* POOL32F_5 instruction pool */
18150enum {
18151 NM_CMP_CONDN_S = 0x00,
18152 NM_CMP_CONDN_D = 0x02,
18153};
18154
18155/* P.GP.LH instruction pool */
18156enum {
18157 NM_LHGP = 0x00,
18158 NM_LHUGP = 0x01,
18159};
18160
18161/* P.GP.SH instruction pool */
18162enum {
18163 NM_SHGP = 0x00,
18164};
18165
18166/* P.GP.CP1 instruction pool */
18167enum {
18168 NM_LWC1GP = 0x00,
18169 NM_SWC1GP = 0x01,
18170 NM_LDC1GP = 0x02,
18171 NM_SDC1GP = 0x03,
18172};
18173
18174/* P.LS.S0 instruction pool */
18175enum {
18176 NM_LBS9 = 0x00,
18177 NM_LHS9 = 0x04,
18178 NM_LWS9 = 0x08,
18179 NM_LDS9 = 0x0c,
18180
18181 NM_SBS9 = 0x01,
18182 NM_SHS9 = 0x05,
18183 NM_SWS9 = 0x09,
18184 NM_SDS9 = 0x0d,
18185
18186 NM_LBUS9 = 0x02,
18187 NM_LHUS9 = 0x06,
18188 NM_LWC1S9 = 0x0a,
18189 NM_LDC1S9 = 0x0e,
18190
18191 NM_P_PREFS9 = 0x03,
18192 NM_LWUS9 = 0x07,
18193 NM_SWC1S9 = 0x0b,
18194 NM_SDC1S9 = 0x0f,
18195};
18196
18197/* P.LS.S1 instruction pool */
18198enum {
18199 NM_ASET_ACLR = 0x02,
18200 NM_UALH = 0x04,
18201 NM_UASH = 0x05,
18202 NM_CACHE = 0x07,
18203 NM_P_LL = 0x0a,
18204 NM_P_SC = 0x0b,
18205};
18206
0d30b3bb
DN
18207/* P.LS.E0 instruction pool */
18208enum {
18209 NM_LBE = 0x00,
18210 NM_SBE = 0x01,
18211 NM_LBUE = 0x02,
18212 NM_P_PREFE = 0x03,
18213 NM_LHE = 0x04,
18214 NM_SHE = 0x05,
18215 NM_LHUE = 0x06,
18216 NM_CACHEE = 0x07,
18217 NM_LWE = 0x08,
18218 NM_SWE = 0x09,
18219 NM_P_LLE = 0x0a,
18220 NM_P_SCE = 0x0b,
18221};
18222
18223/* P.PREFE instruction pool */
18224enum {
18225 NM_SYNCIE = 0x00,
18226 NM_PREFE = 0x01,
18227};
18228
18229/* P.LLE instruction pool */
18230enum {
18231 NM_LLE = 0x00,
18232 NM_LLWPE = 0x01,
18233};
18234
18235/* P.SCE instruction pool */
18236enum {
18237 NM_SCE = 0x00,
18238 NM_SCWPE = 0x01,
18239};
18240
261c95a0
YK
18241/* P.LS.WM instruction pool */
18242enum {
18243 NM_LWM = 0x00,
18244 NM_SWM = 0x01,
18245};
18246
18247/* P.LS.UAWM instruction pool */
18248enum {
18249 NM_UALWM = 0x00,
18250 NM_UASWM = 0x01,
18251};
18252
18253/* P.BR3A instruction pool */
18254enum {
18255 NM_BC1EQZC = 0x00,
18256 NM_BC1NEZC = 0x01,
18257 NM_BC2EQZC = 0x02,
18258 NM_BC2NEZC = 0x03,
18259 NM_BPOSGE32C = 0x04,
18260};
18261
18262/* P16.RI instruction pool */
18263enum {
18264 NM_P16_SYSCALL = 0x01,
18265 NM_BREAK16 = 0x02,
18266 NM_SDBBP16 = 0x03,
18267};
18268
18269/* POOL16C_0 instruction pool */
18270enum {
18271 NM_POOL16C_00 = 0x00,
18272};
18273
18274/* P16.JRC instruction pool */
18275enum {
18276 NM_JRC = 0x00,
18277 NM_JALRC16 = 0x01,
18278};
18279
18280/* P.SYSCALL instruction pool */
18281enum {
18282 NM_SYSCALL = 0x00,
18283 NM_HYPCALL = 0x01,
18284};
18285
18286/* P.TRAP instruction pool */
18287enum {
18288 NM_TEQ = 0x00,
18289 NM_TNE = 0x01,
18290};
18291
18292/* P.CMOVE instruction pool */
18293enum {
18294 NM_MOVZ = 0x00,
18295 NM_MOVN = 0x01,
18296};
18297
18298/* POOL32Axf instruction pool */
18299enum {
b3979b6f
SM
18300 NM_POOL32AXF_1 = 0x01,
18301 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18302 NM_POOL32AXF_4 = 0x04,
18303 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18304 NM_POOL32AXF_7 = 0x07,
18305};
18306
18307/* POOL32Axf_1 instruction pool */
18308enum {
18309 NM_POOL32AXF_1_0 = 0x00,
18310 NM_POOL32AXF_1_1 = 0x01,
18311 NM_POOL32AXF_1_3 = 0x03,
18312 NM_POOL32AXF_1_4 = 0x04,
18313 NM_POOL32AXF_1_5 = 0x05,
18314 NM_POOL32AXF_1_7 = 0x07,
18315};
18316
18317/* POOL32Axf_2 instruction pool */
18318enum {
18319 NM_POOL32AXF_2_0_7 = 0x00,
18320 NM_POOL32AXF_2_8_15 = 0x01,
18321 NM_POOL32AXF_2_16_23 = 0x02,
18322 NM_POOL32AXF_2_24_31 = 0x03,
18323};
18324
18325/* POOL32Axf_7 instruction pool */
18326enum {
18327 NM_SHRA_R_QB = 0x0,
18328 NM_SHRL_PH = 0x1,
18329 NM_REPL_QB = 0x2,
18330};
18331
18332/* POOL32Axf_1_0 instruction pool */
18333enum {
18334 NM_MFHI = 0x0,
18335 NM_MFLO = 0x1,
18336 NM_MTHI = 0x2,
18337 NM_MTLO = 0x3,
18338};
18339
18340/* POOL32Axf_1_1 instruction pool */
18341enum {
18342 NM_MTHLIP = 0x0,
18343 NM_SHILOV = 0x1,
18344};
18345
18346/* POOL32Axf_1_3 instruction pool */
18347enum {
18348 NM_RDDSP = 0x0,
18349 NM_WRDSP = 0x1,
18350 NM_EXTP = 0x2,
18351 NM_EXTPDP = 0x3,
18352};
18353
18354/* POOL32Axf_1_4 instruction pool */
18355enum {
18356 NM_SHLL_QB = 0x0,
18357 NM_SHRL_QB = 0x1,
18358};
18359
18360/* POOL32Axf_1_5 instruction pool */
18361enum {
18362 NM_MAQ_S_W_PHR = 0x0,
18363 NM_MAQ_S_W_PHL = 0x1,
18364 NM_MAQ_SA_W_PHR = 0x2,
18365 NM_MAQ_SA_W_PHL = 0x3,
18366};
18367
18368/* POOL32Axf_1_7 instruction pool */
18369enum {
18370 NM_EXTR_W = 0x0,
18371 NM_EXTR_R_W = 0x1,
18372 NM_EXTR_RS_W = 0x2,
18373 NM_EXTR_S_H = 0x3,
18374};
18375
18376/* POOL32Axf_2_0_7 instruction pool */
18377enum {
18378 NM_DPA_W_PH = 0x0,
18379 NM_DPAQ_S_W_PH = 0x1,
18380 NM_DPS_W_PH = 0x2,
18381 NM_DPSQ_S_W_PH = 0x3,
18382 NM_BALIGN = 0x4,
18383 NM_MADD = 0x5,
18384 NM_MULT = 0x6,
18385 NM_EXTRV_W = 0x7,
18386};
18387
18388/* POOL32Axf_2_8_15 instruction pool */
18389enum {
18390 NM_DPAX_W_PH = 0x0,
18391 NM_DPAQ_SA_L_W = 0x1,
18392 NM_DPSX_W_PH = 0x2,
18393 NM_DPSQ_SA_L_W = 0x3,
18394 NM_MADDU = 0x5,
18395 NM_MULTU = 0x6,
18396 NM_EXTRV_R_W = 0x7,
18397};
18398
18399/* POOL32Axf_2_16_23 instruction pool */
18400enum {
18401 NM_DPAU_H_QBL = 0x0,
18402 NM_DPAQX_S_W_PH = 0x1,
18403 NM_DPSU_H_QBL = 0x2,
18404 NM_DPSQX_S_W_PH = 0x3,
18405 NM_EXTPV = 0x4,
18406 NM_MSUB = 0x5,
18407 NM_MULSA_W_PH = 0x6,
18408 NM_EXTRV_RS_W = 0x7,
18409};
18410
18411/* POOL32Axf_2_24_31 instruction pool */
18412enum {
18413 NM_DPAU_H_QBR = 0x0,
18414 NM_DPAQX_SA_W_PH = 0x1,
18415 NM_DPSU_H_QBR = 0x2,
18416 NM_DPSQX_SA_W_PH = 0x3,
18417 NM_EXTPDPV = 0x4,
18418 NM_MSUBU = 0x5,
18419 NM_MULSAQ_S_W_PH = 0x6,
18420 NM_EXTRV_S_H = 0x7,
261c95a0
YK
18421};
18422
18423/* POOL32Axf_{4, 5} instruction pool */
18424enum {
18425 NM_CLO = 0x25,
18426 NM_CLZ = 0x2d,
18427
18428 NM_TLBP = 0x01,
18429 NM_TLBR = 0x09,
18430 NM_TLBWI = 0x11,
18431 NM_TLBWR = 0x19,
18432 NM_TLBINV = 0x03,
18433 NM_TLBINVF = 0x0b,
18434 NM_DI = 0x23,
18435 NM_EI = 0x2b,
18436 NM_RDPGPR = 0x70,
18437 NM_WRPGPR = 0x78,
18438 NM_WAIT = 0x61,
18439 NM_DERET = 0x71,
18440 NM_ERETX = 0x79,
b3979b6f
SM
18441
18442 /* nanoMIPS DSP instructions */
18443 NM_ABSQ_S_QB = 0x00,
18444 NM_ABSQ_S_PH = 0x08,
18445 NM_ABSQ_S_W = 0x10,
18446 NM_PRECEQ_W_PHL = 0x28,
18447 NM_PRECEQ_W_PHR = 0x30,
18448 NM_PRECEQU_PH_QBL = 0x38,
18449 NM_PRECEQU_PH_QBR = 0x48,
18450 NM_PRECEU_PH_QBL = 0x58,
18451 NM_PRECEU_PH_QBR = 0x68,
18452 NM_PRECEQU_PH_QBLA = 0x39,
18453 NM_PRECEQU_PH_QBRA = 0x49,
18454 NM_PRECEU_PH_QBLA = 0x59,
18455 NM_PRECEU_PH_QBRA = 0x69,
18456 NM_REPLV_PH = 0x01,
18457 NM_REPLV_QB = 0x09,
18458 NM_BITREV = 0x18,
18459 NM_INSV = 0x20,
18460 NM_RADDU_W_QB = 0x78,
18461
18462 NM_BITSWAP = 0x05,
18463 NM_WSBH = 0x3d,
261c95a0
YK
18464};
18465
18466/* PP.SR instruction pool */
18467enum {
18468 NM_SAVE = 0x00,
18469 NM_RESTORE = 0x02,
18470 NM_RESTORE_JRC = 0x03,
18471};
18472
18473/* P.SR.F instruction pool */
18474enum {
18475 NM_SAVEF = 0x00,
18476 NM_RESTOREF = 0x01,
18477};
18478
18479/* P16.SYSCALL instruction pool */
18480enum {
18481 NM_SYSCALL16 = 0x00,
18482 NM_HYPCALL16 = 0x01,
18483};
18484
18485/* POOL16C_00 instruction pool */
18486enum {
18487 NM_NOT16 = 0x00,
18488 NM_XOR16 = 0x01,
18489 NM_AND16 = 0x02,
18490 NM_OR16 = 0x03,
18491};
18492
18493/* PP.LSX and PP.LSXS instruction pool */
18494enum {
18495 NM_LBX = 0x00,
18496 NM_LHX = 0x04,
18497 NM_LWX = 0x08,
18498 NM_LDX = 0x0c,
18499
18500 NM_SBX = 0x01,
18501 NM_SHX = 0x05,
18502 NM_SWX = 0x09,
18503 NM_SDX = 0x0d,
18504
18505 NM_LBUX = 0x02,
18506 NM_LHUX = 0x06,
18507 NM_LWC1X = 0x0a,
18508 NM_LDC1X = 0x0e,
18509
18510 NM_LWUX = 0x07,
18511 NM_SWC1X = 0x0b,
18512 NM_SDC1X = 0x0f,
18513
18514 NM_LHXS = 0x04,
18515 NM_LWXS = 0x08,
18516 NM_LDXS = 0x0c,
18517
18518 NM_SHXS = 0x05,
18519 NM_SWXS = 0x09,
18520 NM_SDXS = 0x0d,
18521
18522 NM_LHUXS = 0x06,
18523 NM_LWC1XS = 0x0a,
18524 NM_LDC1XS = 0x0e,
18525
18526 NM_LWUXS = 0x07,
18527 NM_SWC1XS = 0x0b,
18528 NM_SDC1XS = 0x0f,
18529};
18530
18531/* ERETx instruction pool */
18532enum {
18533 NM_ERET = 0x00,
18534 NM_ERETNC = 0x01,
18535};
18536
18537/* POOL32FxF_{0, 1} insturction pool */
18538enum {
18539 NM_CFC1 = 0x40,
18540 NM_CTC1 = 0x60,
18541 NM_MFC1 = 0x80,
18542 NM_MTC1 = 0xa0,
18543 NM_MFHC1 = 0xc0,
18544 NM_MTHC1 = 0xe0,
18545
18546 NM_CVT_S_PL = 0x84,
18547 NM_CVT_S_PU = 0xa4,
18548
18549 NM_CVT_L_S = 0x004,
18550 NM_CVT_L_D = 0x104,
18551 NM_CVT_W_S = 0x024,
18552 NM_CVT_W_D = 0x124,
18553
18554 NM_RSQRT_S = 0x008,
18555 NM_RSQRT_D = 0x108,
18556
18557 NM_SQRT_S = 0x028,
18558 NM_SQRT_D = 0x128,
18559
18560 NM_RECIP_S = 0x048,
18561 NM_RECIP_D = 0x148,
18562
18563 NM_FLOOR_L_S = 0x00c,
18564 NM_FLOOR_L_D = 0x10c,
18565
18566 NM_FLOOR_W_S = 0x02c,
18567 NM_FLOOR_W_D = 0x12c,
18568
18569 NM_CEIL_L_S = 0x04c,
18570 NM_CEIL_L_D = 0x14c,
18571 NM_CEIL_W_S = 0x06c,
18572 NM_CEIL_W_D = 0x16c,
18573 NM_TRUNC_L_S = 0x08c,
18574 NM_TRUNC_L_D = 0x18c,
18575 NM_TRUNC_W_S = 0x0ac,
18576 NM_TRUNC_W_D = 0x1ac,
18577 NM_ROUND_L_S = 0x0cc,
18578 NM_ROUND_L_D = 0x1cc,
18579 NM_ROUND_W_S = 0x0ec,
18580 NM_ROUND_W_D = 0x1ec,
18581
18582 NM_MOV_S = 0x01,
18583 NM_MOV_D = 0x81,
18584 NM_ABS_S = 0x0d,
18585 NM_ABS_D = 0x8d,
18586 NM_NEG_S = 0x2d,
18587 NM_NEG_D = 0xad,
18588 NM_CVT_D_S = 0x04d,
18589 NM_CVT_D_W = 0x0cd,
18590 NM_CVT_D_L = 0x14d,
18591 NM_CVT_S_D = 0x06d,
18592 NM_CVT_S_W = 0x0ed,
18593 NM_CVT_S_L = 0x16d,
18594};
18595
18596/* P.LL instruction pool */
18597enum {
18598 NM_LL = 0x00,
18599 NM_LLWP = 0x01,
18600};
18601
18602/* P.SC instruction pool */
18603enum {
18604 NM_SC = 0x00,
18605 NM_SCWP = 0x01,
18606};
18607
18608/* P.DVP instruction pool */
18609enum {
18610 NM_DVP = 0x00,
18611 NM_EVP = 0x01,
18612};
18613
c533c0f4
AM
18614
18615/*
18616 *
18617 * nanoMIPS decoding engine
18618 *
18619 */
18620
6bfa9f4c
AM
18621
18622/* extraction utilities */
18623
99e49abf
AM
18624#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18625#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18626#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
18627#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18628#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18629
ea4ca3c2
YK
18630/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18631static inline int decode_gpr_gpr3(int r)
18632{
18633 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18634
18635 return map[r & 0x7];
18636}
18637
8bdb7029
YK
18638/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18639static inline int decode_gpr_gpr3_src_store(int r)
18640{
18641 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18642
18643 return map[r & 0x7];
18644}
18645
ea4ca3c2
YK
18646/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18647static inline int decode_gpr_gpr4(int r)
18648{
18649 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18650 16, 17, 18, 19, 20, 21, 22, 23 };
18651
18652 return map[r & 0xf];
18653}
18654
8bdb7029
YK
18655/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18656static inline int decode_gpr_gpr4_zero(int r)
18657{
18658 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18659 16, 17, 18, 19, 20, 21, 22, 23 };
18660
18661 return map[r & 0xf];
18662}
18663
6bfa9f4c 18664
bf0718c5
SM
18665static void gen_adjust_sp(DisasContext *ctx, int u)
18666{
18667 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18668}
18669
18670static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18671 uint8_t gp, uint16_t u)
18672{
18673 int counter = 0;
18674 TCGv va = tcg_temp_new();
18675 TCGv t0 = tcg_temp_new();
18676
18677 while (counter != count) {
18678 bool use_gp = gp && (counter == count - 1);
18679 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18680 int this_offset = -((counter + 1) << 2);
18681 gen_base_offset_addr(ctx, va, 29, this_offset);
18682 gen_load_gpr(t0, this_rt);
18683 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18684 (MO_TEUL | ctx->default_tcg_memop_mask));
18685 counter++;
18686 }
18687
18688 /* adjust stack pointer */
18689 gen_adjust_sp(ctx, -u);
18690
18691 tcg_temp_free(t0);
18692 tcg_temp_free(va);
18693}
18694
18695static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18696 uint8_t gp, uint16_t u)
18697{
18698 int counter = 0;
18699 TCGv va = tcg_temp_new();
18700 TCGv t0 = tcg_temp_new();
18701
18702 while (counter != count) {
18703 bool use_gp = gp && (counter == count - 1);
18704 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18705 int this_offset = u - ((counter + 1) << 2);
18706 gen_base_offset_addr(ctx, va, 29, this_offset);
18707 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18708 ctx->default_tcg_memop_mask);
18709 tcg_gen_ext32s_tl(t0, t0);
18710 gen_store_gpr(t0, this_rt);
18711 counter++;
18712 }
18713
18714 /* adjust stack pointer */
18715 gen_adjust_sp(ctx, u);
18716
18717 tcg_temp_free(t0);
18718 tcg_temp_free(va);
18719}
18720
80845edf
YK
18721static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18722{
99e49abf
AM
18723 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18724 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
18725
18726 switch (extract32(ctx->opcode, 2, 2)) {
18727 case NM_NOT16:
18728 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18729 break;
18730 case NM_AND16:
18731 gen_logic(ctx, OPC_AND, rt, rt, rs);
18732 break;
18733 case NM_XOR16:
18734 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18735 break;
18736 case NM_OR16:
18737 gen_logic(ctx, OPC_OR, rt, rt, rs);
18738 break;
18739 }
18740}
18741
0a1a6ed7 18742static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18743{
18744 int rt = extract32(ctx->opcode, 21, 5);
18745 int rs = extract32(ctx->opcode, 16, 5);
18746 int rd = extract32(ctx->opcode, 11, 5);
18747
18748 switch (extract32(ctx->opcode, 3, 7)) {
18749 case NM_P_TRAP:
18750 switch (extract32(ctx->opcode, 10, 1)) {
18751 case NM_TEQ:
fb32f8c8 18752 check_nms(ctx);
e0cf0e65
YK
18753 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18754 break;
18755 case NM_TNE:
fb32f8c8 18756 check_nms(ctx);
e0cf0e65
YK
18757 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18758 break;
18759 }
18760 break;
18761 case NM_RDHWR:
fb32f8c8 18762 check_nms(ctx);
e0cf0e65
YK
18763 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18764 break;
18765 case NM_SEB:
fb32f8c8 18766 check_nms(ctx);
e0cf0e65
YK
18767 gen_bshfl(ctx, OPC_SEB, rs, rt);
18768 break;
18769 case NM_SEH:
18770 gen_bshfl(ctx, OPC_SEH, rs, rt);
18771 break;
18772 case NM_SLLV:
18773 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18774 break;
18775 case NM_SRLV:
18776 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18777 break;
18778 case NM_SRAV:
18779 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18780 break;
18781 case NM_ROTRV:
18782 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18783 break;
18784 case NM_ADD:
18785 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18786 break;
18787 case NM_ADDU:
18788 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18789 break;
18790 case NM_SUB:
fb32f8c8 18791 check_nms(ctx);
e0cf0e65
YK
18792 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18793 break;
18794 case NM_SUBU:
18795 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18796 break;
18797 case NM_P_CMOVE:
18798 switch (extract32(ctx->opcode, 10, 1)) {
18799 case NM_MOVZ:
18800 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18801 break;
18802 case NM_MOVN:
18803 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18804 break;
18805 }
18806 break;
18807 case NM_AND:
18808 gen_logic(ctx, OPC_AND, rd, rs, rt);
18809 break;
18810 case NM_OR:
18811 gen_logic(ctx, OPC_OR, rd, rs, rt);
18812 break;
18813 case NM_NOR:
18814 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18815 break;
18816 case NM_XOR:
18817 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18818 break;
18819 case NM_SLT:
18820 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18821 break;
18822 case NM_P_SLTU:
18823 if (rd == 0) {
18824 /* P_DVP */
18825#ifndef CONFIG_USER_ONLY
18826 TCGv t0 = tcg_temp_new();
18827 switch (extract32(ctx->opcode, 10, 1)) {
18828 case NM_DVP:
18829 if (ctx->vp) {
18830 check_cp0_enabled(ctx);
18831 gen_helper_dvp(t0, cpu_env);
18832 gen_store_gpr(t0, rt);
18833 }
18834 break;
18835 case NM_EVP:
18836 if (ctx->vp) {
18837 check_cp0_enabled(ctx);
18838 gen_helper_evp(t0, cpu_env);
18839 gen_store_gpr(t0, rt);
18840 }
18841 break;
18842 }
18843 tcg_temp_free(t0);
18844#endif
18845 } else {
18846 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18847 }
18848 break;
18849 case NM_SOV:
18850 {
18851 TCGv t0 = tcg_temp_new();
18852 TCGv t1 = tcg_temp_new();
18853 TCGv t2 = tcg_temp_new();
18854
18855 gen_load_gpr(t1, rs);
18856 gen_load_gpr(t2, rt);
18857 tcg_gen_add_tl(t0, t1, t2);
18858 tcg_gen_ext32s_tl(t0, t0);
18859 tcg_gen_xor_tl(t1, t1, t2);
18860 tcg_gen_xor_tl(t2, t0, t2);
18861 tcg_gen_andc_tl(t1, t2, t1);
18862
18863 /* operands of same sign, result different sign */
18864 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18865 gen_store_gpr(t0, rd);
18866
18867 tcg_temp_free(t0);
18868 tcg_temp_free(t1);
18869 tcg_temp_free(t2);
18870 }
18871 break;
18872 case NM_MUL:
18873 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18874 break;
18875 case NM_MUH:
18876 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18877 break;
18878 case NM_MULU:
18879 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18880 break;
18881 case NM_MUHU:
18882 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18883 break;
18884 case NM_DIV:
18885 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18886 break;
18887 case NM_MOD:
18888 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18889 break;
18890 case NM_DIVU:
18891 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18892 break;
18893 case NM_MODU:
18894 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18895 break;
18896#ifndef CONFIG_USER_ONLY
18897 case NM_MFC0:
18898 check_cp0_enabled(ctx);
18899 if (rt == 0) {
18900 /* Treat as NOP. */
18901 break;
18902 }
18903 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18904 break;
18905 case NM_MTC0:
18906 check_cp0_enabled(ctx);
18907 {
18908 TCGv t0 = tcg_temp_new();
18909
18910 gen_load_gpr(t0, rt);
18911 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18912 tcg_temp_free(t0);
18913 }
18914 break;
0a1a6ed7
SM
18915 case NM_D_E_MT_VPE:
18916 {
18917 uint8_t sc = extract32(ctx->opcode, 10, 1);
18918 TCGv t0 = tcg_temp_new();
18919
18920 switch (sc) {
18921 case 0:
18922 if (rs == 1) {
18923 /* DMT */
18924 check_cp0_mt(ctx);
18925 gen_helper_dmt(t0);
18926 gen_store_gpr(t0, rt);
18927 } else if (rs == 0) {
18928 /* DVPE */
18929 check_cp0_mt(ctx);
18930 gen_helper_dvpe(t0, cpu_env);
18931 gen_store_gpr(t0, rt);
18932 } else {
18933 generate_exception_end(ctx, EXCP_RI);
18934 }
18935 break;
18936 case 1:
18937 if (rs == 1) {
18938 /* EMT */
18939 check_cp0_mt(ctx);
18940 gen_helper_emt(t0);
18941 gen_store_gpr(t0, rt);
18942 } else if (rs == 0) {
18943 /* EVPE */
18944 check_cp0_mt(ctx);
18945 gen_helper_evpe(t0, cpu_env);
18946 gen_store_gpr(t0, rt);
18947 } else {
18948 generate_exception_end(ctx, EXCP_RI);
18949 }
18950 break;
18951 }
18952
18953 tcg_temp_free(t0);
18954 }
18955 break;
18956 case NM_FORK:
18957 check_mt(ctx);
18958 {
18959 TCGv t0 = tcg_temp_new();
18960 TCGv t1 = tcg_temp_new();
18961
18962 gen_load_gpr(t0, rt);
18963 gen_load_gpr(t1, rs);
18964 gen_helper_fork(t0, t1);
18965 tcg_temp_free(t0);
18966 tcg_temp_free(t1);
18967 }
18968 break;
18969 case NM_MFTR:
18970 case NM_MFHTR:
18971 check_cp0_enabled(ctx);
18972 if (rd == 0) {
18973 /* Treat as NOP. */
18974 return;
18975 }
18976 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18977 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18978 break;
18979 case NM_MTTR:
18980 case NM_MTHTR:
18981 check_cp0_enabled(ctx);
18982 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18983 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18984 break;
18985 case NM_YIELD:
18986 check_mt(ctx);
18987 {
18988 TCGv t0 = tcg_temp_new();
18989
18990 gen_load_gpr(t0, rs);
18991 gen_helper_yield(t0, cpu_env, t0);
18992 gen_store_gpr(t0, rt);
18993 tcg_temp_free(t0);
18994 }
18995 break;
e0cf0e65
YK
18996#endif
18997 default:
18998 generate_exception_end(ctx, EXCP_RI);
18999 break;
19000 }
19001}
19002
2ed42efa
SM
19003/* dsp */
19004static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19005 int ret, int v1, int v2)
19006{
19007 TCGv_i32 t0;
19008 TCGv v0_t;
19009 TCGv v1_t;
19010
19011 t0 = tcg_temp_new_i32();
19012
19013 v0_t = tcg_temp_new();
19014 v1_t = tcg_temp_new();
19015
19016 tcg_gen_movi_i32(t0, v2 >> 3);
19017
19018 gen_load_gpr(v0_t, ret);
19019 gen_load_gpr(v1_t, v1);
19020
19021 switch (opc) {
19022 case NM_MAQ_S_W_PHR:
19023 check_dsp(ctx);
19024 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19025 break;
19026 case NM_MAQ_S_W_PHL:
19027 check_dsp(ctx);
19028 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19029 break;
19030 case NM_MAQ_SA_W_PHR:
19031 check_dsp(ctx);
19032 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19033 break;
19034 case NM_MAQ_SA_W_PHL:
19035 check_dsp(ctx);
19036 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19037 break;
19038 default:
19039 generate_exception_end(ctx, EXCP_RI);
19040 break;
19041 }
19042
19043 tcg_temp_free_i32(t0);
19044
19045 tcg_temp_free(v0_t);
19046 tcg_temp_free(v1_t);
19047}
19048
19049
19050static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19051 int ret, int v1, int v2)
19052{
19053 int16_t imm;
19054 TCGv t0 = tcg_temp_new();
19055 TCGv t1 = tcg_temp_new();
19056 TCGv v0_t = tcg_temp_new();
19057
19058 gen_load_gpr(v0_t, v1);
19059
19060 switch (opc) {
19061 case NM_POOL32AXF_1_0:
19062 check_dsp(ctx);
19063 switch (extract32(ctx->opcode, 12, 2)) {
19064 case NM_MFHI:
19065 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19066 break;
19067 case NM_MFLO:
19068 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19069 break;
19070 case NM_MTHI:
19071 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19072 break;
19073 case NM_MTLO:
19074 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19075 break;
19076 }
19077 break;
19078 case NM_POOL32AXF_1_1:
19079 check_dsp(ctx);
19080 switch (extract32(ctx->opcode, 12, 2)) {
19081 case NM_MTHLIP:
19082 tcg_gen_movi_tl(t0, v2);
19083 gen_helper_mthlip(t0, v0_t, cpu_env);
19084 break;
19085 case NM_SHILOV:
19086 tcg_gen_movi_tl(t0, v2 >> 3);
19087 gen_helper_shilo(t0, v0_t, cpu_env);
19088 break;
19089 default:
19090 generate_exception_end(ctx, EXCP_RI);
19091 break;
19092 }
19093 break;
19094 case NM_POOL32AXF_1_3:
19095 check_dsp(ctx);
19096 imm = extract32(ctx->opcode, 14, 7);
19097 switch (extract32(ctx->opcode, 12, 2)) {
19098 case NM_RDDSP:
19099 tcg_gen_movi_tl(t0, imm);
19100 gen_helper_rddsp(t0, t0, cpu_env);
19101 gen_store_gpr(t0, ret);
19102 break;
19103 case NM_WRDSP:
19104 gen_load_gpr(t0, ret);
19105 tcg_gen_movi_tl(t1, imm);
19106 gen_helper_wrdsp(t0, t1, cpu_env);
19107 break;
19108 case NM_EXTP:
19109 tcg_gen_movi_tl(t0, v2 >> 3);
19110 tcg_gen_movi_tl(t1, v1);
19111 gen_helper_extp(t0, t0, t1, cpu_env);
19112 gen_store_gpr(t0, ret);
19113 break;
19114 case NM_EXTPDP:
19115 tcg_gen_movi_tl(t0, v2 >> 3);
19116 tcg_gen_movi_tl(t1, v1);
19117 gen_helper_extpdp(t0, t0, t1, cpu_env);
19118 gen_store_gpr(t0, ret);
19119 break;
19120 }
19121 break;
19122 case NM_POOL32AXF_1_4:
19123 check_dsp(ctx);
19124 tcg_gen_movi_tl(t0, v2 >> 2);
19125 switch (extract32(ctx->opcode, 12, 1)) {
19126 case NM_SHLL_QB:
19127 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19128 gen_store_gpr(t0, ret);
19129 break;
19130 case NM_SHRL_QB:
19131 gen_helper_shrl_qb(t0, t0, v0_t);
19132 gen_store_gpr(t0, ret);
19133 break;
19134 }
19135 break;
19136 case NM_POOL32AXF_1_5:
19137 opc = extract32(ctx->opcode, 12, 2);
19138 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19139 break;
19140 case NM_POOL32AXF_1_7:
19141 check_dsp(ctx);
19142 tcg_gen_movi_tl(t0, v2 >> 3);
19143 tcg_gen_movi_tl(t1, v1);
19144 switch (extract32(ctx->opcode, 12, 2)) {
19145 case NM_EXTR_W:
19146 gen_helper_extr_w(t0, t0, t1, cpu_env);
19147 gen_store_gpr(t0, ret);
19148 break;
19149 case NM_EXTR_R_W:
19150 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19151 gen_store_gpr(t0, ret);
19152 break;
19153 case NM_EXTR_RS_W:
19154 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19155 gen_store_gpr(t0, ret);
19156 break;
19157 case NM_EXTR_S_H:
19158 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19159 gen_store_gpr(t0, ret);
19160 break;
19161 }
19162 break;
19163 default:
19164 generate_exception_end(ctx, EXCP_RI);
19165 break;
19166 }
19167
19168 tcg_temp_free(t0);
19169 tcg_temp_free(t1);
19170 tcg_temp_free(v0_t);
19171}
19172
8b3698b2
SM
19173static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19174 TCGv v0, TCGv v1, int rd)
19175{
19176 TCGv_i32 t0;
19177
19178 t0 = tcg_temp_new_i32();
19179
19180 tcg_gen_movi_i32(t0, rd >> 3);
19181
19182 switch (opc) {
19183 case NM_POOL32AXF_2_0_7:
19184 switch (extract32(ctx->opcode, 9, 3)) {
19185 case NM_DPA_W_PH:
908f6be1 19186 check_dsp_r2(ctx);
8b3698b2
SM
19187 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19188 break;
19189 case NM_DPAQ_S_W_PH:
19190 check_dsp(ctx);
19191 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19192 break;
19193 case NM_DPS_W_PH:
908f6be1 19194 check_dsp_r2(ctx);
8b3698b2
SM
19195 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19196 break;
19197 case NM_DPSQ_S_W_PH:
19198 check_dsp(ctx);
19199 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19200 break;
19201 default:
19202 generate_exception_end(ctx, EXCP_RI);
19203 break;
19204 }
19205 break;
19206 case NM_POOL32AXF_2_8_15:
19207 switch (extract32(ctx->opcode, 9, 3)) {
19208 case NM_DPAX_W_PH:
908f6be1 19209 check_dsp_r2(ctx);
8b3698b2
SM
19210 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19211 break;
19212 case NM_DPAQ_SA_L_W:
19213 check_dsp(ctx);
19214 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19215 break;
19216 case NM_DPSX_W_PH:
908f6be1 19217 check_dsp_r2(ctx);
8b3698b2
SM
19218 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19219 break;
19220 case NM_DPSQ_SA_L_W:
19221 check_dsp(ctx);
19222 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19223 break;
19224 default:
19225 generate_exception_end(ctx, EXCP_RI);
19226 break;
19227 }
19228 break;
19229 case NM_POOL32AXF_2_16_23:
19230 switch (extract32(ctx->opcode, 9, 3)) {
19231 case NM_DPAU_H_QBL:
19232 check_dsp(ctx);
19233 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19234 break;
19235 case NM_DPAQX_S_W_PH:
908f6be1 19236 check_dsp_r2(ctx);
8b3698b2
SM
19237 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19238 break;
19239 case NM_DPSU_H_QBL:
19240 check_dsp(ctx);
19241 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19242 break;
19243 case NM_DPSQX_S_W_PH:
908f6be1 19244 check_dsp_r2(ctx);
8b3698b2
SM
19245 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19246 break;
19247 case NM_MULSA_W_PH:
908f6be1 19248 check_dsp_r2(ctx);
8b3698b2
SM
19249 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19250 break;
19251 default:
19252 generate_exception_end(ctx, EXCP_RI);
19253 break;
19254 }
19255 break;
19256 case NM_POOL32AXF_2_24_31:
19257 switch (extract32(ctx->opcode, 9, 3)) {
19258 case NM_DPAU_H_QBR:
19259 check_dsp(ctx);
19260 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19261 break;
19262 case NM_DPAQX_SA_W_PH:
908f6be1 19263 check_dsp_r2(ctx);
8b3698b2
SM
19264 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19265 break;
19266 case NM_DPSU_H_QBR:
19267 check_dsp(ctx);
19268 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19269 break;
19270 case NM_DPSQX_SA_W_PH:
908f6be1 19271 check_dsp_r2(ctx);
8b3698b2
SM
19272 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19273 break;
19274 case NM_MULSAQ_S_W_PH:
19275 check_dsp(ctx);
19276 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19277 break;
19278 default:
19279 generate_exception_end(ctx, EXCP_RI);
19280 break;
19281 }
19282 break;
19283 default:
19284 generate_exception_end(ctx, EXCP_RI);
19285 break;
19286 }
19287
19288 tcg_temp_free_i32(t0);
19289}
19290
19291static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19292 int rt, int rs, int rd)
19293{
19294 int ret = rt;
19295 TCGv t0 = tcg_temp_new();
19296 TCGv t1 = tcg_temp_new();
19297 TCGv v0_t = tcg_temp_new();
19298 TCGv v1_t = tcg_temp_new();
19299
19300 gen_load_gpr(v0_t, rt);
19301 gen_load_gpr(v1_t, rs);
19302
19303 switch (opc) {
19304 case NM_POOL32AXF_2_0_7:
19305 switch (extract32(ctx->opcode, 9, 3)) {
19306 case NM_DPA_W_PH:
19307 case NM_DPAQ_S_W_PH:
19308 case NM_DPS_W_PH:
19309 case NM_DPSQ_S_W_PH:
19310 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19311 break;
19312 case NM_BALIGN:
908f6be1 19313 check_dsp_r2(ctx);
8b3698b2
SM
19314 if (rt != 0) {
19315 gen_load_gpr(t0, rs);
19316 rd &= 3;
19317 if (rd != 0 && rd != 2) {
19318 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19319 tcg_gen_ext32u_tl(t0, t0);
19320 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19321 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19322 }
19323 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19324 }
19325 break;
19326 case NM_MADD:
19327 check_dsp(ctx);
19328 {
19329 int acc = extract32(ctx->opcode, 14, 2);
19330 TCGv_i64 t2 = tcg_temp_new_i64();
19331 TCGv_i64 t3 = tcg_temp_new_i64();
19332
19333 gen_load_gpr(t0, rt);
19334 gen_load_gpr(t1, rs);
19335 tcg_gen_ext_tl_i64(t2, t0);
19336 tcg_gen_ext_tl_i64(t3, t1);
19337 tcg_gen_mul_i64(t2, t2, t3);
19338 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19339 tcg_gen_add_i64(t2, t2, t3);
19340 tcg_temp_free_i64(t3);
19341 gen_move_low32(cpu_LO[acc], t2);
19342 gen_move_high32(cpu_HI[acc], t2);
19343 tcg_temp_free_i64(t2);
19344 }
19345 break;
19346 case NM_MULT:
19347 check_dsp(ctx);
19348 {
19349 int acc = extract32(ctx->opcode, 14, 2);
19350 TCGv_i32 t2 = tcg_temp_new_i32();
19351 TCGv_i32 t3 = tcg_temp_new_i32();
19352
19353 gen_load_gpr(t0, rs);
19354 gen_load_gpr(t1, rt);
19355 tcg_gen_trunc_tl_i32(t2, t0);
19356 tcg_gen_trunc_tl_i32(t3, t1);
19357 tcg_gen_muls2_i32(t2, t3, t2, t3);
19358 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19359 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19360 tcg_temp_free_i32(t2);
19361 tcg_temp_free_i32(t3);
19362 }
19363 break;
19364 case NM_EXTRV_W:
19365 check_dsp(ctx);
19366 gen_load_gpr(v1_t, rs);
19367 tcg_gen_movi_tl(t0, rd >> 3);
19368 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19369 gen_store_gpr(t0, ret);
19370 break;
19371 }
19372 break;
19373 case NM_POOL32AXF_2_8_15:
19374 switch (extract32(ctx->opcode, 9, 3)) {
19375 case NM_DPAX_W_PH:
19376 case NM_DPAQ_SA_L_W:
19377 case NM_DPSX_W_PH:
19378 case NM_DPSQ_SA_L_W:
19379 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19380 break;
19381 case NM_MADDU:
19382 check_dsp(ctx);
19383 {
19384 int acc = extract32(ctx->opcode, 14, 2);
19385 TCGv_i64 t2 = tcg_temp_new_i64();
19386 TCGv_i64 t3 = tcg_temp_new_i64();
19387
19388 gen_load_gpr(t0, rs);
19389 gen_load_gpr(t1, rt);
19390 tcg_gen_ext32u_tl(t0, t0);
19391 tcg_gen_ext32u_tl(t1, t1);
19392 tcg_gen_extu_tl_i64(t2, t0);
19393 tcg_gen_extu_tl_i64(t3, t1);
19394 tcg_gen_mul_i64(t2, t2, t3);
19395 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19396 tcg_gen_add_i64(t2, t2, t3);
19397 tcg_temp_free_i64(t3);
19398 gen_move_low32(cpu_LO[acc], t2);
19399 gen_move_high32(cpu_HI[acc], t2);
19400 tcg_temp_free_i64(t2);
19401 }
19402 break;
19403 case NM_MULTU:
19404 check_dsp(ctx);
19405 {
19406 int acc = extract32(ctx->opcode, 14, 2);
19407 TCGv_i32 t2 = tcg_temp_new_i32();
19408 TCGv_i32 t3 = tcg_temp_new_i32();
19409
19410 gen_load_gpr(t0, rs);
19411 gen_load_gpr(t1, rt);
19412 tcg_gen_trunc_tl_i32(t2, t0);
19413 tcg_gen_trunc_tl_i32(t3, t1);
19414 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19415 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19416 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19417 tcg_temp_free_i32(t2);
19418 tcg_temp_free_i32(t3);
19419 }
19420 break;
19421 case NM_EXTRV_R_W:
19422 check_dsp(ctx);
19423 tcg_gen_movi_tl(t0, rd >> 3);
19424 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19425 gen_store_gpr(t0, ret);
19426 break;
19427 default:
19428 generate_exception_end(ctx, EXCP_RI);
19429 break;
19430 }
19431 break;
19432 case NM_POOL32AXF_2_16_23:
19433 switch (extract32(ctx->opcode, 9, 3)) {
19434 case NM_DPAU_H_QBL:
19435 case NM_DPAQX_S_W_PH:
19436 case NM_DPSU_H_QBL:
19437 case NM_DPSQX_S_W_PH:
19438 case NM_MULSA_W_PH:
19439 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19440 break;
19441 case NM_EXTPV:
19442 check_dsp(ctx);
19443 tcg_gen_movi_tl(t0, rd >> 3);
19444 gen_helper_extp(t0, t0, v1_t, cpu_env);
19445 gen_store_gpr(t0, ret);
19446 break;
19447 case NM_MSUB:
19448 check_dsp(ctx);
19449 {
19450 int acc = extract32(ctx->opcode, 14, 2);
19451 TCGv_i64 t2 = tcg_temp_new_i64();
19452 TCGv_i64 t3 = tcg_temp_new_i64();
19453
19454 gen_load_gpr(t0, rs);
19455 gen_load_gpr(t1, rt);
19456 tcg_gen_ext_tl_i64(t2, t0);
19457 tcg_gen_ext_tl_i64(t3, t1);
19458 tcg_gen_mul_i64(t2, t2, t3);
19459 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19460 tcg_gen_sub_i64(t2, t3, t2);
19461 tcg_temp_free_i64(t3);
19462 gen_move_low32(cpu_LO[acc], t2);
19463 gen_move_high32(cpu_HI[acc], t2);
19464 tcg_temp_free_i64(t2);
19465 }
19466 break;
19467 case NM_EXTRV_RS_W:
19468 check_dsp(ctx);
19469 tcg_gen_movi_tl(t0, rd >> 3);
19470 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19471 gen_store_gpr(t0, ret);
19472 break;
19473 }
19474 break;
19475 case NM_POOL32AXF_2_24_31:
19476 switch (extract32(ctx->opcode, 9, 3)) {
19477 case NM_DPAU_H_QBR:
19478 case NM_DPAQX_SA_W_PH:
19479 case NM_DPSU_H_QBR:
19480 case NM_DPSQX_SA_W_PH:
19481 case NM_MULSAQ_S_W_PH:
19482 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19483 break;
19484 case NM_EXTPDPV:
19485 check_dsp(ctx);
19486 tcg_gen_movi_tl(t0, rd >> 3);
19487 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19488 gen_store_gpr(t0, ret);
19489 break;
19490 case NM_MSUBU:
19491 check_dsp(ctx);
19492 {
19493 int acc = extract32(ctx->opcode, 14, 2);
19494 TCGv_i64 t2 = tcg_temp_new_i64();
19495 TCGv_i64 t3 = tcg_temp_new_i64();
19496
19497 gen_load_gpr(t0, rs);
19498 gen_load_gpr(t1, rt);
19499 tcg_gen_ext32u_tl(t0, t0);
19500 tcg_gen_ext32u_tl(t1, t1);
19501 tcg_gen_extu_tl_i64(t2, t0);
19502 tcg_gen_extu_tl_i64(t3, t1);
19503 tcg_gen_mul_i64(t2, t2, t3);
19504 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19505 tcg_gen_sub_i64(t2, t3, t2);
19506 tcg_temp_free_i64(t3);
19507 gen_move_low32(cpu_LO[acc], t2);
19508 gen_move_high32(cpu_HI[acc], t2);
19509 tcg_temp_free_i64(t2);
19510 }
19511 break;
19512 case NM_EXTRV_S_H:
19513 check_dsp(ctx);
19514 tcg_gen_movi_tl(t0, rd >> 3);
19515 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19516 gen_store_gpr(t0, ret);
19517 break;
19518 }
19519 break;
19520 default:
19521 generate_exception_end(ctx, EXCP_RI);
19522 break;
19523 }
19524
19525 tcg_temp_free(t0);
19526 tcg_temp_free(t1);
19527
19528 tcg_temp_free(v0_t);
19529 tcg_temp_free(v1_t);
19530}
19531
4c75c985
SM
19532static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19533 int rt, int rs)
19534{
19535 int ret = rt;
19536 TCGv t0 = tcg_temp_new();
19537 TCGv v0_t = tcg_temp_new();
19538
19539 gen_load_gpr(v0_t, rs);
19540
19541 switch (opc) {
19542 case NM_ABSQ_S_QB:
908f6be1 19543 check_dsp_r2(ctx);
4c75c985
SM
19544 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19545 gen_store_gpr(v0_t, ret);
19546 break;
19547 case NM_ABSQ_S_PH:
19548 check_dsp(ctx);
19549 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19550 gen_store_gpr(v0_t, ret);
19551 break;
19552 case NM_ABSQ_S_W:
19553 check_dsp(ctx);
19554 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19555 gen_store_gpr(v0_t, ret);
19556 break;
19557 case NM_PRECEQ_W_PHL:
19558 check_dsp(ctx);
19559 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19560 tcg_gen_ext32s_tl(v0_t, v0_t);
19561 gen_store_gpr(v0_t, ret);
19562 break;
19563 case NM_PRECEQ_W_PHR:
19564 check_dsp(ctx);
19565 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19566 tcg_gen_shli_tl(v0_t, v0_t, 16);
19567 tcg_gen_ext32s_tl(v0_t, v0_t);
19568 gen_store_gpr(v0_t, ret);
19569 break;
19570 case NM_PRECEQU_PH_QBL:
19571 check_dsp(ctx);
19572 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19573 gen_store_gpr(v0_t, ret);
19574 break;
19575 case NM_PRECEQU_PH_QBR:
19576 check_dsp(ctx);
19577 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19578 gen_store_gpr(v0_t, ret);
19579 break;
19580 case NM_PRECEQU_PH_QBLA:
19581 check_dsp(ctx);
19582 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19583 gen_store_gpr(v0_t, ret);
19584 break;
19585 case NM_PRECEQU_PH_QBRA:
19586 check_dsp(ctx);
19587 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19588 gen_store_gpr(v0_t, ret);
19589 break;
19590 case NM_PRECEU_PH_QBL:
19591 check_dsp(ctx);
19592 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19593 gen_store_gpr(v0_t, ret);
19594 break;
19595 case NM_PRECEU_PH_QBR:
19596 check_dsp(ctx);
19597 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19598 gen_store_gpr(v0_t, ret);
19599 break;
19600 case NM_PRECEU_PH_QBLA:
19601 check_dsp(ctx);
19602 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19603 gen_store_gpr(v0_t, ret);
19604 break;
19605 case NM_PRECEU_PH_QBRA:
19606 check_dsp(ctx);
19607 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19608 gen_store_gpr(v0_t, ret);
19609 break;
19610 case NM_REPLV_PH:
19611 check_dsp(ctx);
19612 tcg_gen_ext16u_tl(v0_t, v0_t);
19613 tcg_gen_shli_tl(t0, v0_t, 16);
19614 tcg_gen_or_tl(v0_t, v0_t, t0);
19615 tcg_gen_ext32s_tl(v0_t, v0_t);
19616 gen_store_gpr(v0_t, ret);
19617 break;
19618 case NM_REPLV_QB:
19619 check_dsp(ctx);
19620 tcg_gen_ext8u_tl(v0_t, v0_t);
19621 tcg_gen_shli_tl(t0, v0_t, 8);
19622 tcg_gen_or_tl(v0_t, v0_t, t0);
19623 tcg_gen_shli_tl(t0, v0_t, 16);
19624 tcg_gen_or_tl(v0_t, v0_t, t0);
19625 tcg_gen_ext32s_tl(v0_t, v0_t);
19626 gen_store_gpr(v0_t, ret);
19627 break;
19628 case NM_BITREV:
19629 check_dsp(ctx);
19630 gen_helper_bitrev(v0_t, v0_t);
19631 gen_store_gpr(v0_t, ret);
19632 break;
19633 case NM_INSV:
19634 check_dsp(ctx);
19635 {
19636 TCGv tv0 = tcg_temp_new();
19637
19638 gen_load_gpr(tv0, rt);
19639 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19640 gen_store_gpr(v0_t, ret);
19641 tcg_temp_free(tv0);
19642 }
19643 break;
19644 case NM_RADDU_W_QB:
19645 check_dsp(ctx);
19646 gen_helper_raddu_w_qb(v0_t, v0_t);
19647 gen_store_gpr(v0_t, ret);
19648 break;
19649 case NM_BITSWAP:
19650 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19651 break;
19652 case NM_CLO:
fb32f8c8 19653 check_nms(ctx);
4c75c985
SM
19654 gen_cl(ctx, OPC_CLO, ret, rs);
19655 break;
19656 case NM_CLZ:
fb32f8c8 19657 check_nms(ctx);
4c75c985
SM
19658 gen_cl(ctx, OPC_CLZ, ret, rs);
19659 break;
19660 case NM_WSBH:
19661 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19662 break;
19663 default:
19664 generate_exception_end(ctx, EXCP_RI);
19665 break;
19666 }
19667
19668 tcg_temp_free(v0_t);
19669 tcg_temp_free(t0);
19670}
19671
0b591184
SM
19672static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19673 int rt, int rs, int rd)
19674{
19675 TCGv t0 = tcg_temp_new();
19676 TCGv rs_t = tcg_temp_new();
19677
19678 gen_load_gpr(rs_t, rs);
19679
19680 switch (opc) {
19681 case NM_SHRA_R_QB:
908f6be1 19682 check_dsp_r2(ctx);
0b591184
SM
19683 tcg_gen_movi_tl(t0, rd >> 2);
19684 switch (extract32(ctx->opcode, 12, 1)) {
19685 case 0:
19686 /* NM_SHRA_QB */
19687 gen_helper_shra_qb(t0, t0, rs_t);
19688 gen_store_gpr(t0, rt);
19689 break;
19690 case 1:
19691 /* NM_SHRA_R_QB */
19692 gen_helper_shra_r_qb(t0, t0, rs_t);
19693 gen_store_gpr(t0, rt);
19694 break;
19695 }
19696 break;
19697 case NM_SHRL_PH:
908f6be1 19698 check_dsp_r2(ctx);
0b591184
SM
19699 tcg_gen_movi_tl(t0, rd >> 1);
19700 gen_helper_shrl_ph(t0, t0, rs_t);
19701 gen_store_gpr(t0, rt);
19702 break;
19703 case NM_REPL_QB:
19704 check_dsp(ctx);
19705 {
19706 int16_t imm;
19707 target_long result;
19708 imm = extract32(ctx->opcode, 13, 8);
19709 result = (uint32_t)imm << 24 |
19710 (uint32_t)imm << 16 |
19711 (uint32_t)imm << 8 |
19712 (uint32_t)imm;
19713 result = (int32_t)result;
19714 tcg_gen_movi_tl(t0, result);
19715 gen_store_gpr(t0, rt);
19716 }
19717 break;
19718 default:
19719 generate_exception_end(ctx, EXCP_RI);
19720 break;
19721 }
19722 tcg_temp_free(t0);
19723 tcg_temp_free(rs_t);
19724}
19725
2ed42efa 19726
64224187
YK
19727static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19728{
64224187
YK
19729 int rt = extract32(ctx->opcode, 21, 5);
19730 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19731 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19732
19733 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19734 case NM_POOL32AXF_1:
19735 {
19736 int32_t op1 = extract32(ctx->opcode, 9, 3);
19737 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19738 }
19739 break;
19740 case NM_POOL32AXF_2:
8b3698b2
SM
19741 {
19742 int32_t op1 = extract32(ctx->opcode, 12, 2);
19743 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19744 }
2ed42efa 19745 break;
64224187 19746 case NM_POOL32AXF_4:
4c75c985
SM
19747 {
19748 int32_t op1 = extract32(ctx->opcode, 9, 7);
19749 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19750 }
2ed42efa 19751 break;
64224187
YK
19752 case NM_POOL32AXF_5:
19753 switch (extract32(ctx->opcode, 9, 7)) {
19754#ifndef CONFIG_USER_ONLY
19755 case NM_TLBP:
19756 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19757 break;
19758 case NM_TLBR:
19759 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19760 break;
19761 case NM_TLBWI:
19762 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19763 break;
19764 case NM_TLBWR:
19765 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19766 break;
19767 case NM_TLBINV:
19768 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19769 break;
19770 case NM_TLBINVF:
19771 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19772 break;
19773 case NM_DI:
19774 check_cp0_enabled(ctx);
19775 {
19776 TCGv t0 = tcg_temp_new();
19777
19778 save_cpu_state(ctx, 1);
19779 gen_helper_di(t0, cpu_env);
19780 gen_store_gpr(t0, rt);
19781 /* Stop translation as we may have switched the execution mode */
19782 ctx->base.is_jmp = DISAS_STOP;
19783 tcg_temp_free(t0);
19784 }
19785 break;
19786 case NM_EI:
19787 check_cp0_enabled(ctx);
19788 {
19789 TCGv t0 = tcg_temp_new();
19790
19791 save_cpu_state(ctx, 1);
19792 gen_helper_ei(t0, cpu_env);
19793 gen_store_gpr(t0, rt);
19794 /* Stop translation as we may have switched the execution mode */
19795 ctx->base.is_jmp = DISAS_STOP;
19796 tcg_temp_free(t0);
19797 }
19798 break;
19799 case NM_RDPGPR:
19800 gen_load_srsgpr(rs, rt);
19801 break;
19802 case NM_WRPGPR:
19803 gen_store_srsgpr(rs, rt);
19804 break;
19805 case NM_WAIT:
19806 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19807 break;
19808 case NM_DERET:
19809 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19810 break;
19811 case NM_ERETX:
19812 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19813 break;
19814#endif
19815 default:
19816 generate_exception_end(ctx, EXCP_RI);
19817 break;
19818 }
19819 break;
2ed42efa 19820 case NM_POOL32AXF_7:
0b591184
SM
19821 {
19822 int32_t op1 = extract32(ctx->opcode, 9, 3);
19823 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19824 }
2ed42efa 19825 break;
64224187
YK
19826 default:
19827 generate_exception_end(ctx, EXCP_RI);
19828 break;
19829 }
19830}
19831
11d0fc10
SM
19832/* Immediate Value Compact Branches */
19833static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19834 int rt, int32_t imm, int32_t offset)
19835{
19836 TCGCond cond;
19837 int bcond_compute = 0;
19838 TCGv t0 = tcg_temp_new();
19839 TCGv t1 = tcg_temp_new();
19840
19841 gen_load_gpr(t0, rt);
19842 tcg_gen_movi_tl(t1, imm);
19843 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19844
19845 /* Load needed operands and calculate btarget */
19846 switch (opc) {
19847 case NM_BEQIC:
19848 if (rt == 0 && imm == 0) {
19849 /* Unconditional branch */
19850 } else if (rt == 0 && imm != 0) {
19851 /* Treat as NOP */
19852 goto out;
19853 } else {
19854 bcond_compute = 1;
19855 cond = TCG_COND_EQ;
19856 }
19857 break;
19858 case NM_BBEQZC:
19859 case NM_BBNEZC:
fb32f8c8 19860 check_nms(ctx);
11d0fc10
SM
19861 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19862 generate_exception_end(ctx, EXCP_RI);
19863 goto out;
19864 } else if (rt == 0 && opc == NM_BBEQZC) {
19865 /* Unconditional branch */
19866 } else if (rt == 0 && opc == NM_BBNEZC) {
19867 /* Treat as NOP */
19868 goto out;
19869 } else {
19870 tcg_gen_shri_tl(t0, t0, imm);
19871 tcg_gen_andi_tl(t0, t0, 1);
19872 tcg_gen_movi_tl(t1, 0);
19873 bcond_compute = 1;
19874 if (opc == NM_BBEQZC) {
19875 cond = TCG_COND_EQ;
19876 } else {
19877 cond = TCG_COND_NE;
19878 }
19879 }
19880 break;
19881 case NM_BNEIC:
19882 if (rt == 0 && imm == 0) {
19883 /* Treat as NOP */
19884 goto out;
19885 } else if (rt == 0 && imm != 0) {
19886 /* Unconditional branch */
19887 } else {
19888 bcond_compute = 1;
19889 cond = TCG_COND_NE;
19890 }
19891 break;
19892 case NM_BGEIC:
19893 if (rt == 0 && imm == 0) {
19894 /* Unconditional branch */
19895 } else {
19896 bcond_compute = 1;
19897 cond = TCG_COND_GE;
19898 }
19899 break;
19900 case NM_BLTIC:
19901 bcond_compute = 1;
19902 cond = TCG_COND_LT;
19903 break;
19904 case NM_BGEIUC:
19905 if (rt == 0 && imm == 0) {
19906 /* Unconditional branch */
19907 } else {
19908 bcond_compute = 1;
19909 cond = TCG_COND_GEU;
19910 }
19911 break;
19912 case NM_BLTIUC:
19913 bcond_compute = 1;
19914 cond = TCG_COND_LTU;
19915 break;
19916 default:
19917 MIPS_INVAL("Immediate Value Compact branch");
19918 generate_exception_end(ctx, EXCP_RI);
19919 goto out;
19920 }
19921
697b7b6b
SM
19922 /* branch completion */
19923 clear_branch_hflags(ctx);
19924 ctx->base.is_jmp = DISAS_NORETURN;
19925
11d0fc10
SM
19926 if (bcond_compute == 0) {
19927 /* Uncoditional compact branch */
19928 gen_goto_tb(ctx, 0, ctx->btarget);
19929 } else {
19930 /* Conditional compact branch */
19931 TCGLabel *fs = gen_new_label();
19932
19933 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19934
19935 gen_goto_tb(ctx, 1, ctx->btarget);
19936 gen_set_label(fs);
19937
19938 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19939 }
19940
19941out:
19942 tcg_temp_free(t0);
19943 tcg_temp_free(t1);
19944}
19945
19946/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19947static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19948 int rt)
19949{
19950 TCGv t0 = tcg_temp_new();
19951 TCGv t1 = tcg_temp_new();
19952
19953 /* load rs */
19954 gen_load_gpr(t0, rs);
19955
19956 /* link */
19957 if (rt != 0) {
19958 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19959 }
19960
19961 /* calculate btarget */
19962 tcg_gen_shli_tl(t0, t0, 1);
19963 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19964 gen_op_addr_add(ctx, btarget, t1, t0);
19965
697b7b6b
SM
19966 /* branch completion */
19967 clear_branch_hflags(ctx);
19968 ctx->base.is_jmp = DISAS_NORETURN;
19969
11d0fc10
SM
19970 /* unconditional branch to register */
19971 tcg_gen_mov_tl(cpu_PC, btarget);
19972 tcg_gen_lookup_and_goto_ptr();
19973
19974 tcg_temp_free(t0);
19975 tcg_temp_free(t1);
19976}
19977
19978/* nanoMIPS Branches */
19979static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19980 int rs, int rt, int32_t offset)
19981{
19982 int bcond_compute = 0;
19983 TCGv t0 = tcg_temp_new();
19984 TCGv t1 = tcg_temp_new();
19985
19986 /* Load needed operands and calculate btarget */
19987 switch (opc) {
19988 /* compact branch */
19989 case OPC_BGEC:
19990 case OPC_BLTC:
19991 gen_load_gpr(t0, rs);
19992 gen_load_gpr(t1, rt);
19993 bcond_compute = 1;
19994 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19995 break;
19996 case OPC_BGEUC:
19997 case OPC_BLTUC:
19998 if (rs == 0 || rs == rt) {
19999 /* OPC_BLEZALC, OPC_BGEZALC */
20000 /* OPC_BGTZALC, OPC_BLTZALC */
20001 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20002 }
20003 gen_load_gpr(t0, rs);
20004 gen_load_gpr(t1, rt);
20005 bcond_compute = 1;
20006 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20007 break;
20008 case OPC_BC:
20009 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20010 break;
20011 case OPC_BEQZC:
20012 if (rs != 0) {
20013 /* OPC_BEQZC, OPC_BNEZC */
20014 gen_load_gpr(t0, rs);
20015 bcond_compute = 1;
20016 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20017 } else {
20018 /* OPC_JIC, OPC_JIALC */
20019 TCGv tbase = tcg_temp_new();
20020 TCGv toffset = tcg_temp_new();
20021
20022 gen_load_gpr(tbase, rt);
20023 tcg_gen_movi_tl(toffset, offset);
20024 gen_op_addr_add(ctx, btarget, tbase, toffset);
20025 tcg_temp_free(tbase);
20026 tcg_temp_free(toffset);
20027 }
20028 break;
20029 default:
20030 MIPS_INVAL("Compact branch/jump");
20031 generate_exception_end(ctx, EXCP_RI);
20032 goto out;
20033 }
20034
20035 if (bcond_compute == 0) {
20036 /* Uncoditional compact branch */
20037 switch (opc) {
20038 case OPC_BC:
20039 gen_goto_tb(ctx, 0, ctx->btarget);
20040 break;
20041 default:
20042 MIPS_INVAL("Compact branch/jump");
20043 generate_exception_end(ctx, EXCP_RI);
20044 goto out;
20045 }
20046 } else {
20047 /* Conditional compact branch */
20048 TCGLabel *fs = gen_new_label();
20049
20050 switch (opc) {
20051 case OPC_BGEUC:
20052 if (rs == 0 && rt != 0) {
20053 /* OPC_BLEZALC */
20054 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20055 } else if (rs != 0 && rt != 0 && rs == rt) {
20056 /* OPC_BGEZALC */
20057 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20058 } else {
20059 /* OPC_BGEUC */
20060 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20061 }
20062 break;
20063 case OPC_BLTUC:
20064 if (rs == 0 && rt != 0) {
20065 /* OPC_BGTZALC */
20066 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20067 } else if (rs != 0 && rt != 0 && rs == rt) {
20068 /* OPC_BLTZALC */
20069 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20070 } else {
20071 /* OPC_BLTUC */
20072 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20073 }
20074 break;
20075 case OPC_BGEC:
20076 if (rs == 0 && rt != 0) {
20077 /* OPC_BLEZC */
20078 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20079 } else if (rs != 0 && rt != 0 && rs == rt) {
20080 /* OPC_BGEZC */
20081 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20082 } else {
20083 /* OPC_BGEC */
20084 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20085 }
20086 break;
20087 case OPC_BLTC:
20088 if (rs == 0 && rt != 0) {
20089 /* OPC_BGTZC */
20090 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20091 } else if (rs != 0 && rt != 0 && rs == rt) {
20092 /* OPC_BLTZC */
20093 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20094 } else {
20095 /* OPC_BLTC */
20096 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20097 }
20098 break;
20099 case OPC_BEQZC:
20100 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20101 break;
20102 default:
20103 MIPS_INVAL("Compact conditional branch/jump");
20104 generate_exception_end(ctx, EXCP_RI);
20105 goto out;
20106 }
20107
697b7b6b
SM
20108 /* branch completion */
20109 clear_branch_hflags(ctx);
20110 ctx->base.is_jmp = DISAS_NORETURN;
20111
11d0fc10
SM
20112 /* Generating branch here as compact branches don't have delay slot */
20113 gen_goto_tb(ctx, 1, ctx->btarget);
20114 gen_set_label(fs);
20115
20116 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20117 }
20118
20119out:
20120 tcg_temp_free(t0);
20121 tcg_temp_free(t1);
20122}
20123
20124
20125/* nanoMIPS CP1 Branches */
20126static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20127 int32_t ft, int32_t offset)
20128{
20129 target_ulong btarget;
20130 TCGv_i64 t0 = tcg_temp_new_i64();
20131
20132 gen_load_fpr64(ctx, t0, ft);
20133 tcg_gen_andi_i64(t0, t0, 1);
20134
20135 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20136
20137 switch (op) {
20138 case NM_BC1EQZC:
20139 tcg_gen_xori_i64(t0, t0, 1);
20140 ctx->hflags |= MIPS_HFLAG_BC;
20141 break;
20142 case NM_BC1NEZC:
20143 /* t0 already set */
20144 ctx->hflags |= MIPS_HFLAG_BC;
20145 break;
20146 default:
20147 MIPS_INVAL("cp1 cond branch");
20148 generate_exception_end(ctx, EXCP_RI);
20149 goto out;
20150 }
20151
20152 tcg_gen_trunc_i64_tl(bcond, t0);
20153
20154 ctx->btarget = btarget;
20155
20156out:
20157 tcg_temp_free_i64(t0);
20158}
20159
eac52664
YK
20160
20161static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20162{
20163 TCGv t0, t1;
20164 t0 = tcg_temp_new();
20165 t1 = tcg_temp_new();
20166
20167 gen_load_gpr(t0, rs);
20168 gen_load_gpr(t1, rt);
20169
20170 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20171 /* PP.LSXS instructions require shifting */
20172 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20173 case NM_SHXS:
fb32f8c8 20174 check_nms(ctx);
45152d05 20175 /* fall through */
fb32f8c8 20176 case NM_LHXS:
eac52664
YK
20177 case NM_LHUXS:
20178 tcg_gen_shli_tl(t0, t0, 1);
20179 break;
eac52664 20180 case NM_SWXS:
fb32f8c8 20181 check_nms(ctx);
45152d05 20182 /* fall through */
fb32f8c8 20183 case NM_LWXS:
eac52664
YK
20184 case NM_LWC1XS:
20185 case NM_SWC1XS:
20186 tcg_gen_shli_tl(t0, t0, 2);
20187 break;
20188 case NM_LDC1XS:
20189 case NM_SDC1XS:
20190 tcg_gen_shli_tl(t0, t0, 3);
20191 break;
20192 }
20193 }
20194 gen_op_addr_add(ctx, t0, t0, t1);
20195
20196 switch (extract32(ctx->opcode, 7, 4)) {
20197 case NM_LBX:
20198 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20199 MO_SB);
20200 gen_store_gpr(t0, rd);
20201 break;
20202 case NM_LHX:
20203 /*case NM_LHXS:*/
20204 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20205 MO_TESW);
20206 gen_store_gpr(t0, rd);
20207 break;
20208 case NM_LWX:
20209 /*case NM_LWXS:*/
20210 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20211 MO_TESL);
20212 gen_store_gpr(t0, rd);
20213 break;
20214 case NM_LBUX:
20215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20216 MO_UB);
20217 gen_store_gpr(t0, rd);
20218 break;
20219 case NM_LHUX:
20220 /*case NM_LHUXS:*/
20221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20222 MO_TEUW);
20223 gen_store_gpr(t0, rd);
20224 break;
20225 case NM_SBX:
fb32f8c8 20226 check_nms(ctx);
eac52664
YK
20227 gen_load_gpr(t1, rd);
20228 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20229 MO_8);
20230 break;
20231 case NM_SHX:
20232 /*case NM_SHXS:*/
fb32f8c8 20233 check_nms(ctx);
eac52664
YK
20234 gen_load_gpr(t1, rd);
20235 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20236 MO_TEUW);
20237 break;
20238 case NM_SWX:
20239 /*case NM_SWXS:*/
fb32f8c8 20240 check_nms(ctx);
eac52664
YK
20241 gen_load_gpr(t1, rd);
20242 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20243 MO_TEUL);
20244 break;
20245 case NM_LWC1X:
20246 /*case NM_LWC1XS:*/
20247 case NM_LDC1X:
20248 /*case NM_LDC1XS:*/
20249 case NM_SWC1X:
20250 /*case NM_SWC1XS:*/
20251 case NM_SDC1X:
20252 /*case NM_SDC1XS:*/
20253 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20254 check_cp1_enabled(ctx);
20255 switch (extract32(ctx->opcode, 7, 4)) {
20256 case NM_LWC1X:
20257 /*case NM_LWC1XS:*/
20258 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20259 break;
20260 case NM_LDC1X:
20261 /*case NM_LDC1XS:*/
20262 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20263 break;
20264 case NM_SWC1X:
20265 /*case NM_SWC1XS:*/
20266 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20267 break;
20268 case NM_SDC1X:
20269 /*case NM_SDC1XS:*/
20270 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20271 break;
20272 }
20273 } else {
20274 generate_exception_err(ctx, EXCP_CpU, 1);
20275 }
20276 break;
20277 default:
20278 generate_exception_end(ctx, EXCP_RI);
20279 break;
20280 }
20281
20282 tcg_temp_free(t0);
20283 tcg_temp_free(t1);
20284}
20285
579b8ea9
YK
20286static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20287{
20288 int rt, rs, rd;
20289
20290 rt = extract32(ctx->opcode, 21, 5);
20291 rs = extract32(ctx->opcode, 16, 5);
20292 rd = extract32(ctx->opcode, 11, 5);
20293
20294 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20295 generate_exception_end(ctx, EXCP_RI);
20296 return;
20297 }
20298 check_cp1_enabled(ctx);
20299 switch (extract32(ctx->opcode, 0, 3)) {
20300 case NM_POOL32F_0:
20301 switch (extract32(ctx->opcode, 3, 7)) {
20302 case NM_RINT_S:
20303 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20304 break;
20305 case NM_RINT_D:
20306 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20307 break;
20308 case NM_CLASS_S:
20309 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20310 break;
20311 case NM_CLASS_D:
20312 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20313 break;
20314 case NM_ADD_S:
20315 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20316 break;
20317 case NM_ADD_D:
20318 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20319 break;
20320 case NM_SUB_S:
20321 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20322 break;
20323 case NM_SUB_D:
20324 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20325 break;
20326 case NM_MUL_S:
20327 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20328 break;
20329 case NM_MUL_D:
20330 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20331 break;
20332 case NM_DIV_S:
20333 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20334 break;
20335 case NM_DIV_D:
20336 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20337 break;
20338 case NM_SELEQZ_S:
20339 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20340 break;
20341 case NM_SELEQZ_D:
20342 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20343 break;
20344 case NM_SELNEZ_S:
20345 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20346 break;
20347 case NM_SELNEZ_D:
20348 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20349 break;
20350 case NM_SEL_S:
20351 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20352 break;
20353 case NM_SEL_D:
20354 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20355 break;
20356 case NM_MADDF_S:
20357 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20358 break;
20359 case NM_MADDF_D:
20360 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20361 break;
20362 case NM_MSUBF_S:
20363 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20364 break;
20365 case NM_MSUBF_D:
20366 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20367 break;
20368 default:
20369 generate_exception_end(ctx, EXCP_RI);
20370 break;
20371 }
20372 break;
20373 case NM_POOL32F_3:
20374 switch (extract32(ctx->opcode, 3, 3)) {
20375 case NM_MIN_FMT:
20376 switch (extract32(ctx->opcode, 9, 1)) {
20377 case FMT_SDPS_S:
20378 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20379 break;
20380 case FMT_SDPS_D:
20381 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20382 break;
20383 }
20384 break;
20385 case NM_MAX_FMT:
20386 switch (extract32(ctx->opcode, 9, 1)) {
20387 case FMT_SDPS_S:
20388 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20389 break;
20390 case FMT_SDPS_D:
20391 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20392 break;
20393 }
20394 break;
20395 case NM_MINA_FMT:
20396 switch (extract32(ctx->opcode, 9, 1)) {
20397 case FMT_SDPS_S:
20398 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20399 break;
20400 case FMT_SDPS_D:
20401 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20402 break;
20403 }
20404 break;
20405 case NM_MAXA_FMT:
20406 switch (extract32(ctx->opcode, 9, 1)) {
20407 case FMT_SDPS_S:
20408 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20409 break;
20410 case FMT_SDPS_D:
20411 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20412 break;
20413 }
20414 break;
20415 case NM_POOL32FXF:
20416 switch (extract32(ctx->opcode, 6, 8)) {
20417 case NM_CFC1:
20418 gen_cp1(ctx, OPC_CFC1, rt, rs);
20419 break;
20420 case NM_CTC1:
20421 gen_cp1(ctx, OPC_CTC1, rt, rs);
20422 break;
20423 case NM_MFC1:
20424 gen_cp1(ctx, OPC_MFC1, rt, rs);
20425 break;
20426 case NM_MTC1:
20427 gen_cp1(ctx, OPC_MTC1, rt, rs);
20428 break;
20429 case NM_MFHC1:
20430 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20431 break;
20432 case NM_MTHC1:
20433 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20434 break;
20435 case NM_CVT_S_PL:
20436 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20437 break;
20438 case NM_CVT_S_PU:
20439 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20440 break;
20441 default:
20442 switch (extract32(ctx->opcode, 6, 9)) {
20443 case NM_CVT_L_S:
20444 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20445 break;
20446 case NM_CVT_L_D:
20447 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20448 break;
20449 case NM_CVT_W_S:
20450 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20451 break;
20452 case NM_CVT_W_D:
20453 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20454 break;
20455 case NM_RSQRT_S:
20456 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20457 break;
20458 case NM_RSQRT_D:
20459 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20460 break;
20461 case NM_SQRT_S:
20462 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20463 break;
20464 case NM_SQRT_D:
20465 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20466 break;
20467 case NM_RECIP_S:
20468 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20469 break;
20470 case NM_RECIP_D:
20471 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20472 break;
20473 case NM_FLOOR_L_S:
20474 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20475 break;
20476 case NM_FLOOR_L_D:
20477 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20478 break;
20479 case NM_FLOOR_W_S:
20480 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20481 break;
20482 case NM_FLOOR_W_D:
20483 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20484 break;
20485 case NM_CEIL_L_S:
20486 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20487 break;
20488 case NM_CEIL_L_D:
20489 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20490 break;
20491 case NM_CEIL_W_S:
20492 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20493 break;
20494 case NM_CEIL_W_D:
20495 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20496 break;
20497 case NM_TRUNC_L_S:
20498 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20499 break;
20500 case NM_TRUNC_L_D:
20501 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20502 break;
20503 case NM_TRUNC_W_S:
20504 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20505 break;
20506 case NM_TRUNC_W_D:
20507 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20508 break;
20509 case NM_ROUND_L_S:
20510 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20511 break;
20512 case NM_ROUND_L_D:
20513 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20514 break;
20515 case NM_ROUND_W_S:
20516 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20517 break;
20518 case NM_ROUND_W_D:
20519 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20520 break;
20521 case NM_MOV_S:
20522 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20523 break;
20524 case NM_MOV_D:
20525 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20526 break;
20527 case NM_ABS_S:
20528 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20529 break;
20530 case NM_ABS_D:
20531 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20532 break;
20533 case NM_NEG_S:
20534 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20535 break;
20536 case NM_NEG_D:
20537 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20538 break;
20539 case NM_CVT_D_S:
20540 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20541 break;
20542 case NM_CVT_D_W:
20543 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20544 break;
20545 case NM_CVT_D_L:
20546 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20547 break;
20548 case NM_CVT_S_D:
20549 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20550 break;
20551 case NM_CVT_S_W:
20552 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20553 break;
20554 case NM_CVT_S_L:
20555 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20556 break;
20557 default:
20558 generate_exception_end(ctx, EXCP_RI);
20559 break;
20560 }
20561 break;
20562 }
20563 break;
20564 }
20565 break;
20566 case NM_POOL32F_5:
20567 switch (extract32(ctx->opcode, 3, 3)) {
20568 case NM_CMP_CONDN_S:
20569 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20570 break;
20571 case NM_CMP_CONDN_D:
20572 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20573 break;
20574 default:
20575 generate_exception_end(ctx, EXCP_RI);
20576 break;
20577 }
20578 break;
20579 default:
20580 generate_exception_end(ctx, EXCP_RI);
20581 break;
20582 }
20583}
20584
3285a3e4
SM
20585static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20586 int rd, int rs, int rt)
20587{
20588 int ret = rd;
20589 TCGv t0 = tcg_temp_new();
20590 TCGv v1_t = tcg_temp_new();
20591 TCGv v2_t = tcg_temp_new();
20592
20593 gen_load_gpr(v1_t, rs);
20594 gen_load_gpr(v2_t, rt);
20595
20596 switch (opc) {
20597 case NM_CMP_EQ_PH:
20598 check_dsp(ctx);
20599 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20600 break;
20601 case NM_CMP_LT_PH:
20602 check_dsp(ctx);
20603 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20604 break;
20605 case NM_CMP_LE_PH:
20606 check_dsp(ctx);
20607 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20608 break;
20609 case NM_CMPU_EQ_QB:
20610 check_dsp(ctx);
20611 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20612 break;
20613 case NM_CMPU_LT_QB:
20614 check_dsp(ctx);
20615 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20616 break;
20617 case NM_CMPU_LE_QB:
20618 check_dsp(ctx);
20619 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20620 break;
20621 case NM_CMPGU_EQ_QB:
20622 check_dsp(ctx);
20623 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20624 gen_store_gpr(v1_t, ret);
20625 break;
20626 case NM_CMPGU_LT_QB:
20627 check_dsp(ctx);
20628 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20629 gen_store_gpr(v1_t, ret);
20630 break;
20631 case NM_CMPGU_LE_QB:
20632 check_dsp(ctx);
20633 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20634 gen_store_gpr(v1_t, ret);
20635 break;
20636 case NM_CMPGDU_EQ_QB:
908f6be1 20637 check_dsp_r2(ctx);
3285a3e4
SM
20638 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20639 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20640 gen_store_gpr(v1_t, ret);
20641 break;
20642 case NM_CMPGDU_LT_QB:
908f6be1 20643 check_dsp_r2(ctx);
3285a3e4
SM
20644 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20645 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20646 gen_store_gpr(v1_t, ret);
20647 break;
20648 case NM_CMPGDU_LE_QB:
908f6be1 20649 check_dsp_r2(ctx);
3285a3e4
SM
20650 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20651 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20652 gen_store_gpr(v1_t, ret);
20653 break;
20654 case NM_PACKRL_PH:
20655 check_dsp(ctx);
20656 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20657 gen_store_gpr(v1_t, ret);
20658 break;
20659 case NM_PICK_QB:
20660 check_dsp(ctx);
20661 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20662 gen_store_gpr(v1_t, ret);
20663 break;
20664 case NM_PICK_PH:
20665 check_dsp(ctx);
20666 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20667 gen_store_gpr(v1_t, ret);
20668 break;
20669 case NM_ADDQ_S_W:
20670 check_dsp(ctx);
20671 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20672 gen_store_gpr(v1_t, ret);
20673 break;
20674 case NM_SUBQ_S_W:
20675 check_dsp(ctx);
20676 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20677 gen_store_gpr(v1_t, ret);
20678 break;
20679 case NM_ADDSC:
20680 check_dsp(ctx);
20681 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20682 gen_store_gpr(v1_t, ret);
20683 break;
20684 case NM_ADDWC:
20685 check_dsp(ctx);
20686 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20687 gen_store_gpr(v1_t, ret);
20688 break;
20689 case NM_ADDQ_S_PH:
20690 check_dsp(ctx);
20691 switch (extract32(ctx->opcode, 10, 1)) {
20692 case 0:
20693 /* ADDQ_PH */
20694 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20695 gen_store_gpr(v1_t, ret);
20696 break;
20697 case 1:
20698 /* ADDQ_S_PH */
20699 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20700 gen_store_gpr(v1_t, ret);
20701 break;
20702 }
20703 break;
20704 case NM_ADDQH_R_PH:
908f6be1 20705 check_dsp_r2(ctx);
3285a3e4
SM
20706 switch (extract32(ctx->opcode, 10, 1)) {
20707 case 0:
20708 /* ADDQH_PH */
20709 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20710 gen_store_gpr(v1_t, ret);
20711 break;
20712 case 1:
20713 /* ADDQH_R_PH */
20714 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20715 gen_store_gpr(v1_t, ret);
20716 break;
20717 }
20718 break;
20719 case NM_ADDQH_R_W:
908f6be1 20720 check_dsp_r2(ctx);
3285a3e4
SM
20721 switch (extract32(ctx->opcode, 10, 1)) {
20722 case 0:
20723 /* ADDQH_W */
20724 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20725 gen_store_gpr(v1_t, ret);
20726 break;
20727 case 1:
20728 /* ADDQH_R_W */
20729 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20730 gen_store_gpr(v1_t, ret);
20731 break;
20732 }
20733 break;
20734 case NM_ADDU_S_QB:
20735 check_dsp(ctx);
20736 switch (extract32(ctx->opcode, 10, 1)) {
20737 case 0:
20738 /* ADDU_QB */
20739 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20740 gen_store_gpr(v1_t, ret);
20741 break;
20742 case 1:
20743 /* ADDU_S_QB */
20744 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20745 gen_store_gpr(v1_t, ret);
20746 break;
20747 }
20748 break;
20749 case NM_ADDU_S_PH:
908f6be1 20750 check_dsp_r2(ctx);
3285a3e4
SM
20751 switch (extract32(ctx->opcode, 10, 1)) {
20752 case 0:
20753 /* ADDU_PH */
20754 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20755 gen_store_gpr(v1_t, ret);
20756 break;
20757 case 1:
20758 /* ADDU_S_PH */
20759 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20760 gen_store_gpr(v1_t, ret);
20761 break;
20762 }
20763 break;
20764 case NM_ADDUH_R_QB:
908f6be1 20765 check_dsp_r2(ctx);
3285a3e4
SM
20766 switch (extract32(ctx->opcode, 10, 1)) {
20767 case 0:
20768 /* ADDUH_QB */
20769 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20770 gen_store_gpr(v1_t, ret);
20771 break;
20772 case 1:
20773 /* ADDUH_R_QB */
20774 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20775 gen_store_gpr(v1_t, ret);
20776 break;
20777 }
20778 break;
20779 case NM_SHRAV_R_PH:
20780 check_dsp(ctx);
20781 switch (extract32(ctx->opcode, 10, 1)) {
20782 case 0:
20783 /* SHRAV_PH */
20784 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20785 gen_store_gpr(v1_t, ret);
20786 break;
20787 case 1:
20788 /* SHRAV_R_PH */
20789 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20790 gen_store_gpr(v1_t, ret);
20791 break;
20792 }
20793 break;
20794 case NM_SHRAV_R_QB:
908f6be1 20795 check_dsp_r2(ctx);
3285a3e4
SM
20796 switch (extract32(ctx->opcode, 10, 1)) {
20797 case 0:
20798 /* SHRAV_QB */
20799 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20800 gen_store_gpr(v1_t, ret);
20801 break;
20802 case 1:
20803 /* SHRAV_R_QB */
20804 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20805 gen_store_gpr(v1_t, ret);
20806 break;
20807 }
20808 break;
20809 case NM_SUBQ_S_PH:
20810 check_dsp(ctx);
20811 switch (extract32(ctx->opcode, 10, 1)) {
20812 case 0:
20813 /* SUBQ_PH */
20814 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20815 gen_store_gpr(v1_t, ret);
20816 break;
20817 case 1:
20818 /* SUBQ_S_PH */
20819 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20820 gen_store_gpr(v1_t, ret);
20821 break;
20822 }
20823 break;
20824 case NM_SUBQH_R_PH:
908f6be1 20825 check_dsp_r2(ctx);
3285a3e4
SM
20826 switch (extract32(ctx->opcode, 10, 1)) {
20827 case 0:
20828 /* SUBQH_PH */
20829 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20830 gen_store_gpr(v1_t, ret);
20831 break;
20832 case 1:
20833 /* SUBQH_R_PH */
20834 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20835 gen_store_gpr(v1_t, ret);
20836 break;
20837 }
20838 break;
20839 case NM_SUBQH_R_W:
908f6be1 20840 check_dsp_r2(ctx);
3285a3e4
SM
20841 switch (extract32(ctx->opcode, 10, 1)) {
20842 case 0:
20843 /* SUBQH_W */
20844 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20845 gen_store_gpr(v1_t, ret);
20846 break;
20847 case 1:
20848 /* SUBQH_R_W */
20849 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20850 gen_store_gpr(v1_t, ret);
20851 break;
20852 }
20853 break;
20854 case NM_SUBU_S_QB:
20855 check_dsp(ctx);
20856 switch (extract32(ctx->opcode, 10, 1)) {
20857 case 0:
20858 /* SUBU_QB */
20859 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20860 gen_store_gpr(v1_t, ret);
20861 break;
20862 case 1:
20863 /* SUBU_S_QB */
20864 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20865 gen_store_gpr(v1_t, ret);
20866 break;
20867 }
20868 break;
20869 case NM_SUBU_S_PH:
908f6be1 20870 check_dsp_r2(ctx);
3285a3e4
SM
20871 switch (extract32(ctx->opcode, 10, 1)) {
20872 case 0:
20873 /* SUBU_PH */
20874 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20875 gen_store_gpr(v1_t, ret);
20876 break;
20877 case 1:
20878 /* SUBU_S_PH */
20879 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20880 gen_store_gpr(v1_t, ret);
20881 break;
20882 }
20883 break;
20884 case NM_SUBUH_R_QB:
908f6be1 20885 check_dsp_r2(ctx);
3285a3e4
SM
20886 switch (extract32(ctx->opcode, 10, 1)) {
20887 case 0:
20888 /* SUBUH_QB */
20889 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20890 gen_store_gpr(v1_t, ret);
20891 break;
20892 case 1:
20893 /* SUBUH_R_QB */
20894 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20895 gen_store_gpr(v1_t, ret);
20896 break;
20897 }
20898 break;
20899 case NM_SHLLV_S_PH:
20900 check_dsp(ctx);
20901 switch (extract32(ctx->opcode, 10, 1)) {
20902 case 0:
20903 /* SHLLV_PH */
20904 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20905 gen_store_gpr(v1_t, ret);
20906 break;
20907 case 1:
20908 /* SHLLV_S_PH */
20909 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20910 gen_store_gpr(v1_t, ret);
20911 break;
20912 }
20913 break;
20914 case NM_PRECR_SRA_R_PH_W:
908f6be1 20915 check_dsp_r2(ctx);
3285a3e4
SM
20916 switch (extract32(ctx->opcode, 10, 1)) {
20917 case 0:
20918 /* PRECR_SRA_PH_W */
20919 {
20920 TCGv_i32 sa_t = tcg_const_i32(rd);
20921 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20922 cpu_gpr[rt]);
20923 gen_store_gpr(v1_t, rt);
20924 tcg_temp_free_i32(sa_t);
20925 }
20926 break;
20927 case 1:
20928 /* PRECR_SRA_R_PH_W */
20929 {
20930 TCGv_i32 sa_t = tcg_const_i32(rd);
20931 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20932 cpu_gpr[rt]);
20933 gen_store_gpr(v1_t, rt);
20934 tcg_temp_free_i32(sa_t);
20935 }
20936 break;
20937 }
20938 break;
20939 case NM_MULEU_S_PH_QBL:
20940 check_dsp(ctx);
20941 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20944 case NM_MULEU_S_PH_QBR:
20945 check_dsp(ctx);
20946 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20947 gen_store_gpr(v1_t, ret);
20948 break;
20949 case NM_MULQ_RS_PH:
20950 check_dsp(ctx);
20951 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20952 gen_store_gpr(v1_t, ret);
20953 break;
20954 case NM_MULQ_S_PH:
908f6be1 20955 check_dsp_r2(ctx);
3285a3e4
SM
20956 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20959 case NM_MULQ_RS_W:
908f6be1 20960 check_dsp_r2(ctx);
3285a3e4
SM
20961 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20962 gen_store_gpr(v1_t, ret);
20963 break;
20964 case NM_MULQ_S_W:
908f6be1 20965 check_dsp_r2(ctx);
3285a3e4
SM
20966 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20967 gen_store_gpr(v1_t, ret);
20968 break;
20969 case NM_APPEND:
908f6be1 20970 check_dsp_r2(ctx);
3285a3e4
SM
20971 gen_load_gpr(t0, rs);
20972 if (rd != 0) {
20973 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20974 }
20975 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20976 break;
20977 case NM_MODSUB:
20978 check_dsp(ctx);
20979 gen_helper_modsub(v1_t, v1_t, v2_t);
20980 gen_store_gpr(v1_t, ret);
20981 break;
20982 case NM_SHRAV_R_W:
20983 check_dsp(ctx);
20984 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20985 gen_store_gpr(v1_t, ret);
20986 break;
20987 case NM_SHRLV_PH:
908f6be1 20988 check_dsp_r2(ctx);
3285a3e4
SM
20989 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20990 gen_store_gpr(v1_t, ret);
20991 break;
20992 case NM_SHRLV_QB:
20993 check_dsp(ctx);
20994 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20995 gen_store_gpr(v1_t, ret);
20996 break;
20997 case NM_SHLLV_QB:
20998 check_dsp(ctx);
20999 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21000 gen_store_gpr(v1_t, ret);
21001 break;
21002 case NM_SHLLV_S_W:
21003 check_dsp(ctx);
21004 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21005 gen_store_gpr(v1_t, ret);
21006 break;
21007 case NM_SHILO:
21008 check_dsp(ctx);
21009 {
21010 TCGv tv0 = tcg_temp_new();
21011 TCGv tv1 = tcg_temp_new();
21012 int16_t imm = extract32(ctx->opcode, 16, 7);
21013
21014 tcg_gen_movi_tl(tv0, rd >> 3);
21015 tcg_gen_movi_tl(tv1, imm);
21016 gen_helper_shilo(tv0, tv1, cpu_env);
21017 }
21018 break;
21019 case NM_MULEQ_S_W_PHL:
21020 check_dsp(ctx);
21021 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21022 gen_store_gpr(v1_t, ret);
21023 break;
21024 case NM_MULEQ_S_W_PHR:
21025 check_dsp(ctx);
21026 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21027 gen_store_gpr(v1_t, ret);
21028 break;
21029 case NM_MUL_S_PH:
908f6be1 21030 check_dsp_r2(ctx);
3285a3e4
SM
21031 switch (extract32(ctx->opcode, 10, 1)) {
21032 case 0:
21033 /* MUL_PH */
21034 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21035 gen_store_gpr(v1_t, ret);
21036 break;
21037 case 1:
21038 /* MUL_S_PH */
21039 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21040 gen_store_gpr(v1_t, ret);
21041 break;
21042 }
21043 break;
21044 case NM_PRECR_QB_PH:
908f6be1 21045 check_dsp_r2(ctx);
3285a3e4
SM
21046 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21049 case NM_PRECRQ_QB_PH:
21050 check_dsp(ctx);
21051 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21052 gen_store_gpr(v1_t, ret);
21053 break;
21054 case NM_PRECRQ_PH_W:
21055 check_dsp(ctx);
21056 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21057 gen_store_gpr(v1_t, ret);
21058 break;
21059 case NM_PRECRQ_RS_PH_W:
21060 check_dsp(ctx);
21061 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21062 gen_store_gpr(v1_t, ret);
21063 break;
21064 case NM_PRECRQU_S_QB_PH:
21065 check_dsp(ctx);
21066 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21067 gen_store_gpr(v1_t, ret);
21068 break;
21069 case NM_SHRA_R_W:
21070 check_dsp(ctx);
21071 tcg_gen_movi_tl(t0, rd);
21072 gen_helper_shra_r_w(v1_t, t0, v1_t);
21073 gen_store_gpr(v1_t, rt);
21074 break;
21075 case NM_SHRA_R_PH:
21076 check_dsp(ctx);
21077 tcg_gen_movi_tl(t0, rd >> 1);
21078 switch (extract32(ctx->opcode, 10, 1)) {
21079 case 0:
21080 /* SHRA_PH */
21081 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 21082 gen_store_gpr(v1_t, rt);
d5ebcbaf 21083 break;
3285a3e4
SM
21084 case 1:
21085 /* SHRA_R_PH */
21086 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21087 gen_store_gpr(v1_t, rt);
21088 break;
21089 }
21090 break;
21091 case NM_SHLL_S_PH:
21092 check_dsp(ctx);
21093 tcg_gen_movi_tl(t0, rd >> 1);
21094 switch (extract32(ctx->opcode, 10, 2)) {
21095 case 0:
21096 /* SHLL_PH */
21097 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21098 gen_store_gpr(v1_t, rt);
21099 break;
21100 case 2:
21101 /* SHLL_S_PH */
21102 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21103 gen_store_gpr(v1_t, rt);
21104 break;
21105 default:
21106 generate_exception_end(ctx, EXCP_RI);
21107 break;
21108 }
21109 break;
21110 case NM_SHLL_S_W:
21111 check_dsp(ctx);
21112 tcg_gen_movi_tl(t0, rd);
21113 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21114 gen_store_gpr(v1_t, rt);
21115 break;
21116 case NM_REPL_PH:
21117 check_dsp(ctx);
21118 {
21119 int16_t imm;
21120 imm = sextract32(ctx->opcode, 11, 11);
21121 imm = (int16_t)(imm << 6) >> 6;
21122 if (rt != 0) {
21123 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21124 }
21125 }
21126 break;
21127 default:
21128 generate_exception_end(ctx, EXCP_RI);
21129 break;
21130 }
21131}
21132
c0280983
YK
21133static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21134{
21135 uint16_t insn;
21136 uint32_t op;
eac52664 21137 int rt, rs, rd;
c0280983
YK
21138 int offset;
21139 int imm;
21140
21141 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21142 ctx->opcode = (ctx->opcode << 16) | insn;
21143
21144 rt = extract32(ctx->opcode, 21, 5);
21145 rs = extract32(ctx->opcode, 16, 5);
eac52664 21146 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
21147
21148 op = extract32(ctx->opcode, 26, 6);
21149 switch (op) {
21150 case NM_P_ADDIU:
21151 if (rt == 0) {
21152 /* P.RI */
21153 switch (extract32(ctx->opcode, 19, 2)) {
21154 case NM_SIGRIE:
21155 default:
21156 generate_exception_end(ctx, EXCP_RI);
21157 break;
21158 case NM_P_SYSCALL:
21159 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21160 generate_exception_end(ctx, EXCP_SYSCALL);
21161 } else {
21162 generate_exception_end(ctx, EXCP_RI);
21163 }
21164 break;
21165 case NM_BREAK:
21166 generate_exception_end(ctx, EXCP_BREAK);
21167 break;
21168 case NM_SDBBP:
21169 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21170 gen_helper_do_semihosting(cpu_env);
21171 } else {
21172 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21173 generate_exception_end(ctx, EXCP_RI);
21174 } else {
21175 generate_exception_end(ctx, EXCP_DBp);
21176 }
21177 }
21178 break;
21179 }
21180 } else {
21181 /* NM_ADDIU */
21182 imm = extract32(ctx->opcode, 0, 16);
21183 if (rs != 0) {
21184 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21185 } else {
21186 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21187 }
21188 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21189 }
21190 break;
21191 case NM_ADDIUPC:
21192 if (rt != 0) {
21193 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21194 extract32(ctx->opcode, 1, 20) << 1;
21195 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21196 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21197 }
21198 break;
21199 case NM_POOL32A:
e0cf0e65
YK
21200 switch (ctx->opcode & 0x07) {
21201 case NM_POOL32A0:
0a1a6ed7 21202 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21203 break;
3285a3e4
SM
21204 case NM_POOL32A5:
21205 {
21206 int32_t op1 = extract32(ctx->opcode, 3, 7);
21207 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21208 }
21209 break;
e0cf0e65 21210 case NM_POOL32A7:
64224187 21211 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21212 case NM_P_LSX:
21213 gen_p_lsx(ctx, rd, rs, rt);
21214 break;
21215 case NM_LSA:
7480515f
AM
21216 /*
21217 * In nanoMIPS, the shift field directly encodes the shift
eac52664 21218 * amount, meaning that the supported shift values are in
7480515f
AM
21219 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21220 */
eac52664
YK
21221 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21222 extract32(ctx->opcode, 9, 2) - 1);
21223 break;
821f2008
JH
21224 case NM_EXTW:
21225 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21226 break;
64224187
YK
21227 case NM_POOL32AXF:
21228 gen_pool32axf_nanomips_insn(env, ctx);
21229 break;
21230 default:
21231 generate_exception_end(ctx, EXCP_RI);
21232 break;
21233 }
e0cf0e65
YK
21234 break;
21235 default:
21236 generate_exception_end(ctx, EXCP_RI);
21237 break;
21238 }
c0280983
YK
21239 break;
21240 case NM_P_GP_W:
21241 switch (ctx->opcode & 0x03) {
21242 case NM_ADDIUGP_W:
21243 if (rt != 0) {
21244 offset = extract32(ctx->opcode, 0, 21);
21245 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21246 }
21247 break;
21248 case NM_LWGP:
21249 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21250 break;
21251 case NM_SWGP:
21252 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21253 break;
21254 default:
21255 generate_exception_end(ctx, EXCP_RI);
21256 break;
21257 }
21258 break;
21259 case NM_P48I:
7ef009b2
YK
21260 {
21261 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21262 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21263 switch (extract32(ctx->opcode, 16, 5)) {
21264 case NM_LI48:
fb32f8c8 21265 check_nms(ctx);
7ef009b2
YK
21266 if (rt != 0) {
21267 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21268 }
21269 break;
21270 case NM_ADDIU48:
fb32f8c8 21271 check_nms(ctx);
7ef009b2
YK
21272 if (rt != 0) {
21273 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21274 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21275 }
21276 break;
21277 case NM_ADDIUGP48:
fb32f8c8 21278 check_nms(ctx);
7ef009b2
YK
21279 if (rt != 0) {
21280 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21281 }
21282 break;
21283 case NM_ADDIUPC48:
fb32f8c8 21284 check_nms(ctx);
7ef009b2
YK
21285 if (rt != 0) {
21286 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21287 addr_off);
21288
21289 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21290 }
21291 break;
21292 case NM_LWPC48:
fb32f8c8 21293 check_nms(ctx);
7ef009b2
YK
21294 if (rt != 0) {
21295 TCGv t0;
21296 t0 = tcg_temp_new();
21297
21298 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21299 addr_off);
21300
21301 tcg_gen_movi_tl(t0, addr);
21302 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21303 tcg_temp_free(t0);
21304 }
21305 break;
21306 case NM_SWPC48:
fb32f8c8 21307 check_nms(ctx);
7ef009b2
YK
21308 {
21309 TCGv t0, t1;
21310 t0 = tcg_temp_new();
21311 t1 = tcg_temp_new();
21312
21313 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21314 addr_off);
21315
21316 tcg_gen_movi_tl(t0, addr);
21317 gen_load_gpr(t1, rt);
21318
21319 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21320
21321 tcg_temp_free(t0);
21322 tcg_temp_free(t1);
21323 }
21324 break;
21325 default:
21326 generate_exception_end(ctx, EXCP_RI);
21327 break;
21328 }
21329 return 6;
21330 }
c0280983
YK
21331 case NM_P_U12:
21332 switch (extract32(ctx->opcode, 12, 4)) {
21333 case NM_ORI:
21334 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21335 break;
21336 case NM_XORI:
21337 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21338 break;
21339 case NM_ANDI:
21340 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21341 break;
21342 case NM_P_SR:
21343 switch (extract32(ctx->opcode, 20, 1)) {
21344 case NM_PP_SR:
21345 switch (ctx->opcode & 3) {
21346 case NM_SAVE:
21347 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21348 extract32(ctx->opcode, 2, 1),
21349 extract32(ctx->opcode, 3, 9) << 3);
21350 break;
21351 case NM_RESTORE:
21352 case NM_RESTORE_JRC:
21353 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21354 extract32(ctx->opcode, 2, 1),
21355 extract32(ctx->opcode, 3, 9) << 3);
21356 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21357 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21358 }
21359 break;
21360 default:
21361 generate_exception_end(ctx, EXCP_RI);
21362 break;
21363 }
21364 break;
21365 case NM_P_SR_F:
21366 generate_exception_end(ctx, EXCP_RI);
21367 break;
21368 }
21369 break;
21370 case NM_SLTI:
21371 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21372 break;
21373 case NM_SLTIU:
21374 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21375 break;
21376 case NM_SEQI:
21377 {
21378 TCGv t0 = tcg_temp_new();
21379
21380 imm = extract32(ctx->opcode, 0, 12);
21381 gen_load_gpr(t0, rs);
21382 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21383 gen_store_gpr(t0, rt);
21384
21385 tcg_temp_free(t0);
21386 }
21387 break;
21388 case NM_ADDIUNEG:
21389 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21390 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21391 break;
21392 case NM_P_SHIFT:
21393 {
21394 int shift = extract32(ctx->opcode, 0, 5);
21395 switch (extract32(ctx->opcode, 5, 4)) {
21396 case NM_P_SLL:
21397 if (rt == 0 && shift == 0) {
21398 /* NOP */
21399 } else if (rt == 0 && shift == 3) {
21400 /* EHB - treat as NOP */
21401 } else if (rt == 0 && shift == 5) {
21402 /* PAUSE - treat as NOP */
21403 } else if (rt == 0 && shift == 6) {
21404 /* SYNC */
21405 gen_sync(extract32(ctx->opcode, 16, 5));
21406 } else {
21407 /* SLL */
21408 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21409 extract32(ctx->opcode, 0, 5));
21410 }
21411 break;
21412 case NM_SRL:
21413 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21414 extract32(ctx->opcode, 0, 5));
21415 break;
21416 case NM_SRA:
21417 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21418 extract32(ctx->opcode, 0, 5));
21419 break;
21420 case NM_ROTR:
21421 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21422 extract32(ctx->opcode, 0, 5));
21423 break;
21424 }
21425 }
21426 break;
21427 case NM_P_ROTX:
fb32f8c8 21428 check_nms(ctx);
e222f506
MF
21429 if (rt != 0) {
21430 TCGv t0 = tcg_temp_new();
21431 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21432 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21433 << 1);
21434 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21435
21436 gen_load_gpr(t0, rs);
21437 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21438 tcg_temp_free(t0);
21439
21440 tcg_temp_free_i32(shift);
21441 tcg_temp_free_i32(shiftx);
21442 tcg_temp_free_i32(stripe);
21443 }
c0280983
YK
21444 break;
21445 case NM_P_INS:
21446 switch (((ctx->opcode >> 10) & 2) |
21447 (extract32(ctx->opcode, 5, 1))) {
21448 case NM_INS:
fb32f8c8 21449 check_nms(ctx);
c0280983
YK
21450 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21451 extract32(ctx->opcode, 6, 5));
21452 break;
21453 default:
21454 generate_exception_end(ctx, EXCP_RI);
21455 break;
21456 }
21457 break;
21458 case NM_P_EXT:
21459 switch (((ctx->opcode >> 10) & 2) |
21460 (extract32(ctx->opcode, 5, 1))) {
21461 case NM_EXT:
fb32f8c8 21462 check_nms(ctx);
c0280983
YK
21463 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21464 extract32(ctx->opcode, 6, 5));
21465 break;
21466 default:
21467 generate_exception_end(ctx, EXCP_RI);
21468 break;
21469 }
21470 break;
21471 default:
21472 generate_exception_end(ctx, EXCP_RI);
21473 break;
21474 }
21475 break;
21476 case NM_POOL32F:
579b8ea9 21477 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
21478 break;
21479 case NM_POOL32S:
21480 break;
21481 case NM_P_LUI:
21482 switch (extract32(ctx->opcode, 1, 1)) {
21483 case NM_LUI:
21484 if (rt != 0) {
21485 tcg_gen_movi_tl(cpu_gpr[rt],
21486 sextract32(ctx->opcode, 0, 1) << 31 |
21487 extract32(ctx->opcode, 2, 10) << 21 |
21488 extract32(ctx->opcode, 12, 9) << 12);
21489 }
21490 break;
21491 case NM_ALUIPC:
21492 if (rt != 0) {
21493 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21494 extract32(ctx->opcode, 2, 10) << 21 |
21495 extract32(ctx->opcode, 12, 9) << 12;
21496 target_long addr;
21497 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21498 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21499 }
21500 break;
21501 }
21502 break;
21503 case NM_P_GP_BH:
8f1d9b6d
YK
21504 {
21505 uint32_t u = extract32(ctx->opcode, 0, 18);
21506
21507 switch (extract32(ctx->opcode, 18, 3)) {
21508 case NM_LBGP:
21509 gen_ld(ctx, OPC_LB, rt, 28, u);
21510 break;
21511 case NM_SBGP:
21512 gen_st(ctx, OPC_SB, rt, 28, u);
21513 break;
21514 case NM_LBUGP:
21515 gen_ld(ctx, OPC_LBU, rt, 28, u);
21516 break;
21517 case NM_ADDIUGP_B:
21518 if (rt != 0) {
21519 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21520 }
21521 break;
21522 case NM_P_GP_LH:
21523 u &= ~1;
21524 switch (ctx->opcode & 1) {
21525 case NM_LHGP:
21526 gen_ld(ctx, OPC_LH, rt, 28, u);
21527 break;
21528 case NM_LHUGP:
21529 gen_ld(ctx, OPC_LHU, rt, 28, u);
21530 break;
21531 }
21532 break;
21533 case NM_P_GP_SH:
21534 u &= ~1;
21535 switch (ctx->opcode & 1) {
21536 case NM_SHGP:
21537 gen_st(ctx, OPC_SH, rt, 28, u);
21538 break;
21539 default:
21540 generate_exception_end(ctx, EXCP_RI);
21541 break;
21542 }
21543 break;
21544 case NM_P_GP_CP1:
21545 u &= ~0x3;
21546 switch (ctx->opcode & 0x3) {
21547 case NM_LWC1GP:
21548 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21549 break;
21550 case NM_LDC1GP:
21551 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21552 break;
21553 case NM_SWC1GP:
21554 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21555 break;
21556 case NM_SDC1GP:
21557 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21558 break;
21559 }
21560 break;
21561 default:
21562 generate_exception_end(ctx, EXCP_RI);
21563 break;
21564 }
21565 }
c0280983
YK
21566 break;
21567 case NM_P_LS_U12:
8f1d9b6d
YK
21568 {
21569 uint32_t u = extract32(ctx->opcode, 0, 12);
21570
21571 switch (extract32(ctx->opcode, 12, 4)) {
21572 case NM_P_PREFU12:
21573 if (rt == 31) {
21574 /* SYNCI */
7480515f
AM
21575 /*
21576 * Break the TB to be able to sync copied instructions
21577 * immediately.
21578 */
8f1d9b6d
YK
21579 ctx->base.is_jmp = DISAS_STOP;
21580 } else {
21581 /* PREF */
21582 /* Treat as NOP. */
21583 }
21584 break;
21585 case NM_LB:
21586 gen_ld(ctx, OPC_LB, rt, rs, u);
21587 break;
21588 case NM_LH:
21589 gen_ld(ctx, OPC_LH, rt, rs, u);
21590 break;
21591 case NM_LW:
21592 gen_ld(ctx, OPC_LW, rt, rs, u);
21593 break;
21594 case NM_LBU:
21595 gen_ld(ctx, OPC_LBU, rt, rs, u);
21596 break;
21597 case NM_LHU:
21598 gen_ld(ctx, OPC_LHU, rt, rs, u);
21599 break;
21600 case NM_SB:
21601 gen_st(ctx, OPC_SB, rt, rs, u);
21602 break;
21603 case NM_SH:
21604 gen_st(ctx, OPC_SH, rt, rs, u);
21605 break;
21606 case NM_SW:
21607 gen_st(ctx, OPC_SW, rt, rs, u);
21608 break;
21609 case NM_LWC1:
21610 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21611 break;
21612 case NM_LDC1:
21613 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21614 break;
21615 case NM_SWC1:
21616 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21617 break;
21618 case NM_SDC1:
21619 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21620 break;
21621 default:
21622 generate_exception_end(ctx, EXCP_RI);
21623 break;
21624 }
21625 }
c0280983
YK
21626 break;
21627 case NM_P_LS_S9:
8f1d9b6d
YK
21628 {
21629 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21630 extract32(ctx->opcode, 0, 8);
21631
21632 switch (extract32(ctx->opcode, 8, 3)) {
21633 case NM_P_LS_S0:
21634 switch (extract32(ctx->opcode, 11, 4)) {
21635 case NM_LBS9:
21636 gen_ld(ctx, OPC_LB, rt, rs, s);
21637 break;
21638 case NM_LHS9:
21639 gen_ld(ctx, OPC_LH, rt, rs, s);
21640 break;
21641 case NM_LWS9:
21642 gen_ld(ctx, OPC_LW, rt, rs, s);
21643 break;
21644 case NM_LBUS9:
21645 gen_ld(ctx, OPC_LBU, rt, rs, s);
21646 break;
21647 case NM_LHUS9:
21648 gen_ld(ctx, OPC_LHU, rt, rs, s);
21649 break;
21650 case NM_SBS9:
21651 gen_st(ctx, OPC_SB, rt, rs, s);
21652 break;
21653 case NM_SHS9:
21654 gen_st(ctx, OPC_SH, rt, rs, s);
21655 break;
21656 case NM_SWS9:
21657 gen_st(ctx, OPC_SW, rt, rs, s);
21658 break;
21659 case NM_LWC1S9:
21660 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21661 break;
21662 case NM_LDC1S9:
21663 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21664 break;
21665 case NM_SWC1S9:
21666 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21667 break;
21668 case NM_SDC1S9:
21669 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21670 break;
21671 case NM_P_PREFS9:
21672 if (rt == 31) {
21673 /* SYNCI */
7480515f
AM
21674 /*
21675 * Break the TB to be able to sync copied instructions
21676 * immediately.
21677 */
8f1d9b6d
YK
21678 ctx->base.is_jmp = DISAS_STOP;
21679 } else {
21680 /* PREF */
21681 /* Treat as NOP. */
21682 }
21683 break;
21684 default:
21685 generate_exception_end(ctx, EXCP_RI);
21686 break;
21687 }
21688 break;
21689 case NM_P_LS_S1:
21690 switch (extract32(ctx->opcode, 11, 4)) {
21691 case NM_UALH:
21692 case NM_UASH:
fb32f8c8 21693 check_nms(ctx);
8f1d9b6d
YK
21694 {
21695 TCGv t0 = tcg_temp_new();
21696 TCGv t1 = tcg_temp_new();
21697
21698 gen_base_offset_addr(ctx, t0, rs, s);
21699
21700 switch (extract32(ctx->opcode, 11, 4)) {
21701 case NM_UALH:
21702 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21703 MO_UNALN);
21704 gen_store_gpr(t0, rt);
21705 break;
21706 case NM_UASH:
21707 gen_load_gpr(t1, rt);
21708 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21709 MO_UNALN);
21710 break;
21711 }
21712 tcg_temp_free(t0);
21713 tcg_temp_free(t1);
21714 }
21715 break;
21716 case NM_P_LL:
21717 switch (ctx->opcode & 0x03) {
21718 case NM_LL:
21719 gen_ld(ctx, OPC_LL, rt, rs, s);
21720 break;
21721 case NM_LLWP:
0b16dcd1
AR
21722 check_xnp(ctx);
21723 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21724 break;
21725 }
21726 break;
21727 case NM_P_SC:
21728 switch (ctx->opcode & 0x03) {
21729 case NM_SC:
33a07fa2 21730 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
21731 break;
21732 case NM_SCWP:
0b16dcd1 21733 check_xnp(ctx);
8d5388c1
AM
21734 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21735 false);
8f1d9b6d
YK
21736 break;
21737 }
21738 break;
21739 case NM_CACHE:
21740 check_cp0_enabled(ctx);
21741 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21742 gen_cache_operation(ctx, rt, rs, s);
21743 }
21744 break;
21745 }
21746 break;
d046a9ea
DN
21747 case NM_P_LS_E0:
21748 switch (extract32(ctx->opcode, 11, 4)) {
21749 case NM_LBE:
21750 check_eva(ctx);
21751 check_cp0_enabled(ctx);
21752 gen_ld(ctx, OPC_LBE, rt, rs, s);
21753 break;
21754 case NM_SBE:
21755 check_eva(ctx);
21756 check_cp0_enabled(ctx);
21757 gen_st(ctx, OPC_SBE, rt, rs, s);
21758 break;
21759 case NM_LBUE:
21760 check_eva(ctx);
21761 check_cp0_enabled(ctx);
21762 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21763 break;
21764 case NM_P_PREFE:
21765 if (rt == 31) {
21766 /* case NM_SYNCIE */
21767 check_eva(ctx);
21768 check_cp0_enabled(ctx);
7480515f
AM
21769 /*
21770 * Break the TB to be able to sync copied instructions
21771 * immediately.
21772 */
d046a9ea
DN
21773 ctx->base.is_jmp = DISAS_STOP;
21774 } else {
21775 /* case NM_PREFE */
21776 check_eva(ctx);
21777 check_cp0_enabled(ctx);
21778 /* Treat as NOP. */
21779 }
21780 break;
21781 case NM_LHE:
21782 check_eva(ctx);
21783 check_cp0_enabled(ctx);
21784 gen_ld(ctx, OPC_LHE, rt, rs, s);
21785 break;
21786 case NM_SHE:
21787 check_eva(ctx);
21788 check_cp0_enabled(ctx);
21789 gen_st(ctx, OPC_SHE, rt, rs, s);
21790 break;
21791 case NM_LHUE:
21792 check_eva(ctx);
21793 check_cp0_enabled(ctx);
21794 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21795 break;
21796 case NM_CACHEE:
21797 check_nms_dl_il_sl_tl_l2c(ctx);
21798 gen_cache_operation(ctx, rt, rs, s);
21799 break;
21800 case NM_LWE:
21801 check_eva(ctx);
21802 check_cp0_enabled(ctx);
21803 gen_ld(ctx, OPC_LWE, rt, rs, s);
21804 break;
21805 case NM_SWE:
21806 check_eva(ctx);
21807 check_cp0_enabled(ctx);
21808 gen_st(ctx, OPC_SWE, rt, rs, s);
21809 break;
21810 case NM_P_LLE:
21811 switch (extract32(ctx->opcode, 2, 2)) {
21812 case NM_LLE:
21813 check_xnp(ctx);
21814 check_eva(ctx);
21815 check_cp0_enabled(ctx);
21816 gen_ld(ctx, OPC_LLE, rt, rs, s);
21817 break;
21818 case NM_LLWPE:
21819 check_xnp(ctx);
21820 check_eva(ctx);
21821 check_cp0_enabled(ctx);
21822 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21823 break;
d046a9ea
DN
21824 default:
21825 generate_exception_end(ctx, EXCP_RI);
21826 break;
21827 }
21828 break;
21829 case NM_P_SCE:
21830 switch (extract32(ctx->opcode, 2, 2)) {
21831 case NM_SCE:
21832 check_xnp(ctx);
21833 check_eva(ctx);
21834 check_cp0_enabled(ctx);
33a07fa2 21835 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
21836 break;
21837 case NM_SCWPE:
21838 check_xnp(ctx);
21839 check_eva(ctx);
21840 check_cp0_enabled(ctx);
8d5388c1
AM
21841 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21842 true);
2431a422 21843 break;
d046a9ea
DN
21844 default:
21845 generate_exception_end(ctx, EXCP_RI);
21846 break;
21847 }
21848 break;
21849 }
21850 break;
8f1d9b6d
YK
21851 case NM_P_LS_WM:
21852 case NM_P_LS_UAWM:
fb32f8c8 21853 check_nms(ctx);
8f1d9b6d
YK
21854 {
21855 int count = extract32(ctx->opcode, 12, 3);
21856 int counter = 0;
21857
21858 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21859 extract32(ctx->opcode, 0, 8);
21860 TCGv va = tcg_temp_new();
21861 TCGv t1 = tcg_temp_new();
14776ab5 21862 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
21863 NM_P_LS_UAWM ? MO_UNALN : 0;
21864
21865 count = (count == 0) ? 8 : count;
21866 while (counter != count) {
21867 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21868 int this_offset = offset + (counter << 2);
21869
21870 gen_base_offset_addr(ctx, va, rs, this_offset);
21871
21872 switch (extract32(ctx->opcode, 11, 1)) {
21873 case NM_LWM:
21874 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21875 memop | MO_TESL);
21876 gen_store_gpr(t1, this_rt);
21877 if ((this_rt == rs) &&
21878 (counter != (count - 1))) {
21879 /* UNPREDICTABLE */
21880 }
21881 break;
21882 case NM_SWM:
21883 this_rt = (rt == 0) ? 0 : this_rt;
21884 gen_load_gpr(t1, this_rt);
21885 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21886 memop | MO_TEUL);
21887 break;
21888 }
21889 counter++;
21890 }
21891 tcg_temp_free(va);
21892 tcg_temp_free(t1);
21893 }
21894 break;
21895 default:
21896 generate_exception_end(ctx, EXCP_RI);
21897 break;
21898 }
21899 }
c0280983
YK
21900 break;
21901 case NM_MOVE_BALC:
fb32f8c8 21902 check_nms(ctx);
11d0fc10
SM
21903 {
21904 TCGv t0 = tcg_temp_new();
21905 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21906 extract32(ctx->opcode, 1, 20) << 1;
21907 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21908 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21909 extract32(ctx->opcode, 21, 3));
21910 gen_load_gpr(t0, rt);
21911 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21912 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21913 tcg_temp_free(t0);
21914 }
c0280983
YK
21915 break;
21916 case NM_P_BAL:
11d0fc10
SM
21917 {
21918 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21919 extract32(ctx->opcode, 1, 24) << 1;
21920
21921 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21922 /* BC */
21923 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21924 } else {
21925 /* BALC */
21926 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21927 }
21928 }
c0280983
YK
21929 break;
21930 case NM_P_J:
11d0fc10
SM
21931 switch (extract32(ctx->opcode, 12, 4)) {
21932 case NM_JALRC:
21933 case NM_JALRC_HB:
21934 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21935 break;
21936 case NM_P_BALRSC:
21937 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21938 break;
21939 default:
21940 generate_exception_end(ctx, EXCP_RI);
21941 break;
21942 }
c0280983
YK
21943 break;
21944 case NM_P_BR1:
11d0fc10
SM
21945 {
21946 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21947 extract32(ctx->opcode, 1, 13) << 1;
21948 switch (extract32(ctx->opcode, 14, 2)) {
21949 case NM_BEQC:
fb32f8c8 21950 check_nms(ctx);
11d0fc10
SM
21951 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21952 break;
21953 case NM_P_BR3A:
21954 s = sextract32(ctx->opcode, 0, 1) << 14 |
21955 extract32(ctx->opcode, 1, 13) << 1;
21956 check_cp1_enabled(ctx);
21957 switch (extract32(ctx->opcode, 16, 5)) {
21958 case NM_BC1EQZC:
21959 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21960 break;
21961 case NM_BC1NEZC:
21962 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21963 break;
6d033ca7 21964 case NM_BPOSGE32C:
908f6be1 21965 check_dsp_r3(ctx);
6d033ca7
SM
21966 {
21967 int32_t imm = extract32(ctx->opcode, 1, 13) |
21968 extract32(ctx->opcode, 0, 1) << 13;
21969
21970 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21971 imm);
21972 }
21973 break;
11d0fc10
SM
21974 default:
21975 generate_exception_end(ctx, EXCP_RI);
21976 break;
21977 }
21978 break;
21979 case NM_BGEC:
21980 if (rs == rt) {
21981 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21982 } else {
21983 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21984 }
21985 break;
21986 case NM_BGEUC:
21987 if (rs == rt || rt == 0) {
21988 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21989 } else if (rs == 0) {
21990 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21991 } else {
21992 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21993 }
21994 break;
21995 }
21996 }
c0280983
YK
21997 break;
21998 case NM_P_BR2:
11d0fc10
SM
21999 {
22000 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22001 extract32(ctx->opcode, 1, 13) << 1;
22002 switch (extract32(ctx->opcode, 14, 2)) {
22003 case NM_BNEC:
fb32f8c8 22004 check_nms(ctx);
11d0fc10
SM
22005 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22006 break;
22007 case NM_BLTC:
22008 if (rs != 0 && rt != 0 && rs == rt) {
22009 /* NOP */
22010 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22011 } else {
22012 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22013 }
22014 break;
22015 case NM_BLTUC:
22016 if (rs == 0 || rs == rt) {
22017 /* NOP */
22018 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22019 } else {
22020 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22021 }
22022 break;
22023 default:
22024 generate_exception_end(ctx, EXCP_RI);
22025 break;
22026 }
22027 }
c0280983
YK
22028 break;
22029 case NM_P_BRI:
11d0fc10
SM
22030 {
22031 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22032 extract32(ctx->opcode, 1, 10) << 1;
22033 uint32_t u = extract32(ctx->opcode, 11, 7);
22034
22035 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22036 rt, u, s);
22037 }
c0280983
YK
22038 break;
22039 default:
22040 generate_exception_end(ctx, EXCP_RI);
22041 break;
22042 }
22043 return 4;
22044}
22045
c533c0f4
AM
22046static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22047{
ea4ca3c2 22048 uint32_t op;
99e49abf
AM
22049 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22050 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22051 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 22052 int offset;
ea4ca3c2
YK
22053 int imm;
22054
22055 /* make sure instructions are on a halfword boundary */
22056 if (ctx->base.pc_next & 0x1) {
22057 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22058 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22059 tcg_temp_free(tmp);
22060 generate_exception_end(ctx, EXCP_AdEL);
22061 return 2;
22062 }
22063
22064 op = extract32(ctx->opcode, 10, 6);
22065 switch (op) {
22066 case NM_P16_MV:
8869ad02
YK
22067 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22068 if (rt != 0) {
22069 /* MOVE */
22070 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22071 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22072 } else {
22073 /* P16.RI */
22074 switch (extract32(ctx->opcode, 3, 2)) {
22075 case NM_P16_SYSCALL:
22076 if (extract32(ctx->opcode, 2, 1) == 0) {
22077 generate_exception_end(ctx, EXCP_SYSCALL);
22078 } else {
22079 generate_exception_end(ctx, EXCP_RI);
22080 }
22081 break;
22082 case NM_BREAK16:
22083 generate_exception_end(ctx, EXCP_BREAK);
22084 break;
22085 case NM_SDBBP16:
22086 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22087 gen_helper_do_semihosting(cpu_env);
22088 } else {
22089 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22090 generate_exception_end(ctx, EXCP_RI);
22091 } else {
22092 generate_exception_end(ctx, EXCP_DBp);
22093 }
22094 }
22095 break;
22096 default:
22097 generate_exception_end(ctx, EXCP_RI);
22098 break;
22099 }
22100 }
ea4ca3c2
YK
22101 break;
22102 case NM_P16_SHIFT:
c46562fb
YK
22103 {
22104 int shift = extract32(ctx->opcode, 0, 3);
22105 uint32_t opc = 0;
22106 shift = (shift == 0) ? 8 : shift;
22107
22108 switch (extract32(ctx->opcode, 3, 1)) {
22109 case NM_SLL16:
22110 opc = OPC_SLL;
22111 break;
22112 case NM_SRL16:
22113 opc = OPC_SRL;
22114 break;
22115 }
22116 gen_shift_imm(ctx, opc, rt, rs, shift);
22117 }
ea4ca3c2
YK
22118 break;
22119 case NM_P16C:
8bdb7029
YK
22120 switch (ctx->opcode & 1) {
22121 case NM_POOL16C_0:
80845edf 22122 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
22123 break;
22124 case NM_LWXS16:
22125 gen_ldxs(ctx, rt, rs, rd);
22126 break;
22127 }
ea4ca3c2
YK
22128 break;
22129 case NM_P16_A1:
22130 switch (extract32(ctx->opcode, 6, 1)) {
22131 case NM_ADDIUR1SP:
22132 imm = extract32(ctx->opcode, 0, 6) << 2;
22133 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22134 break;
22135 default:
22136 generate_exception_end(ctx, EXCP_RI);
22137 break;
22138 }
22139 break;
22140 case NM_P16_A2:
22141 switch (extract32(ctx->opcode, 3, 1)) {
22142 case NM_ADDIUR2:
22143 imm = extract32(ctx->opcode, 0, 3) << 2;
22144 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22145 break;
22146 case NM_P_ADDIURS5:
22147 rt = extract32(ctx->opcode, 5, 5);
22148 if (rt != 0) {
22149 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22150 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22151 (extract32(ctx->opcode, 0, 3));
22152 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22153 }
22154 break;
22155 }
22156 break;
22157 case NM_P16_ADDU:
22158 switch (ctx->opcode & 0x1) {
22159 case NM_ADDU16:
22160 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22161 break;
22162 case NM_SUBU16:
22163 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22164 break;
22165 }
22166 break;
22167 case NM_P16_4X4:
22168 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22169 extract32(ctx->opcode, 5, 3);
22170 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22171 extract32(ctx->opcode, 0, 3);
22172 rt = decode_gpr_gpr4(rt);
22173 rs = decode_gpr_gpr4(rs);
22174 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22175 (extract32(ctx->opcode, 3, 1))) {
22176 case NM_ADDU4X4:
fb32f8c8 22177 check_nms(ctx);
ea4ca3c2
YK
22178 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22179 break;
22180 case NM_MUL4X4:
fb32f8c8 22181 check_nms(ctx);
ea4ca3c2
YK
22182 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22183 break;
22184 default:
22185 generate_exception_end(ctx, EXCP_RI);
22186 break;
22187 }
22188 break;
22189 case NM_LI16:
8869ad02
YK
22190 {
22191 int imm = extract32(ctx->opcode, 0, 7);
22192 imm = (imm == 0x7f ? -1 : imm);
22193 if (rt != 0) {
22194 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22195 }
22196 }
ea4ca3c2
YK
22197 break;
22198 case NM_ANDI16:
80845edf
YK
22199 {
22200 uint32_t u = extract32(ctx->opcode, 0, 4);
22201 u = (u == 12) ? 0xff :
22202 (u == 13) ? 0xffff : u;
22203 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22204 }
ea4ca3c2
YK
22205 break;
22206 case NM_P16_LB:
8bdb7029
YK
22207 offset = extract32(ctx->opcode, 0, 2);
22208 switch (extract32(ctx->opcode, 2, 2)) {
22209 case NM_LB16:
22210 gen_ld(ctx, OPC_LB, rt, rs, offset);
22211 break;
22212 case NM_SB16:
22213 rt = decode_gpr_gpr3_src_store(
99e49abf 22214 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22215 gen_st(ctx, OPC_SB, rt, rs, offset);
22216 break;
22217 case NM_LBU16:
22218 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22219 break;
22220 default:
22221 generate_exception_end(ctx, EXCP_RI);
22222 break;
22223 }
ea4ca3c2
YK
22224 break;
22225 case NM_P16_LH:
8bdb7029
YK
22226 offset = extract32(ctx->opcode, 1, 2) << 1;
22227 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22228 case NM_LH16:
22229 gen_ld(ctx, OPC_LH, rt, rs, offset);
22230 break;
22231 case NM_SH16:
22232 rt = decode_gpr_gpr3_src_store(
99e49abf 22233 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22234 gen_st(ctx, OPC_SH, rt, rs, offset);
22235 break;
22236 case NM_LHU16:
22237 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22238 break;
22239 default:
22240 generate_exception_end(ctx, EXCP_RI);
22241 break;
22242 }
ea4ca3c2
YK
22243 break;
22244 case NM_LW16:
8bdb7029
YK
22245 offset = extract32(ctx->opcode, 0, 4) << 2;
22246 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22247 break;
22248 case NM_LWSP16:
8bdb7029
YK
22249 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22250 offset = extract32(ctx->opcode, 0, 5) << 2;
22251 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22252 break;
22253 case NM_LW4X4:
fb32f8c8 22254 check_nms(ctx);
8bdb7029
YK
22255 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22256 extract32(ctx->opcode, 5, 3);
22257 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22258 extract32(ctx->opcode, 0, 3);
22259 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22260 (extract32(ctx->opcode, 8, 1) << 2);
22261 rt = decode_gpr_gpr4(rt);
22262 rs = decode_gpr_gpr4(rs);
22263 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22264 break;
22265 case NM_SW4X4:
fb32f8c8 22266 check_nms(ctx);
8bdb7029
YK
22267 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22268 extract32(ctx->opcode, 5, 3);
22269 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22270 extract32(ctx->opcode, 0, 3);
22271 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22272 (extract32(ctx->opcode, 8, 1) << 2);
22273 rt = decode_gpr_gpr4_zero(rt);
22274 rs = decode_gpr_gpr4(rs);
22275 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22276 break;
22277 case NM_LWGP16:
8bdb7029
YK
22278 offset = extract32(ctx->opcode, 0, 7) << 2;
22279 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22280 break;
22281 case NM_SWSP16:
8bdb7029
YK
22282 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22283 offset = extract32(ctx->opcode, 0, 5) << 2;
22284 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22285 break;
22286 case NM_SW16:
8bdb7029 22287 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
22288 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22289 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
22290 offset = extract32(ctx->opcode, 0, 4) << 2;
22291 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22292 break;
22293 case NM_SWGP16:
8bdb7029 22294 rt = decode_gpr_gpr3_src_store(
99e49abf 22295 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22296 offset = extract32(ctx->opcode, 0, 7) << 2;
22297 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22298 break;
22299 case NM_BC16:
764371d2
SM
22300 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22301 (sextract32(ctx->opcode, 0, 1) << 10) |
22302 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22303 break;
22304 case NM_BALC16:
764371d2
SM
22305 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22306 (sextract32(ctx->opcode, 0, 1) << 10) |
22307 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22308 break;
22309 case NM_BEQZC16:
764371d2
SM
22310 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22311 (sextract32(ctx->opcode, 0, 1) << 7) |
22312 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22313 break;
22314 case NM_BNEZC16:
764371d2
SM
22315 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22316 (sextract32(ctx->opcode, 0, 1) << 7) |
22317 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22318 break;
22319 case NM_P16_BR:
764371d2
SM
22320 switch (ctx->opcode & 0xf) {
22321 case 0:
22322 /* P16.JRC */
22323 switch (extract32(ctx->opcode, 4, 1)) {
22324 case NM_JRC:
22325 gen_compute_branch_nm(ctx, OPC_JR, 2,
22326 extract32(ctx->opcode, 5, 5), 0, 0);
22327 break;
22328 case NM_JALRC16:
22329 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22330 extract32(ctx->opcode, 5, 5), 31, 0);
22331 break;
22332 }
22333 break;
22334 default:
22335 {
22336 /* P16.BRI */
22337 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22338 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22339 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22340 extract32(ctx->opcode, 0, 4) << 1);
22341 }
22342 break;
22343 }
ea4ca3c2
YK
22344 break;
22345 case NM_P16_SR:
bf0718c5
SM
22346 {
22347 int count = extract32(ctx->opcode, 0, 4);
22348 int u = extract32(ctx->opcode, 4, 4) << 4;
22349
22350 rt = 30 + extract32(ctx->opcode, 9, 1);
22351 switch (extract32(ctx->opcode, 8, 1)) {
22352 case NM_SAVE16:
22353 gen_save(ctx, rt, count, 0, u);
22354 break;
22355 case NM_RESTORE_JRC16:
22356 gen_restore(ctx, rt, count, 0, u);
22357 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22358 break;
22359 }
22360 }
ea4ca3c2
YK
22361 break;
22362 case NM_MOVEP:
ea4ca3c2 22363 case NM_MOVEPREV:
fb32f8c8 22364 check_nms(ctx);
4d18232c
YK
22365 {
22366 static const int gpr2reg1[] = {4, 5, 6, 7};
22367 static const int gpr2reg2[] = {5, 6, 7, 8};
22368 int re;
22369 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22370 extract32(ctx->opcode, 8, 1);
22371 int r1 = gpr2reg1[rd2];
22372 int r2 = gpr2reg2[rd2];
22373 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22374 extract32(ctx->opcode, 0, 3);
22375 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22376 extract32(ctx->opcode, 5, 3);
22377 TCGv t0 = tcg_temp_new();
22378 TCGv t1 = tcg_temp_new();
22379 if (op == NM_MOVEP) {
22380 rd = r1;
22381 re = r2;
22382 rs = decode_gpr_gpr4_zero(r3);
22383 rt = decode_gpr_gpr4_zero(r4);
22384 } else {
22385 rd = decode_gpr_gpr4(r3);
22386 re = decode_gpr_gpr4(r4);
22387 rs = r1;
22388 rt = r2;
22389 }
22390 gen_load_gpr(t0, rs);
22391 gen_load_gpr(t1, rt);
22392 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22393 tcg_gen_mov_tl(cpu_gpr[re], t1);
22394 tcg_temp_free(t0);
22395 tcg_temp_free(t1);
22396 }
ea4ca3c2
YK
22397 break;
22398 default:
c0280983 22399 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
22400 }
22401
c533c0f4
AM
22402 return 2;
22403}
22404
22405
3c824109
NF
22406/* SmartMIPS extension to MIPS32 */
22407
22408#if defined(TARGET_MIPS64)
22409
22410/* MDMX extension to MIPS64 */
22411
22412#endif
22413
9b1a1d68 22414/* MIPSDSP functions. */
d75c135e 22415static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
22416 int rd, int base, int offset)
22417{
9b1a1d68
JL
22418 TCGv t0;
22419
9b1a1d68
JL
22420 check_dsp(ctx);
22421 t0 = tcg_temp_new();
22422
22423 if (base == 0) {
22424 gen_load_gpr(t0, offset);
22425 } else if (offset == 0) {
22426 gen_load_gpr(t0, base);
22427 } else {
22428 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22429 }
22430
9b1a1d68
JL
22431 switch (opc) {
22432 case OPC_LBUX:
5f68f5ae 22433 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 22434 gen_store_gpr(t0, rd);
9b1a1d68
JL
22435 break;
22436 case OPC_LHX:
5f68f5ae 22437 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 22438 gen_store_gpr(t0, rd);
9b1a1d68
JL
22439 break;
22440 case OPC_LWX:
5f68f5ae 22441 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 22442 gen_store_gpr(t0, rd);
9b1a1d68
JL
22443 break;
22444#if defined(TARGET_MIPS64)
22445 case OPC_LDX:
5f68f5ae 22446 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 22447 gen_store_gpr(t0, rd);
9b1a1d68
JL
22448 break;
22449#endif
22450 }
9b1a1d68
JL
22451 tcg_temp_free(t0);
22452}
22453
461c08df
JL
22454static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22455 int ret, int v1, int v2)
22456{
461c08df
JL
22457 TCGv v1_t;
22458 TCGv v2_t;
22459
22460 if (ret == 0) {
22461 /* Treat as NOP. */
461c08df
JL
22462 return;
22463 }
22464
22465 v1_t = tcg_temp_new();
22466 v2_t = tcg_temp_new();
22467
22468 gen_load_gpr(v1_t, v1);
22469 gen_load_gpr(v2_t, v2);
22470
22471 switch (op1) {
22472 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22473 case OPC_MULT_G_2E:
908f6be1 22474 check_dsp_r2(ctx);
461c08df
JL
22475 switch (op2) {
22476 case OPC_ADDUH_QB:
22477 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22478 break;
22479 case OPC_ADDUH_R_QB:
22480 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22481 break;
22482 case OPC_ADDQH_PH:
22483 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22484 break;
22485 case OPC_ADDQH_R_PH:
22486 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22487 break;
22488 case OPC_ADDQH_W:
22489 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22490 break;
22491 case OPC_ADDQH_R_W:
22492 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22493 break;
22494 case OPC_SUBUH_QB:
22495 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22496 break;
22497 case OPC_SUBUH_R_QB:
22498 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22499 break;
22500 case OPC_SUBQH_PH:
22501 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22502 break;
22503 case OPC_SUBQH_R_PH:
22504 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22505 break;
22506 case OPC_SUBQH_W:
22507 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22508 break;
22509 case OPC_SUBQH_R_W:
22510 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22511 break;
22512 }
22513 break;
22514 case OPC_ABSQ_S_PH_DSP:
22515 switch (op2) {
22516 case OPC_ABSQ_S_QB:
908f6be1 22517 check_dsp_r2(ctx);
461c08df
JL
22518 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22519 break;
22520 case OPC_ABSQ_S_PH:
22521 check_dsp(ctx);
22522 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22523 break;
22524 case OPC_ABSQ_S_W:
22525 check_dsp(ctx);
22526 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22527 break;
22528 case OPC_PRECEQ_W_PHL:
22529 check_dsp(ctx);
22530 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22531 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22532 break;
22533 case OPC_PRECEQ_W_PHR:
22534 check_dsp(ctx);
22535 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22536 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22537 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22538 break;
22539 case OPC_PRECEQU_PH_QBL:
22540 check_dsp(ctx);
22541 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22542 break;
22543 case OPC_PRECEQU_PH_QBR:
22544 check_dsp(ctx);
22545 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22546 break;
22547 case OPC_PRECEQU_PH_QBLA:
22548 check_dsp(ctx);
22549 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22550 break;
22551 case OPC_PRECEQU_PH_QBRA:
22552 check_dsp(ctx);
22553 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22554 break;
22555 case OPC_PRECEU_PH_QBL:
22556 check_dsp(ctx);
22557 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22558 break;
22559 case OPC_PRECEU_PH_QBR:
22560 check_dsp(ctx);
22561 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22562 break;
22563 case OPC_PRECEU_PH_QBLA:
22564 check_dsp(ctx);
22565 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22566 break;
22567 case OPC_PRECEU_PH_QBRA:
22568 check_dsp(ctx);
22569 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22570 break;
22571 }
22572 break;
22573 case OPC_ADDU_QB_DSP:
22574 switch (op2) {
22575 case OPC_ADDQ_PH:
22576 check_dsp(ctx);
22577 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22578 break;
22579 case OPC_ADDQ_S_PH:
22580 check_dsp(ctx);
22581 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22582 break;
22583 case OPC_ADDQ_S_W:
22584 check_dsp(ctx);
22585 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22586 break;
22587 case OPC_ADDU_QB:
22588 check_dsp(ctx);
22589 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22590 break;
22591 case OPC_ADDU_S_QB:
22592 check_dsp(ctx);
22593 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22594 break;
22595 case OPC_ADDU_PH:
908f6be1 22596 check_dsp_r2(ctx);
461c08df
JL
22597 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22598 break;
22599 case OPC_ADDU_S_PH:
908f6be1 22600 check_dsp_r2(ctx);
461c08df
JL
22601 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22602 break;
22603 case OPC_SUBQ_PH:
22604 check_dsp(ctx);
22605 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22606 break;
22607 case OPC_SUBQ_S_PH:
22608 check_dsp(ctx);
22609 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22610 break;
22611 case OPC_SUBQ_S_W:
22612 check_dsp(ctx);
22613 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22614 break;
22615 case OPC_SUBU_QB:
22616 check_dsp(ctx);
22617 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22618 break;
22619 case OPC_SUBU_S_QB:
22620 check_dsp(ctx);
22621 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22622 break;
22623 case OPC_SUBU_PH:
908f6be1 22624 check_dsp_r2(ctx);
461c08df
JL
22625 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22626 break;
22627 case OPC_SUBU_S_PH:
908f6be1 22628 check_dsp_r2(ctx);
461c08df
JL
22629 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22630 break;
22631 case OPC_ADDSC:
22632 check_dsp(ctx);
22633 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22634 break;
22635 case OPC_ADDWC:
22636 check_dsp(ctx);
22637 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22638 break;
22639 case OPC_MODSUB:
22640 check_dsp(ctx);
22641 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22642 break;
22643 case OPC_RADDU_W_QB:
22644 check_dsp(ctx);
22645 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22646 break;
22647 }
22648 break;
22649 case OPC_CMPU_EQ_QB_DSP:
22650 switch (op2) {
22651 case OPC_PRECR_QB_PH:
908f6be1 22652 check_dsp_r2(ctx);
461c08df
JL
22653 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22654 break;
22655 case OPC_PRECRQ_QB_PH:
22656 check_dsp(ctx);
22657 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22658 break;
22659 case OPC_PRECR_SRA_PH_W:
908f6be1 22660 check_dsp_r2(ctx);
461c08df
JL
22661 {
22662 TCGv_i32 sa_t = tcg_const_i32(v2);
22663 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22664 cpu_gpr[ret]);
22665 tcg_temp_free_i32(sa_t);
22666 break;
22667 }
22668 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22669 check_dsp_r2(ctx);
461c08df
JL
22670 {
22671 TCGv_i32 sa_t = tcg_const_i32(v2);
22672 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22673 cpu_gpr[ret]);
22674 tcg_temp_free_i32(sa_t);
22675 break;
22676 }
22677 case OPC_PRECRQ_PH_W:
22678 check_dsp(ctx);
22679 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22680 break;
22681 case OPC_PRECRQ_RS_PH_W:
22682 check_dsp(ctx);
22683 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22684 break;
22685 case OPC_PRECRQU_S_QB_PH:
22686 check_dsp(ctx);
22687 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22688 break;
22689 }
22690 break;
22691#ifdef TARGET_MIPS64
22692 case OPC_ABSQ_S_QH_DSP:
22693 switch (op2) {
22694 case OPC_PRECEQ_L_PWL:
22695 check_dsp(ctx);
22696 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22697 break;
22698 case OPC_PRECEQ_L_PWR:
22699 check_dsp(ctx);
22700 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22701 break;
22702 case OPC_PRECEQ_PW_QHL:
22703 check_dsp(ctx);
22704 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22705 break;
22706 case OPC_PRECEQ_PW_QHR:
22707 check_dsp(ctx);
22708 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22709 break;
22710 case OPC_PRECEQ_PW_QHLA:
22711 check_dsp(ctx);
22712 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22713 break;
22714 case OPC_PRECEQ_PW_QHRA:
22715 check_dsp(ctx);
22716 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22717 break;
22718 case OPC_PRECEQU_QH_OBL:
22719 check_dsp(ctx);
22720 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22721 break;
22722 case OPC_PRECEQU_QH_OBR:
22723 check_dsp(ctx);
22724 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22725 break;
22726 case OPC_PRECEQU_QH_OBLA:
22727 check_dsp(ctx);
22728 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22729 break;
22730 case OPC_PRECEQU_QH_OBRA:
22731 check_dsp(ctx);
22732 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22733 break;
22734 case OPC_PRECEU_QH_OBL:
22735 check_dsp(ctx);
22736 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22737 break;
22738 case OPC_PRECEU_QH_OBR:
22739 check_dsp(ctx);
22740 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22741 break;
22742 case OPC_PRECEU_QH_OBLA:
22743 check_dsp(ctx);
22744 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22745 break;
22746 case OPC_PRECEU_QH_OBRA:
22747 check_dsp(ctx);
22748 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22749 break;
22750 case OPC_ABSQ_S_OB:
908f6be1 22751 check_dsp_r2(ctx);
461c08df
JL
22752 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22753 break;
22754 case OPC_ABSQ_S_PW:
22755 check_dsp(ctx);
22756 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22757 break;
22758 case OPC_ABSQ_S_QH:
22759 check_dsp(ctx);
22760 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22761 break;
22762 }
22763 break;
22764 case OPC_ADDU_OB_DSP:
22765 switch (op2) {
22766 case OPC_RADDU_L_OB:
22767 check_dsp(ctx);
22768 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22769 break;
22770 case OPC_SUBQ_PW:
22771 check_dsp(ctx);
22772 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_SUBQ_S_PW:
22775 check_dsp(ctx);
22776 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_SUBQ_QH:
22779 check_dsp(ctx);
22780 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_SUBQ_S_QH:
22783 check_dsp(ctx);
22784 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_SUBU_OB:
22787 check_dsp(ctx);
22788 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_SUBU_S_OB:
22791 check_dsp(ctx);
22792 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_SUBU_QH:
908f6be1 22795 check_dsp_r2(ctx);
461c08df
JL
22796 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_SUBU_S_QH:
908f6be1 22799 check_dsp_r2(ctx);
461c08df
JL
22800 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_SUBUH_OB:
908f6be1 22803 check_dsp_r2(ctx);
461c08df
JL
22804 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22805 break;
22806 case OPC_SUBUH_R_OB:
908f6be1 22807 check_dsp_r2(ctx);
461c08df
JL
22808 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22809 break;
22810 case OPC_ADDQ_PW:
22811 check_dsp(ctx);
22812 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_ADDQ_S_PW:
22815 check_dsp(ctx);
22816 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22817 break;
22818 case OPC_ADDQ_QH:
22819 check_dsp(ctx);
22820 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22821 break;
22822 case OPC_ADDQ_S_QH:
22823 check_dsp(ctx);
22824 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22825 break;
22826 case OPC_ADDU_OB:
22827 check_dsp(ctx);
22828 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22829 break;
22830 case OPC_ADDU_S_OB:
22831 check_dsp(ctx);
22832 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22833 break;
22834 case OPC_ADDU_QH:
908f6be1 22835 check_dsp_r2(ctx);
461c08df
JL
22836 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22837 break;
22838 case OPC_ADDU_S_QH:
908f6be1 22839 check_dsp_r2(ctx);
461c08df
JL
22840 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22841 break;
22842 case OPC_ADDUH_OB:
908f6be1 22843 check_dsp_r2(ctx);
461c08df
JL
22844 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22845 break;
22846 case OPC_ADDUH_R_OB:
908f6be1 22847 check_dsp_r2(ctx);
461c08df
JL
22848 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22849 break;
22850 }
22851 break;
22852 case OPC_CMPU_EQ_OB_DSP:
22853 switch (op2) {
22854 case OPC_PRECR_OB_QH:
908f6be1 22855 check_dsp_r2(ctx);
461c08df
JL
22856 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22857 break;
22858 case OPC_PRECR_SRA_QH_PW:
908f6be1 22859 check_dsp_r2(ctx);
461c08df
JL
22860 {
22861 TCGv_i32 ret_t = tcg_const_i32(ret);
22862 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22863 tcg_temp_free_i32(ret_t);
22864 break;
22865 }
22866 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22867 check_dsp_r2(ctx);
461c08df
JL
22868 {
22869 TCGv_i32 sa_v = tcg_const_i32(ret);
22870 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22871 tcg_temp_free_i32(sa_v);
22872 break;
22873 }
22874 case OPC_PRECRQ_OB_QH:
22875 check_dsp(ctx);
22876 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22877 break;
22878 case OPC_PRECRQ_PW_L:
22879 check_dsp(ctx);
22880 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22881 break;
22882 case OPC_PRECRQ_QH_PW:
22883 check_dsp(ctx);
22884 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22885 break;
22886 case OPC_PRECRQ_RS_QH_PW:
22887 check_dsp(ctx);
22888 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22889 break;
22890 case OPC_PRECRQU_S_OB_QH:
22891 check_dsp(ctx);
22892 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22893 break;
22894 }
22895 break;
22896#endif
22897 }
22898
22899 tcg_temp_free(v1_t);
22900 tcg_temp_free(v2_t);
461c08df 22901}
9b1a1d68 22902
77c5fa8b
JL
22903static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22904 int ret, int v1, int v2)
22905{
22906 uint32_t op2;
77c5fa8b
JL
22907 TCGv t0;
22908 TCGv v1_t;
22909 TCGv v2_t;
22910
22911 if (ret == 0) {
22912 /* Treat as NOP. */
77c5fa8b
JL
22913 return;
22914 }
22915
22916 t0 = tcg_temp_new();
22917 v1_t = tcg_temp_new();
22918 v2_t = tcg_temp_new();
22919
22920 tcg_gen_movi_tl(t0, v1);
22921 gen_load_gpr(v1_t, v1);
22922 gen_load_gpr(v2_t, v2);
22923
22924 switch (opc) {
22925 case OPC_SHLL_QB_DSP:
22926 {
22927 op2 = MASK_SHLL_QB(ctx->opcode);
22928 switch (op2) {
22929 case OPC_SHLL_QB:
22930 check_dsp(ctx);
22931 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22932 break;
22933 case OPC_SHLLV_QB:
22934 check_dsp(ctx);
22935 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22936 break;
22937 case OPC_SHLL_PH:
22938 check_dsp(ctx);
22939 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22940 break;
22941 case OPC_SHLLV_PH:
22942 check_dsp(ctx);
22943 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22944 break;
22945 case OPC_SHLL_S_PH:
22946 check_dsp(ctx);
22947 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22948 break;
22949 case OPC_SHLLV_S_PH:
22950 check_dsp(ctx);
22951 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22952 break;
22953 case OPC_SHLL_S_W:
22954 check_dsp(ctx);
22955 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22956 break;
22957 case OPC_SHLLV_S_W:
22958 check_dsp(ctx);
22959 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22960 break;
22961 case OPC_SHRL_QB:
22962 check_dsp(ctx);
22963 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22964 break;
22965 case OPC_SHRLV_QB:
22966 check_dsp(ctx);
22967 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22968 break;
22969 case OPC_SHRL_PH:
908f6be1 22970 check_dsp_r2(ctx);
77c5fa8b
JL
22971 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22972 break;
22973 case OPC_SHRLV_PH:
908f6be1 22974 check_dsp_r2(ctx);
77c5fa8b
JL
22975 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22976 break;
22977 case OPC_SHRA_QB:
908f6be1 22978 check_dsp_r2(ctx);
77c5fa8b
JL
22979 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22980 break;
22981 case OPC_SHRA_R_QB:
908f6be1 22982 check_dsp_r2(ctx);
77c5fa8b
JL
22983 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22984 break;
22985 case OPC_SHRAV_QB:
908f6be1 22986 check_dsp_r2(ctx);
77c5fa8b
JL
22987 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22988 break;
22989 case OPC_SHRAV_R_QB:
908f6be1 22990 check_dsp_r2(ctx);
77c5fa8b
JL
22991 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22992 break;
22993 case OPC_SHRA_PH:
22994 check_dsp(ctx);
22995 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22996 break;
22997 case OPC_SHRA_R_PH:
22998 check_dsp(ctx);
22999 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23000 break;
23001 case OPC_SHRAV_PH:
23002 check_dsp(ctx);
23003 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23004 break;
23005 case OPC_SHRAV_R_PH:
23006 check_dsp(ctx);
23007 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23008 break;
23009 case OPC_SHRA_R_W:
23010 check_dsp(ctx);
23011 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23012 break;
23013 case OPC_SHRAV_R_W:
23014 check_dsp(ctx);
23015 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23016 break;
23017 default: /* Invalid */
23018 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 23019 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23020 break;
23021 }
23022 break;
23023 }
23024#ifdef TARGET_MIPS64
23025 case OPC_SHLL_OB_DSP:
23026 op2 = MASK_SHLL_OB(ctx->opcode);
23027 switch (op2) {
23028 case OPC_SHLL_PW:
23029 check_dsp(ctx);
23030 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23031 break;
23032 case OPC_SHLLV_PW:
23033 check_dsp(ctx);
23034 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23035 break;
23036 case OPC_SHLL_S_PW:
23037 check_dsp(ctx);
23038 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23039 break;
23040 case OPC_SHLLV_S_PW:
23041 check_dsp(ctx);
23042 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23043 break;
23044 case OPC_SHLL_OB:
23045 check_dsp(ctx);
23046 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23047 break;
23048 case OPC_SHLLV_OB:
23049 check_dsp(ctx);
23050 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23051 break;
23052 case OPC_SHLL_QH:
23053 check_dsp(ctx);
23054 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23055 break;
23056 case OPC_SHLLV_QH:
23057 check_dsp(ctx);
23058 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23059 break;
23060 case OPC_SHLL_S_QH:
23061 check_dsp(ctx);
23062 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23063 break;
23064 case OPC_SHLLV_S_QH:
23065 check_dsp(ctx);
23066 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23067 break;
23068 case OPC_SHRA_OB:
908f6be1 23069 check_dsp_r2(ctx);
77c5fa8b
JL
23070 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23071 break;
23072 case OPC_SHRAV_OB:
908f6be1 23073 check_dsp_r2(ctx);
77c5fa8b
JL
23074 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23075 break;
23076 case OPC_SHRA_R_OB:
908f6be1 23077 check_dsp_r2(ctx);
77c5fa8b
JL
23078 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23079 break;
23080 case OPC_SHRAV_R_OB:
908f6be1 23081 check_dsp_r2(ctx);
77c5fa8b
JL
23082 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23083 break;
23084 case OPC_SHRA_PW:
23085 check_dsp(ctx);
23086 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23087 break;
23088 case OPC_SHRAV_PW:
23089 check_dsp(ctx);
23090 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23091 break;
23092 case OPC_SHRA_R_PW:
23093 check_dsp(ctx);
23094 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23095 break;
23096 case OPC_SHRAV_R_PW:
23097 check_dsp(ctx);
23098 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23099 break;
23100 case OPC_SHRA_QH:
23101 check_dsp(ctx);
23102 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23103 break;
23104 case OPC_SHRAV_QH:
23105 check_dsp(ctx);
23106 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23107 break;
23108 case OPC_SHRA_R_QH:
23109 check_dsp(ctx);
23110 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23111 break;
23112 case OPC_SHRAV_R_QH:
23113 check_dsp(ctx);
23114 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23115 break;
23116 case OPC_SHRL_OB:
23117 check_dsp(ctx);
23118 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23119 break;
23120 case OPC_SHRLV_OB:
23121 check_dsp(ctx);
23122 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23123 break;
23124 case OPC_SHRL_QH:
908f6be1 23125 check_dsp_r2(ctx);
77c5fa8b
JL
23126 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23127 break;
23128 case OPC_SHRLV_QH:
908f6be1 23129 check_dsp_r2(ctx);
77c5fa8b
JL
23130 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23131 break;
23132 default: /* Invalid */
23133 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 23134 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23135 break;
23136 }
23137 break;
23138#endif
23139 }
23140
23141 tcg_temp_free(t0);
23142 tcg_temp_free(v1_t);
23143 tcg_temp_free(v2_t);
77c5fa8b
JL
23144}
23145
a22260ae
JL
23146static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23147 int ret, int v1, int v2, int check_ret)
23148{
a22260ae
JL
23149 TCGv_i32 t0;
23150 TCGv v1_t;
23151 TCGv v2_t;
23152
23153 if ((ret == 0) && (check_ret == 1)) {
23154 /* Treat as NOP. */
a22260ae
JL
23155 return;
23156 }
23157
23158 t0 = tcg_temp_new_i32();
23159 v1_t = tcg_temp_new();
23160 v2_t = tcg_temp_new();
23161
23162 tcg_gen_movi_i32(t0, ret);
23163 gen_load_gpr(v1_t, v1);
23164 gen_load_gpr(v2_t, v2);
23165
23166 switch (op1) {
7480515f
AM
23167 /*
23168 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23169 * the same mask and op1.
23170 */
a22260ae 23171 case OPC_MULT_G_2E:
908f6be1 23172 check_dsp_r2(ctx);
a22260ae
JL
23173 switch (op2) {
23174 case OPC_MUL_PH:
23175 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23176 break;
23177 case OPC_MUL_S_PH:
23178 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23179 break;
23180 case OPC_MULQ_S_W:
23181 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_MULQ_RS_W:
23184 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23185 break;
23186 }
23187 break;
23188 case OPC_DPA_W_PH_DSP:
23189 switch (op2) {
23190 case OPC_DPAU_H_QBL:
23191 check_dsp(ctx);
23192 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23193 break;
23194 case OPC_DPAU_H_QBR:
23195 check_dsp(ctx);
23196 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23197 break;
23198 case OPC_DPSU_H_QBL:
23199 check_dsp(ctx);
23200 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23201 break;
23202 case OPC_DPSU_H_QBR:
23203 check_dsp(ctx);
23204 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23205 break;
23206 case OPC_DPA_W_PH:
908f6be1 23207 check_dsp_r2(ctx);
a22260ae
JL
23208 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23209 break;
23210 case OPC_DPAX_W_PH:
908f6be1 23211 check_dsp_r2(ctx);
a22260ae
JL
23212 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23213 break;
23214 case OPC_DPAQ_S_W_PH:
23215 check_dsp(ctx);
23216 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23217 break;
23218 case OPC_DPAQX_S_W_PH:
908f6be1 23219 check_dsp_r2(ctx);
a22260ae
JL
23220 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23221 break;
23222 case OPC_DPAQX_SA_W_PH:
908f6be1 23223 check_dsp_r2(ctx);
a22260ae
JL
23224 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23225 break;
23226 case OPC_DPS_W_PH:
908f6be1 23227 check_dsp_r2(ctx);
a22260ae
JL
23228 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23229 break;
23230 case OPC_DPSX_W_PH:
908f6be1 23231 check_dsp_r2(ctx);
a22260ae
JL
23232 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23233 break;
23234 case OPC_DPSQ_S_W_PH:
23235 check_dsp(ctx);
23236 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23237 break;
23238 case OPC_DPSQX_S_W_PH:
908f6be1 23239 check_dsp_r2(ctx);
a22260ae
JL
23240 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23241 break;
23242 case OPC_DPSQX_SA_W_PH:
908f6be1 23243 check_dsp_r2(ctx);
a22260ae
JL
23244 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23245 break;
23246 case OPC_MULSAQ_S_W_PH:
23247 check_dsp(ctx);
23248 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23249 break;
23250 case OPC_DPAQ_SA_L_W:
23251 check_dsp(ctx);
23252 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23253 break;
23254 case OPC_DPSQ_SA_L_W:
23255 check_dsp(ctx);
23256 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23257 break;
23258 case OPC_MAQ_S_W_PHL:
23259 check_dsp(ctx);
23260 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23261 break;
23262 case OPC_MAQ_S_W_PHR:
23263 check_dsp(ctx);
23264 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23265 break;
23266 case OPC_MAQ_SA_W_PHL:
23267 check_dsp(ctx);
23268 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23269 break;
23270 case OPC_MAQ_SA_W_PHR:
23271 check_dsp(ctx);
23272 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23273 break;
23274 case OPC_MULSA_W_PH:
908f6be1 23275 check_dsp_r2(ctx);
a22260ae
JL
23276 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23277 break;
23278 }
23279 break;
23280#ifdef TARGET_MIPS64
23281 case OPC_DPAQ_W_QH_DSP:
23282 {
23283 int ac = ret & 0x03;
23284 tcg_gen_movi_i32(t0, ac);
23285
23286 switch (op2) {
23287 case OPC_DMADD:
23288 check_dsp(ctx);
23289 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23290 break;
23291 case OPC_DMADDU:
23292 check_dsp(ctx);
23293 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23294 break;
23295 case OPC_DMSUB:
23296 check_dsp(ctx);
23297 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23298 break;
23299 case OPC_DMSUBU:
23300 check_dsp(ctx);
23301 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23302 break;
23303 case OPC_DPA_W_QH:
908f6be1 23304 check_dsp_r2(ctx);
a22260ae
JL
23305 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23306 break;
23307 case OPC_DPAQ_S_W_QH:
23308 check_dsp(ctx);
23309 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23310 break;
23311 case OPC_DPAQ_SA_L_PW:
23312 check_dsp(ctx);
23313 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23314 break;
23315 case OPC_DPAU_H_OBL:
23316 check_dsp(ctx);
23317 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23318 break;
23319 case OPC_DPAU_H_OBR:
23320 check_dsp(ctx);
23321 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23322 break;
23323 case OPC_DPS_W_QH:
908f6be1 23324 check_dsp_r2(ctx);
a22260ae
JL
23325 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23326 break;
23327 case OPC_DPSQ_S_W_QH:
23328 check_dsp(ctx);
23329 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23330 break;
23331 case OPC_DPSQ_SA_L_PW:
23332 check_dsp(ctx);
23333 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23334 break;
23335 case OPC_DPSU_H_OBL:
23336 check_dsp(ctx);
23337 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23338 break;
23339 case OPC_DPSU_H_OBR:
23340 check_dsp(ctx);
23341 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23342 break;
23343 case OPC_MAQ_S_L_PWL:
23344 check_dsp(ctx);
23345 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23346 break;
23347 case OPC_MAQ_S_L_PWR:
23348 check_dsp(ctx);
23349 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23350 break;
23351 case OPC_MAQ_S_W_QHLL:
23352 check_dsp(ctx);
23353 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23354 break;
23355 case OPC_MAQ_SA_W_QHLL:
23356 check_dsp(ctx);
23357 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23358 break;
23359 case OPC_MAQ_S_W_QHLR:
23360 check_dsp(ctx);
23361 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23362 break;
23363 case OPC_MAQ_SA_W_QHLR:
23364 check_dsp(ctx);
23365 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23366 break;
23367 case OPC_MAQ_S_W_QHRL:
23368 check_dsp(ctx);
23369 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23370 break;
23371 case OPC_MAQ_SA_W_QHRL:
23372 check_dsp(ctx);
23373 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23374 break;
23375 case OPC_MAQ_S_W_QHRR:
23376 check_dsp(ctx);
23377 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23378 break;
23379 case OPC_MAQ_SA_W_QHRR:
23380 check_dsp(ctx);
23381 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23382 break;
23383 case OPC_MULSAQ_S_L_PW:
23384 check_dsp(ctx);
23385 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23386 break;
23387 case OPC_MULSAQ_S_W_QH:
23388 check_dsp(ctx);
23389 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23390 break;
23391 }
23392 }
23393 break;
23394#endif
23395 case OPC_ADDU_QB_DSP:
23396 switch (op2) {
23397 case OPC_MULEU_S_PH_QBL:
23398 check_dsp(ctx);
23399 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23400 break;
23401 case OPC_MULEU_S_PH_QBR:
23402 check_dsp(ctx);
23403 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23404 break;
23405 case OPC_MULQ_RS_PH:
23406 check_dsp(ctx);
23407 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_MULEQ_S_W_PHL:
23410 check_dsp(ctx);
23411 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_MULEQ_S_W_PHR:
23414 check_dsp(ctx);
23415 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_MULQ_S_PH:
908f6be1 23418 check_dsp_r2(ctx);
a22260ae
JL
23419 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23420 break;
23421 }
23422 break;
23423#ifdef TARGET_MIPS64
23424 case OPC_ADDU_OB_DSP:
23425 switch (op2) {
23426 case OPC_MULEQ_S_PW_QHL:
23427 check_dsp(ctx);
23428 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23429 break;
23430 case OPC_MULEQ_S_PW_QHR:
23431 check_dsp(ctx);
23432 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23433 break;
23434 case OPC_MULEU_S_QH_OBL:
23435 check_dsp(ctx);
23436 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23437 break;
23438 case OPC_MULEU_S_QH_OBR:
23439 check_dsp(ctx);
23440 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23441 break;
23442 case OPC_MULQ_RS_QH:
23443 check_dsp(ctx);
23444 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23445 break;
23446 }
23447 break;
23448#endif
23449 }
23450
23451 tcg_temp_free_i32(t0);
23452 tcg_temp_free(v1_t);
23453 tcg_temp_free(v2_t);
a22260ae
JL
23454}
23455
d75c135e 23456static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
23457 int ret, int val)
23458{
1cb6686c
JL
23459 int16_t imm;
23460 TCGv t0;
23461 TCGv val_t;
23462
23463 if (ret == 0) {
23464 /* Treat as NOP. */
1cb6686c
JL
23465 return;
23466 }
23467
23468 t0 = tcg_temp_new();
23469 val_t = tcg_temp_new();
23470 gen_load_gpr(val_t, val);
23471
23472 switch (op1) {
23473 case OPC_ABSQ_S_PH_DSP:
23474 switch (op2) {
23475 case OPC_BITREV:
23476 check_dsp(ctx);
23477 gen_helper_bitrev(cpu_gpr[ret], val_t);
23478 break;
23479 case OPC_REPL_QB:
23480 check_dsp(ctx);
23481 {
23482 target_long result;
23483 imm = (ctx->opcode >> 16) & 0xFF;
23484 result = (uint32_t)imm << 24 |
23485 (uint32_t)imm << 16 |
23486 (uint32_t)imm << 8 |
23487 (uint32_t)imm;
23488 result = (int32_t)result;
23489 tcg_gen_movi_tl(cpu_gpr[ret], result);
23490 }
23491 break;
23492 case OPC_REPLV_QB:
23493 check_dsp(ctx);
23494 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23495 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23496 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23497 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23498 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23499 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23500 break;
23501 case OPC_REPL_PH:
23502 check_dsp(ctx);
23503 {
23504 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23505 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23506 tcg_gen_movi_tl(cpu_gpr[ret], \
23507 (target_long)((int32_t)imm << 16 | \
c4aaba92 23508 (uint16_t)imm));
1cb6686c
JL
23509 }
23510 break;
23511 case OPC_REPLV_PH:
23512 check_dsp(ctx);
23513 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23514 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23515 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23516 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23517 break;
23518 }
23519 break;
23520#ifdef TARGET_MIPS64
23521 case OPC_ABSQ_S_QH_DSP:
23522 switch (op2) {
23523 case OPC_REPL_OB:
23524 check_dsp(ctx);
23525 {
23526 target_long temp;
23527
23528 imm = (ctx->opcode >> 16) & 0xFF;
23529 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23530 temp = (temp << 16) | temp;
23531 temp = (temp << 32) | temp;
23532 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23533 break;
23534 }
23535 case OPC_REPL_PW:
23536 check_dsp(ctx);
23537 {
23538 target_long temp;
23539
23540 imm = (ctx->opcode >> 16) & 0x03FF;
23541 imm = (int16_t)(imm << 6) >> 6;
23542 temp = ((target_long)imm << 32) \
23543 | ((target_long)imm & 0xFFFFFFFF);
23544 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23545 break;
23546 }
23547 case OPC_REPL_QH:
23548 check_dsp(ctx);
23549 {
23550 target_long temp;
23551
23552 imm = (ctx->opcode >> 16) & 0x03FF;
23553 imm = (int16_t)(imm << 6) >> 6;
23554
23555 temp = ((uint64_t)(uint16_t)imm << 48) |
23556 ((uint64_t)(uint16_t)imm << 32) |
23557 ((uint64_t)(uint16_t)imm << 16) |
23558 (uint64_t)(uint16_t)imm;
23559 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23560 break;
23561 }
23562 case OPC_REPLV_OB:
23563 check_dsp(ctx);
23564 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23565 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23566 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23567 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23568 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23569 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23570 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23571 break;
23572 case OPC_REPLV_PW:
23573 check_dsp(ctx);
23574 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23575 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23576 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23577 break;
23578 case OPC_REPLV_QH:
23579 check_dsp(ctx);
23580 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23581 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23582 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23583 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23584 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23585 break;
23586 }
23587 break;
23588#endif
23589 }
23590 tcg_temp_free(t0);
23591 tcg_temp_free(val_t);
1cb6686c
JL
23592}
23593
26690560
JL
23594static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23595 uint32_t op1, uint32_t op2,
23596 int ret, int v1, int v2, int check_ret)
23597{
26690560
JL
23598 TCGv t1;
23599 TCGv v1_t;
23600 TCGv v2_t;
23601
23602 if ((ret == 0) && (check_ret == 1)) {
23603 /* Treat as NOP. */
26690560
JL
23604 return;
23605 }
23606
26690560
JL
23607 t1 = tcg_temp_new();
23608 v1_t = tcg_temp_new();
23609 v2_t = tcg_temp_new();
23610
23611 gen_load_gpr(v1_t, v1);
23612 gen_load_gpr(v2_t, v2);
23613
23614 switch (op1) {
26690560
JL
23615 case OPC_CMPU_EQ_QB_DSP:
23616 switch (op2) {
23617 case OPC_CMPU_EQ_QB:
23618 check_dsp(ctx);
23619 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23620 break;
23621 case OPC_CMPU_LT_QB:
23622 check_dsp(ctx);
23623 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23624 break;
23625 case OPC_CMPU_LE_QB:
23626 check_dsp(ctx);
23627 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23628 break;
23629 case OPC_CMPGU_EQ_QB:
23630 check_dsp(ctx);
23631 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23632 break;
23633 case OPC_CMPGU_LT_QB:
23634 check_dsp(ctx);
23635 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23636 break;
23637 case OPC_CMPGU_LE_QB:
23638 check_dsp(ctx);
23639 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23640 break;
23641 case OPC_CMPGDU_EQ_QB:
908f6be1 23642 check_dsp_r2(ctx);
26690560
JL
23643 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23644 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23645 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23646 tcg_gen_shli_tl(t1, t1, 24);
23647 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23648 break;
23649 case OPC_CMPGDU_LT_QB:
908f6be1 23650 check_dsp_r2(ctx);
26690560
JL
23651 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23652 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23653 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23654 tcg_gen_shli_tl(t1, t1, 24);
23655 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23656 break;
23657 case OPC_CMPGDU_LE_QB:
908f6be1 23658 check_dsp_r2(ctx);
26690560
JL
23659 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23660 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23661 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23662 tcg_gen_shli_tl(t1, t1, 24);
23663 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23664 break;
23665 case OPC_CMP_EQ_PH:
23666 check_dsp(ctx);
23667 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23668 break;
23669 case OPC_CMP_LT_PH:
23670 check_dsp(ctx);
23671 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23672 break;
23673 case OPC_CMP_LE_PH:
23674 check_dsp(ctx);
23675 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23676 break;
23677 case OPC_PICK_QB:
23678 check_dsp(ctx);
23679 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23680 break;
23681 case OPC_PICK_PH:
23682 check_dsp(ctx);
23683 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23684 break;
23685 case OPC_PACKRL_PH:
23686 check_dsp(ctx);
23687 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23688 break;
23689 }
23690 break;
23691#ifdef TARGET_MIPS64
23692 case OPC_CMPU_EQ_OB_DSP:
23693 switch (op2) {
23694 case OPC_CMP_EQ_PW:
23695 check_dsp(ctx);
23696 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23697 break;
23698 case OPC_CMP_LT_PW:
23699 check_dsp(ctx);
23700 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23701 break;
23702 case OPC_CMP_LE_PW:
23703 check_dsp(ctx);
23704 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23705 break;
23706 case OPC_CMP_EQ_QH:
23707 check_dsp(ctx);
23708 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23709 break;
23710 case OPC_CMP_LT_QH:
23711 check_dsp(ctx);
23712 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23713 break;
23714 case OPC_CMP_LE_QH:
23715 check_dsp(ctx);
23716 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23717 break;
23718 case OPC_CMPGDU_EQ_OB:
908f6be1 23719 check_dsp_r2(ctx);
26690560
JL
23720 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23721 break;
23722 case OPC_CMPGDU_LT_OB:
908f6be1 23723 check_dsp_r2(ctx);
26690560
JL
23724 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23725 break;
23726 case OPC_CMPGDU_LE_OB:
908f6be1 23727 check_dsp_r2(ctx);
26690560
JL
23728 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23729 break;
23730 case OPC_CMPGU_EQ_OB:
23731 check_dsp(ctx);
23732 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23733 break;
23734 case OPC_CMPGU_LT_OB:
23735 check_dsp(ctx);
23736 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23737 break;
23738 case OPC_CMPGU_LE_OB:
23739 check_dsp(ctx);
23740 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23741 break;
23742 case OPC_CMPU_EQ_OB:
23743 check_dsp(ctx);
23744 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23745 break;
23746 case OPC_CMPU_LT_OB:
23747 check_dsp(ctx);
23748 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23749 break;
23750 case OPC_CMPU_LE_OB:
23751 check_dsp(ctx);
23752 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23753 break;
23754 case OPC_PACKRL_PW:
23755 check_dsp(ctx);
23756 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23757 break;
23758 case OPC_PICK_OB:
23759 check_dsp(ctx);
23760 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23761 break;
23762 case OPC_PICK_PW:
23763 check_dsp(ctx);
23764 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23765 break;
23766 case OPC_PICK_QH:
23767 check_dsp(ctx);
23768 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23769 break;
23770 }
23771 break;
df6126a7
AJ
23772#endif
23773 }
23774
23775 tcg_temp_free(t1);
23776 tcg_temp_free(v1_t);
23777 tcg_temp_free(v2_t);
df6126a7
AJ
23778}
23779
23780static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23781 uint32_t op1, int rt, int rs, int sa)
23782{
df6126a7
AJ
23783 TCGv t0;
23784
908f6be1 23785 check_dsp_r2(ctx);
df6126a7
AJ
23786
23787 if (rt == 0) {
23788 /* Treat as NOP. */
df6126a7
AJ
23789 return;
23790 }
23791
23792 t0 = tcg_temp_new();
23793 gen_load_gpr(t0, rs);
23794
23795 switch (op1) {
23796 case OPC_APPEND_DSP:
23797 switch (MASK_APPEND(ctx->opcode)) {
23798 case OPC_APPEND:
23799 if (sa != 0) {
23800 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23801 }
23802 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23803 break;
23804 case OPC_PREPEND:
23805 if (sa != 0) {
23806 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23807 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23808 tcg_gen_shli_tl(t0, t0, 32 - sa);
23809 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23810 }
23811 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23812 break;
23813 case OPC_BALIGN:
23814 sa &= 3;
23815 if (sa != 0 && sa != 2) {
23816 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23817 tcg_gen_ext32u_tl(t0, t0);
23818 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23819 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23820 }
23821 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23822 break;
23823 default: /* Invalid */
23824 MIPS_INVAL("MASK APPEND");
9c708c7f 23825 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
23826 break;
23827 }
23828 break;
23829#ifdef TARGET_MIPS64
26690560 23830 case OPC_DAPPEND_DSP:
df6126a7 23831 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23832 case OPC_DAPPEND:
df6126a7
AJ
23833 if (sa != 0) {
23834 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23835 }
26690560
JL
23836 break;
23837 case OPC_PREPENDD:
df6126a7
AJ
23838 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23839 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23840 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23841 break;
23842 case OPC_PREPENDW:
df6126a7
AJ
23843 if (sa != 0) {
23844 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23845 tcg_gen_shli_tl(t0, t0, 64 - sa);
23846 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23847 }
26690560
JL
23848 break;
23849 case OPC_DBALIGN:
df6126a7
AJ
23850 sa &= 7;
23851 if (sa != 0 && sa != 2 && sa != 4) {
23852 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23853 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23854 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23855 }
26690560
JL
23856 break;
23857 default: /* Invalid */
23858 MIPS_INVAL("MASK DAPPEND");
9c708c7f 23859 generate_exception_end(ctx, EXCP_RI);
26690560
JL
23860 break;
23861 }
23862 break;
23863#endif
23864 }
df6126a7 23865 tcg_temp_free(t0);
26690560
JL
23866}
23867
b53371ed
JL
23868static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23869 int ret, int v1, int v2, int check_ret)
23870
23871{
b53371ed
JL
23872 TCGv t0;
23873 TCGv t1;
23874 TCGv v1_t;
23875 TCGv v2_t;
23876 int16_t imm;
23877
23878 if ((ret == 0) && (check_ret == 1)) {
23879 /* Treat as NOP. */
b53371ed
JL
23880 return;
23881 }
23882
23883 t0 = tcg_temp_new();
23884 t1 = tcg_temp_new();
23885 v1_t = tcg_temp_new();
23886 v2_t = tcg_temp_new();
23887
23888 gen_load_gpr(v1_t, v1);
23889 gen_load_gpr(v2_t, v2);
23890
23891 switch (op1) {
23892 case OPC_EXTR_W_DSP:
23893 check_dsp(ctx);
23894 switch (op2) {
23895 case OPC_EXTR_W:
23896 tcg_gen_movi_tl(t0, v2);
23897 tcg_gen_movi_tl(t1, v1);
23898 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23899 break;
23900 case OPC_EXTR_R_W:
23901 tcg_gen_movi_tl(t0, v2);
23902 tcg_gen_movi_tl(t1, v1);
23903 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23904 break;
23905 case OPC_EXTR_RS_W:
23906 tcg_gen_movi_tl(t0, v2);
23907 tcg_gen_movi_tl(t1, v1);
23908 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23909 break;
23910 case OPC_EXTR_S_H:
23911 tcg_gen_movi_tl(t0, v2);
23912 tcg_gen_movi_tl(t1, v1);
23913 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23914 break;
23915 case OPC_EXTRV_S_H:
23916 tcg_gen_movi_tl(t0, v2);
23917 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23918 break;
23919 case OPC_EXTRV_W:
23920 tcg_gen_movi_tl(t0, v2);
23921 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23922 break;
23923 case OPC_EXTRV_R_W:
23924 tcg_gen_movi_tl(t0, v2);
23925 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23926 break;
23927 case OPC_EXTRV_RS_W:
23928 tcg_gen_movi_tl(t0, v2);
23929 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23930 break;
23931 case OPC_EXTP:
23932 tcg_gen_movi_tl(t0, v2);
23933 tcg_gen_movi_tl(t1, v1);
23934 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23935 break;
23936 case OPC_EXTPV:
23937 tcg_gen_movi_tl(t0, v2);
23938 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23939 break;
23940 case OPC_EXTPDP:
23941 tcg_gen_movi_tl(t0, v2);
23942 tcg_gen_movi_tl(t1, v1);
23943 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23944 break;
23945 case OPC_EXTPDPV:
23946 tcg_gen_movi_tl(t0, v2);
23947 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23948 break;
23949 case OPC_SHILO:
23950 imm = (ctx->opcode >> 20) & 0x3F;
23951 tcg_gen_movi_tl(t0, ret);
23952 tcg_gen_movi_tl(t1, imm);
23953 gen_helper_shilo(t0, t1, cpu_env);
23954 break;
23955 case OPC_SHILOV:
23956 tcg_gen_movi_tl(t0, ret);
23957 gen_helper_shilo(t0, v1_t, cpu_env);
23958 break;
23959 case OPC_MTHLIP:
23960 tcg_gen_movi_tl(t0, ret);
23961 gen_helper_mthlip(t0, v1_t, cpu_env);
23962 break;
23963 case OPC_WRDSP:
23964 imm = (ctx->opcode >> 11) & 0x3FF;
23965 tcg_gen_movi_tl(t0, imm);
23966 gen_helper_wrdsp(v1_t, t0, cpu_env);
23967 break;
23968 case OPC_RDDSP:
23969 imm = (ctx->opcode >> 16) & 0x03FF;
23970 tcg_gen_movi_tl(t0, imm);
23971 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23972 break;
23973 }
23974 break;
23975#ifdef TARGET_MIPS64
23976 case OPC_DEXTR_W_DSP:
23977 check_dsp(ctx);
23978 switch (op2) {
23979 case OPC_DMTHLIP:
23980 tcg_gen_movi_tl(t0, ret);
23981 gen_helper_dmthlip(v1_t, t0, cpu_env);
23982 break;
23983 case OPC_DSHILO:
23984 {
23985 int shift = (ctx->opcode >> 19) & 0x7F;
23986 int ac = (ctx->opcode >> 11) & 0x03;
23987 tcg_gen_movi_tl(t0, shift);
23988 tcg_gen_movi_tl(t1, ac);
23989 gen_helper_dshilo(t0, t1, cpu_env);
23990 break;
23991 }
23992 case OPC_DSHILOV:
23993 {
23994 int ac = (ctx->opcode >> 11) & 0x03;
23995 tcg_gen_movi_tl(t0, ac);
23996 gen_helper_dshilo(v1_t, t0, cpu_env);
23997 break;
23998 }
23999 case OPC_DEXTP:
24000 tcg_gen_movi_tl(t0, v2);
24001 tcg_gen_movi_tl(t1, v1);
24002
24003 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24004 break;
24005 case OPC_DEXTPV:
24006 tcg_gen_movi_tl(t0, v2);
24007 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24008 break;
24009 case OPC_DEXTPDP:
24010 tcg_gen_movi_tl(t0, v2);
24011 tcg_gen_movi_tl(t1, v1);
24012 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24013 break;
24014 case OPC_DEXTPDPV:
24015 tcg_gen_movi_tl(t0, v2);
24016 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24017 break;
24018 case OPC_DEXTR_L:
24019 tcg_gen_movi_tl(t0, v2);
24020 tcg_gen_movi_tl(t1, v1);
24021 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24022 break;
24023 case OPC_DEXTR_R_L:
24024 tcg_gen_movi_tl(t0, v2);
24025 tcg_gen_movi_tl(t1, v1);
24026 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24027 break;
24028 case OPC_DEXTR_RS_L:
24029 tcg_gen_movi_tl(t0, v2);
24030 tcg_gen_movi_tl(t1, v1);
24031 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24032 break;
24033 case OPC_DEXTR_W:
24034 tcg_gen_movi_tl(t0, v2);
24035 tcg_gen_movi_tl(t1, v1);
24036 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24037 break;
24038 case OPC_DEXTR_R_W:
24039 tcg_gen_movi_tl(t0, v2);
24040 tcg_gen_movi_tl(t1, v1);
24041 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24042 break;
24043 case OPC_DEXTR_RS_W:
24044 tcg_gen_movi_tl(t0, v2);
24045 tcg_gen_movi_tl(t1, v1);
24046 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24047 break;
24048 case OPC_DEXTR_S_H:
24049 tcg_gen_movi_tl(t0, v2);
24050 tcg_gen_movi_tl(t1, v1);
24051 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24052 break;
24053 case OPC_DEXTRV_S_H:
24054 tcg_gen_movi_tl(t0, v2);
24055 tcg_gen_movi_tl(t1, v1);
24056 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24057 break;
24058 case OPC_DEXTRV_L:
24059 tcg_gen_movi_tl(t0, v2);
24060 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24061 break;
24062 case OPC_DEXTRV_R_L:
24063 tcg_gen_movi_tl(t0, v2);
24064 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24065 break;
24066 case OPC_DEXTRV_RS_L:
24067 tcg_gen_movi_tl(t0, v2);
24068 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24069 break;
24070 case OPC_DEXTRV_W:
24071 tcg_gen_movi_tl(t0, v2);
24072 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24073 break;
24074 case OPC_DEXTRV_R_W:
24075 tcg_gen_movi_tl(t0, v2);
24076 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24077 break;
24078 case OPC_DEXTRV_RS_W:
24079 tcg_gen_movi_tl(t0, v2);
24080 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24081 break;
24082 }
24083 break;
24084#endif
24085 }
24086
24087 tcg_temp_free(t0);
24088 tcg_temp_free(t1);
24089 tcg_temp_free(v1_t);
24090 tcg_temp_free(v2_t);
b53371ed
JL
24091}
24092
9b1a1d68
JL
24093/* End MIPSDSP functions. */
24094
10dc65db
LA
24095static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24096{
4267d3e6 24097 int rs, rt, rd, sa;
b42ee5e1 24098 uint32_t op1, op2;
10dc65db
LA
24099
24100 rs = (ctx->opcode >> 21) & 0x1f;
24101 rt = (ctx->opcode >> 16) & 0x1f;
24102 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 24103 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24104
24105 op1 = MASK_SPECIAL(ctx->opcode);
24106 switch (op1) {
d4ea6acd 24107 case OPC_LSA:
1f1b4c00 24108 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24109 break;
c2e19f3c
AM
24110 case OPC_MULT:
24111 case OPC_MULTU:
24112 case OPC_DIV:
24113 case OPC_DIVU:
b42ee5e1
LA
24114 op2 = MASK_R6_MULDIV(ctx->opcode);
24115 switch (op2) {
24116 case R6_OPC_MUL:
24117 case R6_OPC_MUH:
24118 case R6_OPC_MULU:
24119 case R6_OPC_MUHU:
24120 case R6_OPC_DIV:
24121 case R6_OPC_MOD:
24122 case R6_OPC_DIVU:
24123 case R6_OPC_MODU:
24124 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24125 break;
24126 default:
24127 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24128 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24129 break;
24130 }
24131 break;
10dc65db
LA
24132 case OPC_SELEQZ:
24133 case OPC_SELNEZ:
24134 gen_cond_move(ctx, op1, rd, rs, rt);
24135 break;
4267d3e6
LA
24136 case R6_OPC_CLO:
24137 case R6_OPC_CLZ:
24138 if (rt == 0 && sa == 1) {
7480515f
AM
24139 /*
24140 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24141 * We need additionally to check other fields.
24142 */
4267d3e6
LA
24143 gen_cl(ctx, op1, rd, rs);
24144 } else {
9c708c7f 24145 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24146 }
24147 break;
24148 case R6_OPC_SDBBP:
3b3c1694
LA
24149 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24150 gen_helper_do_semihosting(cpu_env);
faf1f68b 24151 } else {
3b3c1694 24152 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 24153 generate_exception_end(ctx, EXCP_RI);
3b3c1694 24154 } else {
9c708c7f 24155 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24156 }
faf1f68b 24157 }
4267d3e6 24158 break;
b42ee5e1 24159#if defined(TARGET_MIPS64)
d4ea6acd
LA
24160 case OPC_DLSA:
24161 check_mips_64(ctx);
1f1b4c00 24162 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24163 break;
4267d3e6
LA
24164 case R6_OPC_DCLO:
24165 case R6_OPC_DCLZ:
24166 if (rt == 0 && sa == 1) {
7480515f
AM
24167 /*
24168 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24169 * We need additionally to check other fields.
24170 */
4267d3e6
LA
24171 check_mips_64(ctx);
24172 gen_cl(ctx, op1, rd, rs);
24173 } else {
9c708c7f 24174 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24175 }
24176 break;
c2e19f3c
AM
24177 case OPC_DMULT:
24178 case OPC_DMULTU:
24179 case OPC_DDIV:
24180 case OPC_DDIVU:
24181
b42ee5e1
LA
24182 op2 = MASK_R6_MULDIV(ctx->opcode);
24183 switch (op2) {
24184 case R6_OPC_DMUL:
24185 case R6_OPC_DMUH:
24186 case R6_OPC_DMULU:
24187 case R6_OPC_DMUHU:
24188 case R6_OPC_DDIV:
24189 case R6_OPC_DMOD:
24190 case R6_OPC_DDIVU:
24191 case R6_OPC_DMODU:
24192 check_mips_64(ctx);
24193 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24194 break;
24195 default:
24196 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24197 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24198 break;
24199 }
24200 break;
24201#endif
10dc65db
LA
24202 default: /* Invalid */
24203 MIPS_INVAL("special_r6");
9c708c7f 24204 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24205 break;
24206 }
24207}
24208
9dc324ce
FN
24209static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24210{
24211 int rs = extract32(ctx->opcode, 21, 5);
24212 int rt = extract32(ctx->opcode, 16, 5);
24213 int rd = extract32(ctx->opcode, 11, 5);
24214 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24215
24216 switch (op1) {
24217 case OPC_MOVN: /* Conditional move */
24218 case OPC_MOVZ:
24219 gen_cond_move(ctx, op1, rd, rs, rt);
24220 break;
24221 case OPC_MFHI: /* Move from HI/LO */
24222 case OPC_MFLO:
24223 gen_HILO(ctx, op1, 0, rd);
24224 break;
24225 case OPC_MTHI:
24226 case OPC_MTLO: /* Move to HI/LO */
24227 gen_HILO(ctx, op1, 0, rs);
24228 break;
24229 case OPC_MULT:
24230 case OPC_MULTU:
24231 gen_mul_txx9(ctx, op1, rd, rs, rt);
24232 break;
24233 case OPC_DIV:
24234 case OPC_DIVU:
24235 gen_muldiv(ctx, op1, 0, rs, rt);
24236 break;
24237#if defined(TARGET_MIPS64)
24238 case OPC_DMULT:
24239 case OPC_DMULTU:
24240 case OPC_DDIV:
24241 case OPC_DDIVU:
24242 check_insn_opc_user_only(ctx, INSN_R5900);
24243 gen_muldiv(ctx, op1, 0, rs, rt);
24244 break;
24245#endif
24246 case OPC_JR:
24247 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24248 break;
24249 default: /* Invalid */
24250 MIPS_INVAL("special_tx79");
24251 generate_exception_end(ctx, EXCP_RI);
24252 break;
24253 }
24254}
24255
10dc65db
LA
24256static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24257{
b42ee5e1 24258 int rs, rt, rd, sa;
10dc65db
LA
24259 uint32_t op1;
24260
24261 rs = (ctx->opcode >> 21) & 0x1f;
24262 rt = (ctx->opcode >> 16) & 0x1f;
24263 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24264 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24265
24266 op1 = MASK_SPECIAL(ctx->opcode);
24267 switch (op1) {
24268 case OPC_MOVN: /* Conditional move */
24269 case OPC_MOVZ:
24270 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
9dc324ce 24271 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24272 gen_cond_move(ctx, op1, rd, rs, rt);
24273 break;
24274 case OPC_MFHI: /* Move from HI/LO */
24275 case OPC_MFLO:
24276 gen_HILO(ctx, op1, rs & 3, rd);
24277 break;
24278 case OPC_MTHI:
24279 case OPC_MTLO: /* Move to HI/LO */
24280 gen_HILO(ctx, op1, rd & 3, rs);
24281 break;
24282 case OPC_MOVCI:
24283 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24284 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24285 check_cp1_enabled(ctx);
24286 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24287 (ctx->opcode >> 16) & 1);
24288 } else {
24289 generate_exception_err(ctx, EXCP_CpU, 1);
24290 }
24291 break;
b42ee5e1
LA
24292 case OPC_MULT:
24293 case OPC_MULTU:
24294 if (sa) {
24295 check_insn(ctx, INSN_VR54XX);
24296 op1 = MASK_MUL_VR54XX(ctx->opcode);
24297 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24298 } else {
24299 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24300 }
24301 break;
24302 case OPC_DIV:
24303 case OPC_DIVU:
24304 gen_muldiv(ctx, op1, 0, rs, rt);
24305 break;
24306#if defined(TARGET_MIPS64)
c2e19f3c
AM
24307 case OPC_DMULT:
24308 case OPC_DMULTU:
24309 case OPC_DDIV:
24310 case OPC_DDIVU:
b42ee5e1
LA
24311 check_insn(ctx, ISA_MIPS3);
24312 check_mips_64(ctx);
24313 gen_muldiv(ctx, op1, 0, rs, rt);
24314 break;
24315#endif
0aefa333 24316 case OPC_JR:
b231c103 24317 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24318 break;
4267d3e6
LA
24319 case OPC_SPIM:
24320#ifdef MIPS_STRICT_STANDARD
24321 MIPS_INVAL("SPIM");
9c708c7f 24322 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24323#else
24324 /* Implemented as RI exception for now. */
24325 MIPS_INVAL("spim (unofficial)");
9c708c7f 24326 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24327#endif
24328 break;
10dc65db
LA
24329 default: /* Invalid */
24330 MIPS_INVAL("special_legacy");
9c708c7f 24331 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24332 break;
24333 }
24334}
24335
099e5b4d 24336static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24337{
3c824109 24338 int rs, rt, rd, sa;
099e5b4d 24339 uint32_t op1;
3c824109 24340
3c824109
NF
24341 rs = (ctx->opcode >> 21) & 0x1f;
24342 rt = (ctx->opcode >> 16) & 0x1f;
24343 rd = (ctx->opcode >> 11) & 0x1f;
24344 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24345
24346 op1 = MASK_SPECIAL(ctx->opcode);
24347 switch (op1) {
24348 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24349 if (sa == 5 && rd == 0 &&
24350 rs == 0 && rt == 0) { /* PAUSE */
24351 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24352 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24353 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24354 break;
24355 }
24356 }
24357 /* Fallthrough */
099e5b4d
LA
24358 case OPC_SRA:
24359 gen_shift_imm(ctx, op1, rd, rt, sa);
24360 break;
24361 case OPC_SRL:
24362 switch ((ctx->opcode >> 21) & 0x1f) {
24363 case 1:
24364 /* rotr is decoded as srl on non-R2 CPUs */
24365 if (ctx->insn_flags & ISA_MIPS32R2) {
24366 op1 = OPC_ROTR;
ea63e2c3 24367 }
099e5b4d
LA
24368 /* Fallthrough */
24369 case 0:
24370 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24371 break;
099e5b4d 24372 default:
9c708c7f 24373 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24374 break;
099e5b4d
LA
24375 }
24376 break;
c2e19f3c
AM
24377 case OPC_ADD:
24378 case OPC_ADDU:
24379 case OPC_SUB:
24380 case OPC_SUBU:
099e5b4d
LA
24381 gen_arith(ctx, op1, rd, rs, rt);
24382 break;
24383 case OPC_SLLV: /* Shifts */
24384 case OPC_SRAV:
24385 gen_shift(ctx, op1, rd, rs, rt);
24386 break;
24387 case OPC_SRLV:
24388 switch ((ctx->opcode >> 6) & 0x1f) {
24389 case 1:
24390 /* rotrv is decoded as srlv on non-R2 CPUs */
24391 if (ctx->insn_flags & ISA_MIPS32R2) {
24392 op1 = OPC_ROTRV;
26135ead 24393 }
099e5b4d
LA
24394 /* Fallthrough */
24395 case 0:
24396 gen_shift(ctx, op1, rd, rs, rt);
26135ead 24397 break;
099e5b4d 24398 default:
9c708c7f 24399 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 24400 break;
099e5b4d
LA
24401 }
24402 break;
24403 case OPC_SLT: /* Set on less than */
24404 case OPC_SLTU:
24405 gen_slt(ctx, op1, rd, rs, rt);
24406 break;
24407 case OPC_AND: /* Logic*/
24408 case OPC_OR:
24409 case OPC_NOR:
24410 case OPC_XOR:
24411 gen_logic(ctx, op1, rd, rs, rt);
24412 break;
0aefa333 24413 case OPC_JALR:
b231c103 24414 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 24415 break;
c2e19f3c
AM
24416 case OPC_TGE: /* Traps */
24417 case OPC_TGEU:
24418 case OPC_TLT:
24419 case OPC_TLTU:
24420 case OPC_TEQ:
099e5b4d 24421 case OPC_TNE:
d9224450 24422 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
24423 gen_trap(ctx, op1, rs, rt, -1);
24424 break;
d4ea6acd 24425 case OPC_LSA: /* OPC_PMON */
f7685877
YK
24426 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24427 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
24428 decode_opc_special_r6(env, ctx);
24429 } else {
24430 /* Pmon entry point, also R4010 selsl */
b48cfdff 24431#ifdef MIPS_STRICT_STANDARD
d4ea6acd 24432 MIPS_INVAL("PMON / selsl");
9c708c7f 24433 generate_exception_end(ctx, EXCP_RI);
b48cfdff 24434#else
d4ea6acd 24435 gen_helper_0e0i(pmon, sa);
b48cfdff 24436#endif
d4ea6acd 24437 }
099e5b4d
LA
24438 break;
24439 case OPC_SYSCALL:
9c708c7f 24440 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
24441 break;
24442 case OPC_BREAK:
9c708c7f 24443 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 24444 break;
099e5b4d 24445 case OPC_SYNC:
d9224450 24446 check_insn(ctx, ISA_MIPS2);
d208ac0c 24447 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 24448 break;
4ad40f36 24449
d26bc211 24450#if defined(TARGET_MIPS64)
099e5b4d
LA
24451 /* MIPS64 specific opcodes */
24452 case OPC_DSLL:
24453 case OPC_DSRA:
24454 case OPC_DSLL32:
24455 case OPC_DSRA32:
24456 check_insn(ctx, ISA_MIPS3);
24457 check_mips_64(ctx);
24458 gen_shift_imm(ctx, op1, rd, rt, sa);
24459 break;
24460 case OPC_DSRL:
24461 switch ((ctx->opcode >> 21) & 0x1f) {
24462 case 1:
24463 /* drotr is decoded as dsrl on non-R2 CPUs */
24464 if (ctx->insn_flags & ISA_MIPS32R2) {
24465 op1 = OPC_DROTR;
ea63e2c3 24466 }
099e5b4d
LA
24467 /* Fallthrough */
24468 case 0:
d75c135e 24469 check_insn(ctx, ISA_MIPS3);
e189e748 24470 check_mips_64(ctx);
099e5b4d 24471 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24472 break;
099e5b4d 24473 default:
9c708c7f 24474 generate_exception_end(ctx, EXCP_RI);
460f00c4 24475 break;
099e5b4d
LA
24476 }
24477 break;
24478 case OPC_DSRL32:
24479 switch ((ctx->opcode >> 21) & 0x1f) {
24480 case 1:
24481 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24482 if (ctx->insn_flags & ISA_MIPS32R2) {
24483 op1 = OPC_DROTR32;
ea63e2c3 24484 }
099e5b4d
LA
24485 /* Fallthrough */
24486 case 0:
d75c135e 24487 check_insn(ctx, ISA_MIPS3);
e189e748 24488 check_mips_64(ctx);
099e5b4d 24489 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24490 break;
099e5b4d 24491 default:
9c708c7f 24492 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24493 break;
24494 }
24495 break;
c2e19f3c
AM
24496 case OPC_DADD:
24497 case OPC_DADDU:
24498 case OPC_DSUB:
24499 case OPC_DSUBU:
099e5b4d
LA
24500 check_insn(ctx, ISA_MIPS3);
24501 check_mips_64(ctx);
24502 gen_arith(ctx, op1, rd, rs, rt);
24503 break;
24504 case OPC_DSLLV:
24505 case OPC_DSRAV:
24506 check_insn(ctx, ISA_MIPS3);
24507 check_mips_64(ctx);
24508 gen_shift(ctx, op1, rd, rs, rt);
24509 break;
24510 case OPC_DSRLV:
24511 switch ((ctx->opcode >> 6) & 0x1f) {
24512 case 1:
24513 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24514 if (ctx->insn_flags & ISA_MIPS32R2) {
24515 op1 = OPC_DROTRV;
6af0bf9c 24516 }
099e5b4d
LA
24517 /* Fallthrough */
24518 case 0:
24519 check_insn(ctx, ISA_MIPS3);
e189e748 24520 check_mips_64(ctx);
099e5b4d 24521 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 24522 break;
099e5b4d 24523 default:
9c708c7f 24524 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24525 break;
24526 }
24527 break;
f7685877
YK
24528 case OPC_DLSA:
24529 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24530 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24531 decode_opc_special_r6(env, ctx);
24532 }
24533 break;
099e5b4d 24534#endif
10dc65db
LA
24535 default:
24536 if (ctx->insn_flags & ISA_MIPS32R6) {
24537 decode_opc_special_r6(env, ctx);
9dc324ce
FN
24538 } else if (ctx->insn_flags & INSN_R5900) {
24539 decode_opc_special_tx79(env, ctx);
10dc65db
LA
24540 } else {
24541 decode_opc_special_legacy(env, ctx);
24542 }
24543 }
24544}
24545
d67da337 24546
37b9aae2
MM
24547#if defined(TARGET_MIPS64)
24548
24549/*
24550 *
24551 * MMI (MultiMedia Interface) ASE instructions
24552 * ===========================================
24553 */
24554
24555/*
24556 * MMI instructions category: data communication
24557 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24558 *
24559 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24560 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24561 * PCPYUD PEXEH PEXTLW PPACW
24562 * PEXEW PEXTUB
24563 * PEXTUH
24564 * PEXTUW
24565 */
24566
d3434d9f
MM
24567/*
24568 * PCPYH rd, rt
24569 *
24570 * Parallel Copy Halfword
24571 *
24572 * 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
24573 * +-----------+---------+---------+---------+---------+-----------+
24574 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24575 * +-----------+---------+---------+---------+---------+-----------+
24576 */
24577static void gen_mmi_pcpyh(DisasContext *ctx)
24578{
24579 uint32_t pd, rt, rd;
24580 uint32_t opcode;
24581
24582 opcode = ctx->opcode;
24583
24584 pd = extract32(opcode, 21, 5);
24585 rt = extract32(opcode, 16, 5);
24586 rd = extract32(opcode, 11, 5);
24587
24588 if (unlikely(pd != 0)) {
24589 generate_exception_end(ctx, EXCP_RI);
24590 } else if (rd == 0) {
24591 /* nop */
24592 } else if (rt == 0) {
24593 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24594 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24595 } else {
24596 TCGv_i64 t0 = tcg_temp_new();
24597 TCGv_i64 t1 = tcg_temp_new();
24598 uint64_t mask = (1ULL << 16) - 1;
24599
24600 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24601 tcg_gen_movi_i64(t1, 0);
24602 tcg_gen_or_i64(t1, t0, t1);
24603 tcg_gen_shli_i64(t0, t0, 16);
24604 tcg_gen_or_i64(t1, t0, t1);
24605 tcg_gen_shli_i64(t0, t0, 16);
24606 tcg_gen_or_i64(t1, t0, t1);
24607 tcg_gen_shli_i64(t0, t0, 16);
24608 tcg_gen_or_i64(t1, t0, t1);
24609
24610 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24611
24612 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24613 tcg_gen_movi_i64(t1, 0);
24614 tcg_gen_or_i64(t1, t0, t1);
24615 tcg_gen_shli_i64(t0, t0, 16);
24616 tcg_gen_or_i64(t1, t0, t1);
24617 tcg_gen_shli_i64(t0, t0, 16);
24618 tcg_gen_or_i64(t1, t0, t1);
24619 tcg_gen_shli_i64(t0, t0, 16);
24620 tcg_gen_or_i64(t1, t0, t1);
24621
24622 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24623
24624 tcg_temp_free(t0);
24625 tcg_temp_free(t1);
24626 }
24627}
24628
b87eef31
MM
24629/*
24630 * PCPYLD rd, rs, rt
24631 *
24632 * Parallel Copy Lower Doubleword
24633 *
24634 * 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
24635 * +-----------+---------+---------+---------+---------+-----------+
24636 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24637 * +-----------+---------+---------+---------+---------+-----------+
24638 */
24639static void gen_mmi_pcpyld(DisasContext *ctx)
24640{
24641 uint32_t rs, rt, rd;
24642 uint32_t opcode;
24643
24644 opcode = ctx->opcode;
24645
24646 rs = extract32(opcode, 21, 5);
24647 rt = extract32(opcode, 16, 5);
24648 rd = extract32(opcode, 11, 5);
24649
24650 if (rd == 0) {
24651 /* nop */
24652 } else {
24653 if (rs == 0) {
24654 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24655 } else {
24656 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24657 }
24658 if (rt == 0) {
24659 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24660 } else {
24661 if (rd != rt) {
24662 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24663 }
24664 }
24665 }
24666}
24667
fd487f83
MM
24668/*
24669 * PCPYUD rd, rs, rt
24670 *
24671 * Parallel Copy Upper Doubleword
24672 *
24673 * 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
24674 * +-----------+---------+---------+---------+---------+-----------+
24675 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24676 * +-----------+---------+---------+---------+---------+-----------+
24677 */
24678static void gen_mmi_pcpyud(DisasContext *ctx)
24679{
24680 uint32_t rs, rt, rd;
24681 uint32_t opcode;
24682
24683 opcode = ctx->opcode;
24684
24685 rs = extract32(opcode, 21, 5);
24686 rt = extract32(opcode, 16, 5);
24687 rd = extract32(opcode, 11, 5);
24688
24689 if (rd == 0) {
24690 /* nop */
24691 } else {
24692 if (rs == 0) {
24693 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24694 } else {
24695 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24696 }
24697 if (rt == 0) {
24698 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24699 } else {
24700 if (rd != rt) {
24701 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24702 }
24703 }
24704 }
24705}
24706
37b9aae2
MM
24707#endif
24708
24709
b621f018
AM
24710#if !defined(TARGET_MIPS64)
24711
d67da337
AM
24712/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24713#define MXU_APTN1_A 0
24714#define MXU_APTN1_S 1
24715
b70bb918
CJ
24716/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24717#define MXU_APTN2_AA 0
24718#define MXU_APTN2_AS 1
24719#define MXU_APTN2_SA 2
24720#define MXU_APTN2_SS 3
24721
5bb29992
AM
24722/* MXU execute add/subtract 2-bit pattern 'eptn2' */
24723#define MXU_EPTN2_AA 0
24724#define MXU_EPTN2_AS 1
24725#define MXU_EPTN2_SA 2
24726#define MXU_EPTN2_SS 3
24727
a35723f4 24728/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
24729#define MXU_OPTN2_PTN0 0
24730#define MXU_OPTN2_PTN1 1
24731#define MXU_OPTN2_PTN2 2
24732#define MXU_OPTN2_PTN3 3
24733/* alternative naming scheme for 'optn2' */
a35723f4
CJ
24734#define MXU_OPTN2_WW 0
24735#define MXU_OPTN2_LW 1
24736#define MXU_OPTN2_HW 2
24737#define MXU_OPTN2_XW 3
24738
53f1131f
CJ
24739/* MXU operand getting pattern 'optn3' */
24740#define MXU_OPTN3_PTN0 0
24741#define MXU_OPTN3_PTN1 1
24742#define MXU_OPTN3_PTN2 2
24743#define MXU_OPTN3_PTN3 3
24744#define MXU_OPTN3_PTN4 4
24745#define MXU_OPTN3_PTN5 5
24746#define MXU_OPTN3_PTN6 6
24747#define MXU_OPTN3_PTN7 7
24748
d67da337 24749
96992d1a
CJ
24750/*
24751 * S32I2M XRa, rb - Register move from GRF to XRF
24752 */
24753static void gen_mxu_s32i2m(DisasContext *ctx)
24754{
24755 TCGv t0;
24756 uint32_t XRa, Rb;
24757
24758 t0 = tcg_temp_new();
24759
24760 XRa = extract32(ctx->opcode, 6, 5);
24761 Rb = extract32(ctx->opcode, 16, 5);
24762
24763 gen_load_gpr(t0, Rb);
24764 if (XRa <= 15) {
24765 gen_store_mxu_gpr(t0, XRa);
24766 } else if (XRa == 16) {
24767 gen_store_mxu_cr(t0);
24768 }
24769
24770 tcg_temp_free(t0);
24771}
24772
24773/*
24774 * S32M2I XRa, rb - Register move from XRF to GRF
24775 */
24776static void gen_mxu_s32m2i(DisasContext *ctx)
24777{
24778 TCGv t0;
24779 uint32_t XRa, Rb;
24780
24781 t0 = tcg_temp_new();
24782
24783 XRa = extract32(ctx->opcode, 6, 5);
24784 Rb = extract32(ctx->opcode, 16, 5);
24785
24786 if (XRa <= 15) {
24787 gen_load_mxu_gpr(t0, XRa);
24788 } else if (XRa == 16) {
24789 gen_load_mxu_cr(t0);
24790 }
24791
24792 gen_store_gpr(t0, Rb);
24793
24794 tcg_temp_free(t0);
24795}
24796
be57bcdb
CJ
24797/*
24798 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24799 */
24800static void gen_mxu_s8ldd(DisasContext *ctx)
24801{
24802 TCGv t0, t1;
be57bcdb
CJ
24803 uint32_t XRa, Rb, s8, optn3;
24804
24805 t0 = tcg_temp_new();
24806 t1 = tcg_temp_new();
24807
be57bcdb
CJ
24808 XRa = extract32(ctx->opcode, 6, 4);
24809 s8 = extract32(ctx->opcode, 10, 8);
24810 optn3 = extract32(ctx->opcode, 18, 3);
24811 Rb = extract32(ctx->opcode, 21, 5);
24812
be57bcdb
CJ
24813 gen_load_gpr(t0, Rb);
24814 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24815
24816 switch (optn3) {
24817 /* XRa[7:0] = tmp8 */
24818 case MXU_OPTN3_PTN0:
24819 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24820 gen_load_mxu_gpr(t0, XRa);
24821 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24822 break;
24823 /* XRa[15:8] = tmp8 */
24824 case MXU_OPTN3_PTN1:
24825 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24826 gen_load_mxu_gpr(t0, XRa);
24827 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24828 break;
24829 /* XRa[23:16] = tmp8 */
24830 case MXU_OPTN3_PTN2:
24831 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24832 gen_load_mxu_gpr(t0, XRa);
24833 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24834 break;
24835 /* XRa[31:24] = tmp8 */
24836 case MXU_OPTN3_PTN3:
24837 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24838 gen_load_mxu_gpr(t0, XRa);
24839 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24840 break;
24841 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24842 case MXU_OPTN3_PTN4:
24843 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24844 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24845 break;
24846 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24847 case MXU_OPTN3_PTN5:
24848 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24849 tcg_gen_shli_tl(t1, t1, 8);
24850 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24851 break;
24852 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24853 case MXU_OPTN3_PTN6:
24854 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24855 tcg_gen_mov_tl(t0, t1);
24856 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24857 tcg_gen_shli_tl(t1, t1, 16);
24858 tcg_gen_or_tl(t0, t0, t1);
24859 break;
24860 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24861 case MXU_OPTN3_PTN7:
24862 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24863 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24864 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24865 break;
24866 }
24867
24868 gen_store_mxu_gpr(t0, XRa);
24869
be57bcdb
CJ
24870 tcg_temp_free(t0);
24871 tcg_temp_free(t1);
24872}
24873
72c9bcf8
CJ
24874/*
24875 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24876 */
24877static void gen_mxu_d16mul(DisasContext *ctx)
24878{
24879 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
24880 uint32_t XRa, XRb, XRc, XRd, optn2;
24881
24882 t0 = tcg_temp_new();
24883 t1 = tcg_temp_new();
24884 t2 = tcg_temp_new();
24885 t3 = tcg_temp_new();
24886
72c9bcf8
CJ
24887 XRa = extract32(ctx->opcode, 6, 4);
24888 XRb = extract32(ctx->opcode, 10, 4);
24889 XRc = extract32(ctx->opcode, 14, 4);
24890 XRd = extract32(ctx->opcode, 18, 4);
24891 optn2 = extract32(ctx->opcode, 22, 2);
24892
72c9bcf8
CJ
24893 gen_load_mxu_gpr(t1, XRb);
24894 tcg_gen_sextract_tl(t0, t1, 0, 16);
24895 tcg_gen_sextract_tl(t1, t1, 16, 16);
24896 gen_load_mxu_gpr(t3, XRc);
24897 tcg_gen_sextract_tl(t2, t3, 0, 16);
24898 tcg_gen_sextract_tl(t3, t3, 16, 16);
24899
24900 switch (optn2) {
24901 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24902 tcg_gen_mul_tl(t3, t1, t3);
24903 tcg_gen_mul_tl(t2, t0, t2);
24904 break;
24905 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24906 tcg_gen_mul_tl(t3, t0, t3);
24907 tcg_gen_mul_tl(t2, t0, t2);
24908 break;
24909 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24910 tcg_gen_mul_tl(t3, t1, t3);
24911 tcg_gen_mul_tl(t2, t1, t2);
24912 break;
24913 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24914 tcg_gen_mul_tl(t3, t0, t3);
24915 tcg_gen_mul_tl(t2, t1, t2);
24916 break;
24917 }
24918 gen_store_mxu_gpr(t3, XRa);
24919 gen_store_mxu_gpr(t2, XRd);
24920
72c9bcf8
CJ
24921 tcg_temp_free(t0);
24922 tcg_temp_free(t1);
24923 tcg_temp_free(t2);
24924 tcg_temp_free(t3);
24925}
24926
e67915b4
CJ
24927/*
24928 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24929 * and accumulate
24930 */
24931static void gen_mxu_d16mac(DisasContext *ctx)
24932{
24933 TCGv t0, t1, t2, t3;
e67915b4
CJ
24934 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24935
24936 t0 = tcg_temp_new();
24937 t1 = tcg_temp_new();
24938 t2 = tcg_temp_new();
24939 t3 = tcg_temp_new();
24940
e67915b4
CJ
24941 XRa = extract32(ctx->opcode, 6, 4);
24942 XRb = extract32(ctx->opcode, 10, 4);
24943 XRc = extract32(ctx->opcode, 14, 4);
24944 XRd = extract32(ctx->opcode, 18, 4);
24945 optn2 = extract32(ctx->opcode, 22, 2);
24946 aptn2 = extract32(ctx->opcode, 24, 2);
24947
e67915b4
CJ
24948 gen_load_mxu_gpr(t1, XRb);
24949 tcg_gen_sextract_tl(t0, t1, 0, 16);
24950 tcg_gen_sextract_tl(t1, t1, 16, 16);
24951
24952 gen_load_mxu_gpr(t3, XRc);
24953 tcg_gen_sextract_tl(t2, t3, 0, 16);
24954 tcg_gen_sextract_tl(t3, t3, 16, 16);
24955
24956 switch (optn2) {
24957 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24958 tcg_gen_mul_tl(t3, t1, t3);
24959 tcg_gen_mul_tl(t2, t0, t2);
24960 break;
24961 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24962 tcg_gen_mul_tl(t3, t0, t3);
24963 tcg_gen_mul_tl(t2, t0, t2);
24964 break;
24965 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24966 tcg_gen_mul_tl(t3, t1, t3);
24967 tcg_gen_mul_tl(t2, t1, t2);
24968 break;
24969 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24970 tcg_gen_mul_tl(t3, t0, t3);
24971 tcg_gen_mul_tl(t2, t1, t2);
24972 break;
24973 }
24974 gen_load_mxu_gpr(t0, XRa);
24975 gen_load_mxu_gpr(t1, XRd);
24976
24977 switch (aptn2) {
24978 case MXU_APTN2_AA:
24979 tcg_gen_add_tl(t3, t0, t3);
24980 tcg_gen_add_tl(t2, t1, t2);
24981 break;
24982 case MXU_APTN2_AS:
24983 tcg_gen_add_tl(t3, t0, t3);
24984 tcg_gen_sub_tl(t2, t1, t2);
24985 break;
24986 case MXU_APTN2_SA:
24987 tcg_gen_sub_tl(t3, t0, t3);
24988 tcg_gen_add_tl(t2, t1, t2);
24989 break;
24990 case MXU_APTN2_SS:
24991 tcg_gen_sub_tl(t3, t0, t3);
24992 tcg_gen_sub_tl(t2, t1, t2);
24993 break;
24994 }
24995 gen_store_mxu_gpr(t3, XRa);
24996 gen_store_mxu_gpr(t2, XRd);
24997
e67915b4
CJ
24998 tcg_temp_free(t0);
24999 tcg_temp_free(t1);
25000 tcg_temp_free(t2);
25001 tcg_temp_free(t3);
25002}
25003
a9a4181b
CJ
25004/*
25005 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25006 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25007 */
25008static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25009{
25010 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
25011 uint32_t XRa, XRb, XRc, XRd, sel;
25012
25013 t0 = tcg_temp_new();
25014 t1 = tcg_temp_new();
25015 t2 = tcg_temp_new();
25016 t3 = tcg_temp_new();
25017 t4 = tcg_temp_new();
25018 t5 = tcg_temp_new();
25019 t6 = tcg_temp_new();
25020 t7 = tcg_temp_new();
25021
a9a4181b
CJ
25022 XRa = extract32(ctx->opcode, 6, 4);
25023 XRb = extract32(ctx->opcode, 10, 4);
25024 XRc = extract32(ctx->opcode, 14, 4);
25025 XRd = extract32(ctx->opcode, 18, 4);
25026 sel = extract32(ctx->opcode, 22, 2);
25027
a9a4181b
CJ
25028 gen_load_mxu_gpr(t3, XRb);
25029 gen_load_mxu_gpr(t7, XRc);
25030
25031 if (sel == 0x2) {
25032 /* Q8MULSU */
25033 tcg_gen_ext8s_tl(t0, t3);
25034 tcg_gen_shri_tl(t3, t3, 8);
25035 tcg_gen_ext8s_tl(t1, t3);
25036 tcg_gen_shri_tl(t3, t3, 8);
25037 tcg_gen_ext8s_tl(t2, t3);
25038 tcg_gen_shri_tl(t3, t3, 8);
25039 tcg_gen_ext8s_tl(t3, t3);
25040 } else {
25041 /* Q8MUL */
25042 tcg_gen_ext8u_tl(t0, t3);
25043 tcg_gen_shri_tl(t3, t3, 8);
25044 tcg_gen_ext8u_tl(t1, t3);
25045 tcg_gen_shri_tl(t3, t3, 8);
25046 tcg_gen_ext8u_tl(t2, t3);
25047 tcg_gen_shri_tl(t3, t3, 8);
25048 tcg_gen_ext8u_tl(t3, t3);
25049 }
25050
25051 tcg_gen_ext8u_tl(t4, t7);
25052 tcg_gen_shri_tl(t7, t7, 8);
25053 tcg_gen_ext8u_tl(t5, t7);
25054 tcg_gen_shri_tl(t7, t7, 8);
25055 tcg_gen_ext8u_tl(t6, t7);
25056 tcg_gen_shri_tl(t7, t7, 8);
25057 tcg_gen_ext8u_tl(t7, t7);
25058
25059 tcg_gen_mul_tl(t0, t0, t4);
25060 tcg_gen_mul_tl(t1, t1, t5);
25061 tcg_gen_mul_tl(t2, t2, t6);
25062 tcg_gen_mul_tl(t3, t3, t7);
25063
25064 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25065 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25066 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25067 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25068
25069 tcg_gen_shli_tl(t1, t1, 16);
25070 tcg_gen_shli_tl(t3, t3, 16);
25071
25072 tcg_gen_or_tl(t0, t0, t1);
25073 tcg_gen_or_tl(t1, t2, t3);
25074
25075 gen_store_mxu_gpr(t0, XRd);
25076 gen_store_mxu_gpr(t1, XRa);
25077
a9a4181b
CJ
25078 tcg_temp_free(t0);
25079 tcg_temp_free(t1);
25080 tcg_temp_free(t2);
25081 tcg_temp_free(t3);
25082 tcg_temp_free(t4);
25083 tcg_temp_free(t5);
25084 tcg_temp_free(t6);
25085 tcg_temp_free(t7);
25086}
25087
4ca83721
CJ
25088/*
25089 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25090 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25091 */
25092static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25093{
25094 TCGv t0, t1;
4ca83721
CJ
25095 uint32_t XRa, Rb, s12, sel;
25096
25097 t0 = tcg_temp_new();
25098 t1 = tcg_temp_new();
25099
4ca83721
CJ
25100 XRa = extract32(ctx->opcode, 6, 4);
25101 s12 = extract32(ctx->opcode, 10, 10);
25102 sel = extract32(ctx->opcode, 20, 1);
25103 Rb = extract32(ctx->opcode, 21, 5);
25104
4ca83721
CJ
25105 gen_load_gpr(t0, Rb);
25106
25107 tcg_gen_movi_tl(t1, s12);
25108 tcg_gen_shli_tl(t1, t1, 2);
25109 if (s12 & 0x200) {
25110 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25111 }
25112 tcg_gen_add_tl(t1, t0, t1);
25113 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25114
25115 if (sel == 1) {
25116 /* S32LDDR */
25117 tcg_gen_bswap32_tl(t1, t1);
25118 }
25119 gen_store_mxu_gpr(t1, XRa);
25120
4ca83721
CJ
25121 tcg_temp_free(t0);
25122 tcg_temp_free(t1);
25123}
25124
96992d1a 25125
b621f018
AM
25126/*
25127 * MXU instruction category: logic
25128 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25129 *
25130 * S32NOR S32AND S32OR S32XOR
25131 */
25132
25133/*
25134 * S32NOR XRa, XRb, XRc
25135 * Update XRa with the result of logical bitwise 'nor' operation
25136 * applied to the content of XRb and XRc.
25137 *
25138 * 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
25139 * +-----------+---------+-----+-------+-------+-------+-----------+
25140 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25141 * +-----------+---------+-----+-------+-------+-------+-----------+
25142 */
25143static void gen_mxu_S32NOR(DisasContext *ctx)
25144{
25145 uint32_t pad, XRc, XRb, XRa;
25146
25147 pad = extract32(ctx->opcode, 21, 5);
25148 XRc = extract32(ctx->opcode, 14, 4);
25149 XRb = extract32(ctx->opcode, 10, 4);
25150 XRa = extract32(ctx->opcode, 6, 4);
25151
25152 if (unlikely(pad != 0)) {
25153 /* opcode padding incorrect -> do nothing */
25154 } else if (unlikely(XRa == 0)) {
25155 /* destination is zero register -> do nothing */
25156 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25157 /* both operands zero registers -> just set destination to all 1s */
25158 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25159 } else if (unlikely(XRb == 0)) {
25160 /* XRb zero register -> just set destination to the negation of XRc */
25161 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25162 } else if (unlikely(XRc == 0)) {
25163 /* XRa zero register -> just set destination to the negation of XRb */
25164 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25165 } else if (unlikely(XRb == XRc)) {
25166 /* both operands same -> just set destination to the negation of XRb */
25167 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25168 } else {
25169 /* the most general case */
25170 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25171 }
25172}
25173
25174/*
25175 * S32AND XRa, XRb, XRc
25176 * Update XRa with the result of logical bitwise 'and' operation
25177 * applied to the content of XRb and XRc.
25178 *
25179 * 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
25180 * +-----------+---------+-----+-------+-------+-------+-----------+
25181 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25182 * +-----------+---------+-----+-------+-------+-------+-----------+
25183 */
25184static void gen_mxu_S32AND(DisasContext *ctx)
25185{
25186 uint32_t pad, XRc, XRb, XRa;
25187
25188 pad = extract32(ctx->opcode, 21, 5);
25189 XRc = extract32(ctx->opcode, 14, 4);
25190 XRb = extract32(ctx->opcode, 10, 4);
25191 XRa = extract32(ctx->opcode, 6, 4);
25192
25193 if (unlikely(pad != 0)) {
25194 /* opcode padding incorrect -> do nothing */
25195 } else if (unlikely(XRa == 0)) {
25196 /* destination is zero register -> do nothing */
25197 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25198 /* one of operands zero register -> just set destination to all 0s */
25199 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25200 } else if (unlikely(XRb == XRc)) {
25201 /* both operands same -> just set destination to one of them */
25202 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25203 } else {
25204 /* the most general case */
25205 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25206 }
25207}
25208
25209/*
25210 * S32OR XRa, XRb, XRc
25211 * Update XRa with the result of logical bitwise 'or' operation
25212 * applied to the content of XRb and XRc.
25213 *
25214 * 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
25215 * +-----------+---------+-----+-------+-------+-------+-----------+
25216 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25217 * +-----------+---------+-----+-------+-------+-------+-----------+
25218 */
25219static void gen_mxu_S32OR(DisasContext *ctx)
25220{
25221 uint32_t pad, XRc, XRb, XRa;
25222
25223 pad = extract32(ctx->opcode, 21, 5);
25224 XRc = extract32(ctx->opcode, 14, 4);
25225 XRb = extract32(ctx->opcode, 10, 4);
25226 XRa = extract32(ctx->opcode, 6, 4);
25227
25228 if (unlikely(pad != 0)) {
25229 /* opcode padding incorrect -> do nothing */
25230 } else if (unlikely(XRa == 0)) {
25231 /* destination is zero register -> do nothing */
25232 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25233 /* both operands zero registers -> just set destination to all 0s */
25234 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25235 } else if (unlikely(XRb == 0)) {
25236 /* XRb zero register -> just set destination to the content of XRc */
25237 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25238 } else if (unlikely(XRc == 0)) {
25239 /* XRc zero register -> just set destination to the content of XRb */
25240 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25241 } else if (unlikely(XRb == XRc)) {
25242 /* both operands same -> just set destination to one of them */
25243 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25244 } else {
25245 /* the most general case */
25246 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25247 }
25248}
25249
25250/*
25251 * S32XOR XRa, XRb, XRc
25252 * Update XRa with the result of logical bitwise 'xor' operation
25253 * applied to the content of XRb and XRc.
25254 *
25255 * 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
25256 * +-----------+---------+-----+-------+-------+-------+-----------+
25257 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25258 * +-----------+---------+-----+-------+-------+-------+-----------+
25259 */
25260static void gen_mxu_S32XOR(DisasContext *ctx)
25261{
25262 uint32_t pad, XRc, XRb, XRa;
25263
25264 pad = extract32(ctx->opcode, 21, 5);
25265 XRc = extract32(ctx->opcode, 14, 4);
25266 XRb = extract32(ctx->opcode, 10, 4);
25267 XRa = extract32(ctx->opcode, 6, 4);
25268
25269 if (unlikely(pad != 0)) {
25270 /* opcode padding incorrect -> do nothing */
25271 } else if (unlikely(XRa == 0)) {
25272 /* destination is zero register -> do nothing */
25273 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25274 /* both operands zero registers -> just set destination to all 0s */
25275 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25276 } else if (unlikely(XRb == 0)) {
25277 /* XRb zero register -> just set destination to the content of XRc */
25278 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25279 } else if (unlikely(XRc == 0)) {
25280 /* XRc zero register -> just set destination to the content of XRb */
25281 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25282 } else if (unlikely(XRb == XRc)) {
25283 /* both operands same -> just set destination to all 0s */
25284 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25285 } else {
25286 /* the most general case */
25287 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25288 }
25289}
25290
25291
bb84cbf3
AM
25292/*
25293 * MXU instruction category max/min
25294 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25295 *
25296 * S32MAX D16MAX Q8MAX
25297 * S32MIN D16MIN Q8MIN
25298 */
25299
25300/*
25301 * S32MAX XRa, XRb, XRc
25302 * Update XRa with the maximum of signed 32-bit integers contained
25303 * in XRb and XRc.
25304 *
25305 * S32MIN XRa, XRb, XRc
25306 * Update XRa with the minimum of signed 32-bit integers contained
25307 * in XRb and XRc.
25308 *
25309 * 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
25310 * +-----------+---------+-----+-------+-------+-------+-----------+
25311 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25312 * +-----------+---------+-----+-------+-------+-------+-----------+
25313 */
25314static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25315{
25316 uint32_t pad, opc, XRc, XRb, XRa;
25317
25318 pad = extract32(ctx->opcode, 21, 5);
25319 opc = extract32(ctx->opcode, 18, 3);
25320 XRc = extract32(ctx->opcode, 14, 4);
25321 XRb = extract32(ctx->opcode, 10, 4);
25322 XRa = extract32(ctx->opcode, 6, 4);
25323
25324 if (unlikely(pad != 0)) {
25325 /* opcode padding incorrect -> do nothing */
25326 } else if (unlikely(XRa == 0)) {
25327 /* destination is zero register -> do nothing */
25328 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25329 /* both operands zero registers -> just set destination to zero */
25330 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25331 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25332 /* exactly one operand is zero register - find which one is not...*/
25333 uint32_t XRx = XRb ? XRb : XRc;
25334 /* ...and do max/min operation with one operand 0 */
25335 if (opc == OPC_MXU_S32MAX) {
25336 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25337 } else {
25338 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25339 }
25340 } else if (unlikely(XRb == XRc)) {
25341 /* both operands same -> just set destination to one of them */
25342 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25343 } else {
25344 /* the most general case */
25345 if (opc == OPC_MXU_S32MAX) {
25346 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25347 mxu_gpr[XRc - 1]);
25348 } else {
25349 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25350 mxu_gpr[XRc - 1]);
25351 }
25352 }
25353}
25354
25355/*
25356 * D16MAX
25357 * Update XRa with the 16-bit-wise maximums of signed integers
25358 * contained in XRb and XRc.
25359 *
25360 * D16MIN
25361 * Update XRa with the 16-bit-wise minimums of signed integers
25362 * contained in XRb and XRc.
25363 *
25364 * 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
25365 * +-----------+---------+-----+-------+-------+-------+-----------+
25366 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25367 * +-----------+---------+-----+-------+-------+-------+-----------+
25368 */
25369static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25370{
25371 uint32_t pad, opc, XRc, XRb, XRa;
25372
25373 pad = extract32(ctx->opcode, 21, 5);
25374 opc = extract32(ctx->opcode, 18, 3);
25375 XRc = extract32(ctx->opcode, 14, 4);
25376 XRb = extract32(ctx->opcode, 10, 4);
25377 XRa = extract32(ctx->opcode, 6, 4);
25378
25379 if (unlikely(pad != 0)) {
25380 /* opcode padding incorrect -> do nothing */
25381 } else if (unlikely(XRc == 0)) {
25382 /* destination is zero register -> do nothing */
25383 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25384 /* both operands zero registers -> just set destination to zero */
25385 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25386 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25387 /* exactly one operand is zero register - find which one is not...*/
25388 uint32_t XRx = XRb ? XRb : XRc;
25389 /* ...and do half-word-wise max/min with one operand 0 */
25390 TCGv_i32 t0 = tcg_temp_new();
25391 TCGv_i32 t1 = tcg_const_i32(0);
25392
25393 /* the left half-word first */
25394 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25395 if (opc == OPC_MXU_D16MAX) {
25396 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25397 } else {
25398 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25399 }
25400
25401 /* the right half-word */
25402 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25403 /* move half-words to the leftmost position */
25404 tcg_gen_shli_i32(t0, t0, 16);
25405 /* t0 will be max/min of t0 and t1 */
25406 if (opc == OPC_MXU_D16MAX) {
25407 tcg_gen_smax_i32(t0, t0, t1);
25408 } else {
25409 tcg_gen_smin_i32(t0, t0, t1);
25410 }
25411 /* return resulting half-words to its original position */
25412 tcg_gen_shri_i32(t0, t0, 16);
25413 /* finaly update the destination */
25414 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25415
25416 tcg_temp_free(t1);
25417 tcg_temp_free(t0);
25418 } else if (unlikely(XRb == XRc)) {
25419 /* both operands same -> just set destination to one of them */
25420 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25421 } else {
25422 /* the most general case */
25423 TCGv_i32 t0 = tcg_temp_new();
25424 TCGv_i32 t1 = tcg_temp_new();
25425
25426 /* the left half-word first */
25427 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25428 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25429 if (opc == OPC_MXU_D16MAX) {
25430 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25431 } else {
25432 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25433 }
25434
25435 /* the right half-word */
25436 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25437 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25438 /* move half-words to the leftmost position */
25439 tcg_gen_shli_i32(t0, t0, 16);
25440 tcg_gen_shli_i32(t1, t1, 16);
25441 /* t0 will be max/min of t0 and t1 */
25442 if (opc == OPC_MXU_D16MAX) {
25443 tcg_gen_smax_i32(t0, t0, t1);
25444 } else {
25445 tcg_gen_smin_i32(t0, t0, t1);
25446 }
25447 /* return resulting half-words to its original position */
25448 tcg_gen_shri_i32(t0, t0, 16);
25449 /* finaly update the destination */
25450 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25451
25452 tcg_temp_free(t1);
25453 tcg_temp_free(t0);
25454 }
25455}
25456
25457/*
25458 * Q8MAX
25459 * Update XRa with the 8-bit-wise maximums of signed integers
25460 * contained in XRb and XRc.
25461 *
25462 * Q8MIN
25463 * Update XRa with the 8-bit-wise minimums of signed integers
25464 * contained in XRb and XRc.
25465 *
25466 * 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
25467 * +-----------+---------+-----+-------+-------+-------+-----------+
25468 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25469 * +-----------+---------+-----+-------+-------+-------+-----------+
25470 */
25471static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25472{
25473 uint32_t pad, opc, XRc, XRb, XRa;
25474
25475 pad = extract32(ctx->opcode, 21, 5);
25476 opc = extract32(ctx->opcode, 18, 3);
25477 XRc = extract32(ctx->opcode, 14, 4);
25478 XRb = extract32(ctx->opcode, 10, 4);
25479 XRa = extract32(ctx->opcode, 6, 4);
25480
25481 if (unlikely(pad != 0)) {
25482 /* opcode padding incorrect -> do nothing */
25483 } else if (unlikely(XRa == 0)) {
25484 /* destination is zero register -> do nothing */
25485 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25486 /* both operands zero registers -> just set destination to zero */
25487 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25488 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25489 /* exactly one operand is zero register - make it be the first...*/
25490 uint32_t XRx = XRb ? XRb : XRc;
25491 /* ...and do byte-wise max/min with one operand 0 */
25492 TCGv_i32 t0 = tcg_temp_new();
25493 TCGv_i32 t1 = tcg_const_i32(0);
25494 int32_t i;
25495
25496 /* the leftmost byte (byte 3) first */
25497 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25498 if (opc == OPC_MXU_Q8MAX) {
25499 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25500 } else {
25501 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25502 }
25503
25504 /* bytes 2, 1, 0 */
25505 for (i = 2; i >= 0; i--) {
25506 /* extract the byte */
25507 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25508 /* move the byte to the leftmost position */
25509 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25510 /* t0 will be max/min of t0 and t1 */
25511 if (opc == OPC_MXU_Q8MAX) {
25512 tcg_gen_smax_i32(t0, t0, t1);
25513 } else {
25514 tcg_gen_smin_i32(t0, t0, t1);
25515 }
25516 /* return resulting byte to its original position */
25517 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25518 /* finaly update the destination */
25519 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25520 }
25521
25522 tcg_temp_free(t1);
25523 tcg_temp_free(t0);
25524 } else if (unlikely(XRb == XRc)) {
25525 /* both operands same -> just set destination to one of them */
25526 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25527 } else {
25528 /* the most general case */
25529 TCGv_i32 t0 = tcg_temp_new();
25530 TCGv_i32 t1 = tcg_temp_new();
25531 int32_t i;
25532
25533 /* the leftmost bytes (bytes 3) first */
25534 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25535 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25536 if (opc == OPC_MXU_Q8MAX) {
25537 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25538 } else {
25539 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25540 }
25541
25542 /* bytes 2, 1, 0 */
25543 for (i = 2; i >= 0; i--) {
25544 /* extract corresponding bytes */
25545 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25546 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25547 /* move the bytes to the leftmost position */
25548 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25549 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25550 /* t0 will be max/min of t0 and t1 */
25551 if (opc == OPC_MXU_Q8MAX) {
25552 tcg_gen_smax_i32(t0, t0, t1);
25553 } else {
25554 tcg_gen_smin_i32(t0, t0, t1);
25555 }
25556 /* return resulting byte to its original position */
25557 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25558 /* finaly update the destination */
25559 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25560 }
25561
25562 tcg_temp_free(t1);
25563 tcg_temp_free(t0);
25564 }
25565}
25566
25567
79f5fee7
AM
25568/*
25569 * MXU instruction category: align
25570 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25571 *
25572 * S32ALN S32ALNI
25573 */
25574
25575/*
25576 * S32ALNI XRc, XRb, XRa, optn3
25577 * Arrange bytes from XRb and XRc according to one of five sets of
25578 * rules determined by optn3, and place the result in XRa.
25579 *
25580 * 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
25581 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25582 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25583 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25584 *
25585 */
25586static void gen_mxu_S32ALNI(DisasContext *ctx)
25587{
25588 uint32_t optn3, pad, XRc, XRb, XRa;
25589
25590 optn3 = extract32(ctx->opcode, 23, 3);
25591 pad = extract32(ctx->opcode, 21, 2);
25592 XRc = extract32(ctx->opcode, 14, 4);
25593 XRb = extract32(ctx->opcode, 10, 4);
25594 XRa = extract32(ctx->opcode, 6, 4);
25595
25596 if (unlikely(pad != 0)) {
25597 /* opcode padding incorrect -> do nothing */
25598 } else if (unlikely(XRa == 0)) {
25599 /* destination is zero register -> do nothing */
25600 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25601 /* both operands zero registers -> just set destination to all 0s */
25602 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25603 } else if (unlikely(XRb == 0)) {
25604 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25605 switch (optn3) {
25606 case MXU_OPTN3_PTN0:
25607 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25608 break;
25609 case MXU_OPTN3_PTN1:
25610 case MXU_OPTN3_PTN2:
25611 case MXU_OPTN3_PTN3:
25612 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25613 8 * (4 - optn3));
25614 break;
25615 case MXU_OPTN3_PTN4:
25616 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25617 break;
25618 }
25619 } else if (unlikely(XRc == 0)) {
25620 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25621 switch (optn3) {
25622 case MXU_OPTN3_PTN0:
25623 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25624 break;
25625 case MXU_OPTN3_PTN1:
25626 case MXU_OPTN3_PTN2:
25627 case MXU_OPTN3_PTN3:
25628 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25629 break;
25630 case MXU_OPTN3_PTN4:
25631 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25632 break;
25633 }
25634 } else if (unlikely(XRb == XRc)) {
25635 /* both operands same -> just rotation or moving from any of them */
25636 switch (optn3) {
25637 case MXU_OPTN3_PTN0:
25638 case MXU_OPTN3_PTN4:
25639 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25640 break;
25641 case MXU_OPTN3_PTN1:
25642 case MXU_OPTN3_PTN2:
25643 case MXU_OPTN3_PTN3:
25644 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25645 break;
25646 }
25647 } else {
25648 /* the most general case */
25649 switch (optn3) {
25650 case MXU_OPTN3_PTN0:
25651 {
25652 /* */
25653 /* XRb XRc */
25654 /* +---------------+ */
25655 /* | A B C D | E F G H */
25656 /* +-------+-------+ */
25657 /* | */
25658 /* XRa */
25659 /* */
25660
25661 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25662 }
25663 break;
25664 case MXU_OPTN3_PTN1:
25665 {
25666 /* */
25667 /* XRb XRc */
25668 /* +-------------------+ */
25669 /* A | B C D E | F G H */
25670 /* +---------+---------+ */
25671 /* | */
25672 /* XRa */
25673 /* */
25674
25675 TCGv_i32 t0 = tcg_temp_new();
25676 TCGv_i32 t1 = tcg_temp_new();
25677
25678 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25679 tcg_gen_shli_i32(t0, t0, 8);
25680
25681 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25682 tcg_gen_shri_i32(t1, t1, 24);
25683
25684 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25685
25686 tcg_temp_free(t1);
25687 tcg_temp_free(t0);
25688 }
25689 break;
25690 case MXU_OPTN3_PTN2:
25691 {
25692 /* */
25693 /* XRb XRc */
25694 /* +-------------------+ */
25695 /* A B | C D E F | G H */
25696 /* +---------+---------+ */
25697 /* | */
25698 /* XRa */
25699 /* */
25700
25701 TCGv_i32 t0 = tcg_temp_new();
25702 TCGv_i32 t1 = tcg_temp_new();
25703
25704 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25705 tcg_gen_shli_i32(t0, t0, 16);
25706
25707 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25708 tcg_gen_shri_i32(t1, t1, 16);
25709
25710 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25711
25712 tcg_temp_free(t1);
25713 tcg_temp_free(t0);
25714 }
25715 break;
25716 case MXU_OPTN3_PTN3:
25717 {
25718 /* */
25719 /* XRb XRc */
25720 /* +-------------------+ */
25721 /* A B C | D E F G | H */
25722 /* +---------+---------+ */
25723 /* | */
25724 /* XRa */
25725 /* */
25726
25727 TCGv_i32 t0 = tcg_temp_new();
25728 TCGv_i32 t1 = tcg_temp_new();
25729
25730 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25731 tcg_gen_shli_i32(t0, t0, 24);
25732
25733 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25734 tcg_gen_shri_i32(t1, t1, 8);
25735
25736 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25737
25738 tcg_temp_free(t1);
25739 tcg_temp_free(t0);
25740 }
25741 break;
25742 case MXU_OPTN3_PTN4:
25743 {
25744 /* */
25745 /* XRb XRc */
25746 /* +---------------+ */
25747 /* A B C D | E F G H | */
25748 /* +-------+-------+ */
25749 /* | */
25750 /* XRa */
25751 /* */
25752
25753 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25754 }
25755 break;
25756 }
25757 }
25758}
25759
25760
96992d1a
CJ
25761/*
25762 * Decoding engine for MXU
25763 * =======================
25764 */
25765
03f40088
AM
25766/*
25767 *
25768 * Decode MXU pool00
25769 *
25770 * 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
25771 * +-----------+---------+-----+-------+-------+-------+-----------+
25772 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25773 * +-----------+---------+-----+-------+-------+-------+-----------+
25774 *
25775 */
25776static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25777{
25778 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25779
25780 switch (opcode) {
25781 case OPC_MXU_S32MAX:
03f40088 25782 case OPC_MXU_S32MIN:
bb84cbf3 25783 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
25784 break;
25785 case OPC_MXU_D16MAX:
03f40088 25786 case OPC_MXU_D16MIN:
bb84cbf3 25787 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
25788 break;
25789 case OPC_MXU_Q8MAX:
03f40088 25790 case OPC_MXU_Q8MIN:
bb84cbf3 25791 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
25792 break;
25793 case OPC_MXU_Q8SLT:
25794 /* TODO: Implement emulation of Q8SLT instruction. */
25795 MIPS_INVAL("OPC_MXU_Q8SLT");
25796 generate_exception_end(ctx, EXCP_RI);
25797 break;
25798 case OPC_MXU_Q8SLTU:
25799 /* TODO: Implement emulation of Q8SLTU instruction. */
25800 MIPS_INVAL("OPC_MXU_Q8SLTU");
25801 generate_exception_end(ctx, EXCP_RI);
25802 break;
25803 default:
25804 MIPS_INVAL("decode_opc_mxu");
25805 generate_exception_end(ctx, EXCP_RI);
25806 break;
25807 }
25808}
25809
25810/*
25811 *
25812 * Decode MXU pool01
25813 *
25814 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25815 * 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
25816 * +-----------+---------+-----+-------+-------+-------+-----------+
25817 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25818 * +-----------+---------+-----+-------+-------+-------+-----------+
25819 *
25820 * Q8ADD:
25821 * 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
25822 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25823 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25824 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25825 *
25826 */
25827static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25828{
25829 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25830
25831 switch (opcode) {
25832 case OPC_MXU_S32SLT:
25833 /* TODO: Implement emulation of S32SLT instruction. */
25834 MIPS_INVAL("OPC_MXU_S32SLT");
25835 generate_exception_end(ctx, EXCP_RI);
25836 break;
25837 case OPC_MXU_D16SLT:
25838 /* TODO: Implement emulation of D16SLT instruction. */
25839 MIPS_INVAL("OPC_MXU_D16SLT");
25840 generate_exception_end(ctx, EXCP_RI);
25841 break;
25842 case OPC_MXU_D16AVG:
25843 /* TODO: Implement emulation of D16AVG instruction. */
25844 MIPS_INVAL("OPC_MXU_D16AVG");
25845 generate_exception_end(ctx, EXCP_RI);
25846 break;
25847 case OPC_MXU_D16AVGR:
25848 /* TODO: Implement emulation of D16AVGR instruction. */
25849 MIPS_INVAL("OPC_MXU_D16AVGR");
25850 generate_exception_end(ctx, EXCP_RI);
25851 break;
25852 case OPC_MXU_Q8AVG:
25853 /* TODO: Implement emulation of Q8AVG instruction. */
25854 MIPS_INVAL("OPC_MXU_Q8AVG");
25855 generate_exception_end(ctx, EXCP_RI);
25856 break;
25857 case OPC_MXU_Q8AVGR:
25858 /* TODO: Implement emulation of Q8AVGR instruction. */
25859 MIPS_INVAL("OPC_MXU_Q8AVGR");
25860 generate_exception_end(ctx, EXCP_RI);
25861 break;
25862 case OPC_MXU_Q8ADD:
25863 /* TODO: Implement emulation of Q8ADD instruction. */
25864 MIPS_INVAL("OPC_MXU_Q8ADD");
25865 generate_exception_end(ctx, EXCP_RI);
25866 break;
25867 default:
25868 MIPS_INVAL("decode_opc_mxu");
25869 generate_exception_end(ctx, EXCP_RI);
25870 break;
25871 }
25872}
25873
25874/*
25875 *
25876 * Decode MXU pool02
25877 *
25878 * 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
25879 * +-----------+---------+-----+-------+-------+-------+-----------+
25880 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25881 * +-----------+---------+-----+-------+-------+-------+-----------+
25882 *
25883 */
25884static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25885{
25886 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25887
25888 switch (opcode) {
25889 case OPC_MXU_S32CPS:
25890 /* TODO: Implement emulation of S32CPS instruction. */
25891 MIPS_INVAL("OPC_MXU_S32CPS");
25892 generate_exception_end(ctx, EXCP_RI);
25893 break;
25894 case OPC_MXU_D16CPS:
25895 /* TODO: Implement emulation of D16CPS instruction. */
25896 MIPS_INVAL("OPC_MXU_D16CPS");
25897 generate_exception_end(ctx, EXCP_RI);
25898 break;
25899 case OPC_MXU_Q8ABD:
25900 /* TODO: Implement emulation of Q8ABD instruction. */
25901 MIPS_INVAL("OPC_MXU_Q8ABD");
25902 generate_exception_end(ctx, EXCP_RI);
25903 break;
25904 case OPC_MXU_Q16SAT:
25905 /* TODO: Implement emulation of Q16SAT instruction. */
25906 MIPS_INVAL("OPC_MXU_Q16SAT");
25907 generate_exception_end(ctx, EXCP_RI);
25908 break;
25909 default:
25910 MIPS_INVAL("decode_opc_mxu");
25911 generate_exception_end(ctx, EXCP_RI);
25912 break;
25913 }
25914}
25915
25916/*
25917 *
25918 * Decode MXU pool03
25919 *
25920 * D16MULF:
25921 * 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
25922 * +-----------+---+---+-------+-------+-------+-------+-----------+
25923 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25924 * +-----------+---+---+-------+-------+-------+-------+-----------+
25925 *
25926 * D16MULE:
25927 * 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
25928 * +-----------+---+---+-------+-------+-------+-------+-----------+
25929 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25930 * +-----------+---+---+-------+-------+-------+-------+-----------+
25931 *
25932 */
25933static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25934{
25935 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25936
25937 switch (opcode) {
25938 case OPC_MXU_D16MULF:
25939 /* TODO: Implement emulation of D16MULF instruction. */
25940 MIPS_INVAL("OPC_MXU_D16MULF");
25941 generate_exception_end(ctx, EXCP_RI);
25942 break;
25943 case OPC_MXU_D16MULE:
25944 /* TODO: Implement emulation of D16MULE instruction. */
25945 MIPS_INVAL("OPC_MXU_D16MULE");
25946 generate_exception_end(ctx, EXCP_RI);
25947 break;
25948 default:
25949 MIPS_INVAL("decode_opc_mxu");
25950 generate_exception_end(ctx, EXCP_RI);
25951 break;
25952 }
25953}
25954
25955/*
25956 *
25957 * Decode MXU pool04
25958 *
25959 * 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
25960 * +-----------+---------+-+-------------------+-------+-----------+
25961 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25962 * +-----------+---------+-+-------------------+-------+-----------+
25963 *
25964 */
25965static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25966{
25967 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25968
25969 switch (opcode) {
25970 case OPC_MXU_S32LDD:
03f40088 25971 case OPC_MXU_S32LDDR:
4ca83721 25972 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
25973 break;
25974 default:
25975 MIPS_INVAL("decode_opc_mxu");
25976 generate_exception_end(ctx, EXCP_RI);
25977 break;
25978 }
25979}
25980
25981/*
25982 *
25983 * Decode MXU pool05
25984 *
25985 * 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
25986 * +-----------+---------+-+-------------------+-------+-----------+
25987 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25988 * +-----------+---------+-+-------------------+-------+-----------+
25989 *
25990 */
25991static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25992{
25993 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25994
25995 switch (opcode) {
25996 case OPC_MXU_S32STD:
25997 /* TODO: Implement emulation of S32STD instruction. */
25998 MIPS_INVAL("OPC_MXU_S32STD");
25999 generate_exception_end(ctx, EXCP_RI);
26000 break;
26001 case OPC_MXU_S32STDR:
26002 /* TODO: Implement emulation of S32STDR instruction. */
26003 MIPS_INVAL("OPC_MXU_S32STDR");
26004 generate_exception_end(ctx, EXCP_RI);
26005 break;
26006 default:
26007 MIPS_INVAL("decode_opc_mxu");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26010 }
26011}
26012
26013/*
26014 *
26015 * Decode MXU pool06
26016 *
26017 * 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
26018 * +-----------+---------+---------+---+-------+-------+-----------+
26019 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26020 * +-----------+---------+---------+---+-------+-------+-----------+
26021 *
26022 */
26023static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26024{
26025 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26026
26027 switch (opcode) {
26028 case OPC_MXU_S32LDDV:
26029 /* TODO: Implement emulation of S32LDDV instruction. */
26030 MIPS_INVAL("OPC_MXU_S32LDDV");
26031 generate_exception_end(ctx, EXCP_RI);
26032 break;
26033 case OPC_MXU_S32LDDVR:
26034 /* TODO: Implement emulation of S32LDDVR instruction. */
26035 MIPS_INVAL("OPC_MXU_S32LDDVR");
26036 generate_exception_end(ctx, EXCP_RI);
26037 break;
26038 default:
26039 MIPS_INVAL("decode_opc_mxu");
26040 generate_exception_end(ctx, EXCP_RI);
26041 break;
26042 }
26043}
26044
26045/*
26046 *
26047 * Decode MXU pool07
26048 *
26049 * 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
26050 * +-----------+---------+---------+---+-------+-------+-----------+
26051 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26052 * +-----------+---------+---------+---+-------+-------+-----------+
26053 *
26054 */
26055static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26056{
26057 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26058
26059 switch (opcode) {
26060 case OPC_MXU_S32STDV:
26061 /* TODO: Implement emulation of S32TDV instruction. */
26062 MIPS_INVAL("OPC_MXU_S32TDV");
26063 generate_exception_end(ctx, EXCP_RI);
26064 break;
26065 case OPC_MXU_S32STDVR:
26066 /* TODO: Implement emulation of S32TDVR instruction. */
26067 MIPS_INVAL("OPC_MXU_S32TDVR");
26068 generate_exception_end(ctx, EXCP_RI);
26069 break;
26070 default:
26071 MIPS_INVAL("decode_opc_mxu");
26072 generate_exception_end(ctx, EXCP_RI);
26073 break;
26074 }
26075}
26076
26077/*
26078 *
26079 * Decode MXU pool08
26080 *
26081 * 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
26082 * +-----------+---------+-+-------------------+-------+-----------+
26083 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26084 * +-----------+---------+-+-------------------+-------+-----------+
26085 *
7480515f 26086 */
03f40088
AM
26087static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26088{
26089 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26090
26091 switch (opcode) {
26092 case OPC_MXU_S32LDI:
26093 /* TODO: Implement emulation of S32LDI instruction. */
26094 MIPS_INVAL("OPC_MXU_S32LDI");
26095 generate_exception_end(ctx, EXCP_RI);
26096 break;
26097 case OPC_MXU_S32LDIR:
26098 /* TODO: Implement emulation of S32LDIR instruction. */
26099 MIPS_INVAL("OPC_MXU_S32LDIR");
26100 generate_exception_end(ctx, EXCP_RI);
26101 break;
26102 default:
26103 MIPS_INVAL("decode_opc_mxu");
26104 generate_exception_end(ctx, EXCP_RI);
26105 break;
26106 }
26107}
26108
26109/*
26110 *
26111 * Decode MXU pool09
26112 *
26113 * 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
26114 * +-----------+---------+-+-------------------+-------+-----------+
26115 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26116 * +-----------+---------+-+-------------------+-------+-----------+
26117 *
26118 */
26119static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26120{
26121 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26122
26123 switch (opcode) {
26124 case OPC_MXU_S32SDI:
26125 /* TODO: Implement emulation of S32SDI instruction. */
26126 MIPS_INVAL("OPC_MXU_S32SDI");
26127 generate_exception_end(ctx, EXCP_RI);
26128 break;
26129 case OPC_MXU_S32SDIR:
26130 /* TODO: Implement emulation of S32SDIR instruction. */
26131 MIPS_INVAL("OPC_MXU_S32SDIR");
26132 generate_exception_end(ctx, EXCP_RI);
26133 break;
26134 default:
26135 MIPS_INVAL("decode_opc_mxu");
26136 generate_exception_end(ctx, EXCP_RI);
26137 break;
26138 }
26139}
26140
26141/*
26142 *
26143 * Decode MXU pool10
26144 *
26145 * 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
26146 * +-----------+---------+---------+---+-------+-------+-----------+
26147 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26148 * +-----------+---------+---------+---+-------+-------+-----------+
26149 *
26150 */
26151static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26152{
26153 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26154
26155 switch (opcode) {
26156 case OPC_MXU_S32LDIV:
26157 /* TODO: Implement emulation of S32LDIV instruction. */
26158 MIPS_INVAL("OPC_MXU_S32LDIV");
26159 generate_exception_end(ctx, EXCP_RI);
26160 break;
26161 case OPC_MXU_S32LDIVR:
26162 /* TODO: Implement emulation of S32LDIVR instruction. */
26163 MIPS_INVAL("OPC_MXU_S32LDIVR");
26164 generate_exception_end(ctx, EXCP_RI);
26165 break;
26166 default:
26167 MIPS_INVAL("decode_opc_mxu");
26168 generate_exception_end(ctx, EXCP_RI);
26169 break;
26170 }
26171}
26172
26173/*
26174 *
26175 * Decode MXU pool11
26176 *
26177 * 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
26178 * +-----------+---------+---------+---+-------+-------+-----------+
26179 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26180 * +-----------+---------+---------+---+-------+-------+-----------+
26181 *
26182 */
26183static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26184{
26185 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26186
26187 switch (opcode) {
26188 case OPC_MXU_S32SDIV:
26189 /* TODO: Implement emulation of S32SDIV instruction. */
26190 MIPS_INVAL("OPC_MXU_S32SDIV");
26191 generate_exception_end(ctx, EXCP_RI);
26192 break;
26193 case OPC_MXU_S32SDIVR:
26194 /* TODO: Implement emulation of S32SDIVR instruction. */
26195 MIPS_INVAL("OPC_MXU_S32SDIVR");
26196 generate_exception_end(ctx, EXCP_RI);
26197 break;
26198 default:
26199 MIPS_INVAL("decode_opc_mxu");
26200 generate_exception_end(ctx, EXCP_RI);
26201 break;
26202 }
26203}
26204
26205/*
26206 *
26207 * Decode MXU pool12
26208 *
26209 * 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
26210 * +-----------+---+---+-------+-------+-------+-------+-----------+
26211 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26212 * +-----------+---+---+-------+-------+-------+-------+-----------+
26213 *
26214 */
26215static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26216{
26217 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26218
26219 switch (opcode) {
26220 case OPC_MXU_D32ACC:
26221 /* TODO: Implement emulation of D32ACC instruction. */
26222 MIPS_INVAL("OPC_MXU_D32ACC");
26223 generate_exception_end(ctx, EXCP_RI);
26224 break;
26225 case OPC_MXU_D32ACCM:
26226 /* TODO: Implement emulation of D32ACCM instruction. */
26227 MIPS_INVAL("OPC_MXU_D32ACCM");
26228 generate_exception_end(ctx, EXCP_RI);
26229 break;
26230 case OPC_MXU_D32ASUM:
26231 /* TODO: Implement emulation of D32ASUM instruction. */
26232 MIPS_INVAL("OPC_MXU_D32ASUM");
26233 generate_exception_end(ctx, EXCP_RI);
26234 break;
26235 default:
26236 MIPS_INVAL("decode_opc_mxu");
26237 generate_exception_end(ctx, EXCP_RI);
26238 break;
26239 }
26240}
26241
26242/*
26243 *
26244 * Decode MXU pool13
26245 *
26246 * 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
26247 * +-----------+---+---+-------+-------+-------+-------+-----------+
26248 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26249 * +-----------+---+---+-------+-------+-------+-------+-----------+
26250 *
26251 */
26252static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26253{
26254 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26255
26256 switch (opcode) {
26257 case OPC_MXU_Q16ACC:
26258 /* TODO: Implement emulation of Q16ACC instruction. */
26259 MIPS_INVAL("OPC_MXU_Q16ACC");
26260 generate_exception_end(ctx, EXCP_RI);
26261 break;
26262 case OPC_MXU_Q16ACCM:
26263 /* TODO: Implement emulation of Q16ACCM instruction. */
26264 MIPS_INVAL("OPC_MXU_Q16ACCM");
26265 generate_exception_end(ctx, EXCP_RI);
26266 break;
26267 case OPC_MXU_Q16ASUM:
26268 /* TODO: Implement emulation of Q16ASUM instruction. */
26269 MIPS_INVAL("OPC_MXU_Q16ASUM");
26270 generate_exception_end(ctx, EXCP_RI);
26271 break;
26272 default:
26273 MIPS_INVAL("decode_opc_mxu");
26274 generate_exception_end(ctx, EXCP_RI);
26275 break;
26276 }
26277}
26278
26279/*
26280 *
26281 * Decode MXU pool14
26282 *
26283 * Q8ADDE, Q8ACCE:
26284 * 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
26285 * +-----------+---+---+-------+-------+-------+-------+-----------+
26286 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26287 * +-----------+---+---+-------+-------+-------+-------+-----------+
26288 *
26289 * D8SUM, D8SUMC:
26290 * 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
26291 * +-----------+---+---+-------+-------+-------+-------+-----------+
26292 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26293 * +-----------+---+---+-------+-------+-------+-------+-----------+
26294 *
26295 */
26296static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26297{
26298 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26299
26300 switch (opcode) {
26301 case OPC_MXU_Q8ADDE:
26302 /* TODO: Implement emulation of Q8ADDE instruction. */
26303 MIPS_INVAL("OPC_MXU_Q8ADDE");
26304 generate_exception_end(ctx, EXCP_RI);
26305 break;
26306 case OPC_MXU_D8SUM:
26307 /* TODO: Implement emulation of D8SUM instruction. */
26308 MIPS_INVAL("OPC_MXU_D8SUM");
26309 generate_exception_end(ctx, EXCP_RI);
26310 break;
26311 case OPC_MXU_D8SUMC:
26312 /* TODO: Implement emulation of D8SUMC instruction. */
26313 MIPS_INVAL("OPC_MXU_D8SUMC");
26314 generate_exception_end(ctx, EXCP_RI);
26315 break;
26316 default:
26317 MIPS_INVAL("decode_opc_mxu");
26318 generate_exception_end(ctx, EXCP_RI);
26319 break;
26320 }
26321}
26322
26323/*
26324 *
26325 * Decode MXU pool15
26326 *
26327 * S32MUL, S32MULU, S32EXTRV:
26328 * 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
26329 * +-----------+---------+---------+---+-------+-------+-----------+
26330 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26331 * +-----------+---------+---------+---+-------+-------+-----------+
26332 *
26333 * S32EXTR:
26334 * 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
26335 * +-----------+---------+---------+---+-------+-------+-----------+
26336 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26337 * +-----------+---------+---------+---+-------+-------+-----------+
26338 *
26339 */
26340static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26341{
26342 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26343
26344 switch (opcode) {
26345 case OPC_MXU_S32MUL:
26346 /* TODO: Implement emulation of S32MUL instruction. */
26347 MIPS_INVAL("OPC_MXU_S32MUL");
26348 generate_exception_end(ctx, EXCP_RI);
26349 break;
26350 case OPC_MXU_S32MULU:
26351 /* TODO: Implement emulation of S32MULU instruction. */
26352 MIPS_INVAL("OPC_MXU_S32MULU");
26353 generate_exception_end(ctx, EXCP_RI);
26354 break;
26355 case OPC_MXU_S32EXTR:
26356 /* TODO: Implement emulation of S32EXTR instruction. */
26357 MIPS_INVAL("OPC_MXU_S32EXTR");
26358 generate_exception_end(ctx, EXCP_RI);
26359 break;
26360 case OPC_MXU_S32EXTRV:
26361 /* TODO: Implement emulation of S32EXTRV instruction. */
26362 MIPS_INVAL("OPC_MXU_S32EXTRV");
26363 generate_exception_end(ctx, EXCP_RI);
26364 break;
26365 default:
26366 MIPS_INVAL("decode_opc_mxu");
26367 generate_exception_end(ctx, EXCP_RI);
26368 break;
26369 }
26370}
26371
26372/*
26373 *
26374 * Decode MXU pool16
26375 *
26376 * D32SARW:
26377 * 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
26378 * +-----------+---------+-----+-------+-------+-------+-----------+
26379 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26380 * +-----------+---------+-----+-------+-------+-------+-----------+
26381 *
26382 * S32ALN:
26383 * 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
26384 * +-----------+---------+-----+-------+-------+-------+-----------+
26385 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26386 * +-----------+---------+-----+-------+-------+-------+-----------+
26387 *
26388 * S32ALNI:
26389 * 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
26390 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26391 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26392 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26393 *
03f40088
AM
26394 * S32LUI:
26395 * 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
26396 * +-----------+-----+---+-----+-------+---------------+-----------+
26397 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26398 * +-----------+-----+---+-----+-------+---------------+-----------+
26399 *
b621f018
AM
26400 * S32NOR, S32AND, S32OR, S32XOR:
26401 * 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
26402 * +-----------+---------+-----+-------+-------+-------+-----------+
26403 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26404 * +-----------+---------+-----+-------+-------+-------+-----------+
26405 *
03f40088
AM
26406 */
26407static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26408{
26409 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26410
26411 switch (opcode) {
26412 case OPC_MXU_D32SARW:
26413 /* TODO: Implement emulation of D32SARW instruction. */
26414 MIPS_INVAL("OPC_MXU_D32SARW");
26415 generate_exception_end(ctx, EXCP_RI);
26416 break;
26417 case OPC_MXU_S32ALN:
26418 /* TODO: Implement emulation of S32ALN instruction. */
26419 MIPS_INVAL("OPC_MXU_S32ALN");
26420 generate_exception_end(ctx, EXCP_RI);
26421 break;
26422 case OPC_MXU_S32ALNI:
79f5fee7 26423 gen_mxu_S32ALNI(ctx);
03f40088 26424 break;
b621f018
AM
26425 case OPC_MXU_S32LUI:
26426 /* TODO: Implement emulation of S32LUI instruction. */
26427 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
26428 generate_exception_end(ctx, EXCP_RI);
26429 break;
b621f018
AM
26430 case OPC_MXU_S32NOR:
26431 gen_mxu_S32NOR(ctx);
26432 break;
03f40088 26433 case OPC_MXU_S32AND:
b621f018 26434 gen_mxu_S32AND(ctx);
03f40088
AM
26435 break;
26436 case OPC_MXU_S32OR:
b621f018 26437 gen_mxu_S32OR(ctx);
03f40088
AM
26438 break;
26439 case OPC_MXU_S32XOR:
b621f018 26440 gen_mxu_S32XOR(ctx);
03f40088
AM
26441 break;
26442 default:
26443 MIPS_INVAL("decode_opc_mxu");
26444 generate_exception_end(ctx, EXCP_RI);
26445 break;
26446 }
26447}
26448
26449/*
26450 *
26451 * Decode MXU pool17
26452 *
26453 * 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
26454 * +-----------+---------+---------+---+---------+-----+-----------+
26455 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26456 * +-----------+---------+---------+---+---------+-----+-----------+
26457 *
26458 */
26459static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26460{
26461 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26462
26463 switch (opcode) {
26464 case OPC_MXU_LXW:
26465 /* TODO: Implement emulation of LXW instruction. */
26466 MIPS_INVAL("OPC_MXU_LXW");
26467 generate_exception_end(ctx, EXCP_RI);
26468 break;
26469 case OPC_MXU_LXH:
26470 /* TODO: Implement emulation of LXH instruction. */
26471 MIPS_INVAL("OPC_MXU_LXH");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 case OPC_MXU_LXHU:
26475 /* TODO: Implement emulation of LXHU instruction. */
26476 MIPS_INVAL("OPC_MXU_LXHU");
26477 generate_exception_end(ctx, EXCP_RI);
26478 break;
26479 case OPC_MXU_LXB:
26480 /* TODO: Implement emulation of LXB instruction. */
26481 MIPS_INVAL("OPC_MXU_LXB");
26482 generate_exception_end(ctx, EXCP_RI);
26483 break;
26484 case OPC_MXU_LXBU:
26485 /* TODO: Implement emulation of LXBU instruction. */
26486 MIPS_INVAL("OPC_MXU_LXBU");
26487 generate_exception_end(ctx, EXCP_RI);
26488 break;
26489 default:
26490 MIPS_INVAL("decode_opc_mxu");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 }
26494}
26495/*
26496 *
26497 * Decode MXU pool18
26498 *
26499 * 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 26500 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26501 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
26502 * +-----------+---------+-----+-------+-------+-------+-----------+
26503 *
26504 */
c233bf07 26505static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26506{
26507 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26508
26509 switch (opcode) {
26510 case OPC_MXU_D32SLLV:
26511 /* TODO: Implement emulation of D32SLLV instruction. */
26512 MIPS_INVAL("OPC_MXU_D32SLLV");
26513 generate_exception_end(ctx, EXCP_RI);
26514 break;
26515 case OPC_MXU_D32SLRV:
26516 /* TODO: Implement emulation of D32SLRV instruction. */
26517 MIPS_INVAL("OPC_MXU_D32SLRV");
26518 generate_exception_end(ctx, EXCP_RI);
26519 break;
26520 case OPC_MXU_D32SARV:
26521 /* TODO: Implement emulation of D32SARV instruction. */
26522 MIPS_INVAL("OPC_MXU_D32SARV");
26523 generate_exception_end(ctx, EXCP_RI);
26524 break;
26525 case OPC_MXU_Q16SLLV:
26526 /* TODO: Implement emulation of Q16SLLV instruction. */
26527 MIPS_INVAL("OPC_MXU_Q16SLLV");
26528 generate_exception_end(ctx, EXCP_RI);
26529 break;
26530 case OPC_MXU_Q16SLRV:
26531 /* TODO: Implement emulation of Q16SLRV instruction. */
26532 MIPS_INVAL("OPC_MXU_Q16SLRV");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26535 case OPC_MXU_Q16SARV:
26536 /* TODO: Implement emulation of Q16SARV instruction. */
26537 MIPS_INVAL("OPC_MXU_Q16SARV");
26538 generate_exception_end(ctx, EXCP_RI);
26539 break;
26540 default:
26541 MIPS_INVAL("decode_opc_mxu");
26542 generate_exception_end(ctx, EXCP_RI);
26543 break;
26544 }
26545}
26546
26547/*
26548 *
c233bf07 26549 * Decode MXU pool19
03f40088
AM
26550 *
26551 * 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
26552 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26553 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
26554 * +-----------+---+---+-------+-------+-------+-------+-----------+
26555 *
26556 */
c233bf07 26557static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26558{
26559 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26560
26561 switch (opcode) {
26562 case OPC_MXU_Q8MUL:
03f40088 26563 case OPC_MXU_Q8MULSU:
a9a4181b 26564 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
26565 break;
26566 default:
26567 MIPS_INVAL("decode_opc_mxu");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 }
26571}
26572
26573/*
26574 *
c233bf07 26575 * Decode MXU pool20
03f40088
AM
26576 *
26577 * 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
26578 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26579 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
26580 * +-----------+---------+-----+-------+-------+-------+-----------+
26581 *
26582 */
c233bf07 26583static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26584{
26585 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26586
26587 switch (opcode) {
26588 case OPC_MXU_Q8MOVZ:
26589 /* TODO: Implement emulation of Q8MOVZ instruction. */
26590 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26591 generate_exception_end(ctx, EXCP_RI);
26592 break;
26593 case OPC_MXU_Q8MOVN:
26594 /* TODO: Implement emulation of Q8MOVN instruction. */
26595 MIPS_INVAL("OPC_MXU_Q8MOVN");
26596 generate_exception_end(ctx, EXCP_RI);
26597 break;
26598 case OPC_MXU_D16MOVZ:
26599 /* TODO: Implement emulation of D16MOVZ instruction. */
26600 MIPS_INVAL("OPC_MXU_D16MOVZ");
26601 generate_exception_end(ctx, EXCP_RI);
26602 break;
26603 case OPC_MXU_D16MOVN:
26604 /* TODO: Implement emulation of D16MOVN instruction. */
26605 MIPS_INVAL("OPC_MXU_D16MOVN");
26606 generate_exception_end(ctx, EXCP_RI);
26607 break;
26608 case OPC_MXU_S32MOVZ:
26609 /* TODO: Implement emulation of S32MOVZ instruction. */
26610 MIPS_INVAL("OPC_MXU_S32MOVZ");
26611 generate_exception_end(ctx, EXCP_RI);
26612 break;
26613 case OPC_MXU_S32MOVN:
26614 /* TODO: Implement emulation of S32MOVN instruction. */
26615 MIPS_INVAL("OPC_MXU_S32MOVN");
26616 generate_exception_end(ctx, EXCP_RI);
26617 break;
26618 default:
26619 MIPS_INVAL("decode_opc_mxu");
26620 generate_exception_end(ctx, EXCP_RI);
26621 break;
26622 }
26623}
26624
26625/*
26626 *
c233bf07 26627 * Decode MXU pool21
03f40088
AM
26628 *
26629 * 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
26630 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26631 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
26632 * +-----------+---+---+-------+-------+-------+-------+-----------+
26633 *
26634 */
c233bf07 26635static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26636{
26637 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26638
26639 switch (opcode) {
26640 case OPC_MXU_Q8MAC:
26641 /* TODO: Implement emulation of Q8MAC instruction. */
26642 MIPS_INVAL("OPC_MXU_Q8MAC");
26643 generate_exception_end(ctx, EXCP_RI);
26644 break;
26645 case OPC_MXU_Q8MACSU:
26646 /* TODO: Implement emulation of Q8MACSU instruction. */
26647 MIPS_INVAL("OPC_MXU_Q8MACSU");
26648 generate_exception_end(ctx, EXCP_RI);
26649 break;
26650 default:
26651 MIPS_INVAL("decode_opc_mxu");
26652 generate_exception_end(ctx, EXCP_RI);
26653 break;
26654 }
26655}
26656
26657
26658/*
26659 * Main MXU decoding function
26660 *
26661 * 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
26662 * +-----------+---------------------------------------+-----------+
26663 * | SPECIAL2 | |x x x x x x|
26664 * +-----------+---------------------------------------+-----------+
26665 *
26666 */
0a348b9a
AM
26667static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26668{
11d56f61
CJ
26669 /*
26670 * TODO: Investigate necessity of including handling of
26671 * CLZ, CLO, SDBB in this function, as they belong to
26672 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26673 */
03f40088
AM
26674 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26675
87860df5
AM
26676 if (opcode == OPC__MXU_MUL) {
26677 uint32_t rs, rt, rd, op1;
26678
26679 rs = extract32(ctx->opcode, 21, 5);
26680 rt = extract32(ctx->opcode, 16, 5);
26681 rd = extract32(ctx->opcode, 11, 5);
26682 op1 = MASK_SPECIAL2(ctx->opcode);
26683
26684 gen_arith(ctx, op1, rd, rs, rt);
26685
26686 return;
26687 }
26688
26689 if (opcode == OPC_MXU_S32M2I) {
26690 gen_mxu_s32m2i(ctx);
26691 return;
26692 }
26693
26694 if (opcode == OPC_MXU_S32I2M) {
26695 gen_mxu_s32i2m(ctx);
26696 return;
26697 }
26698
e5bf8a08
AM
26699 {
26700 TCGv t_mxu_cr = tcg_temp_new();
26701 TCGLabel *l_exit = gen_new_label();
26702
26703 gen_load_mxu_cr(t_mxu_cr);
26704 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26705 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26706
26707 switch (opcode) {
26708 case OPC_MXU_S32MADD:
26709 /* TODO: Implement emulation of S32MADD instruction. */
26710 MIPS_INVAL("OPC_MXU_S32MADD");
26711 generate_exception_end(ctx, EXCP_RI);
26712 break;
26713 case OPC_MXU_S32MADDU:
26714 /* TODO: Implement emulation of S32MADDU instruction. */
26715 MIPS_INVAL("OPC_MXU_S32MADDU");
26716 generate_exception_end(ctx, EXCP_RI);
26717 break;
26718 case OPC_MXU__POOL00:
26719 decode_opc_mxu__pool00(env, ctx);
26720 break;
26721 case OPC_MXU_S32MSUB:
26722 /* TODO: Implement emulation of S32MSUB instruction. */
26723 MIPS_INVAL("OPC_MXU_S32MSUB");
26724 generate_exception_end(ctx, EXCP_RI);
26725 break;
26726 case OPC_MXU_S32MSUBU:
26727 /* TODO: Implement emulation of S32MSUBU instruction. */
26728 MIPS_INVAL("OPC_MXU_S32MSUBU");
26729 generate_exception_end(ctx, EXCP_RI);
26730 break;
26731 case OPC_MXU__POOL01:
26732 decode_opc_mxu__pool01(env, ctx);
26733 break;
26734 case OPC_MXU__POOL02:
26735 decode_opc_mxu__pool02(env, ctx);
26736 break;
26737 case OPC_MXU_D16MUL:
26738 gen_mxu_d16mul(ctx);
26739 break;
26740 case OPC_MXU__POOL03:
26741 decode_opc_mxu__pool03(env, ctx);
26742 break;
26743 case OPC_MXU_D16MAC:
26744 gen_mxu_d16mac(ctx);
26745 break;
26746 case OPC_MXU_D16MACF:
26747 /* TODO: Implement emulation of D16MACF instruction. */
26748 MIPS_INVAL("OPC_MXU_D16MACF");
26749 generate_exception_end(ctx, EXCP_RI);
26750 break;
26751 case OPC_MXU_D16MADL:
26752 /* TODO: Implement emulation of D16MADL instruction. */
26753 MIPS_INVAL("OPC_MXU_D16MADL");
26754 generate_exception_end(ctx, EXCP_RI);
26755 break;
26756 case OPC_MXU_S16MAD:
26757 /* TODO: Implement emulation of S16MAD instruction. */
26758 MIPS_INVAL("OPC_MXU_S16MAD");
26759 generate_exception_end(ctx, EXCP_RI);
26760 break;
26761 case OPC_MXU_Q16ADD:
26762 /* TODO: Implement emulation of Q16ADD instruction. */
26763 MIPS_INVAL("OPC_MXU_Q16ADD");
26764 generate_exception_end(ctx, EXCP_RI);
26765 break;
26766 case OPC_MXU_D16MACE:
26767 /* TODO: Implement emulation of D16MACE instruction. */
26768 MIPS_INVAL("OPC_MXU_D16MACE");
26769 generate_exception_end(ctx, EXCP_RI);
26770 break;
26771 case OPC_MXU__POOL04:
26772 decode_opc_mxu__pool04(env, ctx);
26773 break;
26774 case OPC_MXU__POOL05:
26775 decode_opc_mxu__pool05(env, ctx);
26776 break;
26777 case OPC_MXU__POOL06:
26778 decode_opc_mxu__pool06(env, ctx);
26779 break;
26780 case OPC_MXU__POOL07:
26781 decode_opc_mxu__pool07(env, ctx);
26782 break;
26783 case OPC_MXU__POOL08:
26784 decode_opc_mxu__pool08(env, ctx);
26785 break;
26786 case OPC_MXU__POOL09:
26787 decode_opc_mxu__pool09(env, ctx);
26788 break;
26789 case OPC_MXU__POOL10:
26790 decode_opc_mxu__pool10(env, ctx);
26791 break;
26792 case OPC_MXU__POOL11:
26793 decode_opc_mxu__pool11(env, ctx);
26794 break;
26795 case OPC_MXU_D32ADD:
26796 /* TODO: Implement emulation of D32ADD instruction. */
26797 MIPS_INVAL("OPC_MXU_D32ADD");
26798 generate_exception_end(ctx, EXCP_RI);
26799 break;
26800 case OPC_MXU__POOL12:
26801 decode_opc_mxu__pool12(env, ctx);
26802 break;
26803 case OPC_MXU__POOL13:
26804 decode_opc_mxu__pool13(env, ctx);
26805 break;
26806 case OPC_MXU__POOL14:
26807 decode_opc_mxu__pool14(env, ctx);
26808 break;
26809 case OPC_MXU_Q8ACCE:
26810 /* TODO: Implement emulation of Q8ACCE instruction. */
26811 MIPS_INVAL("OPC_MXU_Q8ACCE");
26812 generate_exception_end(ctx, EXCP_RI);
26813 break;
26814 case OPC_MXU_S8LDD:
26815 gen_mxu_s8ldd(ctx);
26816 break;
26817 case OPC_MXU_S8STD:
26818 /* TODO: Implement emulation of S8STD instruction. */
26819 MIPS_INVAL("OPC_MXU_S8STD");
26820 generate_exception_end(ctx, EXCP_RI);
26821 break;
26822 case OPC_MXU_S8LDI:
26823 /* TODO: Implement emulation of S8LDI instruction. */
26824 MIPS_INVAL("OPC_MXU_S8LDI");
26825 generate_exception_end(ctx, EXCP_RI);
26826 break;
26827 case OPC_MXU_S8SDI:
26828 /* TODO: Implement emulation of S8SDI instruction. */
26829 MIPS_INVAL("OPC_MXU_S8SDI");
26830 generate_exception_end(ctx, EXCP_RI);
26831 break;
26832 case OPC_MXU__POOL15:
26833 decode_opc_mxu__pool15(env, ctx);
26834 break;
26835 case OPC_MXU__POOL16:
26836 decode_opc_mxu__pool16(env, ctx);
26837 break;
c233bf07
AM
26838 case OPC_MXU__POOL17:
26839 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
26840 break;
26841 case OPC_MXU_S16LDD:
26842 /* TODO: Implement emulation of S16LDD instruction. */
26843 MIPS_INVAL("OPC_MXU_S16LDD");
26844 generate_exception_end(ctx, EXCP_RI);
26845 break;
26846 case OPC_MXU_S16STD:
26847 /* TODO: Implement emulation of S16STD instruction. */
26848 MIPS_INVAL("OPC_MXU_S16STD");
26849 generate_exception_end(ctx, EXCP_RI);
26850 break;
26851 case OPC_MXU_S16LDI:
26852 /* TODO: Implement emulation of S16LDI instruction. */
26853 MIPS_INVAL("OPC_MXU_S16LDI");
26854 generate_exception_end(ctx, EXCP_RI);
26855 break;
26856 case OPC_MXU_S16SDI:
26857 /* TODO: Implement emulation of S16SDI instruction. */
26858 MIPS_INVAL("OPC_MXU_S16SDI");
26859 generate_exception_end(ctx, EXCP_RI);
26860 break;
26861 case OPC_MXU_D32SLL:
26862 /* TODO: Implement emulation of D32SLL instruction. */
26863 MIPS_INVAL("OPC_MXU_D32SLL");
26864 generate_exception_end(ctx, EXCP_RI);
26865 break;
26866 case OPC_MXU_D32SLR:
26867 /* TODO: Implement emulation of D32SLR instruction. */
26868 MIPS_INVAL("OPC_MXU_D32SLR");
26869 generate_exception_end(ctx, EXCP_RI);
26870 break;
26871 case OPC_MXU_D32SARL:
26872 /* TODO: Implement emulation of D32SARL instruction. */
26873 MIPS_INVAL("OPC_MXU_D32SARL");
26874 generate_exception_end(ctx, EXCP_RI);
26875 break;
26876 case OPC_MXU_D32SAR:
26877 /* TODO: Implement emulation of D32SAR instruction. */
26878 MIPS_INVAL("OPC_MXU_D32SAR");
26879 generate_exception_end(ctx, EXCP_RI);
26880 break;
26881 case OPC_MXU_Q16SLL:
26882 /* TODO: Implement emulation of Q16SLL instruction. */
26883 MIPS_INVAL("OPC_MXU_Q16SLL");
26884 generate_exception_end(ctx, EXCP_RI);
26885 break;
26886 case OPC_MXU_Q16SLR:
26887 /* TODO: Implement emulation of Q16SLR instruction. */
26888 MIPS_INVAL("OPC_MXU_Q16SLR");
26889 generate_exception_end(ctx, EXCP_RI);
26890 break;
c233bf07
AM
26891 case OPC_MXU__POOL18:
26892 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
26893 break;
26894 case OPC_MXU_Q16SAR:
26895 /* TODO: Implement emulation of Q16SAR instruction. */
26896 MIPS_INVAL("OPC_MXU_Q16SAR");
26897 generate_exception_end(ctx, EXCP_RI);
26898 break;
e5bf8a08
AM
26899 case OPC_MXU__POOL19:
26900 decode_opc_mxu__pool19(env, ctx);
26901 break;
26902 case OPC_MXU__POOL20:
26903 decode_opc_mxu__pool20(env, ctx);
26904 break;
c233bf07
AM
26905 case OPC_MXU__POOL21:
26906 decode_opc_mxu__pool21(env, ctx);
26907 break;
e5bf8a08
AM
26908 case OPC_MXU_Q16SCOP:
26909 /* TODO: Implement emulation of Q16SCOP instruction. */
26910 MIPS_INVAL("OPC_MXU_Q16SCOP");
26911 generate_exception_end(ctx, EXCP_RI);
26912 break;
26913 case OPC_MXU_Q8MADL:
26914 /* TODO: Implement emulation of Q8MADL instruction. */
26915 MIPS_INVAL("OPC_MXU_Q8MADL");
26916 generate_exception_end(ctx, EXCP_RI);
26917 break;
26918 case OPC_MXU_S32SFL:
26919 /* TODO: Implement emulation of S32SFL instruction. */
26920 MIPS_INVAL("OPC_MXU_S32SFL");
26921 generate_exception_end(ctx, EXCP_RI);
26922 break;
26923 case OPC_MXU_Q8SAD:
26924 /* TODO: Implement emulation of Q8SAD instruction. */
26925 MIPS_INVAL("OPC_MXU_Q8SAD");
26926 generate_exception_end(ctx, EXCP_RI);
26927 break;
26928 default:
26929 MIPS_INVAL("decode_opc_mxu");
26930 generate_exception_end(ctx, EXCP_RI);
26931 }
26932
26933 gen_set_label(l_exit);
26934 tcg_temp_free(t_mxu_cr);
03f40088 26935 }
0a348b9a
AM
26936}
26937
b621f018
AM
26938#endif /* !defined(TARGET_MIPS64) */
26939
03f40088 26940
10dc65db 26941static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
26942{
26943 int rs, rt, rd;
26944 uint32_t op1;
6c5c1e20 26945
4267d3e6
LA
26946 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26947
099e5b4d
LA
26948 rs = (ctx->opcode >> 21) & 0x1f;
26949 rt = (ctx->opcode >> 16) & 0x1f;
26950 rd = (ctx->opcode >> 11) & 0x1f;
26951
26952 op1 = MASK_SPECIAL2(ctx->opcode);
26953 switch (op1) {
c2e19f3c
AM
26954 case OPC_MADD: /* Multiply and add/sub */
26955 case OPC_MADDU:
26956 case OPC_MSUB:
26957 case OPC_MSUBU:
099e5b4d
LA
26958 check_insn(ctx, ISA_MIPS32);
26959 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26960 break;
26961 case OPC_MUL:
099e5b4d
LA
26962 gen_arith(ctx, op1, rd, rs, rt);
26963 break;
fac5a073
LA
26964 case OPC_DIV_G_2F:
26965 case OPC_DIVU_G_2F:
26966 case OPC_MULT_G_2F:
26967 case OPC_MULTU_G_2F:
26968 case OPC_MOD_G_2F:
26969 case OPC_MODU_G_2F:
26970 check_insn(ctx, INSN_LOONGSON2F);
26971 gen_loongson_integer(ctx, op1, rd, rs, rt);
26972 break;
099e5b4d
LA
26973 case OPC_CLO:
26974 case OPC_CLZ:
26975 check_insn(ctx, ISA_MIPS32);
26976 gen_cl(ctx, op1, rd, rs);
26977 break;
26978 case OPC_SDBBP:
3b3c1694
LA
26979 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26980 gen_helper_do_semihosting(cpu_env);
26981 } else {
7480515f
AM
26982 /*
26983 * XXX: not clear which exception should be raised
3b3c1694
LA
26984 * when in debug mode...
26985 */
26986 check_insn(ctx, ISA_MIPS32);
9c708c7f 26987 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 26988 }
099e5b4d 26989 break;
9b1a1d68 26990#if defined(TARGET_MIPS64)
099e5b4d
LA
26991 case OPC_DCLO:
26992 case OPC_DCLZ:
26993 check_insn(ctx, ISA_MIPS64);
26994 check_mips_64(ctx);
26995 gen_cl(ctx, op1, rd, rs);
26996 break;
4267d3e6
LA
26997 case OPC_DMULT_G_2F:
26998 case OPC_DMULTU_G_2F:
26999 case OPC_DDIV_G_2F:
27000 case OPC_DDIVU_G_2F:
27001 case OPC_DMOD_G_2F:
27002 case OPC_DMODU_G_2F:
27003 check_insn(ctx, INSN_LOONGSON2F);
27004 gen_loongson_integer(ctx, op1, rd, rs, rt);
27005 break;
10dc65db 27006#endif
4267d3e6
LA
27007 default: /* Invalid */
27008 MIPS_INVAL("special2_legacy");
9c708c7f 27009 generate_exception_end(ctx, EXCP_RI);
4267d3e6 27010 break;
10dc65db
LA
27011 }
27012}
27013
27014static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27015{
15eacb9b
YK
27016 int rs, rt, rd, sa;
27017 uint32_t op1, op2;
10dc65db
LA
27018 int16_t imm;
27019
27020 rs = (ctx->opcode >> 21) & 0x1f;
27021 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
27022 rd = (ctx->opcode >> 11) & 0x1f;
27023 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
27024 imm = (int16_t)ctx->opcode >> 7;
27025
27026 op1 = MASK_SPECIAL3(ctx->opcode);
27027 switch (op1) {
bf7910c6
LA
27028 case R6_OPC_PREF:
27029 if (rt >= 24) {
27030 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 27031 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
27032 }
27033 /* Treat as NOP. */
27034 break;
27035 case R6_OPC_CACHE:
40d48212 27036 check_cp0_enabled(ctx);
0d74a222
LA
27037 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27038 gen_cache_operation(ctx, rt, rs, imm);
27039 }
bf7910c6 27040 break;
10dc65db 27041 case R6_OPC_SC:
33a07fa2 27042 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
27043 break;
27044 case R6_OPC_LL:
27045 gen_ld(ctx, op1, rt, rs, imm);
27046 break;
15eacb9b
YK
27047 case OPC_BSHFL:
27048 {
27049 if (rd == 0) {
27050 /* Treat as NOP. */
27051 break;
27052 }
15eacb9b
YK
27053 op2 = MASK_BSHFL(ctx->opcode);
27054 switch (op2) {
c2e19f3c 27055 case OPC_ALIGN:
373ecd38
AM
27056 case OPC_ALIGN_1:
27057 case OPC_ALIGN_2:
27058 case OPC_ALIGN_3:
821f2008 27059 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
27060 break;
27061 case OPC_BITSWAP:
1f1b4c00 27062 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27063 break;
27064 }
15eacb9b
YK
27065 }
27066 break;
bf7910c6
LA
27067#if defined(TARGET_MIPS64)
27068 case R6_OPC_SCD:
33a07fa2 27069 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
27070 break;
27071 case R6_OPC_LLD:
27072 gen_ld(ctx, op1, rt, rs, imm);
27073 break;
15eacb9b
YK
27074 case OPC_DBSHFL:
27075 check_mips_64(ctx);
27076 {
27077 if (rd == 0) {
27078 /* Treat as NOP. */
27079 break;
27080 }
15eacb9b
YK
27081 op2 = MASK_DBSHFL(ctx->opcode);
27082 switch (op2) {
c2e19f3c 27083 case OPC_DALIGN:
373ecd38
AM
27084 case OPC_DALIGN_1:
27085 case OPC_DALIGN_2:
27086 case OPC_DALIGN_3:
27087 case OPC_DALIGN_4:
27088 case OPC_DALIGN_5:
27089 case OPC_DALIGN_6:
27090 case OPC_DALIGN_7:
821f2008 27091 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
27092 break;
27093 case OPC_DBITSWAP:
1f1b4c00 27094 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27095 break;
27096 }
1f1b4c00 27097
15eacb9b
YK
27098 }
27099 break;
bf7910c6 27100#endif
10dc65db
LA
27101 default: /* Invalid */
27102 MIPS_INVAL("special3_r6");
9c708c7f 27103 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
27104 break;
27105 }
27106}
27107
27108static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27109{
fac5a073 27110 int rs, rt, rd;
099e5b4d 27111 uint32_t op1, op2;
099e5b4d
LA
27112
27113 rs = (ctx->opcode >> 21) & 0x1f;
27114 rt = (ctx->opcode >> 16) & 0x1f;
27115 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
27116
27117 op1 = MASK_SPECIAL3(ctx->opcode);
27118 switch (op1) {
c2e19f3c
AM
27119 case OPC_DIV_G_2E:
27120 case OPC_DIVU_G_2E:
27121 case OPC_MOD_G_2E:
27122 case OPC_MODU_G_2E:
27123 case OPC_MULT_G_2E:
27124 case OPC_MULTU_G_2E:
7480515f
AM
27125 /*
27126 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27127 * the same mask and op1.
27128 */
908f6be1 27129 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 27130 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 27131 switch (op2) {
099e5b4d
LA
27132 case OPC_ADDUH_QB:
27133 case OPC_ADDUH_R_QB:
27134 case OPC_ADDQH_PH:
27135 case OPC_ADDQH_R_PH:
27136 case OPC_ADDQH_W:
27137 case OPC_ADDQH_R_W:
27138 case OPC_SUBUH_QB:
27139 case OPC_SUBUH_R_QB:
27140 case OPC_SUBQH_PH:
27141 case OPC_SUBQH_R_PH:
27142 case OPC_SUBQH_W:
27143 case OPC_SUBQH_R_W:
461c08df
JL
27144 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27145 break;
099e5b4d
LA
27146 case OPC_MUL_PH:
27147 case OPC_MUL_S_PH:
27148 case OPC_MULQ_S_W:
27149 case OPC_MULQ_RS_W:
27150 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27151 break;
461c08df 27152 default:
099e5b4d 27153 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 27154 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
27155 break;
27156 }
099e5b4d
LA
27157 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27158 gen_loongson_integer(ctx, op1, rd, rs, rt);
27159 } else {
9c708c7f 27160 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27161 }
27162 break;
27163 case OPC_LX_DSP:
27164 op2 = MASK_LX(ctx->opcode);
27165 switch (op2) {
27166#if defined(TARGET_MIPS64)
27167 case OPC_LDX:
27168#endif
27169 case OPC_LBUX:
27170 case OPC_LHX:
27171 case OPC_LWX:
27172 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27173 break;
27174 default: /* Invalid */
27175 MIPS_INVAL("MASK LX");
9c708c7f 27176 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27177 break;
27178 }
27179 break;
27180 case OPC_ABSQ_S_PH_DSP:
27181 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27182 switch (op2) {
27183 case OPC_ABSQ_S_QB:
27184 case OPC_ABSQ_S_PH:
27185 case OPC_ABSQ_S_W:
27186 case OPC_PRECEQ_W_PHL:
27187 case OPC_PRECEQ_W_PHR:
27188 case OPC_PRECEQU_PH_QBL:
27189 case OPC_PRECEQU_PH_QBR:
27190 case OPC_PRECEQU_PH_QBLA:
27191 case OPC_PRECEQU_PH_QBRA:
27192 case OPC_PRECEU_PH_QBL:
27193 case OPC_PRECEU_PH_QBR:
27194 case OPC_PRECEU_PH_QBLA:
27195 case OPC_PRECEU_PH_QBRA:
27196 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27197 break;
27198 case OPC_BITREV:
27199 case OPC_REPL_QB:
27200 case OPC_REPLV_QB:
27201 case OPC_REPL_PH:
27202 case OPC_REPLV_PH:
27203 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27204 break;
27205 default:
27206 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 27207 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27208 break;
27209 }
27210 break;
27211 case OPC_ADDU_QB_DSP:
27212 op2 = MASK_ADDU_QB(ctx->opcode);
27213 switch (op2) {
27214 case OPC_ADDQ_PH:
27215 case OPC_ADDQ_S_PH:
27216 case OPC_ADDQ_S_W:
27217 case OPC_ADDU_QB:
27218 case OPC_ADDU_S_QB:
27219 case OPC_ADDU_PH:
27220 case OPC_ADDU_S_PH:
27221 case OPC_SUBQ_PH:
27222 case OPC_SUBQ_S_PH:
27223 case OPC_SUBQ_S_W:
27224 case OPC_SUBU_QB:
27225 case OPC_SUBU_S_QB:
27226 case OPC_SUBU_PH:
27227 case OPC_SUBU_S_PH:
27228 case OPC_ADDSC:
27229 case OPC_ADDWC:
27230 case OPC_MODSUB:
27231 case OPC_RADDU_W_QB:
27232 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27233 break;
27234 case OPC_MULEU_S_PH_QBL:
27235 case OPC_MULEU_S_PH_QBR:
27236 case OPC_MULQ_RS_PH:
27237 case OPC_MULEQ_S_W_PHL:
27238 case OPC_MULEQ_S_W_PHR:
27239 case OPC_MULQ_S_PH:
27240 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27241 break;
27242 default: /* Invalid */
27243 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 27244 generate_exception_end(ctx, EXCP_RI);
461c08df 27245 break;
461c08df 27246
099e5b4d
LA
27247 }
27248 break;
27249 case OPC_CMPU_EQ_QB_DSP:
27250 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27251 switch (op2) {
27252 case OPC_PRECR_SRA_PH_W:
27253 case OPC_PRECR_SRA_R_PH_W:
27254 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 27255 break;
099e5b4d
LA
27256 case OPC_PRECR_QB_PH:
27257 case OPC_PRECRQ_QB_PH:
27258 case OPC_PRECRQ_PH_W:
27259 case OPC_PRECRQ_RS_PH_W:
27260 case OPC_PRECRQU_S_QB_PH:
27261 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 27262 break;
099e5b4d
LA
27263 case OPC_CMPU_EQ_QB:
27264 case OPC_CMPU_LT_QB:
27265 case OPC_CMPU_LE_QB:
27266 case OPC_CMP_EQ_PH:
27267 case OPC_CMP_LT_PH:
27268 case OPC_CMP_LE_PH:
27269 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 27270 break;
099e5b4d
LA
27271 case OPC_CMPGU_EQ_QB:
27272 case OPC_CMPGU_LT_QB:
27273 case OPC_CMPGU_LE_QB:
27274 case OPC_CMPGDU_EQ_QB:
27275 case OPC_CMPGDU_LT_QB:
27276 case OPC_CMPGDU_LE_QB:
27277 case OPC_PICK_QB:
27278 case OPC_PICK_PH:
27279 case OPC_PACKRL_PH:
27280 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27281 break;
27282 default: /* Invalid */
27283 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 27284 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27285 break;
27286 }
27287 break;
27288 case OPC_SHLL_QB_DSP:
27289 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27290 break;
27291 case OPC_DPA_W_PH_DSP:
27292 op2 = MASK_DPA_W_PH(ctx->opcode);
27293 switch (op2) {
27294 case OPC_DPAU_H_QBL:
27295 case OPC_DPAU_H_QBR:
27296 case OPC_DPSU_H_QBL:
27297 case OPC_DPSU_H_QBR:
27298 case OPC_DPA_W_PH:
27299 case OPC_DPAX_W_PH:
27300 case OPC_DPAQ_S_W_PH:
27301 case OPC_DPAQX_S_W_PH:
27302 case OPC_DPAQX_SA_W_PH:
27303 case OPC_DPS_W_PH:
27304 case OPC_DPSX_W_PH:
27305 case OPC_DPSQ_S_W_PH:
27306 case OPC_DPSQX_S_W_PH:
27307 case OPC_DPSQX_SA_W_PH:
27308 case OPC_MULSAQ_S_W_PH:
27309 case OPC_DPAQ_SA_L_W:
27310 case OPC_DPSQ_SA_L_W:
27311 case OPC_MAQ_S_W_PHL:
27312 case OPC_MAQ_S_W_PHR:
27313 case OPC_MAQ_SA_W_PHL:
27314 case OPC_MAQ_SA_W_PHR:
27315 case OPC_MULSA_W_PH:
27316 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27317 break;
27318 default: /* Invalid */
27319 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 27320 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27321 break;
27322 }
27323 break;
27324 case OPC_INSV_DSP:
27325 op2 = MASK_INSV(ctx->opcode);
27326 switch (op2) {
27327 case OPC_INSV:
27328 check_dsp(ctx);
27329 {
27330 TCGv t0, t1;
27331
27332 if (rt == 0) {
099e5b4d
LA
27333 break;
27334 }
27335
27336 t0 = tcg_temp_new();
27337 t1 = tcg_temp_new();
27338
27339 gen_load_gpr(t0, rt);
27340 gen_load_gpr(t1, rs);
27341
27342 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27343
27344 tcg_temp_free(t0);
27345 tcg_temp_free(t1);
a22260ae
JL
27346 break;
27347 }
099e5b4d
LA
27348 default: /* Invalid */
27349 MIPS_INVAL("MASK INSV");
9c708c7f 27350 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27351 break;
27352 }
27353 break;
27354 case OPC_APPEND_DSP:
27355 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27356 break;
27357 case OPC_EXTR_W_DSP:
27358 op2 = MASK_EXTR_W(ctx->opcode);
27359 switch (op2) {
27360 case OPC_EXTR_W:
27361 case OPC_EXTR_R_W:
27362 case OPC_EXTR_RS_W:
27363 case OPC_EXTR_S_H:
27364 case OPC_EXTRV_S_H:
27365 case OPC_EXTRV_W:
27366 case OPC_EXTRV_R_W:
27367 case OPC_EXTRV_RS_W:
27368 case OPC_EXTP:
27369 case OPC_EXTPV:
27370 case OPC_EXTPDP:
27371 case OPC_EXTPDPV:
27372 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27373 break;
27374 case OPC_RDDSP:
27375 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27376 break;
27377 case OPC_SHILO:
27378 case OPC_SHILOV:
27379 case OPC_MTHLIP:
27380 case OPC_WRDSP:
27381 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27382 break;
27383 default: /* Invalid */
27384 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27385 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27386 break;
27387 }
27388 break;
099e5b4d 27389#if defined(TARGET_MIPS64)
c2e19f3c
AM
27390 case OPC_DDIV_G_2E:
27391 case OPC_DDIVU_G_2E:
27392 case OPC_DMULT_G_2E:
27393 case OPC_DMULTU_G_2E:
27394 case OPC_DMOD_G_2E:
27395 case OPC_DMODU_G_2E:
fac5a073
LA
27396 check_insn(ctx, INSN_LOONGSON2E);
27397 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 27398 break;
099e5b4d
LA
27399 case OPC_ABSQ_S_QH_DSP:
27400 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27401 switch (op2) {
27402 case OPC_PRECEQ_L_PWL:
27403 case OPC_PRECEQ_L_PWR:
27404 case OPC_PRECEQ_PW_QHL:
27405 case OPC_PRECEQ_PW_QHR:
27406 case OPC_PRECEQ_PW_QHLA:
27407 case OPC_PRECEQ_PW_QHRA:
27408 case OPC_PRECEQU_QH_OBL:
27409 case OPC_PRECEQU_QH_OBR:
27410 case OPC_PRECEQU_QH_OBLA:
27411 case OPC_PRECEQU_QH_OBRA:
27412 case OPC_PRECEU_QH_OBL:
27413 case OPC_PRECEU_QH_OBR:
27414 case OPC_PRECEU_QH_OBLA:
27415 case OPC_PRECEU_QH_OBRA:
27416 case OPC_ABSQ_S_OB:
27417 case OPC_ABSQ_S_PW:
27418 case OPC_ABSQ_S_QH:
27419 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27420 break;
27421 case OPC_REPL_OB:
27422 case OPC_REPL_PW:
27423 case OPC_REPL_QH:
27424 case OPC_REPLV_OB:
27425 case OPC_REPLV_PW:
27426 case OPC_REPLV_QH:
27427 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27428 break;
27429 default: /* Invalid */
27430 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 27431 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27432 break;
27433 }
27434 break;
27435 case OPC_ADDU_OB_DSP:
27436 op2 = MASK_ADDU_OB(ctx->opcode);
27437 switch (op2) {
27438 case OPC_RADDU_L_OB:
27439 case OPC_SUBQ_PW:
27440 case OPC_SUBQ_S_PW:
27441 case OPC_SUBQ_QH:
27442 case OPC_SUBQ_S_QH:
27443 case OPC_SUBU_OB:
27444 case OPC_SUBU_S_OB:
27445 case OPC_SUBU_QH:
27446 case OPC_SUBU_S_QH:
27447 case OPC_SUBUH_OB:
27448 case OPC_SUBUH_R_OB:
27449 case OPC_ADDQ_PW:
27450 case OPC_ADDQ_S_PW:
27451 case OPC_ADDQ_QH:
27452 case OPC_ADDQ_S_QH:
27453 case OPC_ADDU_OB:
27454 case OPC_ADDU_S_OB:
27455 case OPC_ADDU_QH:
27456 case OPC_ADDU_S_QH:
27457 case OPC_ADDUH_OB:
27458 case OPC_ADDUH_R_OB:
27459 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 27460 break;
099e5b4d
LA
27461 case OPC_MULEQ_S_PW_QHL:
27462 case OPC_MULEQ_S_PW_QHR:
27463 case OPC_MULEU_S_QH_OBL:
27464 case OPC_MULEU_S_QH_OBR:
27465 case OPC_MULQ_RS_QH:
27466 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27467 break;
099e5b4d
LA
27468 default: /* Invalid */
27469 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 27470 generate_exception_end(ctx, EXCP_RI);
26690560 27471 break;
099e5b4d
LA
27472 }
27473 break;
27474 case OPC_CMPU_EQ_OB_DSP:
27475 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27476 switch (op2) {
27477 case OPC_PRECR_SRA_QH_PW:
27478 case OPC_PRECR_SRA_R_QH_PW:
27479 /* Return value is rt. */
27480 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 27481 break;
099e5b4d
LA
27482 case OPC_PRECR_OB_QH:
27483 case OPC_PRECRQ_OB_QH:
27484 case OPC_PRECRQ_PW_L:
27485 case OPC_PRECRQ_QH_PW:
27486 case OPC_PRECRQ_RS_QH_PW:
27487 case OPC_PRECRQU_S_OB_QH:
27488 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 27489 break;
099e5b4d
LA
27490 case OPC_CMPU_EQ_OB:
27491 case OPC_CMPU_LT_OB:
27492 case OPC_CMPU_LE_OB:
27493 case OPC_CMP_EQ_QH:
27494 case OPC_CMP_LT_QH:
27495 case OPC_CMP_LE_QH:
27496 case OPC_CMP_EQ_PW:
27497 case OPC_CMP_LT_PW:
27498 case OPC_CMP_LE_PW:
27499 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 27500 break;
099e5b4d
LA
27501 case OPC_CMPGDU_EQ_OB:
27502 case OPC_CMPGDU_LT_OB:
27503 case OPC_CMPGDU_LE_OB:
27504 case OPC_CMPGU_EQ_OB:
27505 case OPC_CMPGU_LT_OB:
27506 case OPC_CMPGU_LE_OB:
27507 case OPC_PACKRL_PW:
27508 case OPC_PICK_OB:
27509 case OPC_PICK_PW:
27510 case OPC_PICK_QH:
27511 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 27512 break;
099e5b4d
LA
27513 default: /* Invalid */
27514 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 27515 generate_exception_end(ctx, EXCP_RI);
161f85e6 27516 break;
099e5b4d
LA
27517 }
27518 break;
27519 case OPC_DAPPEND_DSP:
27520 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27521 break;
27522 case OPC_DEXTR_W_DSP:
27523 op2 = MASK_DEXTR_W(ctx->opcode);
27524 switch (op2) {
27525 case OPC_DEXTP:
27526 case OPC_DEXTPDP:
27527 case OPC_DEXTPDPV:
27528 case OPC_DEXTPV:
27529 case OPC_DEXTR_L:
27530 case OPC_DEXTR_R_L:
27531 case OPC_DEXTR_RS_L:
27532 case OPC_DEXTR_W:
27533 case OPC_DEXTR_R_W:
27534 case OPC_DEXTR_RS_W:
27535 case OPC_DEXTR_S_H:
27536 case OPC_DEXTRV_L:
27537 case OPC_DEXTRV_R_L:
27538 case OPC_DEXTRV_RS_L:
27539 case OPC_DEXTRV_S_H:
27540 case OPC_DEXTRV_W:
27541 case OPC_DEXTRV_R_W:
27542 case OPC_DEXTRV_RS_W:
27543 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 27544 break;
099e5b4d
LA
27545 case OPC_DMTHLIP:
27546 case OPC_DSHILO:
27547 case OPC_DSHILOV:
27548 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 27549 break;
099e5b4d
LA
27550 default: /* Invalid */
27551 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27552 generate_exception_end(ctx, EXCP_RI);
461c08df 27553 break;
099e5b4d
LA
27554 }
27555 break;
27556 case OPC_DPAQ_W_QH_DSP:
27557 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27558 switch (op2) {
27559 case OPC_DPAU_H_OBL:
27560 case OPC_DPAU_H_OBR:
27561 case OPC_DPSU_H_OBL:
27562 case OPC_DPSU_H_OBR:
27563 case OPC_DPA_W_QH:
27564 case OPC_DPAQ_S_W_QH:
27565 case OPC_DPS_W_QH:
27566 case OPC_DPSQ_S_W_QH:
27567 case OPC_MULSAQ_S_W_QH:
27568 case OPC_DPAQ_SA_L_PW:
27569 case OPC_DPSQ_SA_L_PW:
27570 case OPC_MULSAQ_S_L_PW:
27571 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27572 break;
27573 case OPC_MAQ_S_W_QHLL:
27574 case OPC_MAQ_S_W_QHLR:
27575 case OPC_MAQ_S_W_QHRL:
27576 case OPC_MAQ_S_W_QHRR:
27577 case OPC_MAQ_SA_W_QHLL:
27578 case OPC_MAQ_SA_W_QHLR:
27579 case OPC_MAQ_SA_W_QHRL:
27580 case OPC_MAQ_SA_W_QHRR:
27581 case OPC_MAQ_S_L_PWL:
27582 case OPC_MAQ_S_L_PWR:
27583 case OPC_DMADD:
27584 case OPC_DMADDU:
27585 case OPC_DMSUB:
27586 case OPC_DMSUBU:
27587 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 27588 break;
099e5b4d
LA
27589 default: /* Invalid */
27590 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 27591 generate_exception_end(ctx, EXCP_RI);
b53371ed 27592 break;
099e5b4d
LA
27593 }
27594 break;
27595 case OPC_DINSV_DSP:
27596 op2 = MASK_INSV(ctx->opcode);
27597 switch (op2) {
27598 case OPC_DINSV:
27599 {
27600 TCGv t0, t1;
27601
27602 if (rt == 0) {
a22260ae
JL
27603 break;
27604 }
099e5b4d 27605 check_dsp(ctx);
1cb6686c 27606
099e5b4d
LA
27607 t0 = tcg_temp_new();
27608 t1 = tcg_temp_new();
1cb6686c 27609
099e5b4d
LA
27610 gen_load_gpr(t0, rt);
27611 gen_load_gpr(t1, rs);
1cb6686c 27612
099e5b4d 27613 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 27614
099e5b4d
LA
27615 tcg_temp_free(t0);
27616 tcg_temp_free(t1);
77c5fa8b 27617 break;
099e5b4d 27618 }
7a387fff 27619 default: /* Invalid */
099e5b4d 27620 MIPS_INVAL("MASK DINSV");
9c708c7f 27621 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
27622 break;
27623 }
27624 break;
099e5b4d
LA
27625 case OPC_SHLL_OB_DSP:
27626 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27627 break;
27628#endif
fac5a073
LA
27629 default: /* Invalid */
27630 MIPS_INVAL("special3_legacy");
9c708c7f 27631 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
27632 break;
27633 }
27634}
27635
37b9aae2
MM
27636
27637#if defined(TARGET_MIPS64)
27638
874b2879 27639static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 27640{
c8341e00 27641 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
27642
27643 switch (opc) {
baa609db
AM
27644 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27645 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27646 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27647 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27648 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27649 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27650 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27651 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27652 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27653 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27654 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27655 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27656 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27657 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27658 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27659 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27660 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27661 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27662 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27663 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27664 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27665 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27666 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27667 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27668 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27669 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
27670 break;
27671 default:
27672 MIPS_INVAL("TX79 MMI class MMI0");
27673 generate_exception_end(ctx, EXCP_RI);
27674 break;
27675 }
27676}
27677
874b2879 27678static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 27679{
c8341e00 27680 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
27681
27682 switch (opc) {
baa609db
AM
27683 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27684 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27685 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27686 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27687 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27688 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27689 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27690 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27691 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27692 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27693 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27694 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27695 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27696 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27697 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27698 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27699 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27700 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27701 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
27702 break;
27703 default:
27704 MIPS_INVAL("TX79 MMI class MMI1");
27705 generate_exception_end(ctx, EXCP_RI);
27706 break;
27707 }
27708}
27709
874b2879 27710static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 27711{
c8341e00 27712 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
27713
27714 switch (opc) {
baa609db
AM
27715 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27716 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27717 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27718 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27719 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27720 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27721 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27722 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27723 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
baa609db
AM
27724 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27725 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27726 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27727 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27728 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27729 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27730 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27731 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27732 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27733 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27734 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27735 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27736 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3 27737 break;
b87eef31
MM
27738 case MMI_OPC_2_PCPYLD:
27739 gen_mmi_pcpyld(ctx);
27740 break;
6c1e48d3
FN
27741 default:
27742 MIPS_INVAL("TX79 MMI class MMI2");
27743 generate_exception_end(ctx, EXCP_RI);
27744 break;
27745 }
27746}
27747
874b2879 27748static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 27749{
c8341e00 27750 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
27751
27752 switch (opc) {
baa609db
AM
27753 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27754 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27755 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27756 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27757 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27758 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27759 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
baa609db
AM
27760 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27761 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27762 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
baa609db
AM
27763 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27764 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc 27765 break;
d3434d9f
MM
27766 case MMI_OPC_3_PCPYH:
27767 gen_mmi_pcpyh(ctx);
27768 break;
fd487f83
MM
27769 case MMI_OPC_3_PCPYUD:
27770 gen_mmi_pcpyud(ctx);
27771 break;
ec1944fc
FN
27772 default:
27773 MIPS_INVAL("TX79 MMI class MMI3");
27774 generate_exception_end(ctx, EXCP_RI);
27775 break;
27776 }
27777}
27778
874b2879 27779static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 27780{
c8341e00 27781 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
27782 int rs = extract32(ctx->opcode, 21, 5);
27783 int rt = extract32(ctx->opcode, 16, 5);
27784 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
27785
27786 switch (opc) {
baa609db 27787 case MMI_OPC_CLASS_MMI0:
874b2879 27788 decode_mmi0(env, ctx);
88eafe0b 27789 break;
baa609db 27790 case MMI_OPC_CLASS_MMI1:
874b2879 27791 decode_mmi1(env, ctx);
7a803ca2 27792 break;
baa609db 27793 case MMI_OPC_CLASS_MMI2:
874b2879 27794 decode_mmi2(env, ctx);
6c1e48d3 27795 break;
baa609db 27796 case MMI_OPC_CLASS_MMI3:
874b2879 27797 decode_mmi3(env, ctx);
ec1944fc 27798 break;
baa609db
AM
27799 case MMI_OPC_MULT1:
27800 case MMI_OPC_MULTU1:
3b948f05
PMD
27801 case MMI_OPC_MADD:
27802 case MMI_OPC_MADDU:
a95c4c26
FN
27803 case MMI_OPC_MADD1:
27804 case MMI_OPC_MADDU1:
06de726b
FN
27805 gen_mul_txx9(ctx, opc, rd, rs, rt);
27806 break;
baa609db
AM
27807 case MMI_OPC_DIV1:
27808 case MMI_OPC_DIVU1:
c42171c3 27809 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 27810 break;
baa609db
AM
27811 case MMI_OPC_MTLO1:
27812 case MMI_OPC_MTHI1:
86efbfb6 27813 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 27814 break;
baa609db
AM
27815 case MMI_OPC_MFLO1:
27816 case MMI_OPC_MFHI1:
86efbfb6 27817 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 27818 break;
baa609db 27819 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
27820 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27821 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27822 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27823 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27824 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27825 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27826 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27827 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27828 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
27829 break;
27830 default:
27831 MIPS_INVAL("TX79 MMI class");
27832 generate_exception_end(ctx, EXCP_RI);
27833 break;
27834 }
27835}
27836
874b2879 27837static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 27838{
baa609db 27839 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
27840}
27841
874b2879 27842static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 27843{
baa609db 27844 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
27845}
27846
27847/*
27848 * The TX79-specific instruction Store Quadword
27849 *
27850 * +--------+-------+-------+------------------------+
27851 * | 011111 | base | rt | offset | SQ
27852 * +--------+-------+-------+------------------------+
27853 * 6 5 5 16
27854 *
27855 * has the same opcode as the Read Hardware Register instruction
27856 *
27857 * +--------+-------+-------+-------+-------+--------+
27858 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27859 * +--------+-------+-------+-------+-------+--------+
27860 * 6 5 5 5 5 6
27861 *
27862 * that is required, trapped and emulated by the Linux kernel. However, all
27863 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27864 * offset is odd. Therefore all valid SQ instructions can execute normally.
27865 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27866 * between SQ and RDHWR, as the Linux kernel does.
27867 */
874b2879 27868static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
27869{
27870 int base = extract32(ctx->opcode, 21, 5);
27871 int rt = extract32(ctx->opcode, 16, 5);
27872 int offset = extract32(ctx->opcode, 0, 16);
27873
27874#ifdef CONFIG_USER_ONLY
27875 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27876 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27877
27878 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27879 int rd = extract32(ctx->opcode, 11, 5);
27880
27881 gen_rdhwr(ctx, rt, rd, 0);
27882 return;
27883 }
27884#endif
27885
874b2879 27886 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
27887}
27888
37b9aae2
MM
27889#endif
27890
fac5a073
LA
27891static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27892{
27893 int rs, rt, rd, sa;
27894 uint32_t op1, op2;
76964147 27895 int16_t imm;
fac5a073
LA
27896
27897 rs = (ctx->opcode >> 21) & 0x1f;
27898 rt = (ctx->opcode >> 16) & 0x1f;
27899 rd = (ctx->opcode >> 11) & 0x1f;
27900 sa = (ctx->opcode >> 6) & 0x1f;
76964147 27901 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
27902
27903 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
27904
27905 /*
27906 * EVA loads and stores overlap Loongson 2E instructions decoded by
27907 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27908 * EVA is absent.
27909 */
27910 if (ctx->eva) {
27911 switch (op1) {
c2e19f3c
AM
27912 case OPC_LWLE:
27913 case OPC_LWRE:
76964147
JH
27914 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27915 /* fall through */
c2e19f3c
AM
27916 case OPC_LBUE:
27917 case OPC_LHUE:
27918 case OPC_LBE:
27919 case OPC_LHE:
27920 case OPC_LLE:
27921 case OPC_LWE:
76964147
JH
27922 check_cp0_enabled(ctx);
27923 gen_ld(ctx, op1, rt, rs, imm);
27924 return;
c2e19f3c
AM
27925 case OPC_SWLE:
27926 case OPC_SWRE:
76964147
JH
27927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27928 /* fall through */
c2e19f3c
AM
27929 case OPC_SBE:
27930 case OPC_SHE:
76964147
JH
27931 case OPC_SWE:
27932 check_cp0_enabled(ctx);
27933 gen_st(ctx, op1, rt, rs, imm);
27934 return;
27935 case OPC_SCE:
27936 check_cp0_enabled(ctx);
33a07fa2 27937 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
27938 return;
27939 case OPC_CACHEE:
27940 check_cp0_enabled(ctx);
27941 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27942 gen_cache_operation(ctx, rt, rs, imm);
27943 }
27944 /* Treat as NOP. */
27945 return;
27946 case OPC_PREFE:
27947 check_cp0_enabled(ctx);
27948 /* Treat as NOP. */
27949 return;
27950 }
27951 }
27952
fac5a073
LA
27953 switch (op1) {
27954 case OPC_EXT:
27955 case OPC_INS:
27956 check_insn(ctx, ISA_MIPS32R2);
27957 gen_bitops(ctx, op1, rt, rs, sa, rd);
27958 break;
27959 case OPC_BSHFL:
fac5a073 27960 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 27961 switch (op2) {
c2e19f3c 27962 case OPC_ALIGN:
373ecd38
AM
27963 case OPC_ALIGN_1:
27964 case OPC_ALIGN_2:
27965 case OPC_ALIGN_3:
15eacb9b
YK
27966 case OPC_BITSWAP:
27967 check_insn(ctx, ISA_MIPS32R6);
27968 decode_opc_special3_r6(env, ctx);
27969 break;
27970 default:
27971 check_insn(ctx, ISA_MIPS32R2);
27972 gen_bshfl(ctx, op2, rt, rd);
27973 break;
27974 }
fac5a073
LA
27975 break;
27976#if defined(TARGET_MIPS64)
c2e19f3c
AM
27977 case OPC_DEXTM:
27978 case OPC_DEXTU:
27979 case OPC_DEXT:
27980 case OPC_DINSM:
27981 case OPC_DINSU:
27982 case OPC_DINS:
fac5a073
LA
27983 check_insn(ctx, ISA_MIPS64R2);
27984 check_mips_64(ctx);
27985 gen_bitops(ctx, op1, rt, rs, sa, rd);
27986 break;
27987 case OPC_DBSHFL:
fac5a073 27988 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 27989 switch (op2) {
c2e19f3c 27990 case OPC_DALIGN:
373ecd38
AM
27991 case OPC_DALIGN_1:
27992 case OPC_DALIGN_2:
27993 case OPC_DALIGN_3:
27994 case OPC_DALIGN_4:
27995 case OPC_DALIGN_5:
27996 case OPC_DALIGN_6:
27997 case OPC_DALIGN_7:
15eacb9b
YK
27998 case OPC_DBITSWAP:
27999 check_insn(ctx, ISA_MIPS32R6);
28000 decode_opc_special3_r6(env, ctx);
28001 break;
28002 default:
28003 check_insn(ctx, ISA_MIPS64R2);
28004 check_mips_64(ctx);
28005 op2 = MASK_DBSHFL(ctx->opcode);
28006 gen_bshfl(ctx, op2, rt, rd);
28007 break;
28008 }
fac5a073
LA
28009 break;
28010#endif
28011 case OPC_RDHWR:
b00c7218 28012 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
28013 break;
28014 case OPC_FORK:
9affc1c5 28015 check_mt(ctx);
fac5a073
LA
28016 {
28017 TCGv t0 = tcg_temp_new();
28018 TCGv t1 = tcg_temp_new();
28019
28020 gen_load_gpr(t0, rt);
28021 gen_load_gpr(t1, rs);
28022 gen_helper_fork(t0, t1);
28023 tcg_temp_free(t0);
28024 tcg_temp_free(t1);
28025 }
28026 break;
28027 case OPC_YIELD:
9affc1c5 28028 check_mt(ctx);
fac5a073
LA
28029 {
28030 TCGv t0 = tcg_temp_new();
28031
fac5a073
LA
28032 gen_load_gpr(t0, rs);
28033 gen_helper_yield(t0, cpu_env, t0);
28034 gen_store_gpr(t0, rd);
28035 tcg_temp_free(t0);
28036 }
28037 break;
10dc65db
LA
28038 default:
28039 if (ctx->insn_flags & ISA_MIPS32R6) {
28040 decode_opc_special3_r6(env, ctx);
28041 } else {
28042 decode_opc_special3_legacy(env, ctx);
28043 }
099e5b4d
LA
28044 }
28045}
28046
863f264d
YK
28047/* MIPS SIMD Architecture (MSA) */
28048static inline int check_msa_access(DisasContext *ctx)
28049{
28050 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28051 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 28052 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28053 return 0;
28054 }
28055
28056 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28057 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 28058 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
28059 return 0;
28060 } else {
9c708c7f 28061 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28062 return 0;
28063 }
28064 }
28065 return 1;
28066}
28067
5692c6e1
YK
28068static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28069{
28070 /* generates tcg ops to check if any element is 0 */
28071 /* Note this function only works with MSA_WRLEN = 128 */
28072 uint64_t eval_zero_or_big = 0;
28073 uint64_t eval_big = 0;
28074 TCGv_i64 t0 = tcg_temp_new_i64();
28075 TCGv_i64 t1 = tcg_temp_new_i64();
28076 switch (df) {
28077 case DF_BYTE:
28078 eval_zero_or_big = 0x0101010101010101ULL;
28079 eval_big = 0x8080808080808080ULL;
28080 break;
28081 case DF_HALF:
28082 eval_zero_or_big = 0x0001000100010001ULL;
28083 eval_big = 0x8000800080008000ULL;
28084 break;
28085 case DF_WORD:
28086 eval_zero_or_big = 0x0000000100000001ULL;
28087 eval_big = 0x8000000080000000ULL;
28088 break;
28089 case DF_DOUBLE:
28090 eval_zero_or_big = 0x0000000000000001ULL;
28091 eval_big = 0x8000000000000000ULL;
28092 break;
28093 }
235785e8
AM
28094 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28095 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
5692c6e1 28096 tcg_gen_andi_i64(t0, t0, eval_big);
235785e8
AM
28097 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28098 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28099 tcg_gen_andi_i64(t1, t1, eval_big);
28100 tcg_gen_or_i64(t0, t0, t1);
28101 /* if all bits are zero then all elements are not zero */
28102 /* if some bit is non-zero then some element is zero */
28103 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28104 tcg_gen_trunc_i64_tl(tresult, t0);
28105 tcg_temp_free_i64(t0);
28106 tcg_temp_free_i64(t1);
28107}
28108
28109static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28110{
28111 uint8_t df = (ctx->opcode >> 21) & 0x3;
28112 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28113 int64_t s16 = (int16_t)ctx->opcode;
28114
28115 check_msa_access(ctx);
28116
075a1fe7 28117 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 28118 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
28119 return;
28120 }
28121 switch (op1) {
28122 case OPC_BZ_V:
28123 case OPC_BNZ_V:
28124 {
28125 TCGv_i64 t0 = tcg_temp_new_i64();
235785e8 28126 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28127 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28128 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28129 tcg_gen_trunc_i64_tl(bcond, t0);
28130 tcg_temp_free_i64(t0);
28131 }
28132 break;
28133 case OPC_BZ_B:
28134 case OPC_BZ_H:
28135 case OPC_BZ_W:
28136 case OPC_BZ_D:
28137 gen_check_zero_element(bcond, df, wt);
28138 break;
28139 case OPC_BNZ_B:
28140 case OPC_BNZ_H:
28141 case OPC_BNZ_W:
28142 case OPC_BNZ_D:
28143 gen_check_zero_element(bcond, df, wt);
28144 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28145 break;
28146 }
28147
eeb3bba8 28148 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
28149
28150 ctx->hflags |= MIPS_HFLAG_BC;
28151 ctx->hflags |= MIPS_HFLAG_BDS32;
28152}
28153
4c789546
YK
28154static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28155{
28156#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28157 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28158 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28159 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28160
28161 TCGv_i32 twd = tcg_const_i32(wd);
28162 TCGv_i32 tws = tcg_const_i32(ws);
28163 TCGv_i32 ti8 = tcg_const_i32(i8);
28164
28165 switch (MASK_MSA_I8(ctx->opcode)) {
28166 case OPC_ANDI_B:
28167 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28168 break;
28169 case OPC_ORI_B:
28170 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28171 break;
28172 case OPC_NORI_B:
28173 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28174 break;
28175 case OPC_XORI_B:
28176 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28177 break;
28178 case OPC_BMNZI_B:
28179 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28180 break;
28181 case OPC_BMZI_B:
28182 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28183 break;
28184 case OPC_BSELI_B:
28185 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28186 break;
28187 case OPC_SHF_B:
28188 case OPC_SHF_H:
28189 case OPC_SHF_W:
28190 {
28191 uint8_t df = (ctx->opcode >> 24) & 0x3;
28192 if (df == DF_DOUBLE) {
9c708c7f 28193 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28194 } else {
28195 TCGv_i32 tdf = tcg_const_i32(df);
28196 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28197 tcg_temp_free_i32(tdf);
28198 }
28199 }
28200 break;
28201 default:
28202 MIPS_INVAL("MSA instruction");
9c708c7f 28203 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28204 break;
28205 }
28206
28207 tcg_temp_free_i32(twd);
28208 tcg_temp_free_i32(tws);
28209 tcg_temp_free_i32(ti8);
28210}
28211
80e71591
YK
28212static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28213{
28214#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28215 uint8_t df = (ctx->opcode >> 21) & 0x3;
28216 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28217 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28218 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28219 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28220
28221 TCGv_i32 tdf = tcg_const_i32(df);
28222 TCGv_i32 twd = tcg_const_i32(wd);
28223 TCGv_i32 tws = tcg_const_i32(ws);
28224 TCGv_i32 timm = tcg_temp_new_i32();
28225 tcg_gen_movi_i32(timm, u5);
28226
28227 switch (MASK_MSA_I5(ctx->opcode)) {
28228 case OPC_ADDVI_df:
28229 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28230 break;
28231 case OPC_SUBVI_df:
28232 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28233 break;
28234 case OPC_MAXI_S_df:
28235 tcg_gen_movi_i32(timm, s5);
28236 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28237 break;
28238 case OPC_MAXI_U_df:
28239 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28240 break;
28241 case OPC_MINI_S_df:
28242 tcg_gen_movi_i32(timm, s5);
28243 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28244 break;
28245 case OPC_MINI_U_df:
28246 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28247 break;
28248 case OPC_CEQI_df:
28249 tcg_gen_movi_i32(timm, s5);
28250 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28251 break;
28252 case OPC_CLTI_S_df:
28253 tcg_gen_movi_i32(timm, s5);
28254 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28255 break;
28256 case OPC_CLTI_U_df:
28257 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28258 break;
28259 case OPC_CLEI_S_df:
28260 tcg_gen_movi_i32(timm, s5);
28261 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28262 break;
28263 case OPC_CLEI_U_df:
28264 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28265 break;
28266 case OPC_LDI_df:
28267 {
28268 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28269 tcg_gen_movi_i32(timm, s10);
28270 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28271 }
28272 break;
28273 default:
28274 MIPS_INVAL("MSA instruction");
9c708c7f 28275 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
28276 break;
28277 }
28278
28279 tcg_temp_free_i32(tdf);
28280 tcg_temp_free_i32(twd);
28281 tcg_temp_free_i32(tws);
28282 tcg_temp_free_i32(timm);
28283}
28284
d4cf28de
YK
28285static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28286{
28287#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28288 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28289 uint32_t df = 0, m = 0;
28290 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28291 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28292
28293 TCGv_i32 tdf;
28294 TCGv_i32 tm;
28295 TCGv_i32 twd;
28296 TCGv_i32 tws;
28297
28298 if ((dfm & 0x40) == 0x00) {
28299 m = dfm & 0x3f;
28300 df = DF_DOUBLE;
28301 } else if ((dfm & 0x60) == 0x40) {
28302 m = dfm & 0x1f;
28303 df = DF_WORD;
28304 } else if ((dfm & 0x70) == 0x60) {
28305 m = dfm & 0x0f;
28306 df = DF_HALF;
28307 } else if ((dfm & 0x78) == 0x70) {
28308 m = dfm & 0x7;
28309 df = DF_BYTE;
28310 } else {
9c708c7f 28311 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28312 return;
28313 }
28314
28315 tdf = tcg_const_i32(df);
28316 tm = tcg_const_i32(m);
28317 twd = tcg_const_i32(wd);
28318 tws = tcg_const_i32(ws);
28319
28320 switch (MASK_MSA_BIT(ctx->opcode)) {
28321 case OPC_SLLI_df:
28322 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28323 break;
28324 case OPC_SRAI_df:
28325 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28326 break;
28327 case OPC_SRLI_df:
28328 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28329 break;
28330 case OPC_BCLRI_df:
28331 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28332 break;
28333 case OPC_BSETI_df:
28334 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28335 break;
28336 case OPC_BNEGI_df:
28337 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28338 break;
28339 case OPC_BINSLI_df:
28340 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28341 break;
28342 case OPC_BINSRI_df:
28343 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28344 break;
28345 case OPC_SAT_S_df:
28346 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28347 break;
28348 case OPC_SAT_U_df:
28349 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28350 break;
28351 case OPC_SRARI_df:
28352 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28353 break;
28354 case OPC_SRLRI_df:
28355 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28356 break;
28357 default:
28358 MIPS_INVAL("MSA instruction");
9c708c7f 28359 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28360 break;
28361 }
28362
28363 tcg_temp_free_i32(tdf);
28364 tcg_temp_free_i32(tm);
28365 tcg_temp_free_i32(twd);
28366 tcg_temp_free_i32(tws);
28367}
28368
28f99f08
YK
28369static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28370{
28371#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28372 uint8_t df = (ctx->opcode >> 21) & 0x3;
28373 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28374 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28375 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28376
28377 TCGv_i32 tdf = tcg_const_i32(df);
28378 TCGv_i32 twd = tcg_const_i32(wd);
28379 TCGv_i32 tws = tcg_const_i32(ws);
28380 TCGv_i32 twt = tcg_const_i32(wt);
28381
28382 switch (MASK_MSA_3R(ctx->opcode)) {
28383 case OPC_SLL_df:
28384 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28385 break;
28386 case OPC_ADDV_df:
28387 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28388 break;
28389 case OPC_CEQ_df:
28390 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28391 break;
28392 case OPC_ADD_A_df:
28393 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28394 break;
28395 case OPC_SUBS_S_df:
28396 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28397 break;
28398 case OPC_MULV_df:
28399 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28400 break;
28401 case OPC_SLD_df:
28402 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28403 break;
28404 case OPC_VSHF_df:
28405 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28406 break;
28407 case OPC_SRA_df:
28408 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28409 break;
28410 case OPC_SUBV_df:
28411 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28412 break;
28413 case OPC_ADDS_A_df:
28414 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28415 break;
28416 case OPC_SUBS_U_df:
28417 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28418 break;
28419 case OPC_MADDV_df:
28420 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28421 break;
28422 case OPC_SPLAT_df:
28423 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28424 break;
28425 case OPC_SRAR_df:
28426 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28427 break;
28428 case OPC_SRL_df:
28429 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28430 break;
28431 case OPC_MAX_S_df:
28432 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28433 break;
28434 case OPC_CLT_S_df:
28435 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28436 break;
28437 case OPC_ADDS_S_df:
28438 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28439 break;
28440 case OPC_SUBSUS_U_df:
28441 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28442 break;
28443 case OPC_MSUBV_df:
28444 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28445 break;
28446 case OPC_PCKEV_df:
28447 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28448 break;
28449 case OPC_SRLR_df:
28450 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28451 break;
28452 case OPC_BCLR_df:
28453 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28454 break;
28455 case OPC_MAX_U_df:
28456 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28457 break;
28458 case OPC_CLT_U_df:
28459 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28460 break;
28461 case OPC_ADDS_U_df:
28462 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28463 break;
28464 case OPC_SUBSUU_S_df:
28465 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28466 break;
28467 case OPC_PCKOD_df:
28468 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28469 break;
28470 case OPC_BSET_df:
28471 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28472 break;
28473 case OPC_MIN_S_df:
28474 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28475 break;
28476 case OPC_CLE_S_df:
28477 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28478 break;
28479 case OPC_AVE_S_df:
28480 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28481 break;
28482 case OPC_ASUB_S_df:
28483 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28484 break;
28485 case OPC_DIV_S_df:
28486 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28487 break;
28488 case OPC_ILVL_df:
28489 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28490 break;
28491 case OPC_BNEG_df:
28492 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28493 break;
28494 case OPC_MIN_U_df:
28495 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28496 break;
28497 case OPC_CLE_U_df:
28498 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28499 break;
28500 case OPC_AVE_U_df:
28501 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28502 break;
28503 case OPC_ASUB_U_df:
28504 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28505 break;
28506 case OPC_DIV_U_df:
28507 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28508 break;
28509 case OPC_ILVR_df:
28510 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28511 break;
28512 case OPC_BINSL_df:
28513 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28514 break;
28515 case OPC_MAX_A_df:
28516 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28517 break;
28518 case OPC_AVER_S_df:
28519 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28520 break;
28521 case OPC_MOD_S_df:
28522 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28523 break;
28524 case OPC_ILVEV_df:
28525 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28526 break;
28527 case OPC_BINSR_df:
28528 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28529 break;
28530 case OPC_MIN_A_df:
28531 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28532 break;
28533 case OPC_AVER_U_df:
28534 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28535 break;
28536 case OPC_MOD_U_df:
28537 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28538 break;
28539 case OPC_ILVOD_df:
28540 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28541 break;
28542
28543 case OPC_DOTP_S_df:
28544 case OPC_DOTP_U_df:
28545 case OPC_DPADD_S_df:
28546 case OPC_DPADD_U_df:
28547 case OPC_DPSUB_S_df:
28548 case OPC_HADD_S_df:
28549 case OPC_DPSUB_U_df:
28550 case OPC_HADD_U_df:
28551 case OPC_HSUB_S_df:
28552 case OPC_HSUB_U_df:
28553 if (df == DF_BYTE) {
9c708c7f
PD
28554 generate_exception_end(ctx, EXCP_RI);
28555 break;
28f99f08
YK
28556 }
28557 switch (MASK_MSA_3R(ctx->opcode)) {
28558 case OPC_DOTP_S_df:
28559 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28560 break;
28561 case OPC_DOTP_U_df:
28562 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28563 break;
28564 case OPC_DPADD_S_df:
28565 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28566 break;
28567 case OPC_DPADD_U_df:
28568 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28569 break;
28570 case OPC_DPSUB_S_df:
28571 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28572 break;
28573 case OPC_HADD_S_df:
28574 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28575 break;
28576 case OPC_DPSUB_U_df:
28577 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28578 break;
28579 case OPC_HADD_U_df:
28580 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28581 break;
28582 case OPC_HSUB_S_df:
28583 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28584 break;
28585 case OPC_HSUB_U_df:
28586 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28587 break;
28588 }
28589 break;
28590 default:
28591 MIPS_INVAL("MSA instruction");
9c708c7f 28592 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
28593 break;
28594 }
28595 tcg_temp_free_i32(twd);
28596 tcg_temp_free_i32(tws);
28597 tcg_temp_free_i32(twt);
28598 tcg_temp_free_i32(tdf);
28599}
28600
1e608ec1
YK
28601static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28602{
28603#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28604 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28605 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28606 TCGv telm = tcg_temp_new();
28607 TCGv_i32 tsr = tcg_const_i32(source);
28608 TCGv_i32 tdt = tcg_const_i32(dest);
28609
28610 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28611 case OPC_CTCMSA:
28612 gen_load_gpr(telm, source);
28613 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28614 break;
28615 case OPC_CFCMSA:
28616 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28617 gen_store_gpr(telm, dest);
28618 break;
28619 case OPC_MOVE_V:
28620 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28621 break;
28622 default:
28623 MIPS_INVAL("MSA instruction");
9c708c7f 28624 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28625 break;
28626 }
28627
28628 tcg_temp_free(telm);
28629 tcg_temp_free_i32(tdt);
28630 tcg_temp_free_i32(tsr);
28631}
28632
28633static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28634 uint32_t n)
28635{
28636#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28637 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28638 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28639
28640 TCGv_i32 tws = tcg_const_i32(ws);
28641 TCGv_i32 twd = tcg_const_i32(wd);
28642 TCGv_i32 tn = tcg_const_i32(n);
28643 TCGv_i32 tdf = tcg_const_i32(df);
28644
28645 switch (MASK_MSA_ELM(ctx->opcode)) {
28646 case OPC_SLDI_df:
28647 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28648 break;
28649 case OPC_SPLATI_df:
28650 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28651 break;
28652 case OPC_INSVE_df:
28653 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28654 break;
28655 case OPC_COPY_S_df:
28656 case OPC_COPY_U_df:
28657 case OPC_INSERT_df:
28658#if !defined(TARGET_MIPS64)
28659 /* Double format valid only for MIPS64 */
28660 if (df == DF_DOUBLE) {
9c708c7f 28661 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28662 break;
28663 }
41d28858
MM
28664 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28665 (df == DF_WORD)) {
28666 generate_exception_end(ctx, EXCP_RI);
28667 break;
28668 }
1e608ec1
YK
28669#endif
28670 switch (MASK_MSA_ELM(ctx->opcode)) {
28671 case OPC_COPY_S_df:
cab48881 28672 if (likely(wd != 0)) {
631c4674
MM
28673 switch (df) {
28674 case DF_BYTE:
28675 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28676 break;
28677 case DF_HALF:
28678 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28679 break;
28680 case DF_WORD:
28681 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28682 break;
28683#if defined(TARGET_MIPS64)
28684 case DF_DOUBLE:
28685 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28686 break;
28687#endif
28688 default:
28689 assert(0);
28690 }
cab48881 28691 }
1e608ec1
YK
28692 break;
28693 case OPC_COPY_U_df:
cab48881 28694 if (likely(wd != 0)) {
41d28858
MM
28695 switch (df) {
28696 case DF_BYTE:
28697 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28698 break;
28699 case DF_HALF:
28700 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28701 break;
28702#if defined(TARGET_MIPS64)
28703 case DF_WORD:
28704 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28705 break;
28706#endif
28707 default:
28708 assert(0);
28709 }
cab48881 28710 }
1e608ec1
YK
28711 break;
28712 case OPC_INSERT_df:
c1c9a10f
MM
28713 switch (df) {
28714 case DF_BYTE:
28715 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28716 break;
28717 case DF_HALF:
28718 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28719 break;
28720 case DF_WORD:
28721 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28722 break;
28723#if defined(TARGET_MIPS64)
28724 case DF_DOUBLE:
28725 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28726 break;
28727#endif
28728 default:
28729 assert(0);
28730 }
1e608ec1
YK
28731 break;
28732 }
28733 break;
28734 default:
28735 MIPS_INVAL("MSA instruction");
9c708c7f 28736 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28737 }
28738 tcg_temp_free_i32(twd);
28739 tcg_temp_free_i32(tws);
28740 tcg_temp_free_i32(tn);
28741 tcg_temp_free_i32(tdf);
28742}
28743
28744static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28745{
28746 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28747 uint32_t df = 0, n = 0;
28748
28749 if ((dfn & 0x30) == 0x00) {
28750 n = dfn & 0x0f;
28751 df = DF_BYTE;
28752 } else if ((dfn & 0x38) == 0x20) {
28753 n = dfn & 0x07;
28754 df = DF_HALF;
28755 } else if ((dfn & 0x3c) == 0x30) {
28756 n = dfn & 0x03;
28757 df = DF_WORD;
28758 } else if ((dfn & 0x3e) == 0x38) {
28759 n = dfn & 0x01;
28760 df = DF_DOUBLE;
28761 } else if (dfn == 0x3E) {
28762 /* CTCMSA, CFCMSA, MOVE.V */
28763 gen_msa_elm_3e(env, ctx);
28764 return;
28765 } else {
9c708c7f 28766 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28767 return;
28768 }
28769
28770 gen_msa_elm_df(env, ctx, df, n);
28771}
28772
7d05b9c8
YK
28773static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28774{
28775#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28776 uint8_t df = (ctx->opcode >> 21) & 0x1;
28777 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28778 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28779 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28780
28781 TCGv_i32 twd = tcg_const_i32(wd);
28782 TCGv_i32 tws = tcg_const_i32(ws);
28783 TCGv_i32 twt = tcg_const_i32(wt);
28784 TCGv_i32 tdf = tcg_temp_new_i32();
28785
28786 /* adjust df value for floating-point instruction */
28787 tcg_gen_movi_i32(tdf, df + 2);
28788
28789 switch (MASK_MSA_3RF(ctx->opcode)) {
28790 case OPC_FCAF_df:
28791 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28792 break;
28793 case OPC_FADD_df:
28794 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28795 break;
28796 case OPC_FCUN_df:
28797 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28798 break;
28799 case OPC_FSUB_df:
28800 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28801 break;
28802 case OPC_FCOR_df:
28803 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28804 break;
28805 case OPC_FCEQ_df:
28806 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28807 break;
28808 case OPC_FMUL_df:
28809 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28810 break;
28811 case OPC_FCUNE_df:
28812 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28813 break;
28814 case OPC_FCUEQ_df:
28815 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28816 break;
28817 case OPC_FDIV_df:
28818 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28819 break;
28820 case OPC_FCNE_df:
28821 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28822 break;
28823 case OPC_FCLT_df:
28824 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28825 break;
28826 case OPC_FMADD_df:
28827 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28828 break;
28829 case OPC_MUL_Q_df:
28830 tcg_gen_movi_i32(tdf, df + 1);
28831 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28832 break;
28833 case OPC_FCULT_df:
28834 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28835 break;
28836 case OPC_FMSUB_df:
28837 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28838 break;
28839 case OPC_MADD_Q_df:
28840 tcg_gen_movi_i32(tdf, df + 1);
28841 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28842 break;
28843 case OPC_FCLE_df:
28844 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28845 break;
28846 case OPC_MSUB_Q_df:
28847 tcg_gen_movi_i32(tdf, df + 1);
28848 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28849 break;
28850 case OPC_FCULE_df:
28851 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28852 break;
28853 case OPC_FEXP2_df:
28854 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28855 break;
28856 case OPC_FSAF_df:
28857 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28858 break;
28859 case OPC_FEXDO_df:
28860 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28861 break;
28862 case OPC_FSUN_df:
28863 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28864 break;
28865 case OPC_FSOR_df:
28866 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28867 break;
28868 case OPC_FSEQ_df:
28869 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28870 break;
28871 case OPC_FTQ_df:
28872 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28873 break;
28874 case OPC_FSUNE_df:
28875 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28876 break;
28877 case OPC_FSUEQ_df:
28878 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28879 break;
28880 case OPC_FSNE_df:
28881 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28882 break;
28883 case OPC_FSLT_df:
28884 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28885 break;
28886 case OPC_FMIN_df:
28887 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28888 break;
28889 case OPC_MULR_Q_df:
28890 tcg_gen_movi_i32(tdf, df + 1);
28891 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28892 break;
28893 case OPC_FSULT_df:
28894 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28895 break;
28896 case OPC_FMIN_A_df:
28897 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28898 break;
28899 case OPC_MADDR_Q_df:
28900 tcg_gen_movi_i32(tdf, df + 1);
28901 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28902 break;
28903 case OPC_FSLE_df:
28904 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28905 break;
28906 case OPC_FMAX_df:
28907 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28908 break;
28909 case OPC_MSUBR_Q_df:
28910 tcg_gen_movi_i32(tdf, df + 1);
28911 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28912 break;
28913 case OPC_FSULE_df:
28914 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28915 break;
28916 case OPC_FMAX_A_df:
28917 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28918 break;
28919 default:
28920 MIPS_INVAL("MSA instruction");
9c708c7f 28921 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
28922 break;
28923 }
28924
28925 tcg_temp_free_i32(twd);
28926 tcg_temp_free_i32(tws);
28927 tcg_temp_free_i32(twt);
28928 tcg_temp_free_i32(tdf);
28929}
28930
cbe50b9a
YK
28931static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28932{
28933#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28934 (op & (0x7 << 18)))
28935 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28936 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28937 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28938 uint8_t df = (ctx->opcode >> 16) & 0x3;
28939 TCGv_i32 twd = tcg_const_i32(wd);
28940 TCGv_i32 tws = tcg_const_i32(ws);
28941 TCGv_i32 twt = tcg_const_i32(wt);
28942 TCGv_i32 tdf = tcg_const_i32(df);
28943
28944 switch (MASK_MSA_2R(ctx->opcode)) {
28945 case OPC_FILL_df:
28946#if !defined(TARGET_MIPS64)
28947 /* Double format valid only for MIPS64 */
28948 if (df == DF_DOUBLE) {
9c708c7f 28949 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28950 break;
28951 }
28952#endif
28953 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28954 break;
28955 case OPC_PCNT_df:
28956 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28957 break;
28958 case OPC_NLOC_df:
28959 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28960 break;
28961 case OPC_NLZC_df:
28962 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28963 break;
28964 default:
28965 MIPS_INVAL("MSA instruction");
9c708c7f 28966 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28967 break;
28968 }
28969
28970 tcg_temp_free_i32(twd);
28971 tcg_temp_free_i32(tws);
28972 tcg_temp_free_i32(twt);
28973 tcg_temp_free_i32(tdf);
28974}
28975
3bdeb688
YK
28976static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28977{
28978#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28979 (op & (0xf << 17)))
28980 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28981 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28982 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28983 uint8_t df = (ctx->opcode >> 16) & 0x1;
28984 TCGv_i32 twd = tcg_const_i32(wd);
28985 TCGv_i32 tws = tcg_const_i32(ws);
28986 TCGv_i32 twt = tcg_const_i32(wt);
28987 /* adjust df value for floating-point instruction */
28988 TCGv_i32 tdf = tcg_const_i32(df + 2);
28989
28990 switch (MASK_MSA_2RF(ctx->opcode)) {
28991 case OPC_FCLASS_df:
28992 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28993 break;
28994 case OPC_FTRUNC_S_df:
28995 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28996 break;
28997 case OPC_FTRUNC_U_df:
28998 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28999 break;
29000 case OPC_FSQRT_df:
29001 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29002 break;
29003 case OPC_FRSQRT_df:
29004 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29005 break;
29006 case OPC_FRCP_df:
29007 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29008 break;
29009 case OPC_FRINT_df:
29010 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29011 break;
29012 case OPC_FLOG2_df:
29013 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29014 break;
29015 case OPC_FEXUPL_df:
29016 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29017 break;
29018 case OPC_FEXUPR_df:
29019 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29020 break;
29021 case OPC_FFQL_df:
29022 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29023 break;
29024 case OPC_FFQR_df:
29025 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29026 break;
29027 case OPC_FTINT_S_df:
29028 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29029 break;
29030 case OPC_FTINT_U_df:
29031 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29032 break;
29033 case OPC_FFINT_S_df:
29034 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29035 break;
29036 case OPC_FFINT_U_df:
29037 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29038 break;
29039 }
29040
29041 tcg_temp_free_i32(twd);
29042 tcg_temp_free_i32(tws);
29043 tcg_temp_free_i32(twt);
29044 tcg_temp_free_i32(tdf);
29045}
29046
cbe50b9a
YK
29047static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29048{
29049#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29050 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29051 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29052 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29053 TCGv_i32 twd = tcg_const_i32(wd);
29054 TCGv_i32 tws = tcg_const_i32(ws);
29055 TCGv_i32 twt = tcg_const_i32(wt);
29056
29057 switch (MASK_MSA_VEC(ctx->opcode)) {
29058 case OPC_AND_V:
29059 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29060 break;
29061 case OPC_OR_V:
29062 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29063 break;
29064 case OPC_NOR_V:
29065 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29066 break;
29067 case OPC_XOR_V:
29068 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29069 break;
29070 case OPC_BMNZ_V:
29071 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29072 break;
29073 case OPC_BMZ_V:
29074 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29075 break;
29076 case OPC_BSEL_V:
29077 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29078 break;
29079 default:
29080 MIPS_INVAL("MSA instruction");
9c708c7f 29081 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29082 break;
29083 }
29084
29085 tcg_temp_free_i32(twd);
29086 tcg_temp_free_i32(tws);
29087 tcg_temp_free_i32(twt);
29088}
29089
29090static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29091{
29092 switch (MASK_MSA_VEC(ctx->opcode)) {
29093 case OPC_AND_V:
29094 case OPC_OR_V:
29095 case OPC_NOR_V:
29096 case OPC_XOR_V:
29097 case OPC_BMNZ_V:
29098 case OPC_BMZ_V:
29099 case OPC_BSEL_V:
29100 gen_msa_vec_v(env, ctx);
29101 break;
29102 case OPC_MSA_2R:
29103 gen_msa_2r(env, ctx);
29104 break;
3bdeb688
YK
29105 case OPC_MSA_2RF:
29106 gen_msa_2rf(env, ctx);
29107 break;
cbe50b9a
YK
29108 default:
29109 MIPS_INVAL("MSA instruction");
9c708c7f 29110 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29111 break;
29112 }
29113}
29114
4c789546
YK
29115static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29116{
29117 uint32_t opcode = ctx->opcode;
29118 check_insn(ctx, ASE_MSA);
29119 check_msa_access(ctx);
29120
29121 switch (MASK_MSA_MINOR(opcode)) {
29122 case OPC_MSA_I8_00:
29123 case OPC_MSA_I8_01:
29124 case OPC_MSA_I8_02:
29125 gen_msa_i8(env, ctx);
29126 break;
80e71591
YK
29127 case OPC_MSA_I5_06:
29128 case OPC_MSA_I5_07:
29129 gen_msa_i5(env, ctx);
29130 break;
d4cf28de
YK
29131 case OPC_MSA_BIT_09:
29132 case OPC_MSA_BIT_0A:
29133 gen_msa_bit(env, ctx);
29134 break;
28f99f08
YK
29135 case OPC_MSA_3R_0D:
29136 case OPC_MSA_3R_0E:
29137 case OPC_MSA_3R_0F:
29138 case OPC_MSA_3R_10:
29139 case OPC_MSA_3R_11:
29140 case OPC_MSA_3R_12:
29141 case OPC_MSA_3R_13:
29142 case OPC_MSA_3R_14:
29143 case OPC_MSA_3R_15:
29144 gen_msa_3r(env, ctx);
29145 break;
1e608ec1
YK
29146 case OPC_MSA_ELM:
29147 gen_msa_elm(env, ctx);
29148 break;
7d05b9c8
YK
29149 case OPC_MSA_3RF_1A:
29150 case OPC_MSA_3RF_1B:
29151 case OPC_MSA_3RF_1C:
29152 gen_msa_3rf(env, ctx);
29153 break;
cbe50b9a
YK
29154 case OPC_MSA_VEC:
29155 gen_msa_vec(env, ctx);
29156 break;
f7685877
YK
29157 case OPC_LD_B:
29158 case OPC_LD_H:
29159 case OPC_LD_W:
29160 case OPC_LD_D:
29161 case OPC_ST_B:
29162 case OPC_ST_H:
29163 case OPC_ST_W:
29164 case OPC_ST_D:
29165 {
29166 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29167 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29168 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29169 uint8_t df = (ctx->opcode >> 0) & 0x3;
29170
f7685877 29171 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
29172 TCGv taddr = tcg_temp_new();
29173 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
29174
29175 switch (MASK_MSA_MINOR(opcode)) {
29176 case OPC_LD_B:
adc370a4
YK
29177 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29178 break;
f7685877 29179 case OPC_LD_H:
adc370a4
YK
29180 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29181 break;
f7685877 29182 case OPC_LD_W:
adc370a4
YK
29183 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29184 break;
f7685877 29185 case OPC_LD_D:
adc370a4 29186 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
29187 break;
29188 case OPC_ST_B:
adc370a4
YK
29189 gen_helper_msa_st_b(cpu_env, twd, taddr);
29190 break;
f7685877 29191 case OPC_ST_H:
adc370a4
YK
29192 gen_helper_msa_st_h(cpu_env, twd, taddr);
29193 break;
f7685877 29194 case OPC_ST_W:
adc370a4
YK
29195 gen_helper_msa_st_w(cpu_env, twd, taddr);
29196 break;
f7685877 29197 case OPC_ST_D:
adc370a4 29198 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
29199 break;
29200 }
29201
29202 tcg_temp_free_i32(twd);
adc370a4 29203 tcg_temp_free(taddr);
f7685877
YK
29204 }
29205 break;
4c789546
YK
29206 default:
29207 MIPS_INVAL("MSA instruction");
9c708c7f 29208 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
29209 break;
29210 }
29211
29212}
29213
d2bfa6e6 29214static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
29215{
29216 int32_t offset;
29217 int rs, rt, rd, sa;
29218 uint32_t op, op1;
29219 int16_t imm;
29220
29221 /* make sure instructions are on a word boundary */
eeb3bba8
EC
29222 if (ctx->base.pc_next & 0x3) {
29223 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 29224 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
29225 return;
29226 }
29227
29228 /* Handle blikely not taken case */
29229 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 29230 TCGLabel *l1 = gen_new_label();
099e5b4d 29231
099e5b4d
LA
29232 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29233 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 29234 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
29235 gen_set_label(l1);
29236 }
29237
099e5b4d
LA
29238 op = MASK_OP_MAJOR(ctx->opcode);
29239 rs = (ctx->opcode >> 21) & 0x1f;
29240 rt = (ctx->opcode >> 16) & 0x1f;
29241 rd = (ctx->opcode >> 11) & 0x1f;
29242 sa = (ctx->opcode >> 6) & 0x1f;
29243 imm = (int16_t)ctx->opcode;
29244 switch (op) {
29245 case OPC_SPECIAL:
29246 decode_opc_special(env, ctx);
29247 break;
29248 case OPC_SPECIAL2:
37b9aae2 29249#if defined(TARGET_MIPS64)
71b8a6b3 29250 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 29251 decode_mmi(env, ctx);
37b9aae2
MM
29252#else
29253 if (ctx->insn_flags & ASE_MXU) {
0a348b9a 29254 decode_opc_mxu(env, ctx);
b621f018 29255#endif
71b8a6b3
FN
29256 } else {
29257 decode_opc_special2_legacy(env, ctx);
29258 }
099e5b4d
LA
29259 break;
29260 case OPC_SPECIAL3:
37b9aae2 29261#if defined(TARGET_MIPS64)
bb41e74b 29262 if (ctx->insn_flags & INSN_R5900) {
874b2879 29263 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
29264 } else {
29265 decode_opc_special3(env, ctx);
29266 }
37b9aae2
MM
29267#else
29268 decode_opc_special3(env, ctx);
29269#endif
099e5b4d 29270 break;
7a387fff
TS
29271 case OPC_REGIMM:
29272 op1 = MASK_REGIMM(ctx->opcode);
29273 switch (op1) {
fecd2646
LA
29274 case OPC_BLTZL: /* REGIMM branches */
29275 case OPC_BGEZL:
29276 case OPC_BLTZALL:
29277 case OPC_BGEZALL:
d9224450 29278 check_insn(ctx, ISA_MIPS2);
fecd2646 29279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29280 /* Fallthrough */
fecd2646
LA
29281 case OPC_BLTZ:
29282 case OPC_BGEZ:
b231c103 29283 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 29284 break;
fecd2646
LA
29285 case OPC_BLTZAL:
29286 case OPC_BGEZAL:
0aefa333
YK
29287 if (ctx->insn_flags & ISA_MIPS32R6) {
29288 if (rs == 0) {
29289 /* OPC_NAL, OPC_BAL */
b231c103 29290 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 29291 } else {
9c708c7f 29292 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
29293 }
29294 } else {
b231c103 29295 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 29296 }
c9602061 29297 break;
c2e19f3c
AM
29298 case OPC_TGEI: /* REGIMM traps */
29299 case OPC_TGEIU:
29300 case OPC_TLTI:
29301 case OPC_TLTIU:
29302 case OPC_TEQI:
29303
7a387fff 29304 case OPC_TNEI:
d9224450 29305 check_insn(ctx, ISA_MIPS2);
fecd2646 29306 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
29307 gen_trap(ctx, op1, rs, -1, imm);
29308 break;
bb238210
YK
29309 case OPC_SIGRIE:
29310 check_insn(ctx, ISA_MIPS32R6);
29311 generate_exception_end(ctx, EXCP_RI);
29312 break;
7a387fff 29313 case OPC_SYNCI:
d75c135e 29314 check_insn(ctx, ISA_MIPS32R2);
7480515f
AM
29315 /*
29316 * Break the TB to be able to sync copied instructions
29317 * immediately.
29318 */
eeb3bba8 29319 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 29320 break;
e45a93e2
JL
29321 case OPC_BPOSGE32: /* MIPS DSP branch */
29322#if defined(TARGET_MIPS64)
29323 case OPC_BPOSGE64:
29324#endif
29325 check_dsp(ctx);
b231c103 29326 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 29327 break;
d4ea6acd
LA
29328#if defined(TARGET_MIPS64)
29329 case OPC_DAHI:
29330 check_insn(ctx, ISA_MIPS32R6);
29331 check_mips_64(ctx);
29332 if (rs != 0) {
29333 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29334 }
d4ea6acd
LA
29335 break;
29336 case OPC_DATI:
29337 check_insn(ctx, ISA_MIPS32R6);
29338 check_mips_64(ctx);
29339 if (rs != 0) {
29340 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29341 }
d4ea6acd
LA
29342 break;
29343#endif
6af0bf9c 29344 default: /* Invalid */
923617a3 29345 MIPS_INVAL("regimm");
9c708c7f 29346 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29347 break;
29348 }
29349 break;
7a387fff 29350 case OPC_CP0:
387a8fe5 29351 check_cp0_enabled(ctx);
7a387fff 29352 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 29353 switch (op1) {
7a387fff
TS
29354 case OPC_MFC0:
29355 case OPC_MTC0:
ead9360e
TS
29356 case OPC_MFTR:
29357 case OPC_MTTR:
5204ea79
LA
29358 case OPC_MFHC0:
29359 case OPC_MTHC0:
d26bc211 29360#if defined(TARGET_MIPS64)
7a387fff
TS
29361 case OPC_DMFC0:
29362 case OPC_DMTC0:
29363#endif
f1aa6320 29364#ifndef CONFIG_USER_ONLY
932e71cd 29365 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 29366#endif /* !CONFIG_USER_ONLY */
7a387fff 29367 break;
c38a1d52
AR
29368 case OPC_C0:
29369 case OPC_C0_1:
29370 case OPC_C0_2:
29371 case OPC_C0_3:
29372 case OPC_C0_4:
29373 case OPC_C0_5:
29374 case OPC_C0_6:
29375 case OPC_C0_7:
29376 case OPC_C0_8:
29377 case OPC_C0_9:
29378 case OPC_C0_A:
29379 case OPC_C0_B:
29380 case OPC_C0_C:
29381 case OPC_C0_D:
29382 case OPC_C0_E:
29383 case OPC_C0_F:
f1aa6320 29384#ifndef CONFIG_USER_ONLY
932e71cd 29385 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 29386#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
29387 break;
29388 case OPC_MFMC0:
8706c382 29389#ifndef CONFIG_USER_ONLY
932e71cd 29390 {
099e5b4d 29391 uint32_t op2;
35fbce2c 29392 TCGv t0 = tcg_temp_new();
6c5c1e20 29393
0eaef5aa 29394 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
29395 switch (op2) {
29396 case OPC_DMT:
9affc1c5 29397 check_cp0_mt(ctx);
9ed5726c 29398 gen_helper_dmt(t0);
35fbce2c 29399 gen_store_gpr(t0, rt);
6c5c1e20
TS
29400 break;
29401 case OPC_EMT:
9affc1c5 29402 check_cp0_mt(ctx);
9ed5726c 29403 gen_helper_emt(t0);
35fbce2c 29404 gen_store_gpr(t0, rt);
da80682b 29405 break;
6c5c1e20 29406 case OPC_DVPE:
9affc1c5 29407 check_cp0_mt(ctx);
895c2d04 29408 gen_helper_dvpe(t0, cpu_env);
35fbce2c 29409 gen_store_gpr(t0, rt);
6c5c1e20
TS
29410 break;
29411 case OPC_EVPE:
9affc1c5 29412 check_cp0_mt(ctx);
895c2d04 29413 gen_helper_evpe(t0, cpu_env);
35fbce2c 29414 gen_store_gpr(t0, rt);
6c5c1e20 29415 break;
01bc435b
YK
29416 case OPC_DVP:
29417 check_insn(ctx, ISA_MIPS32R6);
29418 if (ctx->vp) {
29419 gen_helper_dvp(t0, cpu_env);
29420 gen_store_gpr(t0, rt);
29421 }
29422 break;
29423 case OPC_EVP:
29424 check_insn(ctx, ISA_MIPS32R6);
29425 if (ctx->vp) {
29426 gen_helper_evp(t0, cpu_env);
29427 gen_store_gpr(t0, rt);
29428 }
29429 break;
6c5c1e20 29430 case OPC_DI:
d75c135e 29431 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29432 save_cpu_state(ctx, 1);
895c2d04 29433 gen_helper_di(t0, cpu_env);
35fbce2c 29434 gen_store_gpr(t0, rt);
7480515f
AM
29435 /*
29436 * Stop translation as we may have switched
29437 * the execution mode.
29438 */
eeb3bba8 29439 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
29440 break;
29441 case OPC_EI:
d75c135e 29442 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29443 save_cpu_state(ctx, 1);
895c2d04 29444 gen_helper_ei(t0, cpu_env);
35fbce2c 29445 gen_store_gpr(t0, rt);
7480515f
AM
29446 /*
29447 * DISAS_STOP isn't sufficient, we need to ensure we break
29448 * out of translated code to check for pending interrupts.
29449 */
eeb3bba8
EC
29450 gen_save_pc(ctx->base.pc_next + 4);
29451 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
29452 break;
29453 default: /* Invalid */
29454 MIPS_INVAL("mfmc0");
9c708c7f 29455 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
29456 break;
29457 }
6c5c1e20 29458 tcg_temp_free(t0);
7a387fff 29459 }
0eaef5aa 29460#endif /* !CONFIG_USER_ONLY */
6af0bf9c 29461 break;
7a387fff 29462 case OPC_RDPGPR:
d75c135e 29463 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29464 gen_load_srsgpr(rt, rd);
ead9360e 29465 break;
7a387fff 29466 case OPC_WRPGPR:
d75c135e 29467 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29468 gen_store_srsgpr(rt, rd);
38121543 29469 break;
6af0bf9c 29470 default:
923617a3 29471 MIPS_INVAL("cp0");
9c708c7f 29472 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29473 break;
29474 }
29475 break;
31837be3
YK
29476 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29477 if (ctx->insn_flags & ISA_MIPS32R6) {
29478 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29479 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29480 } else {
29481 /* OPC_ADDI */
29482 /* Arithmetic with immediate opcode */
29483 gen_arith_imm(ctx, op, rt, rs, imm);
29484 }
29485 break;
324d9e32 29486 case OPC_ADDIU:
d75c135e 29487 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29488 break;
324d9e32
AJ
29489 case OPC_SLTI: /* Set on less than with immediate opcode */
29490 case OPC_SLTIU:
d75c135e 29491 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
29492 break;
29493 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 29494 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
29495 case OPC_ORI:
29496 case OPC_XORI:
d75c135e 29497 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 29498 break;
c2e19f3c
AM
29499 case OPC_J: /* Jump */
29500 case OPC_JAL:
7a387fff 29501 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 29502 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 29503 break;
31837be3
YK
29504 /* Branch */
29505 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29506 if (ctx->insn_flags & ISA_MIPS32R6) {
29507 if (rt == 0) {
9c708c7f 29508 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29509 break;
29510 }
29511 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29512 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29513 } else {
29514 /* OPC_BLEZL */
b231c103 29515 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29516 }
29517 break;
29518 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29519 if (ctx->insn_flags & ISA_MIPS32R6) {
29520 if (rt == 0) {
9c708c7f 29521 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29522 break;
29523 }
29524 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29525 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29526 } else {
29527 /* OPC_BGTZL */
b231c103 29528 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29529 }
29530 break;
29531 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29532 if (rt == 0) {
29533 /* OPC_BLEZ */
b231c103 29534 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29535 } else {
29536 check_insn(ctx, ISA_MIPS32R6);
29537 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29538 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29539 }
29540 break;
29541 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29542 if (rt == 0) {
29543 /* OPC_BGTZ */
b231c103 29544 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29545 } else {
29546 check_insn(ctx, ISA_MIPS32R6);
29547 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29548 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29549 }
29550 break;
29551 case OPC_BEQL:
29552 case OPC_BNEL:
d9224450 29553 check_insn(ctx, ISA_MIPS2);
fecd2646 29554 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29555 /* Fallthrough */
31837be3
YK
29556 case OPC_BEQ:
29557 case OPC_BNE:
b231c103 29558 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 29559 break;
d9224450
MR
29560 case OPC_LL: /* Load and stores */
29561 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
29562 if (ctx->insn_flags & INSN_R5900) {
29563 check_insn_opc_user_only(ctx, INSN_R5900);
29564 }
d9224450
MR
29565 /* Fallthrough */
29566 case OPC_LWL:
fecd2646
LA
29567 case OPC_LWR:
29568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29569 /* Fallthrough */
c2e19f3c
AM
29570 case OPC_LB:
29571 case OPC_LH:
29572 case OPC_LW:
29573 case OPC_LWPC:
29574 case OPC_LBU:
29575 case OPC_LHU:
d75c135e 29576 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29577 break;
fecd2646 29578 case OPC_SWL:
7a387fff 29579 case OPC_SWR:
fecd2646 29580 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29581 /* fall through */
c2e19f3c
AM
29582 case OPC_SB:
29583 case OPC_SH:
fecd2646 29584 case OPC_SW:
5c13fdfd 29585 gen_st(ctx, op, rt, rs, imm);
7a387fff 29586 break;
d66c7132 29587 case OPC_SC:
d9224450 29588 check_insn(ctx, ISA_MIPS2);
4368b29a 29589 check_insn_opc_removed(ctx, ISA_MIPS32R6);
55fc7a69
FN
29590 if (ctx->insn_flags & INSN_R5900) {
29591 check_insn_opc_user_only(ctx, INSN_R5900);
29592 }
33a07fa2
LA
29593 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29594 break;
7a387fff 29595 case OPC_CACHE:
bf7910c6 29596 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 29597 check_cp0_enabled(ctx);
d75c135e 29598 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
29599 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29600 gen_cache_operation(ctx, rt, rs, imm);
29601 }
ead9360e 29602 /* Treat as NOP. */
34ae7b51 29603 break;
7a387fff 29604 case OPC_PREF:
bf7910c6 29605 check_insn_opc_removed(ctx, ISA_MIPS32R6);
992e8176
FN
29606 if (ctx->insn_flags & INSN_R5900) {
29607 /* Treat as NOP. */
29608 } else {
29609 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29610 /* Treat as NOP. */
29611 }
6af0bf9c 29612 break;
4ad40f36 29613
923617a3 29614 /* Floating point (COP1). */
7a387fff
TS
29615 case OPC_LWC1:
29616 case OPC_LDC1:
29617 case OPC_SWC1:
29618 case OPC_SDC1:
5ab5c041 29619 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
29620 break;
29621
7a387fff 29622 case OPC_CP1:
5692c6e1
YK
29623 op1 = MASK_CP1(ctx->opcode);
29624
29625 switch (op1) {
29626 case OPC_MFHC1:
29627 case OPC_MTHC1:
5e755519 29628 check_cp1_enabled(ctx);
5692c6e1 29629 check_insn(ctx, ISA_MIPS32R2);
146dd620 29630 /* fall through */
5692c6e1
YK
29631 case OPC_MFC1:
29632 case OPC_CFC1:
29633 case OPC_MTC1:
29634 case OPC_CTC1:
29635 check_cp1_enabled(ctx);
29636 gen_cp1(ctx, op1, rt, rd);
29637 break;
d26bc211 29638#if defined(TARGET_MIPS64)
5692c6e1
YK
29639 case OPC_DMFC1:
29640 case OPC_DMTC1:
29641 check_cp1_enabled(ctx);
29642 check_insn(ctx, ISA_MIPS3);
d9224450 29643 check_mips_64(ctx);
5692c6e1
YK
29644 gen_cp1(ctx, op1, rt, rd);
29645 break;
e189e748 29646#endif
5692c6e1
YK
29647 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29648 check_cp1_enabled(ctx);
29649 if (ctx->insn_flags & ISA_MIPS32R6) {
29650 /* OPC_BC1EQZ */
31837be3 29651 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29652 rt, imm << 2, 4);
5692c6e1
YK
29653 } else {
29654 /* OPC_BC1ANY2 */
b8aa4598 29655 check_cop1x(ctx);
d75c135e 29656 check_insn(ctx, ASE_MIPS3D);
d75c135e 29657 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 29658 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
29659 }
29660 break;
29661 case OPC_BC1NEZ:
29662 check_cp1_enabled(ctx);
29663 check_insn(ctx, ISA_MIPS32R6);
29664 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29665 rt, imm << 2, 4);
5692c6e1
YK
29666 break;
29667 case OPC_BC1ANY4:
29668 check_cp1_enabled(ctx);
29669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29670 check_cop1x(ctx);
29671 check_insn(ctx, ASE_MIPS3D);
29672 /* fall through */
29673 case OPC_BC1:
29674 check_cp1_enabled(ctx);
29675 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29676 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29677 (rt >> 2) & 0x7, imm << 2);
29678 break;
29679 case OPC_PS_FMT:
e29c9628 29680 check_ps(ctx);
b6f3b233 29681 /* fall through */
5692c6e1
YK
29682 case OPC_S_FMT:
29683 case OPC_D_FMT:
29684 check_cp1_enabled(ctx);
29685 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29686 (imm >> 8) & 0x7);
29687 break;
29688 case OPC_W_FMT:
29689 case OPC_L_FMT:
29690 {
29691 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29692 check_cp1_enabled(ctx);
29693 if (ctx->insn_flags & ISA_MIPS32R6) {
29694 switch (r6_op) {
29695 case R6_OPC_CMP_AF_S:
29696 case R6_OPC_CMP_UN_S:
29697 case R6_OPC_CMP_EQ_S:
29698 case R6_OPC_CMP_UEQ_S:
29699 case R6_OPC_CMP_LT_S:
29700 case R6_OPC_CMP_ULT_S:
29701 case R6_OPC_CMP_LE_S:
29702 case R6_OPC_CMP_ULE_S:
29703 case R6_OPC_CMP_SAF_S:
29704 case R6_OPC_CMP_SUN_S:
29705 case R6_OPC_CMP_SEQ_S:
29706 case R6_OPC_CMP_SEUQ_S:
29707 case R6_OPC_CMP_SLT_S:
29708 case R6_OPC_CMP_SULT_S:
29709 case R6_OPC_CMP_SLE_S:
29710 case R6_OPC_CMP_SULE_S:
29711 case R6_OPC_CMP_OR_S:
29712 case R6_OPC_CMP_UNE_S:
29713 case R6_OPC_CMP_NE_S:
29714 case R6_OPC_CMP_SOR_S:
29715 case R6_OPC_CMP_SUNE_S:
29716 case R6_OPC_CMP_SNE_S:
29717 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29718 break;
29719 case R6_OPC_CMP_AF_D:
29720 case R6_OPC_CMP_UN_D:
29721 case R6_OPC_CMP_EQ_D:
29722 case R6_OPC_CMP_UEQ_D:
29723 case R6_OPC_CMP_LT_D:
29724 case R6_OPC_CMP_ULT_D:
29725 case R6_OPC_CMP_LE_D:
29726 case R6_OPC_CMP_ULE_D:
29727 case R6_OPC_CMP_SAF_D:
29728 case R6_OPC_CMP_SUN_D:
29729 case R6_OPC_CMP_SEQ_D:
29730 case R6_OPC_CMP_SEUQ_D:
29731 case R6_OPC_CMP_SLT_D:
29732 case R6_OPC_CMP_SULT_D:
29733 case R6_OPC_CMP_SLE_D:
29734 case R6_OPC_CMP_SULE_D:
29735 case R6_OPC_CMP_OR_D:
29736 case R6_OPC_CMP_UNE_D:
29737 case R6_OPC_CMP_NE_D:
29738 case R6_OPC_CMP_SOR_D:
29739 case R6_OPC_CMP_SUNE_D:
29740 case R6_OPC_CMP_SNE_D:
29741 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29742 break;
29743 default:
d2bfa6e6
MR
29744 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29745 rt, rd, sa, (imm >> 8) & 0x7);
29746
5692c6e1 29747 break;
3f493883 29748 }
5692c6e1
YK
29749 } else {
29750 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29751 (imm >> 8) & 0x7);
36d23958 29752 }
5692c6e1
YK
29753 break;
29754 }
29755 case OPC_BZ_V:
29756 case OPC_BNZ_V:
29757 case OPC_BZ_B:
29758 case OPC_BZ_H:
29759 case OPC_BZ_W:
29760 case OPC_BZ_D:
29761 case OPC_BNZ_B:
29762 case OPC_BNZ_H:
29763 case OPC_BNZ_W:
29764 case OPC_BNZ_D:
29765 check_insn(ctx, ASE_MSA);
29766 gen_msa_branch(env, ctx, op1);
29767 break;
29768 default:
29769 MIPS_INVAL("cp1");
9c708c7f 29770 generate_exception_end(ctx, EXCP_RI);
5692c6e1 29771 break;
6ea83fed 29772 }
4ad40f36
FB
29773 break;
29774
31837be3
YK
29775 /* Compact branches [R6] and COP2 [non-R6] */
29776 case OPC_BC: /* OPC_LWC2 */
29777 case OPC_BALC: /* OPC_SWC2 */
29778 if (ctx->insn_flags & ISA_MIPS32R6) {
29779 /* OPC_BC, OPC_BALC */
29780 gen_compute_compact_branch(ctx, op, 0, 0,
29781 sextract32(ctx->opcode << 2, 0, 28));
29782 } else {
29783 /* OPC_LWC2, OPC_SWC2 */
29784 /* COP2: Not implemented. */
29785 generate_exception_err(ctx, EXCP_CpU, 2);
29786 }
29787 break;
29788 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29789 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29790 if (ctx->insn_flags & ISA_MIPS32R6) {
29791 if (rs != 0) {
29792 /* OPC_BEQZC, OPC_BNEZC */
29793 gen_compute_compact_branch(ctx, op, rs, 0,
29794 sextract32(ctx->opcode << 2, 0, 23));
29795 } else {
29796 /* OPC_JIC, OPC_JIALC */
29797 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29798 }
29799 } else {
29800 /* OPC_LWC2, OPC_SWC2 */
29801 /* COP2: Not implemented. */
29802 generate_exception_err(ctx, EXCP_CpU, 2);
29803 }
4ad40f36 29804 break;
bd277fa1 29805 case OPC_CP2:
d75c135e 29806 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
29807 /* Note that these instructions use different fields. */
29808 gen_loongson_multimedia(ctx, sa, rd, rt);
29809 break;
4ad40f36 29810
7a387fff 29811 case OPC_CP3:
fecd2646 29812 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 29813 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 29814 check_cp1_enabled(ctx);
36d23958
TS
29815 op1 = MASK_CP3(ctx->opcode);
29816 switch (op1) {
d9224450
MR
29817 case OPC_LUXC1:
29818 case OPC_SUXC1:
29819 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29820 /* Fallthrough */
5a5012ec
TS
29821 case OPC_LWXC1:
29822 case OPC_LDXC1:
5a5012ec
TS
29823 case OPC_SWXC1:
29824 case OPC_SDXC1:
d9224450 29825 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 29826 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 29827 break;
e0c84da7 29828 case OPC_PREFX:
d9224450 29829 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 29830 /* Treat as NOP. */
e0c84da7 29831 break;
5a5012ec 29832 case OPC_ALNV_PS:
d9224450
MR
29833 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29834 /* Fallthrough */
5a5012ec
TS
29835 case OPC_MADD_S:
29836 case OPC_MADD_D:
29837 case OPC_MADD_PS:
29838 case OPC_MSUB_S:
29839 case OPC_MSUB_D:
29840 case OPC_MSUB_PS:
29841 case OPC_NMADD_S:
29842 case OPC_NMADD_D:
29843 case OPC_NMADD_PS:
29844 case OPC_NMSUB_S:
29845 case OPC_NMSUB_D:
29846 case OPC_NMSUB_PS:
d9224450 29847 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
29848 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29849 break;
36d23958 29850 default:
923617a3 29851 MIPS_INVAL("cp3");
9c708c7f 29852 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
29853 break;
29854 }
29855 } else {
e397ee33 29856 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 29857 }
4ad40f36
FB
29858 break;
29859
d26bc211 29860#if defined(TARGET_MIPS64)
7a387fff 29861 /* MIPS64 opcodes */
96631327 29862 case OPC_LLD:
55fc7a69
FN
29863 if (ctx->insn_flags & INSN_R5900) {
29864 check_insn_opc_user_only(ctx, INSN_R5900);
29865 }
96631327 29866 /* fall through */
c2e19f3c
AM
29867 case OPC_LDL:
29868 case OPC_LDR:
fecd2646 29869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29870 /* fall through */
fecd2646 29871 case OPC_LWU:
7a387fff 29872 case OPC_LD:
d75c135e 29873 check_insn(ctx, ISA_MIPS3);
5c13fdfd 29874 check_mips_64(ctx);
d75c135e 29875 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29876 break;
c2e19f3c
AM
29877 case OPC_SDL:
29878 case OPC_SDR:
fecd2646 29879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29880 /* fall through */
7a387fff 29881 case OPC_SD:
d75c135e 29882 check_insn(ctx, ISA_MIPS3);
e189e748 29883 check_mips_64(ctx);
5c13fdfd 29884 gen_st(ctx, op, rt, rs, imm);
7a387fff 29885 break;
d66c7132 29886 case OPC_SCD:
bf7910c6 29887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 29888 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
29889 if (ctx->insn_flags & INSN_R5900) {
29890 check_insn_opc_user_only(ctx, INSN_R5900);
29891 }
d66c7132 29892 check_mips_64(ctx);
33a07fa2 29893 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 29894 break;
31837be3
YK
29895 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29896 if (ctx->insn_flags & ISA_MIPS32R6) {
29897 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29898 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29899 } else {
29900 /* OPC_DADDI */
29901 check_insn(ctx, ISA_MIPS3);
29902 check_mips_64(ctx);
29903 gen_arith_imm(ctx, op, rt, rs, imm);
29904 }
29905 break;
324d9e32 29906 case OPC_DADDIU:
d75c135e 29907 check_insn(ctx, ISA_MIPS3);
e189e748 29908 check_mips_64(ctx);
d75c135e 29909 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29910 break;
31837be3
YK
29911#else
29912 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29913 if (ctx->insn_flags & ISA_MIPS32R6) {
29914 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29915 } else {
29916 MIPS_INVAL("major opcode");
9c708c7f 29917 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29918 }
29919 break;
6af0bf9c 29920#endif
d4ea6acd
LA
29921 case OPC_DAUI: /* OPC_JALX */
29922 if (ctx->insn_flags & ISA_MIPS32R6) {
29923#if defined(TARGET_MIPS64)
29924 /* OPC_DAUI */
29925 check_mips_64(ctx);
db77d852
LA
29926 if (rs == 0) {
29927 generate_exception(ctx, EXCP_RI);
29928 } else if (rt != 0) {
d4ea6acd
LA
29929 TCGv t0 = tcg_temp_new();
29930 gen_load_gpr(t0, rs);
29931 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29932 tcg_temp_free(t0);
29933 }
d4ea6acd 29934#else
9c708c7f 29935 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
29936 MIPS_INVAL("major opcode");
29937#endif
29938 } else {
29939 /* OPC_JALX */
29940 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29941 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 29942 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 29943 }
364d4831 29944 break;
4c789546 29945 case OPC_MSA: /* OPC_MDMX */
f08099ad 29946 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 29947#if defined(TARGET_MIPS64)
874b2879 29948 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
37b9aae2 29949#endif
f08099ad
FN
29950 } else {
29951 /* MDMX: Not implemented. */
29952 gen_msa(env, ctx);
29953 }
d4ea6acd
LA
29954 break;
29955 case OPC_PCREL:
29956 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 29957 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 29958 break;
6af0bf9c 29959 default: /* Invalid */
923617a3 29960 MIPS_INVAL("major opcode");
9c708c7f 29961 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29962 break;
29963 }
6af0bf9c
FB
29964}
29965
18f440ed 29966static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 29967{
18f440ed 29968 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 29969 CPUMIPSState *env = cs->env_ptr;
12be9258 29970
18f440ed 29971 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
29972 ctx->saved_pc = -1;
29973 ctx->insn_flags = env->insn_flags;
29974 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 29975 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
29976 ctx->CP0_Config3 = env->CP0_Config3;
29977 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
29978 ctx->btarget = 0;
29979 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29980 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29981 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29982 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29983 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29984 ctx->PAMask = env->PAMask;
29985 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29986 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29987 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29988 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29989 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 29990 /* Restore delay slot state from the tb context. */
12be9258
EC
29991 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29992 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29993 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 29994 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
29995 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29996 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29997 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29998 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29999 restore_cpu_state(env, ctx);
932e71cd 30000#ifdef CONFIG_USER_ONLY
12be9258 30001 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 30002#else
12be9258 30003 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 30004#endif
12be9258
EC
30005 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30006 MO_UNALN : MO_ALIGN;
190ce7fb 30007
18f440ed
EC
30008 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30009 ctx->hflags);
30010}
12be9258 30011
18f440ed
EC
30012static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30013{
30014}
b933066a 30015
18f440ed
EC
30016static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30017{
30018 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30019
18f440ed
EC
30020 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30021 ctx->btarget);
30022}
31837be3 30023
18f440ed
EC
30024static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30025 const CPUBreakpoint *bp)
30026{
30027 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30028
18f440ed
EC
30029 save_cpu_state(ctx, 1);
30030 ctx->base.is_jmp = DISAS_NORETURN;
30031 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
30032 /*
30033 * The address covered by the breakpoint must be included in
30034 * [tb->pc, tb->pc + tb->size) in order to for it to be
30035 * properly cleared -- thus we increment the PC here so that
30036 * the logic setting tb->size below does the right thing.
30037 */
18f440ed
EC
30038 ctx->base.pc_next += 4;
30039 return true;
30040}
4ad40f36 30041
18f440ed
EC
30042static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30043{
30044 CPUMIPSState *env = cs->env_ptr;
30045 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30046 int insn_bytes;
30047 int is_slot;
4ad40f36 30048
18f440ed 30049 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
30050 if (ctx->insn_flags & ISA_NANOMIPS32) {
30051 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30052 insn_bytes = decode_nanomips_opc(env, ctx);
30053 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
30054 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30055 insn_bytes = 4;
30056 decode_opc(env, ctx);
30057 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30058 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30059 insn_bytes = decode_micromips_opc(env, ctx);
30060 } else if (ctx->insn_flags & ASE_MIPS16) {
30061 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30062 insn_bytes = decode_mips16_opc(env, ctx);
30063 } else {
30064 generate_exception_end(ctx, EXCP_RI);
30065 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30066 return;
30067 }
faf7aaa9 30068
18f440ed
EC
30069 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30070 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30071 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
30072 /*
30073 * Force to generate branch as there is neither delay nor
30074 * forbidden slot.
30075 */
18f440ed
EC
30076 is_slot = 1;
30077 }
30078 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30079 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
30080 /*
30081 * Force to generate branch as microMIPS R6 doesn't restrict
30082 * branches in the forbidden slot.
30083 */
18f440ed 30084 is_slot = 1;
eeb3bba8 30085 }
18f440ed
EC
30086 }
30087 if (is_slot) {
30088 gen_branch(ctx, insn_bytes);
30089 }
30090 ctx->base.pc_next += insn_bytes;
1b530a6d 30091
18f440ed
EC
30092 if (ctx->base.is_jmp != DISAS_NEXT) {
30093 return;
6af0bf9c 30094 }
7480515f
AM
30095 /*
30096 * Execute a branch and its delay slot as a single instruction.
30097 * This is what GDB expects and is consistent with what the
30098 * hardware does (e.g. if a delay slot instruction faults, the
30099 * reported PC is the PC of the branch).
30100 */
18f440ed
EC
30101 if (ctx->base.singlestep_enabled &&
30102 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30103 ctx->base.is_jmp = DISAS_TOO_MANY;
30104 }
30105 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30106 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 30107 }
18f440ed
EC
30108}
30109
30110static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30111{
30112 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30113
12be9258
EC
30114 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30115 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 30116 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 30117 } else {
12be9258 30118 switch (ctx->base.is_jmp) {
b28425ba 30119 case DISAS_STOP:
12be9258 30120 gen_save_pc(ctx->base.pc_next);
cd314a7d 30121 tcg_gen_lookup_and_goto_ptr();
df1561e2 30122 break;
b28425ba 30123 case DISAS_NEXT:
18f440ed 30124 case DISAS_TOO_MANY:
12be9258
EC
30125 save_cpu_state(ctx, 0);
30126 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 30127 break;
b28425ba 30128 case DISAS_EXIT:
07ea28b4 30129 tcg_gen_exit_tb(NULL, 0);
16c00cb2 30130 break;
b28425ba 30131 case DISAS_NORETURN:
5a5012ec 30132 break;
18f440ed
EC
30133 default:
30134 g_assert_not_reached();
6958549d 30135 }
6af0bf9c 30136 }
18f440ed
EC
30137}
30138
30139static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30140{
30141 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30142 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30143}
30144
30145static const TranslatorOps mips_tr_ops = {
30146 .init_disas_context = mips_tr_init_disas_context,
30147 .tb_start = mips_tr_tb_start,
30148 .insn_start = mips_tr_insn_start,
30149 .breakpoint_check = mips_tr_breakpoint_check,
30150 .translate_insn = mips_tr_translate_insn,
30151 .tb_stop = mips_tr_tb_stop,
30152 .disas_log = mips_tr_disas_log,
30153};
30154
8b86d6d2 30155void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
30156{
30157 DisasContext ctx;
30158
8b86d6d2 30159 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
30160}
30161
71375b59 30162static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
30163{
30164 int i;
5e755519 30165 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 30166
2a5612e6
SW
30167#define printfpr(fp) \
30168 do { \
30169 if (is_fpu64) \
90c84c56
MA
30170 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30171 " fd:%13g fs:%13g psu: %13g\n", \
30172 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30173 (double)(fp)->fd, \
30174 (double)(fp)->fs[FP_ENDIAN_IDX], \
30175 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
30176 else { \
30177 fpr_t tmp; \
30178 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30179 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
30180 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30181 " fd:%13g fs:%13g psu:%13g\n", \
30182 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30183 (double)tmp.fd, \
30184 (double)tmp.fs[FP_ENDIAN_IDX], \
30185 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 30186 } \
71375b59 30187 } while (0)
6ea83fed 30188
5a5012ec 30189
90c84c56
MA
30190 qemu_fprintf(f,
30191 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30192 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30193 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 30194 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 30195 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 30196 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
30197 }
30198
30199#undef printfpr
30200}
30201
90c84c56 30202void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 30203{
878096ee
AF
30204 MIPSCPU *cpu = MIPS_CPU(cs);
30205 CPUMIPSState *env = &cpu->env;
6af0bf9c 30206 int i;
3b46e624 30207
90c84c56
MA
30208 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30209 " LO=0x" TARGET_FMT_lx " ds %04x "
30210 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30211 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30212 env->hflags, env->btarget, env->bcond);
6af0bf9c 30213 for (i = 0; i < 32; i++) {
1f8929d2 30214 if ((i & 3) == 0) {
90c84c56 30215 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 30216 }
90c84c56
MA
30217 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30218 regnames[i], env->active_tc.gpr[i]);
1f8929d2 30219 if ((i & 3) == 3) {
90c84c56 30220 qemu_fprintf(f, "\n");
1f8929d2 30221 }
90c84c56
MA
30222 }
30223
71375b59
AM
30224 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30225 TARGET_FMT_lx "\n",
90c84c56
MA
30226 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30227 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30228 PRIx64 "\n",
30229 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30230 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30231 env->CP0_Config2, env->CP0_Config3);
30232 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30233 env->CP0_Config4, env->CP0_Config5);
1cc5af69 30234 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 30235 fpu_dump_state(env, f, flags);
1cc5af69 30236 }
6af0bf9c
FB
30237}
30238
78ce64f4 30239void mips_tcg_init(void)
39454628 30240{
f01be154 30241 int i;
39454628 30242
f764718d 30243 cpu_gpr[0] = NULL;
bb928dbe 30244 for (i = 1; i < 32; i++)
e1ccc054 30245 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
71375b59
AM
30246 offsetof(CPUMIPSState,
30247 active_tc.gpr[i]),
4b2eb8d2 30248 regnames[i]);
d73ee8a2 30249
863f264d
YK
30250 for (i = 0; i < 32; i++) {
30251 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30252 msa_wr_d[i * 2] =
e1ccc054 30253 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
7480515f
AM
30254 /*
30255 * The scalar floating-point unit (FPU) registers are mapped on
30256 * the MSA vector registers.
30257 */
cb269f27 30258 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
30259 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30260 msa_wr_d[i * 2 + 1] =
e1ccc054 30261 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
30262 }
30263
e1ccc054 30264 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 30265 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 30266 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 30267 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 30268 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 30269 regnames_HI[i]);
e1ccc054 30270 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 30271 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 30272 regnames_LO[i]);
4b2eb8d2 30273 }
e1ccc054 30274 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
30275 offsetof(CPUMIPSState,
30276 active_tc.DSPControl),
4b2eb8d2 30277 "DSPControl");
e1ccc054 30278 bcond = tcg_global_mem_new(cpu_env,
7db13fae 30279 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 30280 btarget = tcg_global_mem_new(cpu_env,
7db13fae 30281 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 30282 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 30283 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 30284
e1ccc054 30285 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 30286 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 30287 "fcr0");
e1ccc054 30288 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 30289 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 30290 "fcr31");
33a07fa2
LA
30291 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30292 "lladdr");
30293 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30294 "llval");
a168a796
FN
30295
30296#if defined(TARGET_MIPS64)
30297 cpu_mmr[0] = NULL;
30298 for (i = 1; i < 32; i++) {
30299 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30300 offsetof(CPUMIPSState,
30301 active_tc.mmr[i]),
30302 regnames[i]);
30303 }
30304#endif
30305
b621f018 30306#if !defined(TARGET_MIPS64)
eb5559f6
CJ
30307 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30308 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30309 offsetof(CPUMIPSState,
30310 active_tc.mxu_gpr[i]),
30311 mxuregnames[i]);
30312 }
30313
30314 mxu_CR = tcg_global_mem_new(cpu_env,
30315 offsetof(CPUMIPSState, active_tc.mxu_cr),
30316 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 30317#endif
39454628
TS
30318}
30319
5b27a92d 30320#include "translate_init.inc.c"
aaed909a 30321
27e38392
PMD
30322void cpu_mips_realize_env(CPUMIPSState *env)
30323{
30324 env->exception_base = (int32_t)0xBFC00000;
30325
30326#ifndef CONFIG_USER_ONLY
30327 mmu_init(env, env->cpu_model);
30328#endif
30329 fpu_init(env, env->cpu_model);
30330 mvp_init(env, env->cpu_model);
30331}
30332
a7519f2b 30333bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 30334{
a7519f2b
IM
30335 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30336 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
30337}
30338
5b1e0981 30339bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
bed9e5ce 30340{
a7519f2b
IM
30341 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30342 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
30343}
30344
89777fd1
LA
30345void cpu_set_exception_base(int vp_index, target_ulong address)
30346{
30347 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30348 vp->env.exception_base = address;
30349}
30350
1bba0dc9 30351void cpu_state_reset(CPUMIPSState *env)
6ae81775 30352{
5a7330b3 30353 CPUState *cs = env_cpu(env);
6ae81775 30354
51cc2e78
BS
30355 /* Reset registers to their default values */
30356 env->CP0_PRid = env->cpu_model->CP0_PRid;
30357 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30358#ifdef TARGET_WORDS_BIGENDIAN
30359 env->CP0_Config0 |= (1 << CP0C0_BE);
30360#endif
30361 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30362 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30363 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
30364 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30365 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
30366 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30367 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
30368 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30369 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
30370 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30371 << env->cpu_model->CP0_LLAddr_shift;
30372 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
30373 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30374 env->CCRes = env->cpu_model->CCRes;
30375 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30376 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30377 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30378 env->current_tc = 0;
30379 env->SEGBITS = env->cpu_model->SEGBITS;
30380 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30381#if defined(TARGET_MIPS64)
30382 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30383 env->SEGMask |= 3ULL << 62;
30384 }
30385#endif
30386 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
30387 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30388 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30389 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30390 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30391 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30392 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30393 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30394 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30395 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30396 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
30397 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30398 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 30399 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 30400 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 30401 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 30402 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 30403 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
30404 env->insn_flags = env->cpu_model->insn_flags;
30405
0eaef5aa 30406#if defined(CONFIG_USER_ONLY)
03e6e501 30407 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
30408# ifdef TARGET_MIPS64
30409 /* Enable 64-bit register mode. */
30410 env->CP0_Status |= (1 << CP0St_PX);
30411# endif
30412# ifdef TARGET_ABI_MIPSN64
30413 /* Enable 64-bit address mode. */
30414 env->CP0_Status |= (1 << CP0St_UX);
30415# endif
7480515f
AM
30416 /*
30417 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30418 * hardware registers.
30419 */
94159135 30420 env->CP0_HWREna |= 0x0000000F;
91a75935 30421 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 30422 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 30423 }
6f0af304
PJ
30424 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30425 env->CP0_Status |= (1 << CP0St_MX);
853c3240 30426 }
4d66261f
PJ
30427# if defined(TARGET_MIPS64)
30428 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30429 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30430 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
30431 env->CP0_Status |= (1 << CP0St_FR);
30432 }
4d66261f 30433# endif
932e71cd
AJ
30434#else
30435 if (env->hflags & MIPS_HFLAG_BMASK) {
7480515f
AM
30436 /*
30437 * If the exception was raised from a delay slot,
30438 * come back to the jump.
30439 */
c3577479
MR
30440 env->CP0_ErrorEPC = (env->active_tc.PC
30441 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 30442 } else {
932e71cd
AJ
30443 env->CP0_ErrorEPC = env->active_tc.PC;
30444 }
89777fd1 30445 env->active_tc.PC = env->exception_base;
51cc2e78
BS
30446 env->CP0_Random = env->tlb->nb_tlb - 1;
30447 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 30448 env->CP0_Wired = 0;
01bc435b 30449 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 30450 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 30451 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
30452 env->CP0_EBase |= 0x40000000;
30453 } else {
74dbf824 30454 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 30455 }
c870e3f5
YK
30456 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30457 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30458 }
a0c80608
PB
30459 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30460 0x3ff : 0xff;
932e71cd 30461 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
7480515f
AM
30462 /*
30463 * Vectored interrupts not implemented, timer on int 7,
30464 * no performance counters.
30465 */
932e71cd
AJ
30466 env->CP0_IntCtl = 0xe0000000;
30467 {
30468 int i;
30469
30470 for (i = 0; i < 7; i++) {
30471 env->CP0_WatchLo[i] = 0;
30472 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 30473 }
932e71cd
AJ
30474 env->CP0_WatchLo[7] = 0;
30475 env->CP0_WatchHi[7] = 0;
fd88b6ab 30476 }
932e71cd
AJ
30477 /* Count register increments in debug mode, EJTAG version 1 */
30478 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 30479
4b69c7e2
JH
30480 cpu_mips_store_count(env, 1);
30481
9e56e756
EI
30482 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30483 int i;
30484
30485 /* Only TC0 on VPE 0 starts as active. */
30486 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 30487 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
30488 env->tcs[i].CP0_TCHalt = 1;
30489 }
30490 env->active_tc.CP0_TCHalt = 1;
259186a7 30491 cs->halted = 1;
9e56e756 30492
55e5c285 30493 if (cs->cpu_index == 0) {
9e56e756
EI
30494 /* VPE0 starts up enabled. */
30495 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30496 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30497
30498 /* TC0 starts up unhalted. */
259186a7 30499 cs->halted = 0;
9e56e756
EI
30500 env->active_tc.CP0_TCHalt = 0;
30501 env->tcs[0].CP0_TCHalt = 0;
30502 /* With thread 0 active. */
30503 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30504 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30505 }
30506 }
cec56a73
JH
30507
30508 /*
30509 * Configure default legacy segmentation control. We use this regardless of
30510 * whether segmentation control is presented to the guest.
30511 */
30512 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30513 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30514 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30515 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30516 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30517 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30518 (2 << CP0SC_C);
30519 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30520 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30521 (3 << CP0SC_C)) << 16;
30522 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30523 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30524 (1 << CP0SC_EU) | (2 << CP0SC_C);
30525 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30526 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30527 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30528 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30529 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 30530#endif
ddc584bd
LA
30531 if ((env->insn_flags & ISA_MIPS32R6) &&
30532 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30533 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30534 env->CP0_Status |= (1 << CP0St_FR);
30535 }
30536
63010795
YK
30537 if (env->insn_flags & ISA_MIPS32R6) {
30538 /* PTW = 1 */
30539 env->CP0_PWSize = 0x40;
30540 /* GDI = 12 */
30541 /* UDI = 12 */
30542 /* MDI = 12 */
30543 /* PRI = 12 */
30544 /* PTEI = 2 */
30545 env->CP0_PWField = 0x0C30C302;
30546 } else {
30547 /* GDI = 0 */
30548 /* UDI = 0 */
30549 /* MDI = 0 */
30550 /* PRI = 0 */
30551 /* PTEI = 2 */
30552 env->CP0_PWField = 0x02;
30553 }
30554
0bbc0396
SM
30555 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30556 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
30557 env->hflags |= MIPS_HFLAG_M16;
30558 }
30559
863f264d
YK
30560 /* MSA */
30561 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30562 msa_reset(env);
30563 }
30564
03e6e501 30565 compute_hflags(env);
599bc5e8 30566 restore_fp_status(env);
e117f526 30567 restore_pamask(env);
27103424 30568 cs->exception_index = EXCP_NONE;
3b3c1694
LA
30569
30570 if (semihosting_get_argc()) {
30571 /* UHI interface can be used to obtain argc and argv */
30572 env->active_tc.gpr[4] = -1;
30573 }
6af0bf9c 30574}
d2856f1a 30575
bad729e2
RH
30576void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30577 target_ulong *data)
d2856f1a 30578{
bad729e2 30579 env->active_tc.PC = data[0];
d2856f1a 30580 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 30581 env->hflags |= data[1];
4636401d
AJ
30582 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30583 case MIPS_HFLAG_BR:
30584 break;
30585 case MIPS_HFLAG_BC:
30586 case MIPS_HFLAG_BL:
30587 case MIPS_HFLAG_B:
bad729e2 30588 env->btarget = data[2];
4636401d
AJ
30589 break;
30590 }
d2856f1a 30591}