]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
target/mips: Amend CP0 WatchHi register implementation
[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"
dcb32f1d 29#include "tcg/tcg-op.h"
f08b6170 30#include "exec/cpu_ldst.h"
d3d93c6c 31#include "hw/mips/cpudevs.h"
6af0bf9c 32
2ef6175a
RH
33#include "exec/helper-proto.h"
34#include "exec/helper-gen.h"
f1672e6f 35#include "hw/semihosting/semihost.h"
a7812ae4 36
b44a7fb1 37#include "target/mips/trace.h"
a7e30d84 38#include "trace-tcg.h"
b28425ba 39#include "exec/translator.h"
508127e2 40#include "exec/log.h"
0442428a 41#include "qemu/qemu-print.h"
a7e30d84 42
fb7729e2 43#define MIPS_DEBUG_DISAS 0
6af0bf9c 44
7a387fff 45/* MIPS major opcodes */
71375b59 46#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
47
48enum {
49 /* indirect opcode tables */
7a387fff
TS
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 58 /* arithmetic with immediate */
7a387fff
TS
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
324d9e32 63 /* logic with immediate */
7a387fff
TS
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
324d9e32 68 /* arithmetic with immediate */
7a387fff
TS
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
e37e863f 71 /* Jump and branches */
7a387fff
TS
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
b231c103 82 OPC_JALX = (0x1D << 26),
d4ea6acd 83 OPC_DAUI = (0x1D << 26),
e37e863f 84 /* Load and stores */
7a387fff
TS
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
364d4831 91 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
364d4831 106 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
e37e863f 110 /* Floating point load/store */
7a387fff
TS
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
31837be3
YK
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
7a387fff
TS
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
239dfebe
YK
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
e37e863f 148 /* Cache and prefetch */
7a387fff
TS
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
153};
154
155/* PC-relative address computation / loads */
71375b59
AM
156#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
158enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
163
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
170};
171
172/* MIPS special opcodes */
71375b59 173#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 174
e37e863f
FB
175enum {
176 /* Shifts */
7a387fff 177 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 182 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 186 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 194 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 200 /* Multiplication / division */
7a387fff
TS
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 209
e37e863f 210 /* 2 registers arithmetic / logic */
7a387fff
TS
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 225 /* Jumps */
7a387fff
TS
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 228 /* Traps */
7a387fff
TS
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 235 /* HI / LO registers load & stores */
7a387fff
TS
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 240 /* Conditional moves */
7a387fff
TS
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 243
b691d9d2
LA
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246
7a387fff 247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
248
249 /* Special */
a0d700e4 250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
255
7a387fff
TS
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
260};
261
7480515f
AM
262/*
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
265 */
71375b59 266#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
267
268enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
277
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
286
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
292
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
295};
296
e9c71dd1 297/* Multiplication variants of the vr54xx. */
71375b59 298#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
299
300enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
315};
316
7a387fff 317/* REGIMM (rt field) opcodes */
71375b59 318#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
319
320enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
337
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
340};
341
7a387fff 342/* Special2 opcodes */
71375b59 343#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 344
e37e863f 345enum {
7a387fff
TS
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 365 /* Misc */
7a387fff
TS
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 370 /* Special */
7a387fff
TS
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
372};
373
374/* Special3 opcodes */
71375b59 375#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
376
377enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
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;
feafe82c 2550 bool mi;
8e9ade68
TS
2551} DisasContext;
2552
b28425ba
EC
2553#define DISAS_STOP DISAS_TARGET_0
2554#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2555
d73ee8a2
RH
2556static const char * const regnames[] = {
2557 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2558 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2559 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2560 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2561};
6af0bf9c 2562
d73ee8a2
RH
2563static const char * const regnames_HI[] = {
2564 "HI0", "HI1", "HI2", "HI3",
2565};
4b2eb8d2 2566
d73ee8a2
RH
2567static const char * const regnames_LO[] = {
2568 "LO0", "LO1", "LO2", "LO3",
2569};
4b2eb8d2 2570
d73ee8a2
RH
2571static const char * const fregnames[] = {
2572 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2573 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2574 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2575 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2576};
958fb4a9 2577
863f264d
YK
2578static const char * const msaregnames[] = {
2579 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2580 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2581 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2582 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2583 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2584 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2585 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2586 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2587 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2588 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2589 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2590 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2591 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2592 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2593 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2594 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2595};
2596
b621f018 2597#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2598static const char * const mxuregnames[] = {
2599 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2600 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2601};
b621f018 2602#endif
eb5559f6 2603
9d68ac14 2604#define LOG_DISAS(...) \
fb7729e2
RH
2605 do { \
2606 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2607 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2608 } \
2609 } while (0)
2610
9d68ac14 2611#define MIPS_INVAL(op) \
fb7729e2
RH
2612 do { \
2613 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2614 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2615 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2616 ctx->base.pc_next, ctx->opcode, op, \
2617 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2618 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2619 } \
2620 } while (0)
958fb4a9 2621
8e9ade68 2622/* General purpose registers moves. */
235785e8 2623static inline void gen_load_gpr(TCGv t, int reg)
aaa9128a 2624{
1f8929d2 2625 if (reg == 0) {
8e9ade68 2626 tcg_gen_movi_tl(t, 0);
1f8929d2 2627 } else {
4b2eb8d2 2628 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 2629 }
aaa9128a
TS
2630}
2631
235785e8 2632static inline void gen_store_gpr(TCGv t, int reg)
aaa9128a 2633{
1f8929d2 2634 if (reg != 0) {
4b2eb8d2 2635 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 2636 }
aaa9128a
TS
2637}
2638
8e9ade68 2639/* Moves to/from shadow registers. */
235785e8 2640static inline void gen_load_srsgpr(int from, int to)
aaa9128a 2641{
d9bea114 2642 TCGv t0 = tcg_temp_new();
be24bb4f 2643
1f8929d2 2644 if (from == 0) {
d9bea114 2645 tcg_gen_movi_tl(t0, 0);
1f8929d2 2646 } else {
d9bea114 2647 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2648 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2649
7db13fae 2650 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2651 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2652 tcg_gen_andi_i32(t2, t2, 0xf);
2653 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2654 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2655 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2656
d9bea114 2657 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2658 tcg_temp_free_ptr(addr);
d9bea114 2659 tcg_temp_free_i32(t2);
8e9ade68 2660 }
d9bea114
AJ
2661 gen_store_gpr(t0, to);
2662 tcg_temp_free(t0);
aaa9128a
TS
2663}
2664
71375b59 2665static inline void gen_store_srsgpr(int from, int to)
aaa9128a 2666{
be24bb4f 2667 if (to != 0) {
d9bea114
AJ
2668 TCGv t0 = tcg_temp_new();
2669 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2670 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2671
d9bea114 2672 gen_load_gpr(t0, from);
7db13fae 2673 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2674 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2675 tcg_gen_andi_i32(t2, t2, 0xf);
2676 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2677 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2678 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2679
d9bea114 2680 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2681 tcg_temp_free_ptr(addr);
d9bea114
AJ
2682 tcg_temp_free_i32(t2);
2683 tcg_temp_free(t0);
8e9ade68 2684 }
aaa9128a
TS
2685}
2686
b621f018 2687#if !defined(TARGET_MIPS64)
96992d1a
CJ
2688/* MXU General purpose registers moves. */
2689static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2690{
2691 if (reg == 0) {
2692 tcg_gen_movi_tl(t, 0);
2693 } else if (reg <= 15) {
2694 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2695 }
2696}
2697
2698static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2699{
2700 if (reg > 0 && reg <= 15) {
2701 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2702 }
2703}
2704
2705/* MXU control register moves. */
2706static inline void gen_load_mxu_cr(TCGv t)
2707{
2708 tcg_gen_mov_tl(t, mxu_CR);
2709}
2710
2711static inline void gen_store_mxu_cr(TCGv t)
2712{
2713 /* TODO: Add handling of RW rules for MXU_CR. */
2714 tcg_gen_mov_tl(mxu_CR, t);
2715}
b621f018 2716#endif
96992d1a
CJ
2717
2718
eab9944c
LA
2719/* Tests */
2720static inline void gen_save_pc(target_ulong pc)
2721{
2722 tcg_gen_movi_tl(cpu_PC, pc);
2723}
2724
2725static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2726{
2727 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2728 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2729 gen_save_pc(ctx->base.pc_next);
2730 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2731 }
2732 if (ctx->hflags != ctx->saved_hflags) {
2733 tcg_gen_movi_i32(hflags, ctx->hflags);
2734 ctx->saved_hflags = ctx->hflags;
2735 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2736 case MIPS_HFLAG_BR:
2737 break;
2738 case MIPS_HFLAG_BC:
2739 case MIPS_HFLAG_BL:
2740 case MIPS_HFLAG_B:
2741 tcg_gen_movi_tl(btarget, ctx->btarget);
2742 break;
2743 }
2744 }
2745}
2746
2747static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2748{
2749 ctx->saved_hflags = ctx->hflags;
2750 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2751 case MIPS_HFLAG_BR:
2752 break;
2753 case MIPS_HFLAG_BC:
2754 case MIPS_HFLAG_BL:
2755 case MIPS_HFLAG_B:
2756 ctx->btarget = env->btarget;
2757 break;
2758 }
2759}
2760
2761static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2762{
2763 TCGv_i32 texcp = tcg_const_i32(excp);
2764 TCGv_i32 terr = tcg_const_i32(err);
2765 save_cpu_state(ctx, 1);
2766 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2767 tcg_temp_free_i32(terr);
2768 tcg_temp_free_i32(texcp);
eeb3bba8 2769 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2770}
2771
2772static inline void generate_exception(DisasContext *ctx, int excp)
2773{
eab9944c
LA
2774 gen_helper_0e0i(raise_exception, excp);
2775}
2776
9c708c7f
PD
2777static inline void generate_exception_end(DisasContext *ctx, int excp)
2778{
2779 generate_exception_err(ctx, excp, 0);
2780}
2781
aaa9128a 2782/* Floating point register moves. */
7c979afd 2783static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2784{
7c979afd
LA
2785 if (ctx->hflags & MIPS_HFLAG_FRE) {
2786 generate_exception(ctx, EXCP_RI);
2787 }
ecc7b3aa 2788 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2789}
2790
7c979afd 2791static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2792{
7c979afd
LA
2793 TCGv_i64 t64;
2794 if (ctx->hflags & MIPS_HFLAG_FRE) {
2795 generate_exception(ctx, EXCP_RI);
2796 }
2797 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2798 tcg_gen_extu_i32_i64(t64, t);
2799 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2800 tcg_temp_free_i64(t64);
6d066274
AJ
2801}
2802
7f6613ce 2803static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2804{
7f6613ce 2805 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2806 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2807 } else {
7c979afd 2808 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2809 }
6d066274
AJ
2810}
2811
7f6613ce 2812static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2813{
7f6613ce
PJ
2814 if (ctx->hflags & MIPS_HFLAG_F64) {
2815 TCGv_i64 t64 = tcg_temp_new_i64();
2816 tcg_gen_extu_i32_i64(t64, t);
2817 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2818 tcg_temp_free_i64(t64);
2819 } else {
7c979afd 2820 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2821 }
aa0bf00b 2822}
6ea83fed 2823
d73ee8a2 2824static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2825{
f364515c 2826 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2827 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2828 } else {
d73ee8a2 2829 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2830 }
2831}
6ea83fed 2832
d73ee8a2 2833static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2834{
f364515c 2835 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2836 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2837 } else {
d73ee8a2
RH
2838 TCGv_i64 t0;
2839 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2840 t0 = tcg_temp_new_i64();
6d066274 2841 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2842 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2843 tcg_temp_free_i64(t0);
aa0bf00b
TS
2844 }
2845}
6ea83fed 2846
235785e8 2847static inline int get_fp_bit(int cc)
a16336e4 2848{
1f8929d2 2849 if (cc) {
d94536f4 2850 return 24 + cc;
1f8929d2 2851 } else {
d94536f4 2852 return 23;
1f8929d2 2853 }
a16336e4
TS
2854}
2855
48d38ca5 2856/* Addresses computation */
235785e8
AM
2857static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2858 TCGv arg1)
4ad40f36 2859{
941694d0 2860 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2861
2862#if defined(TARGET_MIPS64)
01f72885 2863 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2864 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2865 }
2866#endif
4ad40f36
FB
2867}
2868
bf0718c5
SM
2869static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2870 target_long ofs)
2871{
2872 tcg_gen_addi_tl(ret, base, ofs);
2873
2874#if defined(TARGET_MIPS64)
2875 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2876 tcg_gen_ext32s_i64(ret, ret);
2877 }
2878#endif
2879}
2880
31837be3
YK
2881/* Addresses computation (translation time) */
2882static target_long addr_add(DisasContext *ctx, target_long base,
2883 target_long offset)
2884{
2885 target_long sum = base + offset;
2886
2887#if defined(TARGET_MIPS64)
2888 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2889 sum = (int32_t)sum;
2890 }
2891#endif
2892 return sum;
2893}
2894
71f303cd 2895/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2896static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2897{
2898#if defined(TARGET_MIPS64)
71f303cd
RH
2899 tcg_gen_ext32s_i64(ret, arg);
2900#else
2901 tcg_gen_extrl_i64_i32(ret, arg);
2902#endif
2903}
2904
2905/* Sign-extract the high 32-bits to a target_long. */
2906static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2907{
2908#if defined(TARGET_MIPS64)
2909 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2910#else
71f303cd 2911 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2912#endif
2913}
2914
356265ae 2915static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2916{
1f8929d2 2917 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
c2c65dab 2918 generate_exception_err(ctx, EXCP_CpU, 0);
1f8929d2 2919 }
387a8fe5
TS
2920}
2921
356265ae 2922static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2923{
1f8929d2 2924 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 2925 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 2926 }
5e755519
TS
2927}
2928
7480515f
AM
2929/*
2930 * Verify that the processor is running with COP1X instructions enabled.
2931 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2932 * opcode tables.
2933 */
356265ae 2934static inline void check_cop1x(DisasContext *ctx)
b8aa4598 2935{
1f8929d2 2936 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
9c708c7f 2937 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2938 }
b8aa4598
TS
2939}
2940
7480515f
AM
2941/*
2942 * Verify that the processor is running with 64-bit floating-point
2943 * operations enabled.
2944 */
356265ae 2945static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2946{
1f8929d2 2947 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
9c708c7f 2948 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2949 }
5e755519
TS
2950}
2951
2952/*
2953 * Verify if floating point register is valid; an operation is not defined
2954 * if bit 0 of any register specification is set and the FR bit in the
2955 * Status register equals zero, since the register numbers specify an
2956 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2957 * in the Status register equals one, both even and odd register numbers
2958 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2959 *
2960 * Multiple 64 bit wide registers can be checked by calling
2961 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2962 */
356265ae 2963static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2964{
1f8929d2 2965 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
9c708c7f 2966 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2967 }
5e755519
TS
2968}
2969
7480515f
AM
2970/*
2971 * Verify that the processor is running with DSP instructions enabled.
2972 * This is enabled by CP0 Status register MX(24) bit.
853c3240 2973 */
853c3240
JL
2974static inline void check_dsp(DisasContext *ctx)
2975{
2976 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2977 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2978 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2979 } else {
9c708c7f 2980 generate_exception_end(ctx, EXCP_RI);
ad153f15 2981 }
853c3240
JL
2982 }
2983}
2984
908f6be1 2985static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2986{
908f6be1 2987 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2988 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2989 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2990 } else {
9c708c7f 2991 generate_exception_end(ctx, EXCP_RI);
ad153f15 2992 }
853c3240
JL
2993 }
2994}
2995
908f6be1 2996static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2997{
908f6be1 2998 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
2999 if (ctx->insn_flags & ASE_DSP) {
3000 generate_exception_end(ctx, EXCP_DSPDIS);
3001 } else {
3002 generate_exception_end(ctx, EXCP_RI);
3003 }
3004 }
3005}
3006
7480515f
AM
3007/*
3008 * This code generates a "reserved instruction" exception if the
3009 * CPU does not support the instruction set corresponding to flags.
3010 */
f9c9cd63 3011static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 3012{
d75c135e 3013 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 3014 generate_exception_end(ctx, EXCP_RI);
d75c135e 3015 }
3a95e3a7
TS
3016}
3017
7480515f
AM
3018/*
3019 * This code generates a "reserved instruction" exception if the
3020 * CPU has corresponding flag set which indicates that the instruction
3021 * has been removed.
3022 */
f9c9cd63 3023static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3024{
3025 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3026 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3027 }
3028}
3029
96631327
FN
3030/*
3031 * The Linux kernel traps certain reserved instruction exceptions to
3032 * emulate the corresponding instructions. QEMU is the kernel in user
3033 * mode, so those traps are emulated by accepting the instructions.
3034 *
3035 * A reserved instruction exception is generated for flagged CPUs if
3036 * QEMU runs in system mode.
3037 */
3038static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3039{
3040#ifndef CONFIG_USER_ONLY
3041 check_insn_opc_removed(ctx, flags);
3042#endif
3043}
3044
7480515f
AM
3045/*
3046 * This code generates a "reserved instruction" exception if the
3047 * CPU does not support 64-bit paired-single (PS) floating point data type.
3048 */
e29c9628
YK
3049static inline void check_ps(DisasContext *ctx)
3050{
3051 if (unlikely(!ctx->ps)) {
3052 generate_exception(ctx, EXCP_RI);
3053 }
3054 check_cp1_64bitmode(ctx);
3055}
3056
c7986fd6 3057#ifdef TARGET_MIPS64
7480515f
AM
3058/*
3059 * This code generates a "reserved instruction" exception if 64-bit
3060 * instructions are not enabled.
3061 */
356265ae 3062static inline void check_mips_64(DisasContext *ctx)
e189e748 3063{
1f8929d2 3064 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
9c708c7f 3065 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3066 }
e189e748 3067}
c7986fd6 3068#endif
e189e748 3069
5204ea79
LA
3070#ifndef CONFIG_USER_ONLY
3071static inline void check_mvh(DisasContext *ctx)
3072{
3073 if (unlikely(!ctx->mvh)) {
3074 generate_exception(ctx, EXCP_RI);
3075 }
3076}
3077#endif
3078
0b16dcd1
AR
3079/*
3080 * This code generates a "reserved instruction" exception if the
3081 * Config5 XNP bit is set.
3082 */
3083static inline void check_xnp(DisasContext *ctx)
3084{
3085 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3086 generate_exception_end(ctx, EXCP_RI);
3087 }
3088}
3089
5e31fdd5
YK
3090#ifndef CONFIG_USER_ONLY
3091/*
3092 * This code generates a "reserved instruction" exception if the
3093 * Config3 PW bit is NOT set.
3094 */
3095static inline void check_pw(DisasContext *ctx)
3096{
3097 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3098 generate_exception_end(ctx, EXCP_RI);
3099 }
3100}
3101#endif
3102
9affc1c5
AR
3103/*
3104 * This code generates a "reserved instruction" exception if the
3105 * Config3 MT bit is NOT set.
3106 */
3107static inline void check_mt(DisasContext *ctx)
3108{
3109 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3110 generate_exception_end(ctx, EXCP_RI);
3111 }
3112}
3113
3114#ifndef CONFIG_USER_ONLY
3115/*
3116 * This code generates a "coprocessor unusable" exception if CP0 is not
3117 * available, and, if that is not the case, generates a "reserved instruction"
3118 * exception if the Config5 MT bit is NOT set. This is needed for availability
3119 * control of some of MT ASE instructions.
3120 */
3121static inline void check_cp0_mt(DisasContext *ctx)
3122{
3123 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3124 generate_exception_err(ctx, EXCP_CpU, 0);
3125 } else {
3126 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3127 generate_exception_err(ctx, EXCP_RI, 0);
3128 }
3129 }
3130}
3131#endif
3132
fb32f8c8
DN
3133/*
3134 * This code generates a "reserved instruction" exception if the
3135 * Config5 NMS bit is set.
3136 */
3137static inline void check_nms(DisasContext *ctx)
3138{
3139 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3140 generate_exception_end(ctx, EXCP_RI);
3141 }
3142}
3143
d046a9ea
DN
3144/*
3145 * This code generates a "reserved instruction" exception if the
3146 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3147 * Config2 TL, and Config5 L2C are unset.
3148 */
3149static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3150{
1f8929d2
AM
3151 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3152 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3153 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3154 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3155 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3156 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
d046a9ea
DN
3157 generate_exception_end(ctx, EXCP_RI);
3158 }
3159}
3160
3161/*
3162 * This code generates a "reserved instruction" exception if the
3163 * Config5 EVA bit is NOT set.
3164 */
3165static inline void check_eva(DisasContext *ctx)
3166{
3167 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3168 generate_exception_end(ctx, EXCP_RI);
3169 }
3170}
3171
0b16dcd1 3172
7480515f
AM
3173/*
3174 * Define small wrappers for gen_load_fpr* so that we have a uniform
3175 * calling interface for 32 and 64-bit FPRs. No sense in changing
3176 * all callers for gen_load_fpr32 when we need the CTX parameter for
3177 * this one use.
3178 */
7c979afd 3179#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3180#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3181#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3182static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3183 int ft, int fs, int cc) \
3184{ \
71375b59
AM
3185 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3186 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
3187 switch (ifmt) { \
3188 case FMT_PS: \
e29c9628 3189 check_ps(ctx); \
8153667c
NF
3190 break; \
3191 case FMT_D: \
3192 if (abs) { \
3193 check_cop1x(ctx); \
3194 } \
3195 check_cp1_registers(ctx, fs | ft); \
3196 break; \
3197 case FMT_S: \
3198 if (abs) { \
3199 check_cop1x(ctx); \
3200 } \
3201 break; \
3202 } \
71375b59
AM
3203 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3204 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 3205 switch (n) { \
1f8929d2
AM
3206 case 0: \
3207 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3208 break; \
3209 case 1: \
3210 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3211 break; \
3212 case 2: \
3213 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3214 break; \
3215 case 3: \
3216 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3217 break; \
3218 case 4: \
3219 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3220 break; \
3221 case 5: \
3222 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3223 break; \
3224 case 6: \
3225 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3226 break; \
3227 case 7: \
3228 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3229 break; \
3230 case 8: \
3231 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3232 break; \
3233 case 9: \
3234 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3235 break; \
3236 case 10: \
3237 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3238 break; \
3239 case 11: \
3240 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3241 break; \
3242 case 12: \
3243 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3244 break; \
3245 case 13: \
3246 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3247 break; \
3248 case 14: \
3249 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3250 break; \
3251 case 15: \
3252 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3253 break; \
3254 default: \
3255 abort(); \
8153667c 3256 } \
71375b59
AM
3257 tcg_temp_free_i##bits(fp0); \
3258 tcg_temp_free_i##bits(fp1); \
8153667c
NF
3259}
3260
3261FOP_CONDS(, 0, d, FMT_D, 64)
3262FOP_CONDS(abs, 1, d, FMT_D, 64)
3263FOP_CONDS(, 0, s, FMT_S, 32)
3264FOP_CONDS(abs, 1, s, FMT_S, 32)
3265FOP_CONDS(, 0, ps, FMT_PS, 64)
3266FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3267#undef FOP_CONDS
3f493883
YK
3268
3269#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 3270static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
3271 int ft, int fs, int fd) \
3272{ \
3273 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3274 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3275 if (ifmt == FMT_D) { \
3f493883 3276 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3277 } \
3278 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3279 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3280 switch (n) { \
3281 case 0: \
3282 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3283 break; \
3284 case 1: \
3285 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3286 break; \
3287 case 2: \
3288 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3289 break; \
3290 case 3: \
3291 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3292 break; \
3293 case 4: \
3294 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3295 break; \
3296 case 5: \
3297 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3298 break; \
3299 case 6: \
3300 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3301 break; \
3302 case 7: \
3303 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3304 break; \
3305 case 8: \
3306 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3307 break; \
3308 case 9: \
3309 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3310 break; \
3311 case 10: \
3312 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3313 break; \
3314 case 11: \
3315 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3316 break; \
3317 case 12: \
3318 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3319 break; \
3320 case 13: \
3321 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3322 break; \
3323 case 14: \
3324 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3325 break; \
3326 case 15: \
3327 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3328 break; \
3329 case 17: \
3330 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3331 break; \
3332 case 18: \
3333 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3334 break; \
3335 case 19: \
3336 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3337 break; \
3338 case 25: \
3339 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3340 break; \
3341 case 26: \
3342 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3343 break; \
3344 case 27: \
3345 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3346 break; \
3347 default: \
3348 abort(); \
3349 } \
3350 STORE; \
71375b59
AM
3351 tcg_temp_free_i ## bits(fp0); \
3352 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
3353}
3354
3355FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3356FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3357#undef FOP_CONDNS
8153667c
NF
3358#undef gen_ldcmp_fpr32
3359#undef gen_ldcmp_fpr64
3360
958fb4a9 3361/* load/store instructions. */
e7139c44 3362#ifdef CONFIG_USER_ONLY
71375b59 3363#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3364static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3365 DisasContext *ctx) \
d9bea114
AJ
3366{ \
3367 TCGv t0 = tcg_temp_new(); \
3368 tcg_gen_mov_tl(t0, arg1); \
3369 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
3370 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3371 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3372 tcg_temp_free(t0); \
aaa9128a 3373}
e7139c44 3374#else
71375b59 3375#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3376static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3377 DisasContext *ctx) \
e7139c44 3378{ \
dd4096cd 3379 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3380}
3381#endif
71375b59 3382OP_LD_ATOMIC(ll, ld32s);
aaa9128a 3383#if defined(TARGET_MIPS64)
71375b59 3384OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
3385#endif
3386#undef OP_LD_ATOMIC
3387
235785e8
AM
3388static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3389 int base, int offset)
662d7485
NF
3390{
3391 if (base == 0) {
3392 tcg_gen_movi_tl(addr, offset);
3393 } else if (offset == 0) {
3394 gen_load_gpr(addr, base);
3395 } else {
3396 tcg_gen_movi_tl(addr, offset);
3397 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3398 }
3399}
3400
235785e8 3401static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 3402{
eeb3bba8 3403 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3404
3405 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3406 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3407
3408 pc -= branch_bytes;
3409 }
3410
3411 pc &= ~(target_ulong)3;
3412 return pc;
3413}
3414
5c13fdfd 3415/* Load */
d75c135e 3416static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3417 int rt, int base, int offset)
6af0bf9c 3418{
fc40787a 3419 TCGv t0, t1, t2;
dd4096cd 3420 int mem_idx = ctx->mem_idx;
afa88c3a 3421
d75c135e 3422 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
7480515f
AM
3423 /*
3424 * Loongson CPU uses a load to zero register for prefetch.
3425 * We emulate it as a NOP. On other CPU we must perform the
3426 * actual memory access.
3427 */
afa88c3a
AJ
3428 return;
3429 }
6af0bf9c 3430
afa88c3a 3431 t0 = tcg_temp_new();
662d7485 3432 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3433
6af0bf9c 3434 switch (opc) {
d26bc211 3435#if defined(TARGET_MIPS64)
6e473128 3436 case OPC_LWU:
dd4096cd 3437 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3438 ctx->default_tcg_memop_mask);
78723684 3439 gen_store_gpr(t0, rt);
6e473128 3440 break;
6af0bf9c 3441 case OPC_LD:
dd4096cd 3442 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3443 ctx->default_tcg_memop_mask);
78723684 3444 gen_store_gpr(t0, rt);
6af0bf9c 3445 break;
7a387fff 3446 case OPC_LLD:
bf7910c6 3447 case R6_OPC_LLD:
dd4096cd 3448 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3449 gen_store_gpr(t0, rt);
7a387fff 3450 break;
6af0bf9c 3451 case OPC_LDL:
3cee3050 3452 t1 = tcg_temp_new();
7480515f
AM
3453 /*
3454 * Do a byte access to possibly trigger a page
3455 * fault with the unaligned address.
3456 */
dd4096cd 3457 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3458 tcg_gen_andi_tl(t1, t0, 7);
3459#ifndef TARGET_WORDS_BIGENDIAN
3460 tcg_gen_xori_tl(t1, t1, 7);
3461#endif
3462 tcg_gen_shli_tl(t1, t1, 3);
3463 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3464 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3465 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3466 t2 = tcg_const_tl(-1);
3467 tcg_gen_shl_tl(t2, t2, t1);
78723684 3468 gen_load_gpr(t1, rt);
eb02cc3f 3469 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3470 tcg_temp_free(t2);
3471 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3472 tcg_temp_free(t1);
fc40787a 3473 gen_store_gpr(t0, rt);
6af0bf9c 3474 break;
6af0bf9c 3475 case OPC_LDR:
3cee3050 3476 t1 = tcg_temp_new();
7480515f
AM
3477 /*
3478 * Do a byte access to possibly trigger a page
3479 * fault with the unaligned address.
3480 */
dd4096cd 3481 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3482 tcg_gen_andi_tl(t1, t0, 7);
3483#ifdef TARGET_WORDS_BIGENDIAN
3484 tcg_gen_xori_tl(t1, t1, 7);
3485#endif
3486 tcg_gen_shli_tl(t1, t1, 3);
3487 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3488 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3489 tcg_gen_shr_tl(t0, t0, t1);
3490 tcg_gen_xori_tl(t1, t1, 63);
3491 t2 = tcg_const_tl(0xfffffffffffffffeull);
3492 tcg_gen_shl_tl(t2, t2, t1);
78723684 3493 gen_load_gpr(t1, rt);
fc40787a
AJ
3494 tcg_gen_and_tl(t1, t1, t2);
3495 tcg_temp_free(t2);
3496 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3497 tcg_temp_free(t1);
fc40787a 3498 gen_store_gpr(t0, rt);
6af0bf9c 3499 break;
364d4831 3500 case OPC_LDPC:
3cee3050 3501 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3502 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3503 tcg_temp_free(t1);
dd4096cd 3504 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3505 gen_store_gpr(t0, rt);
3506 break;
6af0bf9c 3507#endif
364d4831 3508 case OPC_LWPC:
3cee3050 3509 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3510 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3511 tcg_temp_free(t1);
dd4096cd 3512 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3513 gen_store_gpr(t0, rt);
3514 break;
76964147
JH
3515 case OPC_LWE:
3516 mem_idx = MIPS_HFLAG_UM;
3517 /* fall through */
6af0bf9c 3518 case OPC_LW:
dd4096cd 3519 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3520 ctx->default_tcg_memop_mask);
78723684 3521 gen_store_gpr(t0, rt);
6af0bf9c 3522 break;
76964147
JH
3523 case OPC_LHE:
3524 mem_idx = MIPS_HFLAG_UM;
3525 /* fall through */
6af0bf9c 3526 case OPC_LH:
dd4096cd 3527 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3528 ctx->default_tcg_memop_mask);
78723684 3529 gen_store_gpr(t0, rt);
6af0bf9c 3530 break;
76964147
JH
3531 case OPC_LHUE:
3532 mem_idx = MIPS_HFLAG_UM;
3533 /* fall through */
6af0bf9c 3534 case OPC_LHU:
dd4096cd 3535 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3536 ctx->default_tcg_memop_mask);
78723684 3537 gen_store_gpr(t0, rt);
6af0bf9c 3538 break;
76964147
JH
3539 case OPC_LBE:
3540 mem_idx = MIPS_HFLAG_UM;
3541 /* fall through */
6af0bf9c 3542 case OPC_LB:
dd4096cd 3543 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3544 gen_store_gpr(t0, rt);
6af0bf9c 3545 break;
76964147
JH
3546 case OPC_LBUE:
3547 mem_idx = MIPS_HFLAG_UM;
3548 /* fall through */
6af0bf9c 3549 case OPC_LBU:
dd4096cd 3550 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3551 gen_store_gpr(t0, rt);
6af0bf9c 3552 break;
76964147
JH
3553 case OPC_LWLE:
3554 mem_idx = MIPS_HFLAG_UM;
3555 /* fall through */
6af0bf9c 3556 case OPC_LWL:
3cee3050 3557 t1 = tcg_temp_new();
7480515f
AM
3558 /*
3559 * Do a byte access to possibly trigger a page
3560 * fault with the unaligned address.
3561 */
dd4096cd 3562 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3563 tcg_gen_andi_tl(t1, t0, 3);
3564#ifndef TARGET_WORDS_BIGENDIAN
3565 tcg_gen_xori_tl(t1, t1, 3);
3566#endif
3567 tcg_gen_shli_tl(t1, t1, 3);
3568 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3569 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3570 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3571 t2 = tcg_const_tl(-1);
3572 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3573 gen_load_gpr(t1, rt);
eb02cc3f 3574 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3575 tcg_temp_free(t2);
3576 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3577 tcg_temp_free(t1);
fc40787a
AJ
3578 tcg_gen_ext32s_tl(t0, t0);
3579 gen_store_gpr(t0, rt);
6af0bf9c 3580 break;
76964147
JH
3581 case OPC_LWRE:
3582 mem_idx = MIPS_HFLAG_UM;
3583 /* fall through */
6af0bf9c 3584 case OPC_LWR:
3cee3050 3585 t1 = tcg_temp_new();
7480515f
AM
3586 /*
3587 * Do a byte access to possibly trigger a page
3588 * fault with the unaligned address.
3589 */
dd4096cd 3590 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3591 tcg_gen_andi_tl(t1, t0, 3);
3592#ifdef TARGET_WORDS_BIGENDIAN
3593 tcg_gen_xori_tl(t1, t1, 3);
3594#endif
3595 tcg_gen_shli_tl(t1, t1, 3);
3596 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3597 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3598 tcg_gen_shr_tl(t0, t0, t1);
3599 tcg_gen_xori_tl(t1, t1, 31);
3600 t2 = tcg_const_tl(0xfffffffeull);
3601 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3602 gen_load_gpr(t1, rt);
fc40787a
AJ
3603 tcg_gen_and_tl(t1, t1, t2);
3604 tcg_temp_free(t2);
3605 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3606 tcg_temp_free(t1);
c728154b 3607 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3608 gen_store_gpr(t0, rt);
6af0bf9c 3609 break;
76964147
JH
3610 case OPC_LLE:
3611 mem_idx = MIPS_HFLAG_UM;
3612 /* fall through */
6af0bf9c 3613 case OPC_LL:
4368b29a 3614 case R6_OPC_LL:
dd4096cd 3615 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3616 gen_store_gpr(t0, rt);
6af0bf9c 3617 break;
d66c7132 3618 }
d66c7132 3619 tcg_temp_free(t0);
d66c7132
AJ
3620}
3621
0b16dcd1
AR
3622static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3623 uint32_t reg1, uint32_t reg2)
3624{
3625 TCGv taddr = tcg_temp_new();
3626 TCGv_i64 tval = tcg_temp_new_i64();
3627 TCGv tmp1 = tcg_temp_new();
3628 TCGv tmp2 = tcg_temp_new();
3629
3630 gen_base_offset_addr(ctx, taddr, base, offset);
3631 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3632#ifdef TARGET_WORDS_BIGENDIAN
3633 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3634#else
3635 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3636#endif
3637 gen_store_gpr(tmp1, reg1);
3638 tcg_temp_free(tmp1);
3639 gen_store_gpr(tmp2, reg2);
3640 tcg_temp_free(tmp2);
3641 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3642 tcg_temp_free_i64(tval);
3643 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3644 tcg_temp_free(taddr);
3645}
3646
5c13fdfd 3647/* Store */
235785e8
AM
3648static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3649 int base, int offset)
5c13fdfd 3650{
5c13fdfd
AJ
3651 TCGv t0 = tcg_temp_new();
3652 TCGv t1 = tcg_temp_new();
dd4096cd 3653 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3654
3655 gen_base_offset_addr(ctx, t0, base, offset);
3656 gen_load_gpr(t1, rt);
3657 switch (opc) {
3658#if defined(TARGET_MIPS64)
3659 case OPC_SD:
dd4096cd 3660 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3661 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3662 break;
3663 case OPC_SDL:
dd4096cd 3664 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3665 break;
3666 case OPC_SDR:
dd4096cd 3667 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3668 break;
3669#endif
76964147
JH
3670 case OPC_SWE:
3671 mem_idx = MIPS_HFLAG_UM;
3672 /* fall through */
5c13fdfd 3673 case OPC_SW:
dd4096cd 3674 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3675 ctx->default_tcg_memop_mask);
5c13fdfd 3676 break;
76964147
JH
3677 case OPC_SHE:
3678 mem_idx = MIPS_HFLAG_UM;
3679 /* fall through */
5c13fdfd 3680 case OPC_SH:
dd4096cd 3681 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3682 ctx->default_tcg_memop_mask);
5c13fdfd 3683 break;
76964147
JH
3684 case OPC_SBE:
3685 mem_idx = MIPS_HFLAG_UM;
3686 /* fall through */
5c13fdfd 3687 case OPC_SB:
dd4096cd 3688 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3689 break;
76964147
JH
3690 case OPC_SWLE:
3691 mem_idx = MIPS_HFLAG_UM;
3692 /* fall through */
5c13fdfd 3693 case OPC_SWL:
dd4096cd 3694 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3695 break;
76964147
JH
3696 case OPC_SWRE:
3697 mem_idx = MIPS_HFLAG_UM;
3698 /* fall through */
5c13fdfd 3699 case OPC_SWR:
dd4096cd 3700 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3701 break;
3702 }
5c13fdfd
AJ
3703 tcg_temp_free(t0);
3704 tcg_temp_free(t1);
3705}
3706
3707
d66c7132 3708/* Store conditional */
33a07fa2 3709static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 3710 MemOp tcg_mo, bool eva)
d66c7132 3711{
33a07fa2
LA
3712 TCGv addr, t0, val;
3713 TCGLabel *l1 = gen_new_label();
3714 TCGLabel *done = gen_new_label();
d66c7132 3715
2d2826b9 3716 t0 = tcg_temp_new();
33a07fa2
LA
3717 addr = tcg_temp_new();
3718 /* compare the address against that of the preceeding LL */
3719 gen_base_offset_addr(ctx, addr, base, offset);
3720 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3721 tcg_temp_free(addr);
3722 tcg_gen_movi_tl(t0, 0);
3723 gen_store_gpr(t0, rt);
3724 tcg_gen_br(done);
3725
3726 gen_set_label(l1);
3727 /* generate cmpxchg */
3728 val = tcg_temp_new();
3729 gen_load_gpr(val, rt);
3730 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3731 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3732 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3733 gen_store_gpr(t0, rt);
3734 tcg_temp_free(val);
3735
3736 gen_set_label(done);
d66c7132 3737 tcg_temp_free(t0);
6af0bf9c
FB
3738}
3739
33a07fa2 3740
0b16dcd1 3741static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 3742 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
3743{
3744 TCGv taddr = tcg_temp_local_new();
3745 TCGv lladdr = tcg_temp_local_new();
3746 TCGv_i64 tval = tcg_temp_new_i64();
3747 TCGv_i64 llval = tcg_temp_new_i64();
3748 TCGv_i64 val = tcg_temp_new_i64();
3749 TCGv tmp1 = tcg_temp_new();
3750 TCGv tmp2 = tcg_temp_new();
3751 TCGLabel *lab_fail = gen_new_label();
3752 TCGLabel *lab_done = gen_new_label();
3753
3754 gen_base_offset_addr(ctx, taddr, base, offset);
3755
3756 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3757 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3758
3759 gen_load_gpr(tmp1, reg1);
3760 gen_load_gpr(tmp2, reg2);
3761
3762#ifdef TARGET_WORDS_BIGENDIAN
3763 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3764#else
3765 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3766#endif
3767
3768 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3769 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 3770 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
3771 if (reg1 != 0) {
3772 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3773 }
3774 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3775
3776 gen_set_label(lab_fail);
3777
3778 if (reg1 != 0) {
3779 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3780 }
3781 gen_set_label(lab_done);
3782 tcg_gen_movi_tl(lladdr, -1);
3783 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3784}
3785
6ea83fed 3786/* Load and store */
235785e8
AM
3787static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3788 TCGv t0)
6ea83fed 3789{
7480515f
AM
3790 /*
3791 * Don't do NOP if destination is zero: we must perform the actual
3792 * memory access.
3793 */
6ea83fed
FB
3794 switch (opc) {
3795 case OPC_LWC1:
b6d96bed 3796 {
a7812ae4 3797 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3798 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3799 ctx->default_tcg_memop_mask);
7c979afd 3800 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3801 tcg_temp_free_i32(fp0);
b6d96bed 3802 }
6ea83fed
FB
3803 break;
3804 case OPC_SWC1:
b6d96bed 3805 {
a7812ae4 3806 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3807 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3808 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3809 ctx->default_tcg_memop_mask);
a7812ae4 3810 tcg_temp_free_i32(fp0);
b6d96bed 3811 }
6ea83fed
FB
3812 break;
3813 case OPC_LDC1:
b6d96bed 3814 {
a7812ae4 3815 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3816 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3817 ctx->default_tcg_memop_mask);
b6d96bed 3818 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3819 tcg_temp_free_i64(fp0);
b6d96bed 3820 }
6ea83fed
FB
3821 break;
3822 case OPC_SDC1:
b6d96bed 3823 {
a7812ae4 3824 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3825 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3826 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3827 ctx->default_tcg_memop_mask);
a7812ae4 3828 tcg_temp_free_i64(fp0);
b6d96bed 3829 }
6ea83fed
FB
3830 break;
3831 default:
9d68ac14 3832 MIPS_INVAL("flt_ldst");
9c708c7f 3833 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3834 break;
6ea83fed 3835 }
6ea83fed 3836}
6ea83fed 3837
5ab5c041
AJ
3838static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3839 int rs, int16_t imm)
26ebe468 3840{
b52d3bfa
YK
3841 TCGv t0 = tcg_temp_new();
3842
5ab5c041 3843 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3844 check_cp1_enabled(ctx);
d9224450
MR
3845 switch (op) {
3846 case OPC_LDC1:
3847 case OPC_SDC1:
3848 check_insn(ctx, ISA_MIPS2);
3849 /* Fallthrough */
3850 default:
b52d3bfa
YK
3851 gen_base_offset_addr(ctx, t0, rs, imm);
3852 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3853 }
26ebe468
NF
3854 } else {
3855 generate_exception_err(ctx, EXCP_CpU, 1);
3856 }
b52d3bfa 3857 tcg_temp_free(t0);
26ebe468
NF
3858}
3859
6af0bf9c 3860/* Arithmetic with immediate operand */
d75c135e 3861static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3862 int rt, int rs, int imm)
6af0bf9c 3863{
324d9e32 3864 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3865
7a387fff 3866 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
3867 /*
3868 * If no destination, treat it as a NOP.
3869 * For addi, we must generate the overflow exception when needed.
3870 */
324d9e32 3871 return;
6af0bf9c
FB
3872 }
3873 switch (opc) {
3874 case OPC_ADDI:
48d38ca5 3875 {
324d9e32
AJ
3876 TCGv t0 = tcg_temp_local_new();
3877 TCGv t1 = tcg_temp_new();
3878 TCGv t2 = tcg_temp_new();
42a268c2 3879 TCGLabel *l1 = gen_new_label();
48d38ca5 3880
324d9e32
AJ
3881 gen_load_gpr(t1, rs);
3882 tcg_gen_addi_tl(t0, t1, uimm);
3883 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3884
324d9e32
AJ
3885 tcg_gen_xori_tl(t1, t1, ~uimm);
3886 tcg_gen_xori_tl(t2, t0, uimm);
3887 tcg_gen_and_tl(t1, t1, t2);
3888 tcg_temp_free(t2);
3889 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3890 tcg_temp_free(t1);
48d38ca5
TS
3891 /* operands of same sign, result different sign */
3892 generate_exception(ctx, EXCP_OVERFLOW);
3893 gen_set_label(l1);
78723684 3894 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3895 gen_store_gpr(t0, rt);
3896 tcg_temp_free(t0);
48d38ca5 3897 }
6af0bf9c
FB
3898 break;
3899 case OPC_ADDIU:
324d9e32
AJ
3900 if (rs != 0) {
3901 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3902 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3903 } else {
3904 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3905 }
6af0bf9c 3906 break;
d26bc211 3907#if defined(TARGET_MIPS64)
7a387fff 3908 case OPC_DADDI:
48d38ca5 3909 {
324d9e32
AJ
3910 TCGv t0 = tcg_temp_local_new();
3911 TCGv t1 = tcg_temp_new();
3912 TCGv t2 = tcg_temp_new();
42a268c2 3913 TCGLabel *l1 = gen_new_label();
48d38ca5 3914
324d9e32
AJ
3915 gen_load_gpr(t1, rs);
3916 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3917
324d9e32
AJ
3918 tcg_gen_xori_tl(t1, t1, ~uimm);
3919 tcg_gen_xori_tl(t2, t0, uimm);
3920 tcg_gen_and_tl(t1, t1, t2);
3921 tcg_temp_free(t2);
3922 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3923 tcg_temp_free(t1);
48d38ca5
TS
3924 /* operands of same sign, result different sign */
3925 generate_exception(ctx, EXCP_OVERFLOW);
3926 gen_set_label(l1);
324d9e32
AJ
3927 gen_store_gpr(t0, rt);
3928 tcg_temp_free(t0);
48d38ca5 3929 }
7a387fff
TS
3930 break;
3931 case OPC_DADDIU:
324d9e32
AJ
3932 if (rs != 0) {
3933 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3934 } else {
3935 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3936 }
7a387fff
TS
3937 break;
3938#endif
324d9e32 3939 }
324d9e32
AJ
3940}
3941
3942/* Logic with immediate operand */
d75c135e 3943static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3944 int rt, int rs, int16_t imm)
324d9e32
AJ
3945{
3946 target_ulong uimm;
324d9e32
AJ
3947
3948 if (rt == 0) {
3949 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3950 return;
3951 }
3952 uimm = (uint16_t)imm;
3953 switch (opc) {
6af0bf9c 3954 case OPC_ANDI:
1f8929d2 3955 if (likely(rs != 0)) {
324d9e32 3956 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3957 } else {
324d9e32 3958 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 3959 }
6af0bf9c
FB
3960 break;
3961 case OPC_ORI:
1f8929d2 3962 if (rs != 0) {
324d9e32 3963 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3964 } else {
324d9e32 3965 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3966 }
6af0bf9c
FB
3967 break;
3968 case OPC_XORI:
1f8929d2 3969 if (likely(rs != 0)) {
324d9e32 3970 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3971 } else {
324d9e32 3972 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3973 }
6af0bf9c
FB
3974 break;
3975 case OPC_LUI:
d4ea6acd
LA
3976 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3977 /* OPC_AUI */
3978 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3979 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3980 } else {
3981 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3982 }
7c2c3ea3
EJ
3983 break;
3984
3985 default:
6af0bf9c 3986 break;
324d9e32 3987 }
324d9e32
AJ
3988}
3989
3990/* Set on less than with immediate operand */
d75c135e 3991static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3992 int rt, int rs, int16_t imm)
324d9e32
AJ
3993{
3994 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3995 TCGv t0;
3996
3997 if (rt == 0) {
3998 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3999 return;
4000 }
4001 t0 = tcg_temp_new();
4002 gen_load_gpr(t0, rs);
4003 switch (opc) {
4004 case OPC_SLTI:
e68dd28f 4005 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4006 break;
4007 case OPC_SLTIU:
e68dd28f 4008 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4009 break;
4010 }
324d9e32
AJ
4011 tcg_temp_free(t0);
4012}
4013
4014/* Shifts with immediate operand */
d75c135e 4015static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
4016 int rt, int rs, int16_t imm)
4017{
4018 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
4019 TCGv t0;
4020
4021 if (rt == 0) {
4022 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4023 return;
4024 }
4025
4026 t0 = tcg_temp_new();
4027 gen_load_gpr(t0, rs);
4028 switch (opc) {
6af0bf9c 4029 case OPC_SLL:
78723684 4030 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 4031 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4032 break;
4033 case OPC_SRA:
324d9e32 4034 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4035 break;
4036 case OPC_SRL:
ea63e2c3
NF
4037 if (uimm != 0) {
4038 tcg_gen_ext32u_tl(t0, t0);
4039 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4040 } else {
4041 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4042 }
ea63e2c3
NF
4043 break;
4044 case OPC_ROTR:
4045 if (uimm != 0) {
4046 TCGv_i32 t1 = tcg_temp_new_i32();
4047
4048 tcg_gen_trunc_tl_i32(t1, t0);
4049 tcg_gen_rotri_i32(t1, t1, uimm);
4050 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4051 tcg_temp_free_i32(t1);
3399e30f
NF
4052 } else {
4053 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4054 }
7a387fff 4055 break;
d26bc211 4056#if defined(TARGET_MIPS64)
7a387fff 4057 case OPC_DSLL:
324d9e32 4058 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4059 break;
4060 case OPC_DSRA:
324d9e32 4061 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4062 break;
4063 case OPC_DSRL:
ea63e2c3 4064 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4065 break;
4066 case OPC_DROTR:
4067 if (uimm != 0) {
4068 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4069 } else {
4070 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4071 }
7a387fff
TS
4072 break;
4073 case OPC_DSLL32:
324d9e32 4074 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4075 break;
4076 case OPC_DSRA32:
324d9e32 4077 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4078 break;
4079 case OPC_DSRL32:
ea63e2c3 4080 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4081 break;
4082 case OPC_DROTR32:
4083 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4084 break;
7a387fff 4085#endif
6af0bf9c 4086 }
78723684 4087 tcg_temp_free(t0);
6af0bf9c
FB
4088}
4089
4090/* Arithmetic */
d75c135e
AJ
4091static void gen_arith(DisasContext *ctx, uint32_t opc,
4092 int rd, int rs, int rt)
6af0bf9c 4093{
7a387fff
TS
4094 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4095 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
4096 /*
4097 * If no destination, treat it as a NOP.
4098 * For add & sub, we must generate the overflow exception when needed.
4099 */
460f00c4 4100 return;
185f0762 4101 }
460f00c4 4102
6af0bf9c
FB
4103 switch (opc) {
4104 case OPC_ADD:
48d38ca5 4105 {
460f00c4
AJ
4106 TCGv t0 = tcg_temp_local_new();
4107 TCGv t1 = tcg_temp_new();
4108 TCGv t2 = tcg_temp_new();
42a268c2 4109 TCGLabel *l1 = gen_new_label();
48d38ca5 4110
460f00c4
AJ
4111 gen_load_gpr(t1, rs);
4112 gen_load_gpr(t2, rt);
4113 tcg_gen_add_tl(t0, t1, t2);
4114 tcg_gen_ext32s_tl(t0, t0);
4115 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4116 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4117 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4118 tcg_temp_free(t2);
4119 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4120 tcg_temp_free(t1);
48d38ca5
TS
4121 /* operands of same sign, result different sign */
4122 generate_exception(ctx, EXCP_OVERFLOW);
4123 gen_set_label(l1);
460f00c4
AJ
4124 gen_store_gpr(t0, rd);
4125 tcg_temp_free(t0);
48d38ca5 4126 }
6af0bf9c
FB
4127 break;
4128 case OPC_ADDU:
460f00c4
AJ
4129 if (rs != 0 && rt != 0) {
4130 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4131 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4132 } else if (rs == 0 && rt != 0) {
4133 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4134 } else if (rs != 0 && rt == 0) {
4135 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4136 } else {
4137 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4138 }
6af0bf9c
FB
4139 break;
4140 case OPC_SUB:
48d38ca5 4141 {
460f00c4
AJ
4142 TCGv t0 = tcg_temp_local_new();
4143 TCGv t1 = tcg_temp_new();
4144 TCGv t2 = tcg_temp_new();
42a268c2 4145 TCGLabel *l1 = gen_new_label();
48d38ca5 4146
460f00c4
AJ
4147 gen_load_gpr(t1, rs);
4148 gen_load_gpr(t2, rt);
4149 tcg_gen_sub_tl(t0, t1, t2);
4150 tcg_gen_ext32s_tl(t0, t0);
4151 tcg_gen_xor_tl(t2, t1, t2);
4152 tcg_gen_xor_tl(t1, t0, t1);
4153 tcg_gen_and_tl(t1, t1, t2);
4154 tcg_temp_free(t2);
4155 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4156 tcg_temp_free(t1);
7480515f
AM
4157 /*
4158 * operands of different sign, first operand and the result
4159 * of different sign
4160 */
48d38ca5
TS
4161 generate_exception(ctx, EXCP_OVERFLOW);
4162 gen_set_label(l1);
460f00c4
AJ
4163 gen_store_gpr(t0, rd);
4164 tcg_temp_free(t0);
48d38ca5 4165 }
6af0bf9c
FB
4166 break;
4167 case OPC_SUBU:
460f00c4
AJ
4168 if (rs != 0 && rt != 0) {
4169 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4170 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4171 } else if (rs == 0 && rt != 0) {
4172 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4173 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4174 } else if (rs != 0 && rt == 0) {
4175 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4176 } else {
4177 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4178 }
6af0bf9c 4179 break;
d26bc211 4180#if defined(TARGET_MIPS64)
7a387fff 4181 case OPC_DADD:
48d38ca5 4182 {
460f00c4
AJ
4183 TCGv t0 = tcg_temp_local_new();
4184 TCGv t1 = tcg_temp_new();
4185 TCGv t2 = tcg_temp_new();
42a268c2 4186 TCGLabel *l1 = gen_new_label();
48d38ca5 4187
460f00c4
AJ
4188 gen_load_gpr(t1, rs);
4189 gen_load_gpr(t2, rt);
4190 tcg_gen_add_tl(t0, t1, t2);
4191 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4192 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4193 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4194 tcg_temp_free(t2);
4195 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4196 tcg_temp_free(t1);
48d38ca5
TS
4197 /* operands of same sign, result different sign */
4198 generate_exception(ctx, EXCP_OVERFLOW);
4199 gen_set_label(l1);
460f00c4
AJ
4200 gen_store_gpr(t0, rd);
4201 tcg_temp_free(t0);
48d38ca5 4202 }
7a387fff
TS
4203 break;
4204 case OPC_DADDU:
460f00c4
AJ
4205 if (rs != 0 && rt != 0) {
4206 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4207 } else if (rs == 0 && rt != 0) {
4208 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4209 } else if (rs != 0 && rt == 0) {
4210 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4211 } else {
4212 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4213 }
7a387fff
TS
4214 break;
4215 case OPC_DSUB:
48d38ca5 4216 {
460f00c4
AJ
4217 TCGv t0 = tcg_temp_local_new();
4218 TCGv t1 = tcg_temp_new();
4219 TCGv t2 = tcg_temp_new();
42a268c2 4220 TCGLabel *l1 = gen_new_label();
48d38ca5 4221
460f00c4
AJ
4222 gen_load_gpr(t1, rs);
4223 gen_load_gpr(t2, rt);
4224 tcg_gen_sub_tl(t0, t1, t2);
4225 tcg_gen_xor_tl(t2, t1, t2);
4226 tcg_gen_xor_tl(t1, t0, t1);
4227 tcg_gen_and_tl(t1, t1, t2);
4228 tcg_temp_free(t2);
4229 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4230 tcg_temp_free(t1);
71375b59
AM
4231 /*
4232 * Operands of different sign, first operand and result different
4233 * sign.
4234 */
48d38ca5
TS
4235 generate_exception(ctx, EXCP_OVERFLOW);
4236 gen_set_label(l1);
460f00c4
AJ
4237 gen_store_gpr(t0, rd);
4238 tcg_temp_free(t0);
48d38ca5 4239 }
7a387fff
TS
4240 break;
4241 case OPC_DSUBU:
460f00c4
AJ
4242 if (rs != 0 && rt != 0) {
4243 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4244 } else if (rs == 0 && rt != 0) {
4245 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4246 } else if (rs != 0 && rt == 0) {
4247 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4248 } else {
4249 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4250 }
7a387fff
TS
4251 break;
4252#endif
460f00c4
AJ
4253 case OPC_MUL:
4254 if (likely(rs != 0 && rt != 0)) {
4255 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4256 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4257 } else {
4258 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4259 }
6af0bf9c 4260 break;
460f00c4 4261 }
460f00c4
AJ
4262}
4263
4264/* Conditional move */
d75c135e 4265static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4266 int rd, int rs, int rt)
460f00c4 4267{
acf12465 4268 TCGv t0, t1, t2;
460f00c4
AJ
4269
4270 if (rd == 0) {
acf12465 4271 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4272 return;
4273 }
4274
acf12465
AJ
4275 t0 = tcg_temp_new();
4276 gen_load_gpr(t0, rt);
4277 t1 = tcg_const_tl(0);
4278 t2 = tcg_temp_new();
4279 gen_load_gpr(t2, rs);
460f00c4
AJ
4280 switch (opc) {
4281 case OPC_MOVN:
acf12465 4282 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4283 break;
460f00c4 4284 case OPC_MOVZ:
acf12465 4285 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4286 break;
b691d9d2
LA
4287 case OPC_SELNEZ:
4288 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4289 break;
4290 case OPC_SELEQZ:
4291 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4292 break;
460f00c4 4293 }
acf12465
AJ
4294 tcg_temp_free(t2);
4295 tcg_temp_free(t1);
4296 tcg_temp_free(t0);
460f00c4
AJ
4297}
4298
4299/* Logic */
d75c135e 4300static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4301 int rd, int rs, int rt)
460f00c4 4302{
460f00c4
AJ
4303 if (rd == 0) {
4304 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4305 return;
4306 }
4307
4308 switch (opc) {
6af0bf9c 4309 case OPC_AND:
460f00c4
AJ
4310 if (likely(rs != 0 && rt != 0)) {
4311 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4312 } else {
4313 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4314 }
6af0bf9c
FB
4315 break;
4316 case OPC_NOR:
460f00c4
AJ
4317 if (rs != 0 && rt != 0) {
4318 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4319 } else if (rs == 0 && rt != 0) {
4320 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4321 } else if (rs != 0 && rt == 0) {
4322 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4323 } else {
4324 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4325 }
6af0bf9c
FB
4326 break;
4327 case OPC_OR:
460f00c4
AJ
4328 if (likely(rs != 0 && rt != 0)) {
4329 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4330 } else if (rs == 0 && rt != 0) {
4331 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4332 } else if (rs != 0 && rt == 0) {
4333 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4334 } else {
4335 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4336 }
6af0bf9c
FB
4337 break;
4338 case OPC_XOR:
460f00c4
AJ
4339 if (likely(rs != 0 && rt != 0)) {
4340 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4341 } else if (rs == 0 && rt != 0) {
4342 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4343 } else if (rs != 0 && rt == 0) {
4344 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4345 } else {
4346 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4347 }
6af0bf9c 4348 break;
460f00c4 4349 }
460f00c4
AJ
4350}
4351
4352/* Set on lower than */
d75c135e 4353static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4354 int rd, int rs, int rt)
460f00c4 4355{
460f00c4
AJ
4356 TCGv t0, t1;
4357
4358 if (rd == 0) {
4359 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4360 return;
4361 }
4362
4363 t0 = tcg_temp_new();
4364 t1 = tcg_temp_new();
4365 gen_load_gpr(t0, rs);
4366 gen_load_gpr(t1, rt);
4367 switch (opc) {
4368 case OPC_SLT:
e68dd28f 4369 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4370 break;
460f00c4 4371 case OPC_SLTU:
e68dd28f 4372 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4373 break;
4374 }
460f00c4
AJ
4375 tcg_temp_free(t0);
4376 tcg_temp_free(t1);
4377}
20c4c97c 4378
460f00c4 4379/* Shifts */
d75c135e
AJ
4380static void gen_shift(DisasContext *ctx, uint32_t opc,
4381 int rd, int rs, int rt)
460f00c4 4382{
460f00c4 4383 TCGv t0, t1;
20c4c97c 4384
460f00c4 4385 if (rd == 0) {
7480515f
AM
4386 /*
4387 * If no destination, treat it as a NOP.
4388 * For add & sub, we must generate the overflow exception when needed.
4389 */
460f00c4
AJ
4390 return;
4391 }
4392
4393 t0 = tcg_temp_new();
4394 t1 = tcg_temp_new();
4395 gen_load_gpr(t0, rs);
4396 gen_load_gpr(t1, rt);
4397 switch (opc) {
6af0bf9c 4398 case OPC_SLLV:
78723684
TS
4399 tcg_gen_andi_tl(t0, t0, 0x1f);
4400 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4401 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4402 break;
4403 case OPC_SRAV:
78723684 4404 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4405 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4406 break;
4407 case OPC_SRLV:
ea63e2c3
NF
4408 tcg_gen_ext32u_tl(t1, t1);
4409 tcg_gen_andi_tl(t0, t0, 0x1f);
4410 tcg_gen_shr_tl(t0, t1, t0);
4411 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4412 break;
4413 case OPC_ROTRV:
4414 {
4415 TCGv_i32 t2 = tcg_temp_new_i32();
4416 TCGv_i32 t3 = tcg_temp_new_i32();
4417
4418 tcg_gen_trunc_tl_i32(t2, t0);
4419 tcg_gen_trunc_tl_i32(t3, t1);
4420 tcg_gen_andi_i32(t2, t2, 0x1f);
4421 tcg_gen_rotr_i32(t2, t3, t2);
4422 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4423 tcg_temp_free_i32(t2);
4424 tcg_temp_free_i32(t3);
5a63bcb2 4425 }
7a387fff 4426 break;
d26bc211 4427#if defined(TARGET_MIPS64)
7a387fff 4428 case OPC_DSLLV:
78723684 4429 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4430 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4431 break;
4432 case OPC_DSRAV:
78723684 4433 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4434 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4435 break;
4436 case OPC_DSRLV:
ea63e2c3
NF
4437 tcg_gen_andi_tl(t0, t0, 0x3f);
4438 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4439 break;
4440 case OPC_DROTRV:
4441 tcg_gen_andi_tl(t0, t0, 0x3f);
4442 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4443 break;
7a387fff 4444#endif
6af0bf9c 4445 }
78723684
TS
4446 tcg_temp_free(t0);
4447 tcg_temp_free(t1);
6af0bf9c
FB
4448}
4449
37b9aae2 4450#if defined(TARGET_MIPS64)
86efbfb6
FN
4451/* Copy GPR to and from TX79 HI1/LO1 register. */
4452static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4453{
baa609db 4454 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4455 /* Treat as NOP. */
4456 return;
4457 }
4458
4459 switch (opc) {
baa609db 4460 case MMI_OPC_MFHI1:
86efbfb6
FN
4461 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4462 break;
baa609db 4463 case MMI_OPC_MFLO1:
86efbfb6
FN
4464 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4465 break;
baa609db 4466 case MMI_OPC_MTHI1:
86efbfb6
FN
4467 if (reg != 0) {
4468 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4469 } else {
4470 tcg_gen_movi_tl(cpu_HI[1], 0);
4471 }
4472 break;
baa609db 4473 case MMI_OPC_MTLO1:
86efbfb6
FN
4474 if (reg != 0) {
4475 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4476 } else {
4477 tcg_gen_movi_tl(cpu_LO[1], 0);
4478 }
4479 break;
4480 default:
4481 MIPS_INVAL("mfthilo1 TX79");
4482 generate_exception_end(ctx, EXCP_RI);
4483 break;
4484 }
4485}
37b9aae2 4486#endif
86efbfb6 4487
6af0bf9c 4488/* Arithmetic on HI/LO registers */
26135ead 4489static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4490{
86efbfb6 4491 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4492 /* Treat as NOP. */
a1f6684d 4493 return;
6af0bf9c 4494 }
4133498f 4495
4133498f 4496 if (acc != 0) {
86efbfb6 4497 check_dsp(ctx);
4133498f
JL
4498 }
4499
6af0bf9c
FB
4500 switch (opc) {
4501 case OPC_MFHI:
4133498f
JL
4502#if defined(TARGET_MIPS64)
4503 if (acc != 0) {
4504 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4505 } else
4506#endif
4507 {
4508 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4509 }
6af0bf9c
FB
4510 break;
4511 case OPC_MFLO:
4133498f
JL
4512#if defined(TARGET_MIPS64)
4513 if (acc != 0) {
4514 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4515 } else
4516#endif
4517 {
4518 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4519 }
6af0bf9c
FB
4520 break;
4521 case OPC_MTHI:
4133498f
JL
4522 if (reg != 0) {
4523#if defined(TARGET_MIPS64)
4524 if (acc != 0) {
4525 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4526 } else
4527#endif
4528 {
4529 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4530 }
4531 } else {
4532 tcg_gen_movi_tl(cpu_HI[acc], 0);
4533 }
6af0bf9c
FB
4534 break;
4535 case OPC_MTLO:
4133498f
JL
4536 if (reg != 0) {
4537#if defined(TARGET_MIPS64)
4538 if (acc != 0) {
4539 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4540 } else
4541#endif
4542 {
4543 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4544 }
4545 } else {
4546 tcg_gen_movi_tl(cpu_LO[acc], 0);
4547 }
6af0bf9c 4548 break;
6af0bf9c 4549 }
6af0bf9c
FB
4550}
4551
d4ea6acd 4552static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 4553 MemOp memop)
d4ea6acd
LA
4554{
4555 TCGv t0 = tcg_const_tl(addr);
4556 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4557 gen_store_gpr(t0, reg);
4558 tcg_temp_free(t0);
4559}
4560
ab39ee45
YK
4561static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4562 int rs)
d4ea6acd
LA
4563{
4564 target_long offset;
4565 target_long addr;
4566
ab39ee45 4567 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4568 case OPC_ADDIUPC:
4569 if (rs != 0) {
4570 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4571 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4572 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4573 }
4574 break;
4575 case R6_OPC_LWPC:
4576 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4577 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4578 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4579 break;
4580#if defined(TARGET_MIPS64)
4581 case OPC_LWUPC:
4582 check_mips_64(ctx);
4583 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4584 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4585 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4586 break;
4587#endif
4588 default:
ab39ee45 4589 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4590 case OPC_AUIPC:
4591 if (rs != 0) {
ab39ee45
YK
4592 offset = sextract32(ctx->opcode, 0, 16) << 16;
4593 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4594 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4595 }
4596 break;
4597 case OPC_ALUIPC:
4598 if (rs != 0) {
ab39ee45
YK
4599 offset = sextract32(ctx->opcode, 0, 16) << 16;
4600 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4601 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4602 }
4603 break;
4604#if defined(TARGET_MIPS64)
4605 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4606 case R6_OPC_LDPC + (1 << 16):
4607 case R6_OPC_LDPC + (2 << 16):
4608 case R6_OPC_LDPC + (3 << 16):
4609 check_mips_64(ctx);
4610 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4611 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4612 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4613 break;
4614#endif
4615 default:
4616 MIPS_INVAL("OPC_PCREL");
9c708c7f 4617 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4618 break;
4619 }
4620 break;
4621 }
4622}
4623
b42ee5e1
LA
4624static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4625{
b42ee5e1
LA
4626 TCGv t0, t1;
4627
4628 if (rd == 0) {
4629 /* Treat as NOP. */
b42ee5e1
LA
4630 return;
4631 }
4632
4633 t0 = tcg_temp_new();
4634 t1 = tcg_temp_new();
4635
4636 gen_load_gpr(t0, rs);
4637 gen_load_gpr(t1, rt);
4638
4639 switch (opc) {
4640 case R6_OPC_DIV:
4641 {
4642 TCGv t2 = tcg_temp_new();
4643 TCGv t3 = tcg_temp_new();
4644 tcg_gen_ext32s_tl(t0, t0);
4645 tcg_gen_ext32s_tl(t1, t1);
4646 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4647 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4648 tcg_gen_and_tl(t2, t2, t3);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4650 tcg_gen_or_tl(t2, t2, t3);
4651 tcg_gen_movi_tl(t3, 0);
4652 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4653 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4654 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4655 tcg_temp_free(t3);
4656 tcg_temp_free(t2);
4657 }
b42ee5e1
LA
4658 break;
4659 case R6_OPC_MOD:
4660 {
4661 TCGv t2 = tcg_temp_new();
4662 TCGv t3 = tcg_temp_new();
4663 tcg_gen_ext32s_tl(t0, t0);
4664 tcg_gen_ext32s_tl(t1, t1);
4665 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4666 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4667 tcg_gen_and_tl(t2, t2, t3);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4669 tcg_gen_or_tl(t2, t2, t3);
4670 tcg_gen_movi_tl(t3, 0);
4671 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4672 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4673 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4674 tcg_temp_free(t3);
4675 tcg_temp_free(t2);
4676 }
b42ee5e1
LA
4677 break;
4678 case R6_OPC_DIVU:
4679 {
4680 TCGv t2 = tcg_const_tl(0);
4681 TCGv t3 = tcg_const_tl(1);
4682 tcg_gen_ext32u_tl(t0, t0);
4683 tcg_gen_ext32u_tl(t1, t1);
4684 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4685 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4686 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4687 tcg_temp_free(t3);
4688 tcg_temp_free(t2);
4689 }
b42ee5e1
LA
4690 break;
4691 case R6_OPC_MODU:
4692 {
4693 TCGv t2 = tcg_const_tl(0);
4694 TCGv t3 = tcg_const_tl(1);
4695 tcg_gen_ext32u_tl(t0, t0);
4696 tcg_gen_ext32u_tl(t1, t1);
4697 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4698 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4699 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4700 tcg_temp_free(t3);
4701 tcg_temp_free(t2);
4702 }
b42ee5e1
LA
4703 break;
4704 case R6_OPC_MUL:
4705 {
4706 TCGv_i32 t2 = tcg_temp_new_i32();
4707 TCGv_i32 t3 = tcg_temp_new_i32();
4708 tcg_gen_trunc_tl_i32(t2, t0);
4709 tcg_gen_trunc_tl_i32(t3, t1);
4710 tcg_gen_mul_i32(t2, t2, t3);
4711 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4712 tcg_temp_free_i32(t2);
4713 tcg_temp_free_i32(t3);
4714 }
b42ee5e1
LA
4715 break;
4716 case R6_OPC_MUH:
4717 {
4718 TCGv_i32 t2 = tcg_temp_new_i32();
4719 TCGv_i32 t3 = tcg_temp_new_i32();
4720 tcg_gen_trunc_tl_i32(t2, t0);
4721 tcg_gen_trunc_tl_i32(t3, t1);
4722 tcg_gen_muls2_i32(t2, t3, t2, t3);
4723 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4724 tcg_temp_free_i32(t2);
4725 tcg_temp_free_i32(t3);
4726 }
b42ee5e1
LA
4727 break;
4728 case R6_OPC_MULU:
4729 {
4730 TCGv_i32 t2 = tcg_temp_new_i32();
4731 TCGv_i32 t3 = tcg_temp_new_i32();
4732 tcg_gen_trunc_tl_i32(t2, t0);
4733 tcg_gen_trunc_tl_i32(t3, t1);
4734 tcg_gen_mul_i32(t2, t2, t3);
4735 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4736 tcg_temp_free_i32(t2);
4737 tcg_temp_free_i32(t3);
4738 }
b42ee5e1
LA
4739 break;
4740 case R6_OPC_MUHU:
4741 {
4742 TCGv_i32 t2 = tcg_temp_new_i32();
4743 TCGv_i32 t3 = tcg_temp_new_i32();
4744 tcg_gen_trunc_tl_i32(t2, t0);
4745 tcg_gen_trunc_tl_i32(t3, t1);
4746 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4747 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4748 tcg_temp_free_i32(t2);
4749 tcg_temp_free_i32(t3);
4750 }
b42ee5e1
LA
4751 break;
4752#if defined(TARGET_MIPS64)
4753 case R6_OPC_DDIV:
4754 {
4755 TCGv t2 = tcg_temp_new();
4756 TCGv t3 = tcg_temp_new();
4757 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4758 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4759 tcg_gen_and_tl(t2, t2, t3);
4760 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4761 tcg_gen_or_tl(t2, t2, t3);
4762 tcg_gen_movi_tl(t3, 0);
4763 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4764 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4765 tcg_temp_free(t3);
4766 tcg_temp_free(t2);
4767 }
b42ee5e1
LA
4768 break;
4769 case R6_OPC_DMOD:
4770 {
4771 TCGv t2 = tcg_temp_new();
4772 TCGv t3 = tcg_temp_new();
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4774 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4775 tcg_gen_and_tl(t2, t2, t3);
4776 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4777 tcg_gen_or_tl(t2, t2, t3);
4778 tcg_gen_movi_tl(t3, 0);
4779 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4780 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4781 tcg_temp_free(t3);
4782 tcg_temp_free(t2);
4783 }
b42ee5e1
LA
4784 break;
4785 case R6_OPC_DDIVU:
4786 {
4787 TCGv t2 = tcg_const_tl(0);
4788 TCGv t3 = tcg_const_tl(1);
4789 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4790 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4791 tcg_temp_free(t3);
4792 tcg_temp_free(t2);
4793 }
b42ee5e1
LA
4794 break;
4795 case R6_OPC_DMODU:
4796 {
4797 TCGv t2 = tcg_const_tl(0);
4798 TCGv t3 = tcg_const_tl(1);
4799 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4800 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4801 tcg_temp_free(t3);
4802 tcg_temp_free(t2);
4803 }
b42ee5e1
LA
4804 break;
4805 case R6_OPC_DMUL:
4806 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4807 break;
4808 case R6_OPC_DMUH:
4809 {
4810 TCGv t2 = tcg_temp_new();
4811 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4812 tcg_temp_free(t2);
4813 }
b42ee5e1
LA
4814 break;
4815 case R6_OPC_DMULU:
4816 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4817 break;
4818 case R6_OPC_DMUHU:
4819 {
4820 TCGv t2 = tcg_temp_new();
4821 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4822 tcg_temp_free(t2);
4823 }
b42ee5e1
LA
4824 break;
4825#endif
4826 default:
9d68ac14 4827 MIPS_INVAL("r6 mul/div");
9c708c7f 4828 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4829 goto out;
4830 }
b42ee5e1
LA
4831 out:
4832 tcg_temp_free(t0);
4833 tcg_temp_free(t1);
4834}
4835
37b9aae2 4836#if defined(TARGET_MIPS64)
c42171c3
FN
4837static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4838{
4839 TCGv t0, t1;
4840
4841 t0 = tcg_temp_new();
4842 t1 = tcg_temp_new();
4843
4844 gen_load_gpr(t0, rs);
4845 gen_load_gpr(t1, rt);
4846
4847 switch (opc) {
baa609db 4848 case MMI_OPC_DIV1:
c42171c3
FN
4849 {
4850 TCGv t2 = tcg_temp_new();
4851 TCGv t3 = tcg_temp_new();
4852 tcg_gen_ext32s_tl(t0, t0);
4853 tcg_gen_ext32s_tl(t1, t1);
4854 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4855 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4856 tcg_gen_and_tl(t2, t2, t3);
4857 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4858 tcg_gen_or_tl(t2, t2, t3);
4859 tcg_gen_movi_tl(t3, 0);
4860 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4861 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4862 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4863 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4864 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4865 tcg_temp_free(t3);
4866 tcg_temp_free(t2);
4867 }
4868 break;
baa609db 4869 case MMI_OPC_DIVU1:
c42171c3
FN
4870 {
4871 TCGv t2 = tcg_const_tl(0);
4872 TCGv t3 = tcg_const_tl(1);
4873 tcg_gen_ext32u_tl(t0, t0);
4874 tcg_gen_ext32u_tl(t1, t1);
4875 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4876 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4877 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4878 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4879 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4880 tcg_temp_free(t3);
4881 tcg_temp_free(t2);
4882 }
4883 break;
4884 default:
4885 MIPS_INVAL("div1 TX79");
4886 generate_exception_end(ctx, EXCP_RI);
4887 goto out;
4888 }
4889 out:
4890 tcg_temp_free(t0);
4891 tcg_temp_free(t1);
4892}
37b9aae2 4893#endif
c42171c3 4894
26135ead
RS
4895static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4896 int acc, int rs, int rt)
6af0bf9c 4897{
d45f89f4
AJ
4898 TCGv t0, t1;
4899
51127181
AJ
4900 t0 = tcg_temp_new();
4901 t1 = tcg_temp_new();
6af0bf9c 4902
78723684
TS
4903 gen_load_gpr(t0, rs);
4904 gen_load_gpr(t1, rt);
51127181 4905
26135ead 4906 if (acc != 0) {
c42171c3 4907 check_dsp(ctx);
26135ead
RS
4908 }
4909
6af0bf9c
FB
4910 switch (opc) {
4911 case OPC_DIV:
48d38ca5 4912 {
51127181
AJ
4913 TCGv t2 = tcg_temp_new();
4914 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4915 tcg_gen_ext32s_tl(t0, t0);
4916 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4917 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4918 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4919 tcg_gen_and_tl(t2, t2, t3);
4920 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4921 tcg_gen_or_tl(t2, t2, t3);
4922 tcg_gen_movi_tl(t3, 0);
4923 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4924 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4925 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4926 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4927 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4928 tcg_temp_free(t3);
4929 tcg_temp_free(t2);
48d38ca5 4930 }
6af0bf9c
FB
4931 break;
4932 case OPC_DIVU:
48d38ca5 4933 {
51127181
AJ
4934 TCGv t2 = tcg_const_tl(0);
4935 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4936 tcg_gen_ext32u_tl(t0, t0);
4937 tcg_gen_ext32u_tl(t1, t1);
51127181 4938 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4939 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4940 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4941 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4942 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4943 tcg_temp_free(t3);
4944 tcg_temp_free(t2);
48d38ca5 4945 }
6af0bf9c
FB
4946 break;
4947 case OPC_MULT:
214c465f 4948 {
ce1dd5d1
RH
4949 TCGv_i32 t2 = tcg_temp_new_i32();
4950 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4951 tcg_gen_trunc_tl_i32(t2, t0);
4952 tcg_gen_trunc_tl_i32(t3, t1);
4953 tcg_gen_muls2_i32(t2, t3, t2, t3);
4954 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4955 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4956 tcg_temp_free_i32(t2);
4957 tcg_temp_free_i32(t3);
214c465f 4958 }
6af0bf9c
FB
4959 break;
4960 case OPC_MULTU:
214c465f 4961 {
ce1dd5d1
RH
4962 TCGv_i32 t2 = tcg_temp_new_i32();
4963 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4964 tcg_gen_trunc_tl_i32(t2, t0);
4965 tcg_gen_trunc_tl_i32(t3, t1);
4966 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4967 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4968 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4969 tcg_temp_free_i32(t2);
4970 tcg_temp_free_i32(t3);
214c465f 4971 }
6af0bf9c 4972 break;
d26bc211 4973#if defined(TARGET_MIPS64)
7a387fff 4974 case OPC_DDIV:
48d38ca5 4975 {
51127181
AJ
4976 TCGv t2 = tcg_temp_new();
4977 TCGv t3 = tcg_temp_new();
4978 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4979 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4980 tcg_gen_and_tl(t2, t2, t3);
4981 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4982 tcg_gen_or_tl(t2, t2, t3);
4983 tcg_gen_movi_tl(t3, 0);
4984 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4985 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4986 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4987 tcg_temp_free(t3);
4988 tcg_temp_free(t2);
48d38ca5 4989 }
7a387fff
TS
4990 break;
4991 case OPC_DDIVU:
48d38ca5 4992 {
51127181
AJ
4993 TCGv t2 = tcg_const_tl(0);
4994 TCGv t3 = tcg_const_tl(1);
4995 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4996 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4997 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
4998 tcg_temp_free(t3);
4999 tcg_temp_free(t2);
48d38ca5 5000 }
7a387fff
TS
5001 break;
5002 case OPC_DMULT:
26135ead 5003 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5004 break;
5005 case OPC_DMULTU:
26135ead 5006 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5007 break;
5008#endif
6af0bf9c 5009 case OPC_MADD:
214c465f 5010 {
d45f89f4
AJ
5011 TCGv_i64 t2 = tcg_temp_new_i64();
5012 TCGv_i64 t3 = tcg_temp_new_i64();
5013
5014 tcg_gen_ext_tl_i64(t2, t0);
5015 tcg_gen_ext_tl_i64(t3, t1);
5016 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5017 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5018 tcg_gen_add_i64(t2, t2, t3);
5019 tcg_temp_free_i64(t3);
71f303cd
RH
5020 gen_move_low32(cpu_LO[acc], t2);
5021 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5022 tcg_temp_free_i64(t2);
214c465f 5023 }
6af0bf9c
FB
5024 break;
5025 case OPC_MADDU:
4133498f 5026 {
d45f89f4
AJ
5027 TCGv_i64 t2 = tcg_temp_new_i64();
5028 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5029
78723684
TS
5030 tcg_gen_ext32u_tl(t0, t0);
5031 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5032 tcg_gen_extu_tl_i64(t2, t0);
5033 tcg_gen_extu_tl_i64(t3, t1);
5034 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5035 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5036 tcg_gen_add_i64(t2, t2, t3);
5037 tcg_temp_free_i64(t3);
71f303cd
RH
5038 gen_move_low32(cpu_LO[acc], t2);
5039 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5040 tcg_temp_free_i64(t2);
214c465f 5041 }
6af0bf9c
FB
5042 break;
5043 case OPC_MSUB:
214c465f 5044 {
d45f89f4
AJ
5045 TCGv_i64 t2 = tcg_temp_new_i64();
5046 TCGv_i64 t3 = tcg_temp_new_i64();
5047
5048 tcg_gen_ext_tl_i64(t2, t0);
5049 tcg_gen_ext_tl_i64(t3, t1);
5050 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5051 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5052 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5053 tcg_temp_free_i64(t3);
71f303cd
RH
5054 gen_move_low32(cpu_LO[acc], t2);
5055 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5056 tcg_temp_free_i64(t2);
214c465f 5057 }
6af0bf9c
FB
5058 break;
5059 case OPC_MSUBU:
214c465f 5060 {
d45f89f4
AJ
5061 TCGv_i64 t2 = tcg_temp_new_i64();
5062 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5063
78723684
TS
5064 tcg_gen_ext32u_tl(t0, t0);
5065 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5066 tcg_gen_extu_tl_i64(t2, t0);
5067 tcg_gen_extu_tl_i64(t3, t1);
5068 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5069 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5070 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5071 tcg_temp_free_i64(t3);
71f303cd
RH
5072 gen_move_low32(cpu_LO[acc], t2);
5073 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5074 tcg_temp_free_i64(t2);
214c465f 5075 }
6af0bf9c
FB
5076 break;
5077 default:
9d68ac14 5078 MIPS_INVAL("mul/div");
9c708c7f 5079 generate_exception_end(ctx, EXCP_RI);
78723684 5080 goto out;
6af0bf9c 5081 }
78723684
TS
5082 out:
5083 tcg_temp_free(t0);
5084 tcg_temp_free(t1);
6af0bf9c
FB
5085}
5086
21e8e8b2 5087/*
3b948f05
PMD
5088 * These MULT[U] and MADD[U] instructions implemented in for example
5089 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5090 * architectures are special three-operand variants with the syntax
5091 *
06de726b 5092 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5093 *
5094 * such that
5095 *
5096 * (rd, LO, HI) <- rs * rt
5097 *
3b948f05
PMD
5098 * and
5099 *
a95c4c26 5100 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5101 *
5102 * such that
5103 *
5104 * (rd, LO, HI) <- (LO, HI) + rs * rt
5105 *
21e8e8b2
FN
5106 * where the low-order 32-bits of the result is placed into both the
5107 * GPR rd and the special register LO. The high-order 32-bits of the
5108 * result is placed into the special register HI.
5109 *
5110 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5111 * which is the zero register that always reads as 0.
5112 */
5113static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5114 int rd, int rs, int rt)
5115{
5116 TCGv t0 = tcg_temp_new();
5117 TCGv t1 = tcg_temp_new();
5118 int acc = 0;
5119
5120 gen_load_gpr(t0, rs);
5121 gen_load_gpr(t1, rt);
5122
5123 switch (opc) {
baa609db 5124 case MMI_OPC_MULT1:
06de726b
FN
5125 acc = 1;
5126 /* Fall through */
21e8e8b2
FN
5127 case OPC_MULT:
5128 {
5129 TCGv_i32 t2 = tcg_temp_new_i32();
5130 TCGv_i32 t3 = tcg_temp_new_i32();
5131 tcg_gen_trunc_tl_i32(t2, t0);
5132 tcg_gen_trunc_tl_i32(t3, t1);
5133 tcg_gen_muls2_i32(t2, t3, t2, t3);
5134 if (rd) {
5135 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5136 }
5137 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5138 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5139 tcg_temp_free_i32(t2);
5140 tcg_temp_free_i32(t3);
5141 }
5142 break;
baa609db 5143 case MMI_OPC_MULTU1:
06de726b
FN
5144 acc = 1;
5145 /* Fall through */
21e8e8b2
FN
5146 case OPC_MULTU:
5147 {
5148 TCGv_i32 t2 = tcg_temp_new_i32();
5149 TCGv_i32 t3 = tcg_temp_new_i32();
5150 tcg_gen_trunc_tl_i32(t2, t0);
5151 tcg_gen_trunc_tl_i32(t3, t1);
5152 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5153 if (rd) {
5154 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5155 }
5156 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5157 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5158 tcg_temp_free_i32(t2);
5159 tcg_temp_free_i32(t3);
5160 }
5161 break;
a95c4c26
FN
5162 case MMI_OPC_MADD1:
5163 acc = 1;
5164 /* Fall through */
3b948f05
PMD
5165 case MMI_OPC_MADD:
5166 {
5167 TCGv_i64 t2 = tcg_temp_new_i64();
5168 TCGv_i64 t3 = tcg_temp_new_i64();
5169
5170 tcg_gen_ext_tl_i64(t2, t0);
5171 tcg_gen_ext_tl_i64(t3, t1);
5172 tcg_gen_mul_i64(t2, t2, t3);
5173 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5174 tcg_gen_add_i64(t2, t2, t3);
5175 tcg_temp_free_i64(t3);
5176 gen_move_low32(cpu_LO[acc], t2);
5177 gen_move_high32(cpu_HI[acc], t2);
5178 if (rd) {
5179 gen_move_low32(cpu_gpr[rd], t2);
5180 }
5181 tcg_temp_free_i64(t2);
5182 }
5183 break;
a95c4c26
FN
5184 case MMI_OPC_MADDU1:
5185 acc = 1;
5186 /* Fall through */
3b948f05
PMD
5187 case MMI_OPC_MADDU:
5188 {
5189 TCGv_i64 t2 = tcg_temp_new_i64();
5190 TCGv_i64 t3 = tcg_temp_new_i64();
5191
5192 tcg_gen_ext32u_tl(t0, t0);
5193 tcg_gen_ext32u_tl(t1, t1);
5194 tcg_gen_extu_tl_i64(t2, t0);
5195 tcg_gen_extu_tl_i64(t3, t1);
5196 tcg_gen_mul_i64(t2, t2, t3);
5197 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5198 tcg_gen_add_i64(t2, t2, t3);
5199 tcg_temp_free_i64(t3);
5200 gen_move_low32(cpu_LO[acc], t2);
5201 gen_move_high32(cpu_HI[acc], t2);
5202 if (rd) {
5203 gen_move_low32(cpu_gpr[rd], t2);
5204 }
5205 tcg_temp_free_i64(t2);
5206 }
5207 break;
21e8e8b2 5208 default:
3b948f05 5209 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5210 generate_exception_end(ctx, EXCP_RI);
5211 goto out;
5212 }
5213
5214 out:
5215 tcg_temp_free(t0);
5216 tcg_temp_free(t1);
5217}
5218
235785e8
AM
5219static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5220 int rd, int rs, int rt)
e9c71dd1 5221{
f157bfe1
AJ
5222 TCGv t0 = tcg_temp_new();
5223 TCGv t1 = tcg_temp_new();
e9c71dd1 5224
6c5c1e20
TS
5225 gen_load_gpr(t0, rs);
5226 gen_load_gpr(t1, rt);
e9c71dd1
TS
5227
5228 switch (opc) {
5229 case OPC_VR54XX_MULS:
895c2d04 5230 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5231 break;
e9c71dd1 5232 case OPC_VR54XX_MULSU:
895c2d04 5233 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5234 break;
e9c71dd1 5235 case OPC_VR54XX_MACC:
895c2d04 5236 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5237 break;
e9c71dd1 5238 case OPC_VR54XX_MACCU:
895c2d04 5239 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5240 break;
e9c71dd1 5241 case OPC_VR54XX_MSAC:
895c2d04 5242 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5243 break;
e9c71dd1 5244 case OPC_VR54XX_MSACU:
895c2d04 5245 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5246 break;
e9c71dd1 5247 case OPC_VR54XX_MULHI:
895c2d04 5248 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5249 break;
e9c71dd1 5250 case OPC_VR54XX_MULHIU:
895c2d04 5251 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5252 break;
e9c71dd1 5253 case OPC_VR54XX_MULSHI:
895c2d04 5254 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5255 break;
e9c71dd1 5256 case OPC_VR54XX_MULSHIU:
895c2d04 5257 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5258 break;
e9c71dd1 5259 case OPC_VR54XX_MACCHI:
895c2d04 5260 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5261 break;
e9c71dd1 5262 case OPC_VR54XX_MACCHIU:
895c2d04 5263 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5264 break;
e9c71dd1 5265 case OPC_VR54XX_MSACHI:
895c2d04 5266 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5267 break;
e9c71dd1 5268 case OPC_VR54XX_MSACHIU:
895c2d04 5269 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5270 break;
e9c71dd1
TS
5271 default:
5272 MIPS_INVAL("mul vr54xx");
9c708c7f 5273 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5274 goto out;
e9c71dd1 5275 }
6c5c1e20 5276 gen_store_gpr(t0, rd);
6c5c1e20
TS
5277
5278 out:
5279 tcg_temp_free(t0);
5280 tcg_temp_free(t1);
e9c71dd1
TS
5281}
5282
235785e8
AM
5283static void gen_cl(DisasContext *ctx, uint32_t opc,
5284 int rd, int rs)
6af0bf9c 5285{
20e1fb52 5286 TCGv t0;
6c5c1e20 5287
6af0bf9c 5288 if (rd == 0) {
ead9360e 5289 /* Treat as NOP. */
20e1fb52 5290 return;
6af0bf9c 5291 }
1a0196c5 5292 t0 = cpu_gpr[rd];
6c5c1e20 5293 gen_load_gpr(t0, rs);
1a0196c5 5294
6af0bf9c
FB
5295 switch (opc) {
5296 case OPC_CLO:
4267d3e6 5297 case R6_OPC_CLO:
1a0196c5
RH
5298#if defined(TARGET_MIPS64)
5299 case OPC_DCLO:
5300 case R6_OPC_DCLO:
5301#endif
5302 tcg_gen_not_tl(t0, t0);
6af0bf9c 5303 break;
1a0196c5
RH
5304 }
5305
5306 switch (opc) {
5307 case OPC_CLO:
5308 case R6_OPC_CLO:
6af0bf9c 5309 case OPC_CLZ:
4267d3e6 5310 case R6_OPC_CLZ:
1a0196c5
RH
5311 tcg_gen_ext32u_tl(t0, t0);
5312 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5313 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5314 break;
d26bc211 5315#if defined(TARGET_MIPS64)
7a387fff 5316 case OPC_DCLO:
4267d3e6 5317 case R6_OPC_DCLO:
7a387fff 5318 case OPC_DCLZ:
4267d3e6 5319 case R6_OPC_DCLZ:
1a0196c5 5320 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5321 break;
5322#endif
6af0bf9c 5323 }
6af0bf9c
FB
5324}
5325
161f85e6 5326/* Godson integer instructions */
bd277fa1
RH
5327static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5328 int rd, int rs, int rt)
161f85e6 5329{
161f85e6
AJ
5330 TCGv t0, t1;
5331
5332 if (rd == 0) {
5333 /* Treat as NOP. */
161f85e6
AJ
5334 return;
5335 }
5336
5337 switch (opc) {
5338 case OPC_MULT_G_2E:
5339 case OPC_MULT_G_2F:
5340 case OPC_MULTU_G_2E:
5341 case OPC_MULTU_G_2F:
5342#if defined(TARGET_MIPS64)
5343 case OPC_DMULT_G_2E:
5344 case OPC_DMULT_G_2F:
5345 case OPC_DMULTU_G_2E:
5346 case OPC_DMULTU_G_2F:
5347#endif
5348 t0 = tcg_temp_new();
5349 t1 = tcg_temp_new();
5350 break;
5351 default:
5352 t0 = tcg_temp_local_new();
5353 t1 = tcg_temp_local_new();
5354 break;
5355 }
5356
5357 gen_load_gpr(t0, rs);
5358 gen_load_gpr(t1, rt);
5359
5360 switch (opc) {
5361 case OPC_MULT_G_2E:
5362 case OPC_MULT_G_2F:
5363 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5364 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5365 break;
5366 case OPC_MULTU_G_2E:
5367 case OPC_MULTU_G_2F:
5368 tcg_gen_ext32u_tl(t0, t0);
5369 tcg_gen_ext32u_tl(t1, t1);
5370 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5371 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5372 break;
5373 case OPC_DIV_G_2E:
5374 case OPC_DIV_G_2F:
5375 {
42a268c2
RH
5376 TCGLabel *l1 = gen_new_label();
5377 TCGLabel *l2 = gen_new_label();
5378 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5379 tcg_gen_ext32s_tl(t0, t0);
5380 tcg_gen_ext32s_tl(t1, t1);
5381 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5382 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5383 tcg_gen_br(l3);
5384 gen_set_label(l1);
5385 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5386 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5387 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5388 tcg_gen_br(l3);
5389 gen_set_label(l2);
5390 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5391 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5392 gen_set_label(l3);
5393 }
161f85e6
AJ
5394 break;
5395 case OPC_DIVU_G_2E:
5396 case OPC_DIVU_G_2F:
5397 {
42a268c2
RH
5398 TCGLabel *l1 = gen_new_label();
5399 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5400 tcg_gen_ext32u_tl(t0, t0);
5401 tcg_gen_ext32u_tl(t1, t1);
5402 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5403 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5404 tcg_gen_br(l2);
5405 gen_set_label(l1);
5406 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5407 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5408 gen_set_label(l2);
5409 }
161f85e6
AJ
5410 break;
5411 case OPC_MOD_G_2E:
5412 case OPC_MOD_G_2F:
5413 {
42a268c2
RH
5414 TCGLabel *l1 = gen_new_label();
5415 TCGLabel *l2 = gen_new_label();
5416 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5417 tcg_gen_ext32u_tl(t0, t0);
5418 tcg_gen_ext32u_tl(t1, t1);
5419 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5421 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5422 gen_set_label(l1);
5423 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5424 tcg_gen_br(l3);
5425 gen_set_label(l2);
5426 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5427 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5428 gen_set_label(l3);
5429 }
161f85e6
AJ
5430 break;
5431 case OPC_MODU_G_2E:
5432 case OPC_MODU_G_2F:
5433 {
42a268c2
RH
5434 TCGLabel *l1 = gen_new_label();
5435 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5436 tcg_gen_ext32u_tl(t0, t0);
5437 tcg_gen_ext32u_tl(t1, t1);
5438 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5439 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5440 tcg_gen_br(l2);
5441 gen_set_label(l1);
5442 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5443 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5444 gen_set_label(l2);
5445 }
161f85e6
AJ
5446 break;
5447#if defined(TARGET_MIPS64)
5448 case OPC_DMULT_G_2E:
5449 case OPC_DMULT_G_2F:
5450 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5451 break;
5452 case OPC_DMULTU_G_2E:
5453 case OPC_DMULTU_G_2F:
5454 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5455 break;
5456 case OPC_DDIV_G_2E:
5457 case OPC_DDIV_G_2F:
5458 {
42a268c2
RH
5459 TCGLabel *l1 = gen_new_label();
5460 TCGLabel *l2 = gen_new_label();
5461 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5462 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5463 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5464 tcg_gen_br(l3);
5465 gen_set_label(l1);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5467 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5468 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5469 tcg_gen_br(l3);
5470 gen_set_label(l2);
5471 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5472 gen_set_label(l3);
5473 }
161f85e6
AJ
5474 break;
5475 case OPC_DDIVU_G_2E:
5476 case OPC_DDIVU_G_2F:
5477 {
42a268c2
RH
5478 TCGLabel *l1 = gen_new_label();
5479 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5480 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5481 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5482 tcg_gen_br(l2);
5483 gen_set_label(l1);
5484 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5485 gen_set_label(l2);
5486 }
161f85e6
AJ
5487 break;
5488 case OPC_DMOD_G_2E:
5489 case OPC_DMOD_G_2F:
5490 {
42a268c2
RH
5491 TCGLabel *l1 = gen_new_label();
5492 TCGLabel *l2 = gen_new_label();
5493 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5494 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5495 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5496 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5497 gen_set_label(l1);
5498 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5499 tcg_gen_br(l3);
5500 gen_set_label(l2);
5501 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5502 gen_set_label(l3);
5503 }
161f85e6
AJ
5504 break;
5505 case OPC_DMODU_G_2E:
5506 case OPC_DMODU_G_2F:
5507 {
42a268c2
RH
5508 TCGLabel *l1 = gen_new_label();
5509 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5510 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5511 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5512 tcg_gen_br(l2);
5513 gen_set_label(l1);
5514 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5515 gen_set_label(l2);
5516 }
161f85e6
AJ
5517 break;
5518#endif
5519 }
5520
161f85e6
AJ
5521 tcg_temp_free(t0);
5522 tcg_temp_free(t1);
5523}
5524
bd277fa1
RH
5525/* Loongson multimedia instructions */
5526static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5527{
bd277fa1
RH
5528 uint32_t opc, shift_max;
5529 TCGv_i64 t0, t1;
5530
5531 opc = MASK_LMI(ctx->opcode);
5532 switch (opc) {
5533 case OPC_ADD_CP2:
5534 case OPC_SUB_CP2:
5535 case OPC_DADD_CP2:
5536 case OPC_DSUB_CP2:
5537 t0 = tcg_temp_local_new_i64();
5538 t1 = tcg_temp_local_new_i64();
5539 break;
5540 default:
5541 t0 = tcg_temp_new_i64();
5542 t1 = tcg_temp_new_i64();
5543 break;
5544 }
5545
b5a587b6 5546 check_cp1_enabled(ctx);
bd277fa1
RH
5547 gen_load_fpr64(ctx, t0, rs);
5548 gen_load_fpr64(ctx, t1, rt);
5549
bd277fa1 5550 switch (opc) {
b1cf82f0
AM
5551 case OPC_PADDSH:
5552 gen_helper_paddsh(t0, t0, t1);
5553 break;
5554 case OPC_PADDUSH:
5555 gen_helper_paddush(t0, t0, t1);
5556 break;
5557 case OPC_PADDH:
5558 gen_helper_paddh(t0, t0, t1);
5559 break;
5560 case OPC_PADDW:
5561 gen_helper_paddw(t0, t0, t1);
5562 break;
5563 case OPC_PADDSB:
5564 gen_helper_paddsb(t0, t0, t1);
5565 break;
5566 case OPC_PADDUSB:
5567 gen_helper_paddusb(t0, t0, t1);
5568 break;
5569 case OPC_PADDB:
5570 gen_helper_paddb(t0, t0, t1);
5571 break;
5572
5573 case OPC_PSUBSH:
5574 gen_helper_psubsh(t0, t0, t1);
5575 break;
5576 case OPC_PSUBUSH:
5577 gen_helper_psubush(t0, t0, t1);
5578 break;
5579 case OPC_PSUBH:
5580 gen_helper_psubh(t0, t0, t1);
5581 break;
5582 case OPC_PSUBW:
5583 gen_helper_psubw(t0, t0, t1);
5584 break;
5585 case OPC_PSUBSB:
5586 gen_helper_psubsb(t0, t0, t1);
5587 break;
5588 case OPC_PSUBUSB:
5589 gen_helper_psubusb(t0, t0, t1);
5590 break;
5591 case OPC_PSUBB:
5592 gen_helper_psubb(t0, t0, t1);
5593 break;
5594
5595 case OPC_PSHUFH:
5596 gen_helper_pshufh(t0, t0, t1);
5597 break;
5598 case OPC_PACKSSWH:
5599 gen_helper_packsswh(t0, t0, t1);
5600 break;
5601 case OPC_PACKSSHB:
5602 gen_helper_packsshb(t0, t0, t1);
5603 break;
5604 case OPC_PACKUSHB:
5605 gen_helper_packushb(t0, t0, t1);
5606 break;
5607
5608 case OPC_PUNPCKLHW:
5609 gen_helper_punpcklhw(t0, t0, t1);
5610 break;
5611 case OPC_PUNPCKHHW:
5612 gen_helper_punpckhhw(t0, t0, t1);
5613 break;
5614 case OPC_PUNPCKLBH:
5615 gen_helper_punpcklbh(t0, t0, t1);
5616 break;
5617 case OPC_PUNPCKHBH:
5618 gen_helper_punpckhbh(t0, t0, t1);
5619 break;
5620 case OPC_PUNPCKLWD:
5621 gen_helper_punpcklwd(t0, t0, t1);
5622 break;
5623 case OPC_PUNPCKHWD:
5624 gen_helper_punpckhwd(t0, t0, t1);
5625 break;
5626
5627 case OPC_PAVGH:
5628 gen_helper_pavgh(t0, t0, t1);
5629 break;
5630 case OPC_PAVGB:
5631 gen_helper_pavgb(t0, t0, t1);
5632 break;
5633 case OPC_PMAXSH:
5634 gen_helper_pmaxsh(t0, t0, t1);
5635 break;
5636 case OPC_PMINSH:
5637 gen_helper_pminsh(t0, t0, t1);
5638 break;
5639 case OPC_PMAXUB:
5640 gen_helper_pmaxub(t0, t0, t1);
5641 break;
5642 case OPC_PMINUB:
5643 gen_helper_pminub(t0, t0, t1);
5644 break;
5645
5646 case OPC_PCMPEQW:
5647 gen_helper_pcmpeqw(t0, t0, t1);
5648 break;
5649 case OPC_PCMPGTW:
5650 gen_helper_pcmpgtw(t0, t0, t1);
5651 break;
5652 case OPC_PCMPEQH:
5653 gen_helper_pcmpeqh(t0, t0, t1);
5654 break;
5655 case OPC_PCMPGTH:
5656 gen_helper_pcmpgth(t0, t0, t1);
5657 break;
5658 case OPC_PCMPEQB:
5659 gen_helper_pcmpeqb(t0, t0, t1);
5660 break;
5661 case OPC_PCMPGTB:
5662 gen_helper_pcmpgtb(t0, t0, t1);
5663 break;
5664
5665 case OPC_PSLLW:
5666 gen_helper_psllw(t0, t0, t1);
5667 break;
5668 case OPC_PSLLH:
5669 gen_helper_psllh(t0, t0, t1);
5670 break;
5671 case OPC_PSRLW:
5672 gen_helper_psrlw(t0, t0, t1);
5673 break;
5674 case OPC_PSRLH:
5675 gen_helper_psrlh(t0, t0, t1);
5676 break;
5677 case OPC_PSRAW:
5678 gen_helper_psraw(t0, t0, t1);
5679 break;
5680 case OPC_PSRAH:
5681 gen_helper_psrah(t0, t0, t1);
5682 break;
5683
5684 case OPC_PMULLH:
5685 gen_helper_pmullh(t0, t0, t1);
5686 break;
5687 case OPC_PMULHH:
5688 gen_helper_pmulhh(t0, t0, t1);
5689 break;
5690 case OPC_PMULHUH:
5691 gen_helper_pmulhuh(t0, t0, t1);
5692 break;
5693 case OPC_PMADDHW:
5694 gen_helper_pmaddhw(t0, t0, t1);
5695 break;
5696
5697 case OPC_PASUBUB:
5698 gen_helper_pasubub(t0, t0, t1);
5699 break;
5700 case OPC_BIADD:
5701 gen_helper_biadd(t0, t0);
5702 break;
5703 case OPC_PMOVMSKB:
5704 gen_helper_pmovmskb(t0, t0);
5705 break;
5706
5707 case OPC_PADDD:
5708 tcg_gen_add_i64(t0, t0, t1);
5709 break;
5710 case OPC_PSUBD:
5711 tcg_gen_sub_i64(t0, t0, t1);
5712 break;
5713 case OPC_XOR_CP2:
5714 tcg_gen_xor_i64(t0, t0, t1);
5715 break;
5716 case OPC_NOR_CP2:
5717 tcg_gen_nor_i64(t0, t0, t1);
5718 break;
5719 case OPC_AND_CP2:
5720 tcg_gen_and_i64(t0, t0, t1);
5721 break;
5722 case OPC_OR_CP2:
5723 tcg_gen_or_i64(t0, t0, t1);
5724 break;
bd277fa1 5725
9099a36b
H
5726 case OPC_PANDN:
5727 tcg_gen_andc_i64(t0, t1, t0);
5728 break;
5729
bd277fa1
RH
5730 case OPC_PINSRH_0:
5731 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5732 break;
5733 case OPC_PINSRH_1:
5734 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5735 break;
5736 case OPC_PINSRH_2:
5737 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5738 break;
5739 case OPC_PINSRH_3:
5740 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5741 break;
5742
5743 case OPC_PEXTRH:
5744 tcg_gen_andi_i64(t1, t1, 3);
5745 tcg_gen_shli_i64(t1, t1, 4);
5746 tcg_gen_shr_i64(t0, t0, t1);
5747 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5748 break;
5749
5750 case OPC_ADDU_CP2:
5751 tcg_gen_add_i64(t0, t0, t1);
5752 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5753 break;
5754 case OPC_SUBU_CP2:
5755 tcg_gen_sub_i64(t0, t0, t1);
5756 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5757 break;
5758
5759 case OPC_SLL_CP2:
bd277fa1
RH
5760 shift_max = 32;
5761 goto do_shift;
5762 case OPC_SRL_CP2:
bd277fa1
RH
5763 shift_max = 32;
5764 goto do_shift;
5765 case OPC_SRA_CP2:
bd277fa1
RH
5766 shift_max = 32;
5767 goto do_shift;
5768 case OPC_DSLL_CP2:
bd277fa1
RH
5769 shift_max = 64;
5770 goto do_shift;
5771 case OPC_DSRL_CP2:
bd277fa1
RH
5772 shift_max = 64;
5773 goto do_shift;
5774 case OPC_DSRA_CP2:
bd277fa1
RH
5775 shift_max = 64;
5776 goto do_shift;
5777 do_shift:
5778 /* Make sure shift count isn't TCG undefined behaviour. */
5779 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5780
5781 switch (opc) {
5782 case OPC_SLL_CP2:
5783 case OPC_DSLL_CP2:
5784 tcg_gen_shl_i64(t0, t0, t1);
5785 break;
5786 case OPC_SRA_CP2:
5787 case OPC_DSRA_CP2:
7480515f
AM
5788 /*
5789 * Since SRA is UndefinedResult without sign-extended inputs,
5790 * we can treat SRA and DSRA the same.
5791 */
bd277fa1
RH
5792 tcg_gen_sar_i64(t0, t0, t1);
5793 break;
5794 case OPC_SRL_CP2:
5795 /* We want to shift in zeros for SRL; zero-extend first. */
5796 tcg_gen_ext32u_i64(t0, t0);
5797 /* FALLTHRU */
5798 case OPC_DSRL_CP2:
5799 tcg_gen_shr_i64(t0, t0, t1);
5800 break;
5801 }
5802
5803 if (shift_max == 32) {
5804 tcg_gen_ext32s_i64(t0, t0);
5805 }
5806
5807 /* Shifts larger than MAX produce zero. */
5808 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5809 tcg_gen_neg_i64(t1, t1);
5810 tcg_gen_and_i64(t0, t0, t1);
5811 break;
5812
5813 case OPC_ADD_CP2:
5814 case OPC_DADD_CP2:
5815 {
5816 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5817 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5818
5819 tcg_gen_mov_i64(t2, t0);
5820 tcg_gen_add_i64(t0, t1, t2);
5821 if (opc == OPC_ADD_CP2) {
5822 tcg_gen_ext32s_i64(t0, t0);
5823 }
5824 tcg_gen_xor_i64(t1, t1, t2);
5825 tcg_gen_xor_i64(t2, t2, t0);
5826 tcg_gen_andc_i64(t1, t2, t1);
5827 tcg_temp_free_i64(t2);
5828 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5829 generate_exception(ctx, EXCP_OVERFLOW);
5830 gen_set_label(lab);
bd277fa1
RH
5831 break;
5832 }
5833
5834 case OPC_SUB_CP2:
5835 case OPC_DSUB_CP2:
5836 {
5837 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5838 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5839
5840 tcg_gen_mov_i64(t2, t0);
5841 tcg_gen_sub_i64(t0, t1, t2);
5842 if (opc == OPC_SUB_CP2) {
5843 tcg_gen_ext32s_i64(t0, t0);
5844 }
5845 tcg_gen_xor_i64(t1, t1, t2);
5846 tcg_gen_xor_i64(t2, t2, t0);
5847 tcg_gen_and_i64(t1, t1, t2);
5848 tcg_temp_free_i64(t2);
5849 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5850 generate_exception(ctx, EXCP_OVERFLOW);
5851 gen_set_label(lab);
bd277fa1
RH
5852 break;
5853 }
5854
5855 case OPC_PMULUW:
5856 tcg_gen_ext32u_i64(t0, t0);
5857 tcg_gen_ext32u_i64(t1, t1);
5858 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5859 break;
5860
5861 case OPC_SEQU_CP2:
5862 case OPC_SEQ_CP2:
5863 case OPC_SLTU_CP2:
5864 case OPC_SLT_CP2:
5865 case OPC_SLEU_CP2:
5866 case OPC_SLE_CP2:
7480515f
AM
5867 /*
5868 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5869 * FD field is the CC field?
5870 */
bd277fa1 5871 default:
9d68ac14 5872 MIPS_INVAL("loongson_cp2");
9c708c7f 5873 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5874 return;
5875 }
5876
bd277fa1
RH
5877 gen_store_fpr64(ctx, t0, rd);
5878
bd277fa1
RH
5879 tcg_temp_free_i64(t0);
5880 tcg_temp_free_i64(t1);
5881}
5882
6af0bf9c 5883/* Traps */
71375b59
AM
5884static void gen_trap(DisasContext *ctx, uint32_t opc,
5885 int rs, int rt, int16_t imm)
6af0bf9c
FB
5886{
5887 int cond;
cdc0faa6 5888 TCGv t0 = tcg_temp_new();
1ba74fb8 5889 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5890
5891 cond = 0;
5892 /* Load needed operands */
5893 switch (opc) {
5894 case OPC_TEQ:
5895 case OPC_TGE:
5896 case OPC_TGEU:
5897 case OPC_TLT:
5898 case OPC_TLTU:
5899 case OPC_TNE:
5900 /* Compare two registers */
5901 if (rs != rt) {
be24bb4f
TS
5902 gen_load_gpr(t0, rs);
5903 gen_load_gpr(t1, rt);
6af0bf9c
FB
5904 cond = 1;
5905 }
179e32bb 5906 break;
6af0bf9c
FB
5907 case OPC_TEQI:
5908 case OPC_TGEI:
5909 case OPC_TGEIU:
5910 case OPC_TLTI:
5911 case OPC_TLTIU:
5912 case OPC_TNEI:
5913 /* Compare register to immediate */
5914 if (rs != 0 || imm != 0) {
be24bb4f
TS
5915 gen_load_gpr(t0, rs);
5916 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5917 cond = 1;
5918 }
5919 break;
5920 }
5921 if (cond == 0) {
5922 switch (opc) {
5923 case OPC_TEQ: /* rs == rs */
5924 case OPC_TEQI: /* r0 == 0 */
5925 case OPC_TGE: /* rs >= rs */
5926 case OPC_TGEI: /* r0 >= 0 */
5927 case OPC_TGEU: /* rs >= rs unsigned */
5928 case OPC_TGEIU: /* r0 >= 0 unsigned */
5929 /* Always trap */
9c708c7f 5930 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5931 break;
5932 case OPC_TLT: /* rs < rs */
5933 case OPC_TLTI: /* r0 < 0 */
5934 case OPC_TLTU: /* rs < rs unsigned */
5935 case OPC_TLTIU: /* r0 < 0 unsigned */
5936 case OPC_TNE: /* rs != rs */
5937 case OPC_TNEI: /* r0 != 0 */
ead9360e 5938 /* Never trap: treat as NOP. */
cdc0faa6 5939 break;
6af0bf9c
FB
5940 }
5941 } else {
42a268c2 5942 TCGLabel *l1 = gen_new_label();
cdc0faa6 5943
6af0bf9c
FB
5944 switch (opc) {
5945 case OPC_TEQ:
5946 case OPC_TEQI:
cdc0faa6 5947 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5948 break;
5949 case OPC_TGE:
5950 case OPC_TGEI:
cdc0faa6 5951 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5952 break;
5953 case OPC_TGEU:
5954 case OPC_TGEIU:
cdc0faa6 5955 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5956 break;
5957 case OPC_TLT:
5958 case OPC_TLTI:
cdc0faa6 5959 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5960 break;
5961 case OPC_TLTU:
5962 case OPC_TLTIU:
cdc0faa6 5963 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5964 break;
5965 case OPC_TNE:
5966 case OPC_TNEI:
cdc0faa6 5967 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5968 break;
6af0bf9c 5969 }
cdc0faa6 5970 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5971 gen_set_label(l1);
5972 }
be24bb4f
TS
5973 tcg_temp_free(t0);
5974 tcg_temp_free(t1);
6af0bf9c
FB
5975}
5976
90aa39a1
SF
5977static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5978{
eeb3bba8 5979 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5980 return false;
5981 }
5982
5983#ifndef CONFIG_USER_ONLY
eeb3bba8 5984 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5985#else
5986 return true;
5987#endif
5988}
5989
356265ae 5990static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5991{
90aa39a1 5992 if (use_goto_tb(ctx, dest)) {
57fec1fe 5993 tcg_gen_goto_tb(n);
9b9e4393 5994 gen_save_pc(dest);
07ea28b4 5995 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5996 } else {
9b9e4393 5997 gen_save_pc(dest);
eeb3bba8 5998 if (ctx->base.singlestep_enabled) {
7b270ef2 5999 save_cpu_state(ctx, 0);
9c708c7f 6000 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 6001 }
7f11636d 6002 tcg_gen_lookup_and_goto_ptr();
6e256c93 6003 }
c53be334
FB
6004}
6005
6af0bf9c 6006/* Branches (before delay slot) */
71375b59
AM
6007static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6008 int insn_bytes,
6009 int rs, int rt, int32_t offset,
6010 int delayslot_size)
6af0bf9c 6011{
d077b6f7 6012 target_ulong btgt = -1;
3ad4bb2d 6013 int blink = 0;
2fdbad25 6014 int bcond_compute = 0;
1ba74fb8
AJ
6015 TCGv t0 = tcg_temp_new();
6016 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
6017
6018 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 6019#ifdef MIPS_DEBUG_DISAS
339cd2a8 6020 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 6021 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 6022#endif
9c708c7f 6023 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6024 goto out;
3ad4bb2d 6025 }
6af0bf9c 6026
6af0bf9c
FB
6027 /* Load needed operands */
6028 switch (opc) {
6029 case OPC_BEQ:
6030 case OPC_BEQL:
6031 case OPC_BNE:
6032 case OPC_BNEL:
6033 /* Compare two registers */
6034 if (rs != rt) {
6c5c1e20
TS
6035 gen_load_gpr(t0, rs);
6036 gen_load_gpr(t1, rt);
2fdbad25 6037 bcond_compute = 1;
6af0bf9c 6038 }
eeb3bba8 6039 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
6040 break;
6041 case OPC_BGEZ:
6042 case OPC_BGEZAL:
6043 case OPC_BGEZALL:
6044 case OPC_BGEZL:
6045 case OPC_BGTZ:
6046 case OPC_BGTZL:
6047 case OPC_BLEZ:
6048 case OPC_BLEZL:
6049 case OPC_BLTZ:
6050 case OPC_BLTZAL:
6051 case OPC_BLTZALL:
6052 case OPC_BLTZL:
6053 /* Compare to zero */
6054 if (rs != 0) {
6c5c1e20 6055 gen_load_gpr(t0, rs);
2fdbad25 6056 bcond_compute = 1;
6af0bf9c 6057 }
eeb3bba8 6058 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 6059 break;
e45a93e2
JL
6060 case OPC_BPOSGE32:
6061#if defined(TARGET_MIPS64)
6062 case OPC_BPOSGE64:
6063 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6064#else
6065 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6066#endif
6067 bcond_compute = 1;
eeb3bba8 6068 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 6069 break;
6af0bf9c
FB
6070 case OPC_J:
6071 case OPC_JAL:
364d4831 6072 case OPC_JALX:
6af0bf9c 6073 /* Jump to immediate */
eeb3bba8
EC
6074 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6075 (uint32_t)offset;
6af0bf9c
FB
6076 break;
6077 case OPC_JR:
6078 case OPC_JALR:
6079 /* Jump to register */
7a387fff 6080 if (offset != 0 && offset != 16) {
7480515f
AM
6081 /*
6082 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6083 * others are reserved.
6084 */
923617a3 6085 MIPS_INVAL("jump hint");
9c708c7f 6086 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6087 goto out;
6af0bf9c 6088 }
d077b6f7 6089 gen_load_gpr(btarget, rs);
6af0bf9c
FB
6090 break;
6091 default:
6092 MIPS_INVAL("branch/jump");
9c708c7f 6093 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6094 goto out;
6af0bf9c 6095 }
2fdbad25 6096 if (bcond_compute == 0) {
6af0bf9c
FB
6097 /* No condition to be computed */
6098 switch (opc) {
6099 case OPC_BEQ: /* rx == rx */
6100 case OPC_BEQL: /* rx == rx likely */
6101 case OPC_BGEZ: /* 0 >= 0 */
6102 case OPC_BGEZL: /* 0 >= 0 likely */
6103 case OPC_BLEZ: /* 0 <= 0 */
6104 case OPC_BLEZL: /* 0 <= 0 likely */
6105 /* Always take */
4ad40f36 6106 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6107 break;
6108 case OPC_BGEZAL: /* 0 >= 0 */
6109 case OPC_BGEZALL: /* 0 >= 0 likely */
6110 /* Always take and link */
6111 blink = 31;
4ad40f36 6112 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6113 break;
6114 case OPC_BNE: /* rx != rx */
6115 case OPC_BGTZ: /* 0 > 0 */
6116 case OPC_BLTZ: /* 0 < 0 */
ead9360e 6117 /* Treat as NOP. */
6c5c1e20 6118 goto out;
eeef26cd 6119 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
6120 /*
6121 * Handle as an unconditional branch to get correct delay
6122 * slot checking.
6123 */
3c824109 6124 blink = 31;
eeb3bba8 6125 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 6126 ctx->hflags |= MIPS_HFLAG_B;
3c824109 6127 break;
eeef26cd 6128 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 6129 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 6130 /* Skip the instruction in the delay slot */
eeb3bba8 6131 ctx->base.pc_next += 4;
6c5c1e20 6132 goto out;
6af0bf9c
FB
6133 case OPC_BNEL: /* rx != rx likely */
6134 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
6135 case OPC_BLTZL: /* 0 < 0 likely */
6136 /* Skip the instruction in the delay slot */
eeb3bba8 6137 ctx->base.pc_next += 4;
6c5c1e20 6138 goto out;
6af0bf9c 6139 case OPC_J:
4ad40f36 6140 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 6141 break;
364d4831
NF
6142 case OPC_JALX:
6143 ctx->hflags |= MIPS_HFLAG_BX;
6144 /* Fallthrough */
6af0bf9c
FB
6145 case OPC_JAL:
6146 blink = 31;
4ad40f36 6147 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6148 break;
6149 case OPC_JR:
4ad40f36 6150 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6151 break;
6152 case OPC_JALR:
6153 blink = rt;
4ad40f36 6154 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6155 break;
6156 default:
6157 MIPS_INVAL("branch/jump");
9c708c7f 6158 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6159 goto out;
6af0bf9c
FB
6160 }
6161 } else {
6162 switch (opc) {
6163 case OPC_BEQ:
e68dd28f 6164 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6165 goto not_likely;
6166 case OPC_BEQL:
e68dd28f 6167 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6168 goto likely;
6169 case OPC_BNE:
e68dd28f 6170 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6171 goto not_likely;
6172 case OPC_BNEL:
e68dd28f 6173 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6174 goto likely;
6175 case OPC_BGEZ:
e68dd28f 6176 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6177 goto not_likely;
6178 case OPC_BGEZL:
e68dd28f 6179 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6180 goto likely;
6181 case OPC_BGEZAL:
e68dd28f 6182 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6183 blink = 31;
6184 goto not_likely;
6185 case OPC_BGEZALL:
e68dd28f 6186 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6187 blink = 31;
6af0bf9c
FB
6188 goto likely;
6189 case OPC_BGTZ:
e68dd28f 6190 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6191 goto not_likely;
6192 case OPC_BGTZL:
e68dd28f 6193 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6194 goto likely;
6195 case OPC_BLEZ:
e68dd28f 6196 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6197 goto not_likely;
6198 case OPC_BLEZL:
e68dd28f 6199 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6200 goto likely;
6201 case OPC_BLTZ:
e68dd28f 6202 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6203 goto not_likely;
6204 case OPC_BLTZL:
e68dd28f 6205 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6206 goto likely;
e45a93e2
JL
6207 case OPC_BPOSGE32:
6208 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6209 goto not_likely;
6210#if defined(TARGET_MIPS64)
6211 case OPC_BPOSGE64:
6212 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6213 goto not_likely;
6214#endif
6af0bf9c 6215 case OPC_BLTZAL:
e68dd28f 6216 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6217 blink = 31;
6af0bf9c 6218 not_likely:
4ad40f36 6219 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6220 break;
6221 case OPC_BLTZALL:
e68dd28f 6222 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6223 blink = 31;
6af0bf9c 6224 likely:
4ad40f36 6225 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6226 break;
c53f4a62
TS
6227 default:
6228 MIPS_INVAL("conditional branch/jump");
9c708c7f 6229 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6230 goto out;
6af0bf9c 6231 }
6af0bf9c 6232 }
9b9e4393 6233
d077b6f7 6234 ctx->btarget = btgt;
b231c103
YK
6235
6236 switch (delayslot_size) {
6237 case 2:
6238 ctx->hflags |= MIPS_HFLAG_BDS16;
6239 break;
6240 case 4:
6241 ctx->hflags |= MIPS_HFLAG_BDS32;
6242 break;
6243 }
6244
6af0bf9c 6245 if (blink > 0) {
b231c103 6246 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6247 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6248
eeb3bba8
EC
6249 tcg_gen_movi_tl(cpu_gpr[blink],
6250 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6251 }
6c5c1e20
TS
6252
6253 out:
1f8929d2 6254 if (insn_bytes == 2) {
364d4831 6255 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 6256 }
6c5c1e20
TS
6257 tcg_temp_free(t0);
6258 tcg_temp_free(t1);
6af0bf9c
FB
6259}
6260
764371d2
SM
6261
6262/* nanoMIPS Branches */
6263static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6264 int insn_bytes,
6265 int rs, int rt, int32_t offset)
6266{
6267 target_ulong btgt = -1;
6268 int bcond_compute = 0;
6269 TCGv t0 = tcg_temp_new();
6270 TCGv t1 = tcg_temp_new();
6271
6272 /* Load needed operands */
6273 switch (opc) {
6274 case OPC_BEQ:
6275 case OPC_BNE:
6276 /* Compare two registers */
6277 if (rs != rt) {
6278 gen_load_gpr(t0, rs);
6279 gen_load_gpr(t1, rt);
6280 bcond_compute = 1;
6281 }
6282 btgt = ctx->base.pc_next + insn_bytes + offset;
6283 break;
6284 case OPC_BGEZAL:
6285 /* Compare to zero */
6286 if (rs != 0) {
6287 gen_load_gpr(t0, rs);
6288 bcond_compute = 1;
6289 }
6290 btgt = ctx->base.pc_next + insn_bytes + offset;
6291 break;
6292 case OPC_BPOSGE32:
6293 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6294 bcond_compute = 1;
6295 btgt = ctx->base.pc_next + insn_bytes + offset;
6296 break;
6297 case OPC_JR:
6298 case OPC_JALR:
6299 /* Jump to register */
6300 if (offset != 0 && offset != 16) {
7480515f
AM
6301 /*
6302 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6303 * others are reserved.
6304 */
764371d2
SM
6305 MIPS_INVAL("jump hint");
6306 generate_exception_end(ctx, EXCP_RI);
6307 goto out;
6308 }
6309 gen_load_gpr(btarget, rs);
6310 break;
6311 default:
6312 MIPS_INVAL("branch/jump");
6313 generate_exception_end(ctx, EXCP_RI);
6314 goto out;
6315 }
6316 if (bcond_compute == 0) {
6317 /* No condition to be computed */
6318 switch (opc) {
6319 case OPC_BEQ: /* rx == rx */
6320 /* Always take */
6321 ctx->hflags |= MIPS_HFLAG_B;
6322 break;
6323 case OPC_BGEZAL: /* 0 >= 0 */
6324 /* Always take and link */
6325 tcg_gen_movi_tl(cpu_gpr[31],
6326 ctx->base.pc_next + insn_bytes);
6327 ctx->hflags |= MIPS_HFLAG_B;
6328 break;
6329 case OPC_BNE: /* rx != rx */
6330 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6331 /* Skip the instruction in the delay slot */
6332 ctx->base.pc_next += 4;
6333 goto out;
6334 case OPC_JR:
6335 ctx->hflags |= MIPS_HFLAG_BR;
6336 break;
6337 case OPC_JALR:
6338 if (rt > 0) {
6339 tcg_gen_movi_tl(cpu_gpr[rt],
6340 ctx->base.pc_next + insn_bytes);
6341 }
6342 ctx->hflags |= MIPS_HFLAG_BR;
6343 break;
6344 default:
6345 MIPS_INVAL("branch/jump");
6346 generate_exception_end(ctx, EXCP_RI);
6347 goto out;
6348 }
6349 } else {
6350 switch (opc) {
6351 case OPC_BEQ:
6352 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6353 goto not_likely;
6354 case OPC_BNE:
6355 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6356 goto not_likely;
6357 case OPC_BGEZAL:
6358 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6359 tcg_gen_movi_tl(cpu_gpr[31],
6360 ctx->base.pc_next + insn_bytes);
6361 goto not_likely;
6362 case OPC_BPOSGE32:
6363 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6364 not_likely:
6365 ctx->hflags |= MIPS_HFLAG_BC;
6366 break;
6367 default:
6368 MIPS_INVAL("conditional branch/jump");
6369 generate_exception_end(ctx, EXCP_RI);
6370 goto out;
6371 }
6372 }
6373
6374 ctx->btarget = btgt;
6375
6376 out:
6377 if (insn_bytes == 2) {
6378 ctx->hflags |= MIPS_HFLAG_B16;
6379 }
6380 tcg_temp_free(t0);
6381 tcg_temp_free(t1);
6382}
6383
6384
7a387fff 6385/* special3 bitfield operations */
235785e8
AM
6386static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6387 int rs, int lsb, int msb)
7a387fff 6388{
a7812ae4
PB
6389 TCGv t0 = tcg_temp_new();
6390 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6391
6392 gen_load_gpr(t1, rs);
7a387fff
TS
6393 switch (opc) {
6394 case OPC_EXT:
b7f26e52 6395 if (lsb + msb > 31) {
7a387fff 6396 goto fail;
b7f26e52 6397 }
505ad7c2 6398 if (msb != 31) {
6eebb7a4 6399 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6400 } else {
7480515f
AM
6401 /*
6402 * The two checks together imply that lsb == 0,
6403 * so this is a simple sign-extension.
6404 */
6eebb7a4 6405 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6406 }
7a387fff 6407 break;
c6d6dd7c 6408#if defined(TARGET_MIPS64)
7a387fff 6409 case OPC_DEXTU:
b7f26e52
RH
6410 lsb += 32;
6411 goto do_dext;
6412 case OPC_DEXTM:
6413 msb += 32;
6414 goto do_dext;
7a387fff 6415 case OPC_DEXT:
b7f26e52
RH
6416 do_dext:
6417 if (lsb + msb > 63) {
6418 goto fail;
6419 }
6eebb7a4 6420 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6421 break;
c6d6dd7c 6422#endif
7a387fff 6423 case OPC_INS:
b7f26e52 6424 if (lsb > msb) {
7a387fff 6425 goto fail;
b7f26e52 6426 }
6c5c1e20 6427 gen_load_gpr(t0, rt);
e0d002f1 6428 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6429 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6430 break;
c6d6dd7c 6431#if defined(TARGET_MIPS64)
7a387fff 6432 case OPC_DINSU:
b7f26e52
RH
6433 lsb += 32;
6434 /* FALLTHRU */
6435 case OPC_DINSM:
6436 msb += 32;
6437 /* FALLTHRU */
7a387fff 6438 case OPC_DINS:
b7f26e52
RH
6439 if (lsb > msb) {
6440 goto fail;
6441 }
6c5c1e20 6442 gen_load_gpr(t0, rt);
e0d002f1 6443 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6444 break;
c6d6dd7c 6445#endif
7a387fff
TS
6446 default:
6447fail:
6448 MIPS_INVAL("bitops");
9c708c7f 6449 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6450 tcg_temp_free(t0);
6451 tcg_temp_free(t1);
7a387fff
TS
6452 return;
6453 }
6c5c1e20
TS
6454 gen_store_gpr(t0, rt);
6455 tcg_temp_free(t0);
6456 tcg_temp_free(t1);
7a387fff
TS
6457}
6458
235785e8 6459static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 6460{
3a55fa47 6461 TCGv t0;
49bcf33c 6462
3a55fa47
AJ
6463 if (rd == 0) {
6464 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6465 return;
6466 }
6467
6468 t0 = tcg_temp_new();
6469 gen_load_gpr(t0, rt);
49bcf33c
AJ
6470 switch (op2) {
6471 case OPC_WSBH:
3a55fa47
AJ
6472 {
6473 TCGv t1 = tcg_temp_new();
06a57e5c 6474 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6475
6476 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6477 tcg_gen_and_tl(t1, t1, t2);
6478 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6479 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6480 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6481 tcg_temp_free(t2);
3a55fa47
AJ
6482 tcg_temp_free(t1);
6483 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6484 }
49bcf33c
AJ
6485 break;
6486 case OPC_SEB:
3a55fa47 6487 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6488 break;
6489 case OPC_SEH:
3a55fa47 6490 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6491 break;
6492#if defined(TARGET_MIPS64)
6493 case OPC_DSBH:
3a55fa47
AJ
6494 {
6495 TCGv t1 = tcg_temp_new();
06a57e5c 6496 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6497
6498 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6499 tcg_gen_and_tl(t1, t1, t2);
6500 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6501 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6502 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6503 tcg_temp_free(t2);
3a55fa47
AJ
6504 tcg_temp_free(t1);
6505 }
49bcf33c
AJ
6506 break;
6507 case OPC_DSHD:
3a55fa47
AJ
6508 {
6509 TCGv t1 = tcg_temp_new();
06a57e5c 6510 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6511
6512 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6513 tcg_gen_and_tl(t1, t1, t2);
6514 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6515 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6516 tcg_gen_or_tl(t0, t0, t1);
6517 tcg_gen_shri_tl(t1, t0, 32);
6518 tcg_gen_shli_tl(t0, t0, 32);
6519 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6520 tcg_temp_free(t2);
3a55fa47
AJ
6521 tcg_temp_free(t1);
6522 }
49bcf33c
AJ
6523 break;
6524#endif
6525 default:
6526 MIPS_INVAL("bsfhl");
9c708c7f 6527 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6528 tcg_temp_free(t0);
49bcf33c
AJ
6529 return;
6530 }
49bcf33c 6531 tcg_temp_free(t0);
49bcf33c
AJ
6532}
6533
1f1b4c00
YK
6534static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6535 int imm2)
6536{
6537 TCGv t0;
6538 TCGv t1;
6539 if (rd == 0) {
6540 /* Treat as NOP. */
6541 return;
6542 }
6543 t0 = tcg_temp_new();
6544 t1 = tcg_temp_new();
6545 gen_load_gpr(t0, rs);
6546 gen_load_gpr(t1, rt);
6547 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6548 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6549 if (opc == OPC_LSA) {
6550 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6551 }
6552
6553 tcg_temp_free(t1);
6554 tcg_temp_free(t0);
6555
6556 return;
6557}
6558
821f2008
JH
6559static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6560 int rt, int bits)
284b731a 6561{
1f1b4c00
YK
6562 TCGv t0;
6563 if (rd == 0) {
6564 /* Treat as NOP. */
6565 return;
6566 }
6567 t0 = tcg_temp_new();
821f2008
JH
6568 if (bits == 0 || bits == wordsz) {
6569 if (bits == 0) {
6570 gen_load_gpr(t0, rt);
6571 } else {
6572 gen_load_gpr(t0, rs);
6573 }
6574 switch (wordsz) {
6575 case 32:
51243852
MD
6576 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6577 break;
6578#if defined(TARGET_MIPS64)
821f2008 6579 case 64:
51243852
MD
6580 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6581 break;
6582#endif
6583 }
1f1b4c00
YK
6584 } else {
6585 TCGv t1 = tcg_temp_new();
821f2008 6586 gen_load_gpr(t0, rt);
1f1b4c00 6587 gen_load_gpr(t1, rs);
821f2008
JH
6588 switch (wordsz) {
6589 case 32:
1f1b4c00
YK
6590 {
6591 TCGv_i64 t2 = tcg_temp_new_i64();
6592 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6593 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6594 gen_move_low32(cpu_gpr[rd], t2);
6595 tcg_temp_free_i64(t2);
6596 }
6597 break;
284b731a 6598#if defined(TARGET_MIPS64)
821f2008
JH
6599 case 64:
6600 tcg_gen_shli_tl(t0, t0, bits);
6601 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6602 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6603 break;
284b731a 6604#endif
1f1b4c00
YK
6605 }
6606 tcg_temp_free(t1);
6607 }
6608
6609 tcg_temp_free(t0);
6610}
6611
821f2008
JH
6612static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6613 int bp)
6614{
6615 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6616}
6617
6618static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6619 int shift)
6620{
6621 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6622}
6623
1f1b4c00
YK
6624static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6625{
6626 TCGv t0;
6627 if (rd == 0) {
6628 /* Treat as NOP. */
6629 return;
6630 }
6631 t0 = tcg_temp_new();
6632 gen_load_gpr(t0, rt);
6633 switch (opc) {
6634 case OPC_BITSWAP:
6635 gen_helper_bitswap(cpu_gpr[rd], t0);
6636 break;
6637#if defined(TARGET_MIPS64)
6638 case OPC_DBITSWAP:
6639 gen_helper_dbitswap(cpu_gpr[rd], t0);
6640 break;
6641#endif
6642 }
6643 tcg_temp_free(t0);
284b731a
LA
6644}
6645
1f1b4c00
YK
6646#ifndef CONFIG_USER_ONLY
6647/* CP0 (MMU and control) */
5204ea79
LA
6648static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6649{
6650 TCGv_i64 t0 = tcg_temp_new_i64();
6651 TCGv_i64 t1 = tcg_temp_new_i64();
6652
6653 tcg_gen_ext_tl_i64(t0, arg);
6654 tcg_gen_ld_i64(t1, cpu_env, off);
6655#if defined(TARGET_MIPS64)
6656 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6657#else
6658 tcg_gen_concat32_i64(t1, t1, t0);
6659#endif
6660 tcg_gen_st_i64(t1, cpu_env, off);
6661 tcg_temp_free_i64(t1);
6662 tcg_temp_free_i64(t0);
6663}
6664
6665static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6666{
6667 TCGv_i64 t0 = tcg_temp_new_i64();
6668 TCGv_i64 t1 = tcg_temp_new_i64();
6669
6670 tcg_gen_ext_tl_i64(t0, arg);
6671 tcg_gen_ld_i64(t1, cpu_env, off);
6672 tcg_gen_concat32_i64(t1, t1, t0);
6673 tcg_gen_st_i64(t1, cpu_env, off);
6674 tcg_temp_free_i64(t1);
6675 tcg_temp_free_i64(t0);
6676}
6677
6678static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6679{
6680 TCGv_i64 t0 = tcg_temp_new_i64();
6681
6682 tcg_gen_ld_i64(t0, cpu_env, off);
6683#if defined(TARGET_MIPS64)
6684 tcg_gen_shri_i64(t0, t0, 30);
6685#else
6686 tcg_gen_shri_i64(t0, t0, 32);
6687#endif
6688 gen_move_low32(arg, t0);
6689 tcg_temp_free_i64(t0);
6690}
6691
6692static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6693{
6694 TCGv_i64 t0 = tcg_temp_new_i64();
6695
6696 tcg_gen_ld_i64(t0, cpu_env, off);
6697 tcg_gen_shri_i64(t0, t0, 32 + shift);
6698 gen_move_low32(arg, t0);
6699 tcg_temp_free_i64(t0);
6700}
6701
235785e8 6702static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 6703{
d9bea114 6704 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6705
d9bea114
AJ
6706 tcg_gen_ld_i32(t0, cpu_env, off);
6707 tcg_gen_ext_i32_tl(arg, t0);
6708 tcg_temp_free_i32(t0);
4f57689a
TS
6709}
6710
235785e8 6711static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 6712{
d9bea114
AJ
6713 tcg_gen_ld_tl(arg, cpu_env, off);
6714 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6715}
6716
235785e8 6717static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 6718{
d9bea114 6719 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6720
d9bea114
AJ
6721 tcg_gen_trunc_tl_i32(t0, arg);
6722 tcg_gen_st_i32(t0, cpu_env, off);
6723 tcg_temp_free_i32(t0);
f1aa6320
TS
6724}
6725
c98d3d79
YK
6726#define CP0_CHECK(c) \
6727 do { \
6728 if (!(c)) { \
6729 goto cp0_unimplemented; \
6730 } \
6731 } while (0)
6732
5204ea79
LA
6733static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6734{
294fc2ea 6735 const char *register_name = "invalid";
5204ea79 6736
5204ea79 6737 switch (reg) {
04992c8c 6738 case CP0_REGISTER_02:
5204ea79
LA
6739 switch (sel) {
6740 case 0:
59488dda 6741 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6742 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6743 register_name = "EntryLo0";
5204ea79
LA
6744 break;
6745 default:
c98d3d79 6746 goto cp0_unimplemented;
5204ea79
LA
6747 }
6748 break;
04992c8c 6749 case CP0_REGISTER_03:
5204ea79 6750 switch (sel) {
acd37316 6751 case CP0_REG03__ENTRYLO1:
59488dda 6752 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6753 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6754 register_name = "EntryLo1";
5204ea79
LA
6755 break;
6756 default:
c98d3d79 6757 goto cp0_unimplemented;
5204ea79
LA
6758 }
6759 break;
04992c8c 6760 case CP0_REGISTER_09:
5fb2dcd1 6761 switch (sel) {
e5a98a72 6762 case CP0_REG09__SAAR:
5fb2dcd1
YK
6763 CP0_CHECK(ctx->saar);
6764 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 6765 register_name = "SAAR";
5fb2dcd1
YK
6766 break;
6767 default:
6768 goto cp0_unimplemented;
6769 }
6770 break;
04992c8c 6771 case CP0_REGISTER_17:
5204ea79 6772 switch (sel) {
706ce142 6773 case CP0_REG17__LLADDR:
c7c7e1e9 6774 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 6775 ctx->CP0_LLAddr_shift);
294fc2ea 6776 register_name = "LLAddr";
5204ea79 6777 break;
706ce142 6778 case CP0_REG17__MAAR:
f6d4dd81
YK
6779 CP0_CHECK(ctx->mrp);
6780 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 6781 register_name = "MAAR";
f6d4dd81 6782 break;
5204ea79 6783 default:
c98d3d79 6784 goto cp0_unimplemented;
5204ea79
LA
6785 }
6786 break;
feafe82c
YK
6787 case CP0_REGISTER_19:
6788 switch (sel) {
6789 case CP0_REG19__WATCHHI0:
6790 case CP0_REG19__WATCHHI1:
6791 case CP0_REG19__WATCHHI2:
6792 case CP0_REG19__WATCHHI3:
6793 case CP0_REG19__WATCHHI4:
6794 case CP0_REG19__WATCHHI5:
6795 case CP0_REG19__WATCHHI6:
6796 case CP0_REG19__WATCHHI7:
6797 /* upper 32 bits are only available when Config5MI != 0 */
6798 CP0_CHECK(ctx->mi);
6799 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6800 register_name = "WatchHi";
6801 break;
6802 default:
6803 goto cp0_unimplemented;
6804 }
6805 break;
04992c8c 6806 case CP0_REGISTER_28:
5204ea79
LA
6807 switch (sel) {
6808 case 0:
6809 case 2:
6810 case 4:
6811 case 6:
6812 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 6813 register_name = "TagLo";
5204ea79
LA
6814 break;
6815 default:
c98d3d79 6816 goto cp0_unimplemented;
5204ea79
LA
6817 }
6818 break;
6819 default:
c98d3d79 6820 goto cp0_unimplemented;
5204ea79 6821 }
294fc2ea 6822 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
6823 return;
6824
c98d3d79 6825cp0_unimplemented:
294fc2ea
AM
6826 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6827 register_name, reg, sel);
5204ea79
LA
6828 tcg_gen_movi_tl(arg, 0);
6829}
6830
6831static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6832{
294fc2ea 6833 const char *register_name = "invalid";
5204ea79
LA
6834 uint64_t mask = ctx->PAMask >> 36;
6835
5204ea79 6836 switch (reg) {
04992c8c 6837 case CP0_REGISTER_02:
5204ea79
LA
6838 switch (sel) {
6839 case 0:
59488dda 6840 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6841 tcg_gen_andi_tl(arg, arg, mask);
6842 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6843 register_name = "EntryLo0";
5204ea79
LA
6844 break;
6845 default:
c98d3d79 6846 goto cp0_unimplemented;
5204ea79
LA
6847 }
6848 break;
04992c8c 6849 case CP0_REGISTER_03:
5204ea79 6850 switch (sel) {
acd37316 6851 case CP0_REG03__ENTRYLO1:
59488dda 6852 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6853 tcg_gen_andi_tl(arg, arg, mask);
6854 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6855 register_name = "EntryLo1";
5204ea79
LA
6856 break;
6857 default:
c98d3d79 6858 goto cp0_unimplemented;
5204ea79
LA
6859 }
6860 break;
04992c8c 6861 case CP0_REGISTER_09:
5fb2dcd1 6862 switch (sel) {
e5a98a72 6863 case CP0_REG09__SAAR:
5fb2dcd1
YK
6864 CP0_CHECK(ctx->saar);
6865 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 6866 register_name = "SAAR";
5fb2dcd1
YK
6867 break;
6868 default:
6869 goto cp0_unimplemented;
6870 }
ab8c3410 6871 break;
04992c8c 6872 case CP0_REGISTER_17:
5204ea79 6873 switch (sel) {
706ce142 6874 case CP0_REG17__LLADDR:
7480515f
AM
6875 /*
6876 * LLAddr is read-only (the only exception is bit 0 if LLB is
6877 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6878 * relevant for modern MIPS cores supporting MTHC0, therefore
6879 * treating MTHC0 to LLAddr as NOP.
6880 */
294fc2ea 6881 register_name = "LLAddr";
5204ea79 6882 break;
706ce142 6883 case CP0_REG17__MAAR:
f6d4dd81
YK
6884 CP0_CHECK(ctx->mrp);
6885 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 6886 register_name = "MAAR";
f6d4dd81 6887 break;
5204ea79 6888 default:
c98d3d79 6889 goto cp0_unimplemented;
5204ea79
LA
6890 }
6891 break;
feafe82c
YK
6892 case CP0_REGISTER_19:
6893 switch (sel) {
6894 case CP0_REG19__WATCHHI0:
6895 case CP0_REG19__WATCHHI1:
6896 case CP0_REG19__WATCHHI2:
6897 case CP0_REG19__WATCHHI3:
6898 case CP0_REG19__WATCHHI4:
6899 case CP0_REG19__WATCHHI5:
6900 case CP0_REG19__WATCHHI6:
6901 case CP0_REG19__WATCHHI7:
6902 /* upper 32 bits are only available when Config5MI != 0 */
6903 CP0_CHECK(ctx->mi);
6904 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6905 register_name = "WatchHi";
6906 break;
6907 default:
6908 goto cp0_unimplemented;
6909 }
6910 break;
04992c8c 6911 case CP0_REGISTER_28:
5204ea79
LA
6912 switch (sel) {
6913 case 0:
6914 case 2:
6915 case 4:
6916 case 6:
6917 tcg_gen_andi_tl(arg, arg, mask);
6918 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 6919 register_name = "TagLo";
5204ea79
LA
6920 break;
6921 default:
c98d3d79 6922 goto cp0_unimplemented;
5204ea79
LA
6923 }
6924 break;
6925 default:
c98d3d79 6926 goto cp0_unimplemented;
5204ea79 6927 }
294fc2ea 6928 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 6929
c98d3d79 6930cp0_unimplemented:
294fc2ea
AM
6931 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6932 register_name, reg, sel);
5204ea79
LA
6933}
6934
e98c0d17
LA
6935static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6936{
6937 if (ctx->insn_flags & ISA_MIPS32R6) {
6938 tcg_gen_movi_tl(arg, 0);
6939 } else {
6940 tcg_gen_movi_tl(arg, ~0);
6941 }
6942}
6943
d75c135e 6944static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6945{
294fc2ea 6946 const char *register_name = "invalid";
873eb012 6947
1f8929d2 6948 if (sel != 0) {
d75c135e 6949 check_insn(ctx, ISA_MIPS32);
1f8929d2 6950 }
e189e748 6951
873eb012 6952 switch (reg) {
04992c8c 6953 case CP0_REGISTER_00:
7a387fff 6954 switch (sel) {
1b142da5 6955 case CP0_REG00__INDEX:
7db13fae 6956 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6957 register_name = "Index";
7a387fff 6958 break;
1b142da5 6959 case CP0_REG00__MVPCONTROL:
f31b035a 6960 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6961 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 6962 register_name = "MVPControl";
ead9360e 6963 break;
1b142da5 6964 case CP0_REG00__MVPCONF0:
f31b035a 6965 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6966 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 6967 register_name = "MVPConf0";
ead9360e 6968 break;
1b142da5 6969 case CP0_REG00__MVPCONF1:
f31b035a 6970 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6971 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 6972 register_name = "MVPConf1";
ead9360e 6973 break;
1b142da5 6974 case CP0_REG00__VPCONTROL:
01bc435b
YK
6975 CP0_CHECK(ctx->vp);
6976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 6977 register_name = "VPControl";
01bc435b 6978 break;
7a387fff 6979 default:
f31b035a 6980 goto cp0_unimplemented;
7a387fff 6981 }
873eb012 6982 break;
04992c8c 6983 case CP0_REGISTER_01:
7a387fff 6984 switch (sel) {
30deb460 6985 case CP0_REG01__RANDOM:
f31b035a 6986 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6987 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6988 register_name = "Random";
2423f660 6989 break;
30deb460 6990 case CP0_REG01__VPECONTROL:
f31b035a 6991 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6993 register_name = "VPEControl";
ead9360e 6994 break;
30deb460 6995 case CP0_REG01__VPECONF0:
f31b035a 6996 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6998 register_name = "VPEConf0";
ead9360e 6999 break;
30deb460 7000 case CP0_REG01__VPECONF1:
f31b035a 7001 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 7003 register_name = "VPEConf1";
ead9360e 7004 break;
30deb460 7005 case CP0_REG01__YQMASK:
f31b035a 7006 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7007 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 7008 register_name = "YQMask";
ead9360e 7009 break;
30deb460 7010 case CP0_REG01__VPESCHEDULE:
f31b035a 7011 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7012 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7013 register_name = "VPESchedule";
ead9360e 7014 break;
30deb460 7015 case CP0_REG01__VPESCHEFBACK:
f31b035a 7016 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7017 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7018 register_name = "VPEScheFBack";
ead9360e 7019 break;
30deb460 7020 case CP0_REG01__VPEOPT:
f31b035a 7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 7023 register_name = "VPEOpt";
ead9360e 7024 break;
7a387fff 7025 default:
f31b035a 7026 goto cp0_unimplemented;
7a387fff 7027 }
873eb012 7028 break;
04992c8c 7029 case CP0_REGISTER_02:
7a387fff 7030 switch (sel) {
6d27d5bd 7031 case CP0_REG02__ENTRYLO0:
284b731a
LA
7032 {
7033 TCGv_i64 tmp = tcg_temp_new_i64();
7034 tcg_gen_ld_i64(tmp, cpu_env,
7035 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 7036#if defined(TARGET_MIPS64)
284b731a
LA
7037 if (ctx->rxi) {
7038 /* Move RI/XI fields to bits 31:30 */
7039 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7040 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7041 }
7207c7f9 7042#endif
284b731a
LA
7043 gen_move_low32(arg, tmp);
7044 tcg_temp_free_i64(tmp);
7045 }
294fc2ea 7046 register_name = "EntryLo0";
2423f660 7047 break;
6d27d5bd 7048 case CP0_REG02__TCSTATUS:
f31b035a 7049 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7050 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 7051 register_name = "TCStatus";
ead9360e 7052 break;
6d27d5bd 7053 case CP0_REG02__TCBIND:
f31b035a 7054 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7055 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 7056 register_name = "TCBind";
ead9360e 7057 break;
6d27d5bd 7058 case CP0_REG02__TCRESTART:
f31b035a 7059 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7060 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 7061 register_name = "TCRestart";
ead9360e 7062 break;
6d27d5bd 7063 case CP0_REG02__TCHALT:
f31b035a 7064 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7065 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 7066 register_name = "TCHalt";
ead9360e 7067 break;
6d27d5bd 7068 case CP0_REG02__TCCONTEXT:
f31b035a 7069 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7070 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 7071 register_name = "TCContext";
ead9360e 7072 break;
6d27d5bd 7073 case CP0_REG02__TCSCHEDULE:
f31b035a 7074 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7075 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 7076 register_name = "TCSchedule";
ead9360e 7077 break;
6d27d5bd 7078 case CP0_REG02__TCSCHEFBACK:
f31b035a 7079 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7080 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 7081 register_name = "TCScheFBack";
ead9360e 7082 break;
7a387fff 7083 default:
f31b035a 7084 goto cp0_unimplemented;
7a387fff 7085 }
873eb012 7086 break;
04992c8c 7087 case CP0_REGISTER_03:
7a387fff 7088 switch (sel) {
acd37316 7089 case CP0_REG03__ENTRYLO1:
284b731a
LA
7090 {
7091 TCGv_i64 tmp = tcg_temp_new_i64();
7092 tcg_gen_ld_i64(tmp, cpu_env,
7093 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 7094#if defined(TARGET_MIPS64)
284b731a
LA
7095 if (ctx->rxi) {
7096 /* Move RI/XI fields to bits 31:30 */
7097 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7098 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7099 }
7207c7f9 7100#endif
284b731a
LA
7101 gen_move_low32(arg, tmp);
7102 tcg_temp_free_i64(tmp);
7103 }
294fc2ea 7104 register_name = "EntryLo1";
2423f660 7105 break;
acd37316 7106 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7107 CP0_CHECK(ctx->vp);
7108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7109 register_name = "GlobalNumber";
01bc435b 7110 break;
7a387fff 7111 default:
f31b035a 7112 goto cp0_unimplemented;
1579a72e 7113 }
873eb012 7114 break;
04992c8c 7115 case CP0_REGISTER_04:
7a387fff 7116 switch (sel) {
020fe379 7117 case CP0_REG04__CONTEXT:
7db13fae 7118 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 7119 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7120 register_name = "Context";
2423f660 7121 break;
020fe379
AM
7122 case CP0_REG04__CONTEXTCONFIG:
7123 /* SmartMIPS ASE */
7124 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 7125 register_name = "ContextConfig";
f31b035a 7126 goto cp0_unimplemented;
020fe379 7127 case CP0_REG04__USERLOCAL:
f31b035a 7128 CP0_CHECK(ctx->ulri);
e40df9a8
JH
7129 tcg_gen_ld_tl(arg, cpu_env,
7130 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7131 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7132 register_name = "UserLocal";
d279279e 7133 break;
7a387fff 7134 default:
f31b035a 7135 goto cp0_unimplemented;
1579a72e 7136 }
873eb012 7137 break;
04992c8c 7138 case CP0_REGISTER_05:
7a387fff 7139 switch (sel) {
a1e76353 7140 case CP0_REG05__PAGEMASK:
7db13fae 7141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7142 register_name = "PageMask";
2423f660 7143 break;
a1e76353 7144 case CP0_REG05__PAGEGRAIN:
d75c135e 7145 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7147 register_name = "PageGrain";
2423f660 7148 break;
a1e76353 7149 case CP0_REG05__SEGCTL0:
cec56a73
JH
7150 CP0_CHECK(ctx->sc);
7151 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7152 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7153 register_name = "SegCtl0";
cec56a73 7154 break;
a1e76353 7155 case CP0_REG05__SEGCTL1:
cec56a73
JH
7156 CP0_CHECK(ctx->sc);
7157 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7158 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7159 register_name = "SegCtl1";
cec56a73 7160 break;
a1e76353 7161 case CP0_REG05__SEGCTL2:
cec56a73
JH
7162 CP0_CHECK(ctx->sc);
7163 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7164 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7165 register_name = "SegCtl2";
cec56a73 7166 break;
a1e76353 7167 case CP0_REG05__PWBASE:
5e31fdd5
YK
7168 check_pw(ctx);
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7170 register_name = "PWBase";
5e31fdd5 7171 break;
a1e76353 7172 case CP0_REG05__PWFIELD:
fa75ad14
YK
7173 check_pw(ctx);
7174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7175 register_name = "PWField";
fa75ad14 7176 break;
a1e76353 7177 case CP0_REG05__PWSIZE:
20b28ebc
YK
7178 check_pw(ctx);
7179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7180 register_name = "PWSize";
20b28ebc 7181 break;
7a387fff 7182 default:
f31b035a 7183 goto cp0_unimplemented;
1579a72e 7184 }
873eb012 7185 break;
04992c8c 7186 case CP0_REGISTER_06:
7a387fff 7187 switch (sel) {
9023594b 7188 case CP0_REG06__WIRED:
7db13fae 7189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7190 register_name = "Wired";
2423f660 7191 break;
9023594b 7192 case CP0_REG06__SRSCONF0:
d75c135e 7193 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7195 register_name = "SRSConf0";
ead9360e 7196 break;
9023594b 7197 case CP0_REG06__SRSCONF1:
d75c135e 7198 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7200 register_name = "SRSConf1";
ead9360e 7201 break;
9023594b 7202 case CP0_REG06__SRSCONF2:
d75c135e 7203 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7205 register_name = "SRSConf2";
ead9360e 7206 break;
9023594b 7207 case CP0_REG06__SRSCONF3:
d75c135e 7208 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7210 register_name = "SRSConf3";
ead9360e 7211 break;
9023594b 7212 case CP0_REG06__SRSCONF4:
d75c135e 7213 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7215 register_name = "SRSConf4";
ead9360e 7216 break;
9023594b 7217 case CP0_REG06__PWCTL:
103be64c
YK
7218 check_pw(ctx);
7219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7220 register_name = "PWCtl";
103be64c 7221 break;
7a387fff 7222 default:
f31b035a 7223 goto cp0_unimplemented;
1579a72e 7224 }
873eb012 7225 break;
04992c8c 7226 case CP0_REGISTER_07:
7a387fff 7227 switch (sel) {
143a9875 7228 case CP0_REG07__HWRENA:
d75c135e 7229 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7230 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7231 register_name = "HWREna";
2423f660 7232 break;
7a387fff 7233 default:
f31b035a 7234 goto cp0_unimplemented;
1579a72e 7235 }
8c0fdd85 7236 break;
04992c8c 7237 case CP0_REGISTER_08:
7a387fff 7238 switch (sel) {
67d167d2 7239 case CP0_REG08__BADVADDR:
7db13fae 7240 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7241 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7242 register_name = "BadVAddr";
2423f660 7243 break;
67d167d2 7244 case CP0_REG08__BADINSTR:
f31b035a
LA
7245 CP0_CHECK(ctx->bi);
7246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7247 register_name = "BadInstr";
aea14095 7248 break;
67d167d2 7249 case CP0_REG08__BADINSTRP:
f31b035a
LA
7250 CP0_CHECK(ctx->bp);
7251 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7252 register_name = "BadInstrP";
aea14095 7253 break;
67d167d2 7254 case CP0_REG08__BADINSTRX:
25beba9b
SM
7255 CP0_CHECK(ctx->bi);
7256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7257 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7258 register_name = "BadInstrX";
25beba9b 7259 break;
05aa7e93 7260 default:
f31b035a 7261 goto cp0_unimplemented;
aea14095 7262 }
873eb012 7263 break;
04992c8c 7264 case CP0_REGISTER_09:
7a387fff 7265 switch (sel) {
e5a98a72 7266 case CP0_REG09__COUNT:
2e70f6ef 7267 /* Mark as an IO operation because we read the time. */
eeb3bba8 7268 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7269 gen_io_start();
7d37435b 7270 }
895c2d04 7271 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7272 /*
7273 * Break the TB to be able to take timer interrupts immediately
7274 * after reading count. DISAS_STOP isn't sufficient, we need to
7275 * ensure we break completely out of translated code.
7276 */
eeb3bba8
EC
7277 gen_save_pc(ctx->base.pc_next + 4);
7278 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7279 register_name = "Count";
2423f660 7280 break;
e5a98a72 7281 case CP0_REG09__SAARI:
5fb2dcd1
YK
7282 CP0_CHECK(ctx->saar);
7283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7284 register_name = "SAARI";
5fb2dcd1 7285 break;
e5a98a72 7286 case CP0_REG09__SAAR:
5fb2dcd1
YK
7287 CP0_CHECK(ctx->saar);
7288 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7289 register_name = "SAAR";
5fb2dcd1 7290 break;
7a387fff 7291 default:
f31b035a 7292 goto cp0_unimplemented;
2423f660 7293 }
873eb012 7294 break;
04992c8c 7295 case CP0_REGISTER_10:
7a387fff 7296 switch (sel) {
860ffef0 7297 case CP0_REG10__ENTRYHI:
7db13fae 7298 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7299 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7300 register_name = "EntryHi";
2423f660 7301 break;
7a387fff 7302 default:
f31b035a 7303 goto cp0_unimplemented;
1579a72e 7304 }
873eb012 7305 break;
04992c8c 7306 case CP0_REGISTER_11:
7a387fff 7307 switch (sel) {
f5f3834f 7308 case CP0_REG11__COMPARE:
7db13fae 7309 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7310 register_name = "Compare";
2423f660
TS
7311 break;
7312 /* 6,7 are implementation dependent */
7a387fff 7313 default:
f31b035a 7314 goto cp0_unimplemented;
2423f660 7315 }
873eb012 7316 break;
04992c8c 7317 case CP0_REGISTER_12:
7a387fff 7318 switch (sel) {
2b084867 7319 case CP0_REG12__STATUS:
7db13fae 7320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7321 register_name = "Status";
2423f660 7322 break;
2b084867 7323 case CP0_REG12__INTCTL:
d75c135e 7324 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7326 register_name = "IntCtl";
2423f660 7327 break;
2b084867 7328 case CP0_REG12__SRSCTL:
d75c135e 7329 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7331 register_name = "SRSCtl";
2423f660 7332 break;
2b084867 7333 case CP0_REG12__SRSMAP:
d75c135e 7334 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7336 register_name = "SRSMap";
fd88b6ab 7337 break;
7a387fff 7338 default:
f31b035a 7339 goto cp0_unimplemented;
7a387fff 7340 }
873eb012 7341 break;
04992c8c 7342 case CP0_REGISTER_13:
7a387fff 7343 switch (sel) {
e3c7559d 7344 case CP0_REG13__CAUSE:
7db13fae 7345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7346 register_name = "Cause";
2423f660 7347 break;
7a387fff 7348 default:
f31b035a 7349 goto cp0_unimplemented;
7a387fff 7350 }
873eb012 7351 break;
04992c8c 7352 case CP0_REGISTER_14:
7a387fff 7353 switch (sel) {
35e4b54d 7354 case CP0_REG14__EPC:
7db13fae 7355 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7356 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7357 register_name = "EPC";
2423f660 7358 break;
7a387fff 7359 default:
f31b035a 7360 goto cp0_unimplemented;
1579a72e 7361 }
873eb012 7362 break;
04992c8c 7363 case CP0_REGISTER_15:
7a387fff 7364 switch (sel) {
4466cd49 7365 case CP0_REG15__PRID:
7db13fae 7366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7367 register_name = "PRid";
2423f660 7368 break;
4466cd49 7369 case CP0_REG15__EBASE:
d75c135e 7370 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
7371 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7372 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7373 register_name = "EBase";
2423f660 7374 break;
4466cd49 7375 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
7376 check_insn(ctx, ISA_MIPS32R2);
7377 CP0_CHECK(ctx->cmgcr);
7378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7379 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7380 register_name = "CMGCRBase";
c870e3f5 7381 break;
7a387fff 7382 default:
f31b035a 7383 goto cp0_unimplemented;
7a387fff 7384 }
873eb012 7385 break;
04992c8c 7386 case CP0_REGISTER_16:
873eb012 7387 switch (sel) {
433efb4c 7388 case CP0_REG16__CONFIG:
7db13fae 7389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7390 register_name = "Config";
873eb012 7391 break;
433efb4c 7392 case CP0_REG16__CONFIG1:
7db13fae 7393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7394 register_name = "Config1";
873eb012 7395 break;
433efb4c 7396 case CP0_REG16__CONFIG2:
7db13fae 7397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7398 register_name = "Config2";
7a387fff 7399 break;
433efb4c 7400 case CP0_REG16__CONFIG3:
7db13fae 7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7402 register_name = "Config3";
7a387fff 7403 break;
433efb4c 7404 case CP0_REG16__CONFIG4:
b4160af1 7405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7406 register_name = "Config4";
b4160af1 7407 break;
433efb4c 7408 case CP0_REG16__CONFIG5:
b4dd99a3 7409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7410 register_name = "Config5";
b4dd99a3 7411 break;
e397ee33 7412 /* 6,7 are implementation dependent */
433efb4c 7413 case CP0_REG16__CONFIG6:
7db13fae 7414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7415 register_name = "Config6";
e397ee33 7416 break;
433efb4c 7417 case CP0_REG16__CONFIG7:
7db13fae 7418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7419 register_name = "Config7";
e397ee33 7420 break;
873eb012 7421 default:
f31b035a 7422 goto cp0_unimplemented;
873eb012
TS
7423 }
7424 break;
04992c8c 7425 case CP0_REGISTER_17:
7a387fff 7426 switch (sel) {
706ce142 7427 case CP0_REG17__LLADDR:
895c2d04 7428 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7429 register_name = "LLAddr";
2423f660 7430 break;
706ce142 7431 case CP0_REG17__MAAR:
f6d4dd81
YK
7432 CP0_CHECK(ctx->mrp);
7433 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7434 register_name = "MAAR";
f6d4dd81 7435 break;
706ce142 7436 case CP0_REG17__MAARI:
f6d4dd81
YK
7437 CP0_CHECK(ctx->mrp);
7438 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7439 register_name = "MAARI";
f6d4dd81 7440 break;
7a387fff 7441 default:
f31b035a 7442 goto cp0_unimplemented;
7a387fff 7443 }
873eb012 7444 break;
04992c8c 7445 case CP0_REGISTER_18:
7a387fff 7446 switch (sel) {
e8dcfe82
AM
7447 case CP0_REG18__WATCHLO0:
7448 case CP0_REG18__WATCHLO1:
7449 case CP0_REG18__WATCHLO2:
7450 case CP0_REG18__WATCHLO3:
7451 case CP0_REG18__WATCHLO4:
7452 case CP0_REG18__WATCHLO5:
7453 case CP0_REG18__WATCHLO6:
7454 case CP0_REG18__WATCHLO7:
fa192d49 7455 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7456 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7457 register_name = "WatchLo";
2423f660 7458 break;
7a387fff 7459 default:
f31b035a 7460 goto cp0_unimplemented;
7a387fff 7461 }
873eb012 7462 break;
04992c8c 7463 case CP0_REGISTER_19:
7a387fff 7464 switch (sel) {
be274dc1
AM
7465 case CP0_REG19__WATCHHI0:
7466 case CP0_REG19__WATCHHI1:
7467 case CP0_REG19__WATCHHI2:
7468 case CP0_REG19__WATCHHI3:
7469 case CP0_REG19__WATCHHI4:
7470 case CP0_REG19__WATCHHI5:
7471 case CP0_REG19__WATCHHI6:
7472 case CP0_REG19__WATCHHI7:
fa192d49 7473 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7474 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7475 register_name = "WatchHi";
2423f660 7476 break;
7a387fff 7477 default:
f31b035a 7478 goto cp0_unimplemented;
7a387fff 7479 }
873eb012 7480 break;
04992c8c 7481 case CP0_REGISTER_20:
7a387fff 7482 switch (sel) {
14f92b0b 7483 case CP0_REG20__XCONTEXT:
d26bc211 7484#if defined(TARGET_MIPS64)
d75c135e 7485 check_insn(ctx, ISA_MIPS3);
7db13fae 7486 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7487 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7488 register_name = "XContext";
2423f660 7489 break;
703eaf37 7490#endif
7a387fff 7491 default:
f31b035a 7492 goto cp0_unimplemented;
7a387fff 7493 }
8c0fdd85 7494 break;
04992c8c 7495 case CP0_REGISTER_21:
7a387fff 7496 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7497 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7498 switch (sel) {
7499 case 0:
7db13fae 7500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7501 register_name = "Framemask";
2423f660 7502 break;
7a387fff 7503 default:
f31b035a 7504 goto cp0_unimplemented;
7a387fff 7505 }
8c0fdd85 7506 break;
04992c8c 7507 case CP0_REGISTER_22:
d9bea114 7508 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7509 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7510 break;
04992c8c 7511 case CP0_REGISTER_23:
7a387fff 7512 switch (sel) {
4cbf4b6d 7513 case CP0_REG23__DEBUG:
895c2d04 7514 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7515 register_name = "Debug";
2423f660 7516 break;
4cbf4b6d
AM
7517 case CP0_REG23__TRACECONTROL:
7518 /* PDtrace support */
7519 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 7520 register_name = "TraceControl";
3570d7f6 7521 goto cp0_unimplemented;
4cbf4b6d
AM
7522 case CP0_REG23__TRACECONTROL2:
7523 /* PDtrace support */
7524 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 7525 register_name = "TraceControl2";
3570d7f6 7526 goto cp0_unimplemented;
4cbf4b6d
AM
7527 case CP0_REG23__USERTRACEDATA1:
7528 /* PDtrace support */
7529 /* gen_helper_mfc0_usertracedata1(arg);*/
7530 register_name = "UserTraceData1";
3570d7f6 7531 goto cp0_unimplemented;
4cbf4b6d
AM
7532 case CP0_REG23__TRACEIBPC:
7533 /* PDtrace support */
7534 /* gen_helper_mfc0_traceibpc(arg); */
7535 register_name = "TraceIBPC";
7536 goto cp0_unimplemented;
7537 case CP0_REG23__TRACEDBPC:
7538 /* PDtrace support */
7539 /* gen_helper_mfc0_tracedbpc(arg); */
7540 register_name = "TraceDBPC";
3570d7f6 7541 goto cp0_unimplemented;
7a387fff 7542 default:
f31b035a 7543 goto cp0_unimplemented;
7a387fff 7544 }
873eb012 7545 break;
04992c8c 7546 case CP0_REGISTER_24:
7a387fff 7547 switch (sel) {
8d7b4b6e 7548 case CP0_REG24__DEPC:
f0b3f3ae 7549 /* EJTAG support */
7db13fae 7550 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7551 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7552 register_name = "DEPC";
2423f660 7553 break;
7a387fff 7554 default:
f31b035a 7555 goto cp0_unimplemented;
7a387fff 7556 }
873eb012 7557 break;
04992c8c 7558 case CP0_REGISTER_25:
7a387fff 7559 switch (sel) {
1176b328 7560 case CP0_REG25__PERFCTL0:
7db13fae 7561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7562 register_name = "Performance0";
7a387fff 7563 break;
1176b328 7564 case CP0_REG25__PERFCNT0:
7480515f 7565 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 7566 register_name = "Performance1";
3570d7f6 7567 goto cp0_unimplemented;
1176b328 7568 case CP0_REG25__PERFCTL1:
7480515f 7569 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 7570 register_name = "Performance2";
3570d7f6 7571 goto cp0_unimplemented;
1176b328 7572 case CP0_REG25__PERFCNT1:
7480515f 7573 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 7574 register_name = "Performance3";
3570d7f6 7575 goto cp0_unimplemented;
1176b328 7576 case CP0_REG25__PERFCTL2:
7480515f 7577 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 7578 register_name = "Performance4";
3570d7f6 7579 goto cp0_unimplemented;
1176b328 7580 case CP0_REG25__PERFCNT2:
7480515f 7581 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 7582 register_name = "Performance5";
3570d7f6 7583 goto cp0_unimplemented;
1176b328 7584 case CP0_REG25__PERFCTL3:
7480515f 7585 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 7586 register_name = "Performance6";
3570d7f6 7587 goto cp0_unimplemented;
1176b328 7588 case CP0_REG25__PERFCNT3:
7480515f 7589 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 7590 register_name = "Performance7";
3570d7f6 7591 goto cp0_unimplemented;
7a387fff 7592 default:
f31b035a 7593 goto cp0_unimplemented;
7a387fff 7594 }
8c0fdd85 7595 break;
04992c8c 7596 case CP0_REGISTER_26:
0d74a222 7597 switch (sel) {
dbbf08b2 7598 case CP0_REG26__ERRCTL:
0d74a222 7599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7600 register_name = "ErrCtl";
0d74a222
LA
7601 break;
7602 default:
7603 goto cp0_unimplemented;
7604 }
da80682b 7605 break;
04992c8c 7606 case CP0_REGISTER_27:
7a387fff 7607 switch (sel) {
5a10873d 7608 case CP0_REG27__CACHERR:
d9bea114 7609 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7610 register_name = "CacheErr";
2423f660 7611 break;
7a387fff 7612 default:
f31b035a 7613 goto cp0_unimplemented;
7a387fff 7614 }
8c0fdd85 7615 break;
04992c8c 7616 case CP0_REGISTER_28:
873eb012 7617 switch (sel) {
a30e2f21
AM
7618 case CP0_REG28__TAGLO:
7619 case CP0_REG28__TAGLO1:
7620 case CP0_REG28__TAGLO2:
7621 case CP0_REG28__TAGLO3:
284b731a
LA
7622 {
7623 TCGv_i64 tmp = tcg_temp_new_i64();
7624 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7625 gen_move_low32(arg, tmp);
7626 tcg_temp_free_i64(tmp);
7627 }
294fc2ea 7628 register_name = "TagLo";
873eb012 7629 break;
a30e2f21
AM
7630 case CP0_REG28__DATALO:
7631 case CP0_REG28__DATALO1:
7632 case CP0_REG28__DATALO2:
7633 case CP0_REG28__DATALO3:
7db13fae 7634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7635 register_name = "DataLo";
873eb012
TS
7636 break;
7637 default:
f31b035a 7638 goto cp0_unimplemented;
873eb012
TS
7639 }
7640 break;
04992c8c 7641 case CP0_REGISTER_29:
7a387fff 7642 switch (sel) {
af4bb6da
AM
7643 case CP0_REG29__TAGHI:
7644 case CP0_REG29__TAGHI1:
7645 case CP0_REG29__TAGHI2:
7646 case CP0_REG29__TAGHI3:
7db13fae 7647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7648 register_name = "TagHi";
7a387fff 7649 break;
af4bb6da
AM
7650 case CP0_REG29__DATAHI:
7651 case CP0_REG29__DATAHI1:
7652 case CP0_REG29__DATAHI2:
7653 case CP0_REG29__DATAHI3:
7db13fae 7654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7655 register_name = "DataHi";
7a387fff
TS
7656 break;
7657 default:
f31b035a 7658 goto cp0_unimplemented;
7a387fff 7659 }
8c0fdd85 7660 break;
04992c8c 7661 case CP0_REGISTER_30:
7a387fff 7662 switch (sel) {
4bcf121e 7663 case CP0_REG30__ERROREPC:
7db13fae 7664 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7665 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7666 register_name = "ErrorEPC";
2423f660 7667 break;
7a387fff 7668 default:
f31b035a 7669 goto cp0_unimplemented;
7a387fff 7670 }
873eb012 7671 break;
04992c8c 7672 case CP0_REGISTER_31:
7a387fff 7673 switch (sel) {
14d92efd 7674 case CP0_REG31__DESAVE:
f0b3f3ae 7675 /* EJTAG support */
7db13fae 7676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7677 register_name = "DESAVE";
2423f660 7678 break;
14d92efd
AM
7679 case CP0_REG31__KSCRATCH1:
7680 case CP0_REG31__KSCRATCH2:
7681 case CP0_REG31__KSCRATCH3:
7682 case CP0_REG31__KSCRATCH4:
7683 case CP0_REG31__KSCRATCH5:
7684 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7685 CP0_CHECK(ctx->kscrexist & (1 << sel));
7686 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 7687 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 7688 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7689 register_name = "KScratch";
e98c0d17 7690 break;
7a387fff 7691 default:
f31b035a 7692 goto cp0_unimplemented;
7a387fff 7693 }
873eb012
TS
7694 break;
7695 default:
f31b035a 7696 goto cp0_unimplemented;
873eb012 7697 }
294fc2ea 7698 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
7699 return;
7700
f31b035a 7701cp0_unimplemented:
294fc2ea
AM
7702 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7703 register_name, reg, sel);
f31b035a 7704 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7705}
7706
d75c135e 7707static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7708{
294fc2ea 7709 const char *register_name = "invalid";
7a387fff 7710
1f8929d2 7711 if (sel != 0) {
d75c135e 7712 check_insn(ctx, ISA_MIPS32);
1f8929d2 7713 }
e189e748 7714
eeb3bba8 7715 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7716 gen_io_start();
bd79255d 7717 }
2e70f6ef 7718
8c0fdd85 7719 switch (reg) {
04992c8c 7720 case CP0_REGISTER_00:
7a387fff 7721 switch (sel) {
1b142da5 7722 case CP0_REG00__INDEX:
895c2d04 7723 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 7724 register_name = "Index";
7a387fff 7725 break;
1b142da5 7726 case CP0_REG00__MVPCONTROL:
f31b035a 7727 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7728 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 7729 register_name = "MVPControl";
ead9360e 7730 break;
1b142da5 7731 case CP0_REG00__MVPCONF0:
f31b035a 7732 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7733 /* ignored */
294fc2ea 7734 register_name = "MVPConf0";
ead9360e 7735 break;
1b142da5 7736 case CP0_REG00__MVPCONF1:
f31b035a 7737 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7738 /* ignored */
294fc2ea 7739 register_name = "MVPConf1";
ead9360e 7740 break;
1b142da5 7741 case CP0_REG00__VPCONTROL:
01bc435b
YK
7742 CP0_CHECK(ctx->vp);
7743 /* ignored */
294fc2ea 7744 register_name = "VPControl";
01bc435b 7745 break;
7a387fff 7746 default:
f31b035a 7747 goto cp0_unimplemented;
7a387fff 7748 }
8c0fdd85 7749 break;
04992c8c 7750 case CP0_REGISTER_01:
7a387fff 7751 switch (sel) {
30deb460 7752 case CP0_REG01__RANDOM:
2423f660 7753 /* ignored */
294fc2ea 7754 register_name = "Random";
2423f660 7755 break;
30deb460 7756 case CP0_REG01__VPECONTROL:
f31b035a 7757 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7758 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 7759 register_name = "VPEControl";
ead9360e 7760 break;
30deb460 7761 case CP0_REG01__VPECONF0:
f31b035a 7762 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7763 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 7764 register_name = "VPEConf0";
ead9360e 7765 break;
30deb460 7766 case CP0_REG01__VPECONF1:
f31b035a 7767 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7768 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 7769 register_name = "VPEConf1";
ead9360e 7770 break;
30deb460 7771 case CP0_REG01__YQMASK:
f31b035a 7772 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7773 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 7774 register_name = "YQMask";
ead9360e 7775 break;
30deb460 7776 case CP0_REG01__VPESCHEDULE:
f31b035a 7777 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7778 tcg_gen_st_tl(arg, cpu_env,
7779 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7780 register_name = "VPESchedule";
ead9360e 7781 break;
30deb460 7782 case CP0_REG01__VPESCHEFBACK:
f31b035a 7783 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7784 tcg_gen_st_tl(arg, cpu_env,
7785 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7786 register_name = "VPEScheFBack";
ead9360e 7787 break;
30deb460 7788 case CP0_REG01__VPEOPT:
f31b035a 7789 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7790 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 7791 register_name = "VPEOpt";
ead9360e 7792 break;
7a387fff 7793 default:
f31b035a 7794 goto cp0_unimplemented;
7a387fff 7795 }
8c0fdd85 7796 break;
04992c8c 7797 case CP0_REGISTER_02:
7a387fff 7798 switch (sel) {
6d27d5bd 7799 case CP0_REG02__ENTRYLO0:
895c2d04 7800 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 7801 register_name = "EntryLo0";
2423f660 7802 break;
6d27d5bd 7803 case CP0_REG02__TCSTATUS:
f31b035a 7804 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7805 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 7806 register_name = "TCStatus";
ead9360e 7807 break;
6d27d5bd 7808 case CP0_REG02__TCBIND:
f31b035a 7809 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7810 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 7811 register_name = "TCBind";
ead9360e 7812 break;
6d27d5bd 7813 case CP0_REG02__TCRESTART:
f31b035a 7814 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7815 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 7816 register_name = "TCRestart";
ead9360e 7817 break;
6d27d5bd 7818 case CP0_REG02__TCHALT:
f31b035a 7819 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7820 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 7821 register_name = "TCHalt";
ead9360e 7822 break;
6d27d5bd 7823 case CP0_REG02__TCCONTEXT:
f31b035a 7824 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7825 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 7826 register_name = "TCContext";
ead9360e 7827 break;
6d27d5bd 7828 case CP0_REG02__TCSCHEDULE:
f31b035a 7829 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7830 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 7831 register_name = "TCSchedule";
ead9360e 7832 break;
6d27d5bd 7833 case CP0_REG02__TCSCHEFBACK:
f31b035a 7834 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7835 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 7836 register_name = "TCScheFBack";
ead9360e 7837 break;
7a387fff 7838 default:
f31b035a 7839 goto cp0_unimplemented;
7a387fff 7840 }
8c0fdd85 7841 break;
04992c8c 7842 case CP0_REGISTER_03:
7a387fff 7843 switch (sel) {
acd37316 7844 case CP0_REG03__ENTRYLO1:
895c2d04 7845 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 7846 register_name = "EntryLo1";
2423f660 7847 break;
acd37316 7848 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7849 CP0_CHECK(ctx->vp);
7850 /* ignored */
294fc2ea 7851 register_name = "GlobalNumber";
01bc435b 7852 break;
7a387fff 7853 default:
f31b035a 7854 goto cp0_unimplemented;
876d4b07 7855 }
8c0fdd85 7856 break;
04992c8c 7857 case CP0_REGISTER_04:
7a387fff 7858 switch (sel) {
020fe379 7859 case CP0_REG04__CONTEXT:
895c2d04 7860 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 7861 register_name = "Context";
2423f660 7862 break;
020fe379
AM
7863 case CP0_REG04__CONTEXTCONFIG:
7864 /* SmartMIPS ASE */
7865 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 7866 register_name = "ContextConfig";
f31b035a 7867 goto cp0_unimplemented;
020fe379 7868 case CP0_REG04__USERLOCAL:
f31b035a
LA
7869 CP0_CHECK(ctx->ulri);
7870 tcg_gen_st_tl(arg, cpu_env,
7871 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7872 register_name = "UserLocal";
d279279e 7873 break;
7a387fff 7874 default:
f31b035a 7875 goto cp0_unimplemented;
876d4b07 7876 }
8c0fdd85 7877 break;
04992c8c 7878 case CP0_REGISTER_05:
7a387fff 7879 switch (sel) {
a1e76353 7880 case CP0_REG05__PAGEMASK:
895c2d04 7881 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 7882 register_name = "PageMask";
2423f660 7883 break;
a1e76353 7884 case CP0_REG05__PAGEGRAIN:
d75c135e 7885 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7886 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 7887 register_name = "PageGrain";
eeb3bba8 7888 ctx->base.is_jmp = DISAS_STOP;
2423f660 7889 break;
a1e76353 7890 case CP0_REG05__SEGCTL0:
cec56a73
JH
7891 CP0_CHECK(ctx->sc);
7892 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 7893 register_name = "SegCtl0";
cec56a73 7894 break;
a1e76353 7895 case CP0_REG05__SEGCTL1:
cec56a73
JH
7896 CP0_CHECK(ctx->sc);
7897 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 7898 register_name = "SegCtl1";
cec56a73 7899 break;
a1e76353 7900 case CP0_REG05__SEGCTL2:
cec56a73
JH
7901 CP0_CHECK(ctx->sc);
7902 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 7903 register_name = "SegCtl2";
cec56a73 7904 break;
a1e76353 7905 case CP0_REG05__PWBASE:
5e31fdd5
YK
7906 check_pw(ctx);
7907 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7908 register_name = "PWBase";
5e31fdd5 7909 break;
a1e76353 7910 case CP0_REG05__PWFIELD:
fa75ad14
YK
7911 check_pw(ctx);
7912 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 7913 register_name = "PWField";
fa75ad14 7914 break;
a1e76353 7915 case CP0_REG05__PWSIZE:
20b28ebc
YK
7916 check_pw(ctx);
7917 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 7918 register_name = "PWSize";
20b28ebc 7919 break;
7a387fff 7920 default:
f31b035a 7921 goto cp0_unimplemented;
876d4b07 7922 }
8c0fdd85 7923 break;
04992c8c 7924 case CP0_REGISTER_06:
7a387fff 7925 switch (sel) {
9023594b 7926 case CP0_REG06__WIRED:
895c2d04 7927 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 7928 register_name = "Wired";
2423f660 7929 break;
9023594b 7930 case CP0_REG06__SRSCONF0:
d75c135e 7931 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7932 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 7933 register_name = "SRSConf0";
ead9360e 7934 break;
9023594b 7935 case CP0_REG06__SRSCONF1:
d75c135e 7936 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7937 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 7938 register_name = "SRSConf1";
ead9360e 7939 break;
9023594b 7940 case CP0_REG06__SRSCONF2:
d75c135e 7941 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7942 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 7943 register_name = "SRSConf2";
ead9360e 7944 break;
9023594b 7945 case CP0_REG06__SRSCONF3:
d75c135e 7946 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7947 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 7948 register_name = "SRSConf3";
ead9360e 7949 break;
9023594b 7950 case CP0_REG06__SRSCONF4:
d75c135e 7951 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7952 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 7953 register_name = "SRSConf4";
ead9360e 7954 break;
9023594b 7955 case CP0_REG06__PWCTL:
103be64c
YK
7956 check_pw(ctx);
7957 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 7958 register_name = "PWCtl";
103be64c 7959 break;
7a387fff 7960 default:
f31b035a 7961 goto cp0_unimplemented;
876d4b07 7962 }
8c0fdd85 7963 break;
04992c8c 7964 case CP0_REGISTER_07:
7a387fff 7965 switch (sel) {
143a9875 7966 case CP0_REG07__HWRENA:
d75c135e 7967 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7968 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7969 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7970 register_name = "HWREna";
2423f660 7971 break;
7a387fff 7972 default:
f31b035a 7973 goto cp0_unimplemented;
876d4b07 7974 }
8c0fdd85 7975 break;
04992c8c 7976 case CP0_REGISTER_08:
aea14095 7977 switch (sel) {
67d167d2 7978 case CP0_REG08__BADVADDR:
aea14095 7979 /* ignored */
294fc2ea 7980 register_name = "BadVAddr";
aea14095 7981 break;
67d167d2 7982 case CP0_REG08__BADINSTR:
aea14095 7983 /* ignored */
294fc2ea 7984 register_name = "BadInstr";
aea14095 7985 break;
67d167d2 7986 case CP0_REG08__BADINSTRP:
aea14095 7987 /* ignored */
294fc2ea 7988 register_name = "BadInstrP";
aea14095 7989 break;
67d167d2 7990 case CP0_REG08__BADINSTRX:
25beba9b 7991 /* ignored */
294fc2ea 7992 register_name = "BadInstrX";
25beba9b 7993 break;
aea14095 7994 default:
f31b035a 7995 goto cp0_unimplemented;
aea14095 7996 }
8c0fdd85 7997 break;
04992c8c 7998 case CP0_REGISTER_09:
7a387fff 7999 switch (sel) {
e5a98a72 8000 case CP0_REG09__COUNT:
895c2d04 8001 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 8002 register_name = "Count";
2423f660 8003 break;
e5a98a72 8004 case CP0_REG09__SAARI:
5fb2dcd1
YK
8005 CP0_CHECK(ctx->saar);
8006 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 8007 register_name = "SAARI";
5fb2dcd1 8008 break;
e5a98a72 8009 case CP0_REG09__SAAR:
5fb2dcd1
YK
8010 CP0_CHECK(ctx->saar);
8011 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 8012 register_name = "SAAR";
5fb2dcd1 8013 break;
7a387fff 8014 default:
f31b035a 8015 goto cp0_unimplemented;
876d4b07 8016 }
8c0fdd85 8017 break;
04992c8c 8018 case CP0_REGISTER_10:
7a387fff 8019 switch (sel) {
860ffef0 8020 case CP0_REG10__ENTRYHI:
895c2d04 8021 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 8022 register_name = "EntryHi";
2423f660 8023 break;
7a387fff 8024 default:
f31b035a 8025 goto cp0_unimplemented;
876d4b07 8026 }
8c0fdd85 8027 break;
04992c8c 8028 case CP0_REGISTER_11:
7a387fff 8029 switch (sel) {
f5f3834f 8030 case CP0_REG11__COMPARE:
895c2d04 8031 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 8032 register_name = "Compare";
2423f660
TS
8033 break;
8034 /* 6,7 are implementation dependent */
7a387fff 8035 default:
f31b035a 8036 goto cp0_unimplemented;
876d4b07 8037 }
8c0fdd85 8038 break;
04992c8c 8039 case CP0_REGISTER_12:
7a387fff 8040 switch (sel) {
2b084867 8041 case CP0_REG12__STATUS:
867abc7e 8042 save_cpu_state(ctx, 1);
895c2d04 8043 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8044 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8045 gen_save_pc(ctx->base.pc_next + 4);
8046 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8047 register_name = "Status";
2423f660 8048 break;
2b084867 8049 case CP0_REG12__INTCTL:
d75c135e 8050 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8051 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8052 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8053 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8054 register_name = "IntCtl";
2423f660 8055 break;
2b084867 8056 case CP0_REG12__SRSCTL:
d75c135e 8057 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8058 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8059 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8060 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8061 register_name = "SRSCtl";
2423f660 8062 break;
2b084867 8063 case CP0_REG12__SRSMAP:
d75c135e 8064 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8065 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8066 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8067 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8068 register_name = "SRSMap";
fd88b6ab 8069 break;
7a387fff 8070 default:
f31b035a 8071 goto cp0_unimplemented;
876d4b07 8072 }
8c0fdd85 8073 break;
04992c8c 8074 case CP0_REGISTER_13:
7a387fff 8075 switch (sel) {
e3c7559d 8076 case CP0_REG13__CAUSE:
867abc7e 8077 save_cpu_state(ctx, 1);
895c2d04 8078 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
8079 /*
8080 * Stop translation as we may have triggered an interrupt.
b28425ba 8081 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
8082 * translated code to check for pending interrupts.
8083 */
eeb3bba8
EC
8084 gen_save_pc(ctx->base.pc_next + 4);
8085 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8086 register_name = "Cause";
2423f660 8087 break;
7a387fff 8088 default:
f31b035a 8089 goto cp0_unimplemented;
876d4b07 8090 }
8c0fdd85 8091 break;
04992c8c 8092 case CP0_REGISTER_14:
7a387fff 8093 switch (sel) {
35e4b54d 8094 case CP0_REG14__EPC:
d54a299b 8095 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8096 register_name = "EPC";
2423f660 8097 break;
7a387fff 8098 default:
f31b035a 8099 goto cp0_unimplemented;
876d4b07 8100 }
8c0fdd85 8101 break;
04992c8c 8102 case CP0_REGISTER_15:
7a387fff 8103 switch (sel) {
4466cd49 8104 case CP0_REG15__PRID:
2423f660 8105 /* ignored */
294fc2ea 8106 register_name = "PRid";
2423f660 8107 break;
4466cd49 8108 case CP0_REG15__EBASE:
d75c135e 8109 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8110 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 8111 register_name = "EBase";
2423f660 8112 break;
7a387fff 8113 default:
f31b035a 8114 goto cp0_unimplemented;
1579a72e 8115 }
8c0fdd85 8116 break;
04992c8c 8117 case CP0_REGISTER_16:
8c0fdd85 8118 switch (sel) {
433efb4c 8119 case CP0_REG16__CONFIG:
895c2d04 8120 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 8121 register_name = "Config";
2423f660 8122 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8123 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8124 break;
433efb4c 8125 case CP0_REG16__CONFIG1:
e397ee33 8126 /* ignored, read only */
294fc2ea 8127 register_name = "Config1";
7a387fff 8128 break;
433efb4c 8129 case CP0_REG16__CONFIG2:
895c2d04 8130 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 8131 register_name = "Config2";
2423f660 8132 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8133 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 8134 break;
433efb4c 8135 case CP0_REG16__CONFIG3:
90f12d73 8136 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 8137 register_name = "Config3";
90f12d73 8138 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8139 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8140 break;
433efb4c 8141 case CP0_REG16__CONFIG4:
b4160af1 8142 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 8143 register_name = "Config4";
eeb3bba8 8144 ctx->base.is_jmp = DISAS_STOP;
b4160af1 8145 break;
433efb4c 8146 case CP0_REG16__CONFIG5:
b4dd99a3 8147 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8148 register_name = "Config5";
b4dd99a3 8149 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8150 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 8151 break;
e397ee33 8152 /* 6,7 are implementation dependent */
433efb4c 8153 case CP0_REG16__CONFIG6:
e397ee33 8154 /* ignored */
294fc2ea 8155 register_name = "Config6";
e397ee33 8156 break;
433efb4c 8157 case CP0_REG16__CONFIG7:
e397ee33 8158 /* ignored */
294fc2ea 8159 register_name = "Config7";
e397ee33 8160 break;
8c0fdd85 8161 default:
294fc2ea 8162 register_name = "Invalid config selector";
f31b035a 8163 goto cp0_unimplemented;
8c0fdd85
TS
8164 }
8165 break;
04992c8c 8166 case CP0_REGISTER_17:
7a387fff 8167 switch (sel) {
706ce142 8168 case CP0_REG17__LLADDR:
895c2d04 8169 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8170 register_name = "LLAddr";
2423f660 8171 break;
706ce142 8172 case CP0_REG17__MAAR:
f6d4dd81
YK
8173 CP0_CHECK(ctx->mrp);
8174 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8175 register_name = "MAAR";
f6d4dd81 8176 break;
706ce142 8177 case CP0_REG17__MAARI:
f6d4dd81
YK
8178 CP0_CHECK(ctx->mrp);
8179 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8180 register_name = "MAARI";
f6d4dd81 8181 break;
7a387fff 8182 default:
f31b035a 8183 goto cp0_unimplemented;
7a387fff 8184 }
8c0fdd85 8185 break;
04992c8c 8186 case CP0_REGISTER_18:
7a387fff 8187 switch (sel) {
e8dcfe82
AM
8188 case CP0_REG18__WATCHLO0:
8189 case CP0_REG18__WATCHLO1:
8190 case CP0_REG18__WATCHLO2:
8191 case CP0_REG18__WATCHLO3:
8192 case CP0_REG18__WATCHLO4:
8193 case CP0_REG18__WATCHLO5:
8194 case CP0_REG18__WATCHLO6:
8195 case CP0_REG18__WATCHLO7:
fa192d49 8196 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8197 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8198 register_name = "WatchLo";
2423f660 8199 break;
7a387fff 8200 default:
f31b035a 8201 goto cp0_unimplemented;
7a387fff 8202 }
8c0fdd85 8203 break;
04992c8c 8204 case CP0_REGISTER_19:
7a387fff 8205 switch (sel) {
be274dc1
AM
8206 case CP0_REG19__WATCHHI0:
8207 case CP0_REG19__WATCHHI1:
8208 case CP0_REG19__WATCHHI2:
8209 case CP0_REG19__WATCHHI3:
8210 case CP0_REG19__WATCHHI4:
8211 case CP0_REG19__WATCHHI5:
8212 case CP0_REG19__WATCHHI6:
8213 case CP0_REG19__WATCHHI7:
fa192d49 8214 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8215 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8216 register_name = "WatchHi";
2423f660 8217 break;
7a387fff 8218 default:
f31b035a 8219 goto cp0_unimplemented;
7a387fff 8220 }
8c0fdd85 8221 break;
04992c8c 8222 case CP0_REGISTER_20:
7a387fff 8223 switch (sel) {
14f92b0b 8224 case CP0_REG20__XCONTEXT:
d26bc211 8225#if defined(TARGET_MIPS64)
d75c135e 8226 check_insn(ctx, ISA_MIPS3);
895c2d04 8227 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8228 register_name = "XContext";
2423f660 8229 break;
703eaf37 8230#endif
7a387fff 8231 default:
f31b035a 8232 goto cp0_unimplemented;
7a387fff 8233 }
8c0fdd85 8234 break;
04992c8c 8235 case CP0_REGISTER_21:
7a387fff 8236 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8237 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
8238 switch (sel) {
8239 case 0:
895c2d04 8240 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8241 register_name = "Framemask";
2423f660 8242 break;
7a387fff 8243 default:
f31b035a 8244 goto cp0_unimplemented;
7a387fff
TS
8245 }
8246 break;
04992c8c 8247 case CP0_REGISTER_22:
7a387fff 8248 /* ignored */
294fc2ea 8249 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8250 break;
04992c8c 8251 case CP0_REGISTER_23:
7a387fff 8252 switch (sel) {
4cbf4b6d 8253 case CP0_REG23__DEBUG:
895c2d04 8254 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8255 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8256 gen_save_pc(ctx->base.pc_next + 4);
8257 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8258 register_name = "Debug";
2423f660 8259 break;
4cbf4b6d
AM
8260 case CP0_REG23__TRACECONTROL:
8261 /* PDtrace support */
8262 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 8263 register_name = "TraceControl";
8487327a 8264 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8265 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8266 goto cp0_unimplemented;
4cbf4b6d
AM
8267 case CP0_REG23__TRACECONTROL2:
8268 /* PDtrace support */
8269 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 8270 register_name = "TraceControl2";
8487327a 8271 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8272 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8273 goto cp0_unimplemented;
4cbf4b6d 8274 case CP0_REG23__USERTRACEDATA1:
8487327a 8275 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8276 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8277 /* PDtrace support */
8278 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 8279 register_name = "UserTraceData";
8487327a 8280 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8281 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8282 goto cp0_unimplemented;
4cbf4b6d
AM
8283 case CP0_REG23__TRACEIBPC:
8284 /* PDtrace support */
8285 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 8286 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8287 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8288 register_name = "TraceIBPC";
8289 goto cp0_unimplemented;
8290 case CP0_REG23__TRACEDBPC:
8291 /* PDtrace support */
8292 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8293 /* Stop translation as we may have switched the execution mode */
8294 ctx->base.is_jmp = DISAS_STOP;
8295 register_name = "TraceDBPC";
3570d7f6 8296 goto cp0_unimplemented;
7a387fff 8297 default:
f31b035a 8298 goto cp0_unimplemented;
7a387fff 8299 }
8c0fdd85 8300 break;
04992c8c 8301 case CP0_REGISTER_24:
7a387fff 8302 switch (sel) {
8d7b4b6e 8303 case CP0_REG24__DEPC:
f1aa6320 8304 /* EJTAG support */
d54a299b 8305 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8306 register_name = "DEPC";
2423f660 8307 break;
7a387fff 8308 default:
f31b035a 8309 goto cp0_unimplemented;
7a387fff 8310 }
8c0fdd85 8311 break;
04992c8c 8312 case CP0_REGISTER_25:
7a387fff 8313 switch (sel) {
1176b328 8314 case CP0_REG25__PERFCTL0:
895c2d04 8315 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8316 register_name = "Performance0";
2423f660 8317 break;
1176b328 8318 case CP0_REG25__PERFCNT0:
7480515f 8319 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 8320 register_name = "Performance1";
3570d7f6 8321 goto cp0_unimplemented;
1176b328 8322 case CP0_REG25__PERFCTL1:
7480515f 8323 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 8324 register_name = "Performance2";
3570d7f6 8325 goto cp0_unimplemented;
1176b328 8326 case CP0_REG25__PERFCNT1:
7480515f 8327 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 8328 register_name = "Performance3";
3570d7f6 8329 goto cp0_unimplemented;
1176b328 8330 case CP0_REG25__PERFCTL2:
7480515f 8331 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 8332 register_name = "Performance4";
3570d7f6 8333 goto cp0_unimplemented;
1176b328 8334 case CP0_REG25__PERFCNT2:
7480515f 8335 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 8336 register_name = "Performance5";
3570d7f6 8337 goto cp0_unimplemented;
1176b328 8338 case CP0_REG25__PERFCTL3:
7480515f 8339 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 8340 register_name = "Performance6";
3570d7f6 8341 goto cp0_unimplemented;
1176b328 8342 case CP0_REG25__PERFCNT3:
7480515f 8343 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 8344 register_name = "Performance7";
3570d7f6 8345 goto cp0_unimplemented;
7a387fff 8346 default:
f31b035a 8347 goto cp0_unimplemented;
7a387fff 8348 }
8c0fdd85 8349 break;
04992c8c 8350 case CP0_REGISTER_26:
0d74a222 8351 switch (sel) {
dbbf08b2 8352 case CP0_REG26__ERRCTL:
0d74a222 8353 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8354 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8355 register_name = "ErrCtl";
0d74a222
LA
8356 break;
8357 default:
8358 goto cp0_unimplemented;
8359 }
2423f660 8360 break;
04992c8c 8361 case CP0_REGISTER_27:
7a387fff 8362 switch (sel) {
5a10873d 8363 case CP0_REG27__CACHERR:
2423f660 8364 /* ignored */
294fc2ea 8365 register_name = "CacheErr";
2423f660 8366 break;
7a387fff 8367 default:
f31b035a 8368 goto cp0_unimplemented;
7a387fff 8369 }
8c0fdd85 8370 break;
04992c8c 8371 case CP0_REGISTER_28:
8c0fdd85 8372 switch (sel) {
a30e2f21
AM
8373 case CP0_REG28__TAGLO:
8374 case CP0_REG28__TAGLO1:
8375 case CP0_REG28__TAGLO2:
8376 case CP0_REG28__TAGLO3:
895c2d04 8377 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8378 register_name = "TagLo";
8c0fdd85 8379 break;
a30e2f21
AM
8380 case CP0_REG28__DATALO:
8381 case CP0_REG28__DATALO1:
8382 case CP0_REG28__DATALO2:
8383 case CP0_REG28__DATALO3:
895c2d04 8384 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8385 register_name = "DataLo";
7a387fff 8386 break;
8c0fdd85 8387 default:
f31b035a 8388 goto cp0_unimplemented;
8c0fdd85
TS
8389 }
8390 break;
04992c8c 8391 case CP0_REGISTER_29:
7a387fff 8392 switch (sel) {
af4bb6da
AM
8393 case CP0_REG29__TAGHI:
8394 case CP0_REG29__TAGHI1:
8395 case CP0_REG29__TAGHI2:
8396 case CP0_REG29__TAGHI3:
895c2d04 8397 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8398 register_name = "TagHi";
7a387fff 8399 break;
af4bb6da
AM
8400 case CP0_REG29__DATAHI:
8401 case CP0_REG29__DATAHI1:
8402 case CP0_REG29__DATAHI2:
8403 case CP0_REG29__DATAHI3:
895c2d04 8404 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8405 register_name = "DataHi";
7a387fff
TS
8406 break;
8407 default:
294fc2ea 8408 register_name = "invalid sel";
f31b035a 8409 goto cp0_unimplemented;
7a387fff 8410 }
8c0fdd85 8411 break;
04992c8c 8412 case CP0_REGISTER_30:
7a387fff 8413 switch (sel) {
4bcf121e 8414 case CP0_REG30__ERROREPC:
d54a299b 8415 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8416 register_name = "ErrorEPC";
2423f660 8417 break;
7a387fff 8418 default:
f31b035a 8419 goto cp0_unimplemented;
7a387fff 8420 }
8c0fdd85 8421 break;
04992c8c 8422 case CP0_REGISTER_31:
7a387fff 8423 switch (sel) {
14d92efd 8424 case CP0_REG31__DESAVE:
f1aa6320 8425 /* EJTAG support */
7db13fae 8426 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8427 register_name = "DESAVE";
2423f660 8428 break;
14d92efd
AM
8429 case CP0_REG31__KSCRATCH1:
8430 case CP0_REG31__KSCRATCH2:
8431 case CP0_REG31__KSCRATCH3:
8432 case CP0_REG31__KSCRATCH4:
8433 case CP0_REG31__KSCRATCH5:
8434 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8435 CP0_CHECK(ctx->kscrexist & (1 << sel));
8436 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 8437 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8438 register_name = "KScratch";
e98c0d17 8439 break;
7a387fff 8440 default:
f31b035a 8441 goto cp0_unimplemented;
7a387fff 8442 }
8c0fdd85
TS
8443 break;
8444 default:
f31b035a 8445 goto cp0_unimplemented;
8c0fdd85 8446 }
294fc2ea 8447 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8448
bf20dc07 8449 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8450 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8451 /*
8452 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8453 * translated code to check for pending interrupts.
8454 */
eeb3bba8
EC
8455 gen_save_pc(ctx->base.pc_next + 4);
8456 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8457 }
8c0fdd85
TS
8458 return;
8459
f31b035a 8460cp0_unimplemented:
294fc2ea
AM
8461 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8462 register_name, reg, sel);
8c0fdd85
TS
8463}
8464
d26bc211 8465#if defined(TARGET_MIPS64)
d75c135e 8466static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8467{
294fc2ea 8468 const char *register_name = "invalid";
9c2149c8 8469
1f8929d2 8470 if (sel != 0) {
d75c135e 8471 check_insn(ctx, ISA_MIPS64);
1f8929d2 8472 }
e189e748 8473
9c2149c8 8474 switch (reg) {
04992c8c 8475 case CP0_REGISTER_00:
9c2149c8 8476 switch (sel) {
1b142da5 8477 case CP0_REG00__INDEX:
7db13fae 8478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8479 register_name = "Index";
9c2149c8 8480 break;
1b142da5 8481 case CP0_REG00__MVPCONTROL:
f31b035a 8482 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8483 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8484 register_name = "MVPControl";
ead9360e 8485 break;
1b142da5 8486 case CP0_REG00__MVPCONF0:
f31b035a 8487 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8488 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8489 register_name = "MVPConf0";
ead9360e 8490 break;
1b142da5 8491 case CP0_REG00__MVPCONF1:
f31b035a 8492 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8493 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8494 register_name = "MVPConf1";
ead9360e 8495 break;
1b142da5 8496 case CP0_REG00__VPCONTROL:
01bc435b
YK
8497 CP0_CHECK(ctx->vp);
8498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8499 register_name = "VPControl";
01bc435b 8500 break;
9c2149c8 8501 default:
f31b035a 8502 goto cp0_unimplemented;
9c2149c8
TS
8503 }
8504 break;
04992c8c 8505 case CP0_REGISTER_01:
9c2149c8 8506 switch (sel) {
30deb460 8507 case CP0_REG01__RANDOM:
f31b035a 8508 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 8509 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8510 register_name = "Random";
2423f660 8511 break;
30deb460 8512 case CP0_REG01__VPECONTROL:
f31b035a 8513 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8515 register_name = "VPEControl";
ead9360e 8516 break;
30deb460 8517 case CP0_REG01__VPECONF0:
f31b035a 8518 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8520 register_name = "VPEConf0";
ead9360e 8521 break;
30deb460 8522 case CP0_REG01__VPECONF1:
f31b035a 8523 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 8525 register_name = "VPEConf1";
ead9360e 8526 break;
30deb460 8527 case CP0_REG01__YQMASK:
f31b035a 8528 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8529 tcg_gen_ld_tl(arg, cpu_env,
8530 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 8531 register_name = "YQMask";
ead9360e 8532 break;
30deb460 8533 case CP0_REG01__VPESCHEDULE:
f31b035a 8534 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8535 tcg_gen_ld_tl(arg, cpu_env,
8536 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8537 register_name = "VPESchedule";
ead9360e 8538 break;
30deb460 8539 case CP0_REG01__VPESCHEFBACK:
f31b035a 8540 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8541 tcg_gen_ld_tl(arg, cpu_env,
8542 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8543 register_name = "VPEScheFBack";
ead9360e 8544 break;
30deb460 8545 case CP0_REG01__VPEOPT:
f31b035a 8546 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 8548 register_name = "VPEOpt";
ead9360e 8549 break;
9c2149c8 8550 default:
f31b035a 8551 goto cp0_unimplemented;
9c2149c8
TS
8552 }
8553 break;
04992c8c 8554 case CP0_REGISTER_02:
9c2149c8 8555 switch (sel) {
6d27d5bd 8556 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
8557 tcg_gen_ld_tl(arg, cpu_env,
8558 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 8559 register_name = "EntryLo0";
2423f660 8560 break;
6d27d5bd 8561 case CP0_REG02__TCSTATUS:
f31b035a 8562 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8563 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 8564 register_name = "TCStatus";
ead9360e 8565 break;
6d27d5bd 8566 case CP0_REG02__TCBIND:
f31b035a 8567 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8568 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 8569 register_name = "TCBind";
ead9360e 8570 break;
6d27d5bd 8571 case CP0_REG02__TCRESTART:
f31b035a 8572 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8573 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 8574 register_name = "TCRestart";
ead9360e 8575 break;
6d27d5bd 8576 case CP0_REG02__TCHALT:
f31b035a 8577 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8578 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 8579 register_name = "TCHalt";
ead9360e 8580 break;
6d27d5bd 8581 case CP0_REG02__TCCONTEXT:
f31b035a 8582 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8583 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 8584 register_name = "TCContext";
ead9360e 8585 break;
6d27d5bd 8586 case CP0_REG02__TCSCHEDULE:
f31b035a 8587 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8588 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 8589 register_name = "TCSchedule";
ead9360e 8590 break;
6d27d5bd 8591 case CP0_REG02__TCSCHEFBACK:
f31b035a 8592 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8593 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 8594 register_name = "TCScheFBack";
ead9360e 8595 break;
9c2149c8 8596 default:
f31b035a 8597 goto cp0_unimplemented;
9c2149c8
TS
8598 }
8599 break;
04992c8c 8600 case CP0_REGISTER_03:
9c2149c8 8601 switch (sel) {
acd37316 8602 case CP0_REG03__ENTRYLO1:
7db13fae 8603 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 8604 register_name = "EntryLo1";
2423f660 8605 break;
acd37316 8606 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8607 CP0_CHECK(ctx->vp);
8608 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 8609 register_name = "GlobalNumber";
01bc435b 8610 break;
9c2149c8 8611 default:
f31b035a 8612 goto cp0_unimplemented;
1579a72e 8613 }
9c2149c8 8614 break;
04992c8c 8615 case CP0_REGISTER_04:
9c2149c8 8616 switch (sel) {
020fe379 8617 case CP0_REG04__CONTEXT:
7db13fae 8618 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 8619 register_name = "Context";
2423f660 8620 break;
020fe379
AM
8621 case CP0_REG04__CONTEXTCONFIG:
8622 /* SmartMIPS ASE */
8623 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 8624 register_name = "ContextConfig";
f31b035a 8625 goto cp0_unimplemented;
020fe379 8626 case CP0_REG04__USERLOCAL:
f31b035a
LA
8627 CP0_CHECK(ctx->ulri);
8628 tcg_gen_ld_tl(arg, cpu_env,
8629 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8630 register_name = "UserLocal";
d279279e 8631 break;
9c2149c8 8632 default:
f31b035a 8633 goto cp0_unimplemented;
876d4b07 8634 }
9c2149c8 8635 break;
04992c8c 8636 case CP0_REGISTER_05:
9c2149c8 8637 switch (sel) {
a1e76353 8638 case CP0_REG05__PAGEMASK:
7db13fae 8639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 8640 register_name = "PageMask";
2423f660 8641 break;
a1e76353 8642 case CP0_REG05__PAGEGRAIN:
d75c135e 8643 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 8645 register_name = "PageGrain";
2423f660 8646 break;
a1e76353 8647 case CP0_REG05__SEGCTL0:
cec56a73
JH
8648 CP0_CHECK(ctx->sc);
8649 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 8650 register_name = "SegCtl0";
cec56a73 8651 break;
a1e76353 8652 case CP0_REG05__SEGCTL1:
cec56a73
JH
8653 CP0_CHECK(ctx->sc);
8654 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 8655 register_name = "SegCtl1";
cec56a73 8656 break;
a1e76353 8657 case CP0_REG05__SEGCTL2:
cec56a73
JH
8658 CP0_CHECK(ctx->sc);
8659 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 8660 register_name = "SegCtl2";
cec56a73 8661 break;
a1e76353 8662 case CP0_REG05__PWBASE:
5e31fdd5
YK
8663 check_pw(ctx);
8664 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8665 register_name = "PWBase";
5e31fdd5 8666 break;
a1e76353 8667 case CP0_REG05__PWFIELD:
fa75ad14
YK
8668 check_pw(ctx);
8669 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 8670 register_name = "PWField";
fa75ad14 8671 break;
a1e76353 8672 case CP0_REG05__PWSIZE:
20b28ebc
YK
8673 check_pw(ctx);
8674 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 8675 register_name = "PWSize";
20b28ebc 8676 break;
9c2149c8 8677 default:
f31b035a 8678 goto cp0_unimplemented;
876d4b07 8679 }
9c2149c8 8680 break;
04992c8c 8681 case CP0_REGISTER_06:
9c2149c8 8682 switch (sel) {
9023594b 8683 case CP0_REG06__WIRED:
7db13fae 8684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 8685 register_name = "Wired";
2423f660 8686 break;
9023594b 8687 case CP0_REG06__SRSCONF0:
d75c135e 8688 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 8690 register_name = "SRSConf0";
ead9360e 8691 break;
9023594b 8692 case CP0_REG06__SRSCONF1:
d75c135e 8693 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 8695 register_name = "SRSConf1";
ead9360e 8696 break;
9023594b 8697 case CP0_REG06__SRSCONF2:
d75c135e 8698 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 8700 register_name = "SRSConf2";
ead9360e 8701 break;
9023594b 8702 case CP0_REG06__SRSCONF3:
d75c135e 8703 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 8705 register_name = "SRSConf3";
ead9360e 8706 break;
9023594b 8707 case CP0_REG06__SRSCONF4:
d75c135e 8708 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8709 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 8710 register_name = "SRSConf4";
ead9360e 8711 break;
9023594b 8712 case CP0_REG06__PWCTL:
103be64c
YK
8713 check_pw(ctx);
8714 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 8715 register_name = "PWCtl";
103be64c 8716 break;
9c2149c8 8717 default:
f31b035a 8718 goto cp0_unimplemented;
876d4b07 8719 }
9c2149c8 8720 break;
04992c8c 8721 case CP0_REGISTER_07:
9c2149c8 8722 switch (sel) {
143a9875 8723 case CP0_REG07__HWRENA:
d75c135e 8724 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 8726 register_name = "HWREna";
2423f660 8727 break;
9c2149c8 8728 default:
f31b035a 8729 goto cp0_unimplemented;
876d4b07 8730 }
9c2149c8 8731 break;
04992c8c 8732 case CP0_REGISTER_08:
9c2149c8 8733 switch (sel) {
67d167d2 8734 case CP0_REG08__BADVADDR:
7db13fae 8735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 8736 register_name = "BadVAddr";
2423f660 8737 break;
67d167d2 8738 case CP0_REG08__BADINSTR:
f31b035a
LA
8739 CP0_CHECK(ctx->bi);
8740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 8741 register_name = "BadInstr";
aea14095 8742 break;
67d167d2 8743 case CP0_REG08__BADINSTRP:
f31b035a
LA
8744 CP0_CHECK(ctx->bp);
8745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 8746 register_name = "BadInstrP";
aea14095 8747 break;
67d167d2 8748 case CP0_REG08__BADINSTRX:
25beba9b
SM
8749 CP0_CHECK(ctx->bi);
8750 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8751 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 8752 register_name = "BadInstrX";
25beba9b 8753 break;
9c2149c8 8754 default:
f31b035a 8755 goto cp0_unimplemented;
876d4b07 8756 }
9c2149c8 8757 break;
04992c8c 8758 case CP0_REGISTER_09:
9c2149c8 8759 switch (sel) {
e5a98a72 8760 case CP0_REG09__COUNT:
2e70f6ef 8761 /* Mark as an IO operation because we read the time. */
eeb3bba8 8762 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8763 gen_io_start();
bd79255d 8764 }
895c2d04 8765 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
8766 /*
8767 * Break the TB to be able to take timer interrupts immediately
8768 * after reading count. DISAS_STOP isn't sufficient, we need to
8769 * ensure we break completely out of translated code.
8770 */
eeb3bba8
EC
8771 gen_save_pc(ctx->base.pc_next + 4);
8772 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8773 register_name = "Count";
2423f660 8774 break;
e5a98a72 8775 case CP0_REG09__SAARI:
5fb2dcd1
YK
8776 CP0_CHECK(ctx->saar);
8777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 8778 register_name = "SAARI";
5fb2dcd1 8779 break;
e5a98a72 8780 case CP0_REG09__SAAR:
5fb2dcd1
YK
8781 CP0_CHECK(ctx->saar);
8782 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 8783 register_name = "SAAR";
5fb2dcd1 8784 break;
9c2149c8 8785 default:
f31b035a 8786 goto cp0_unimplemented;
876d4b07 8787 }
9c2149c8 8788 break;
04992c8c 8789 case CP0_REGISTER_10:
9c2149c8 8790 switch (sel) {
860ffef0 8791 case CP0_REG10__ENTRYHI:
7db13fae 8792 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 8793 register_name = "EntryHi";
2423f660 8794 break;
9c2149c8 8795 default:
f31b035a 8796 goto cp0_unimplemented;
876d4b07 8797 }
9c2149c8 8798 break;
04992c8c 8799 case CP0_REGISTER_11:
9c2149c8 8800 switch (sel) {
f5f3834f 8801 case CP0_REG11__COMPARE:
7db13fae 8802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 8803 register_name = "Compare";
2423f660 8804 break;
876d4b07 8805 /* 6,7 are implementation dependent */
9c2149c8 8806 default:
f31b035a 8807 goto cp0_unimplemented;
876d4b07 8808 }
9c2149c8 8809 break;
04992c8c 8810 case CP0_REGISTER_12:
9c2149c8 8811 switch (sel) {
2b084867 8812 case CP0_REG12__STATUS:
7db13fae 8813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 8814 register_name = "Status";
2423f660 8815 break;
2b084867 8816 case CP0_REG12__INTCTL:
d75c135e 8817 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8818 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 8819 register_name = "IntCtl";
2423f660 8820 break;
2b084867 8821 case CP0_REG12__SRSCTL:
d75c135e 8822 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8823 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 8824 register_name = "SRSCtl";
2423f660 8825 break;
2b084867 8826 case CP0_REG12__SRSMAP:
d75c135e 8827 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8828 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 8829 register_name = "SRSMap";
2423f660 8830 break;
9c2149c8 8831 default:
f31b035a 8832 goto cp0_unimplemented;
876d4b07 8833 }
9c2149c8 8834 break;
04992c8c 8835 case CP0_REGISTER_13:
9c2149c8 8836 switch (sel) {
e3c7559d 8837 case CP0_REG13__CAUSE:
7db13fae 8838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 8839 register_name = "Cause";
2423f660 8840 break;
9c2149c8 8841 default:
f31b035a 8842 goto cp0_unimplemented;
876d4b07 8843 }
9c2149c8 8844 break;
04992c8c 8845 case CP0_REGISTER_14:
9c2149c8 8846 switch (sel) {
35e4b54d 8847 case CP0_REG14__EPC:
7db13fae 8848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8849 register_name = "EPC";
2423f660 8850 break;
9c2149c8 8851 default:
f31b035a 8852 goto cp0_unimplemented;
876d4b07 8853 }
9c2149c8 8854 break;
04992c8c 8855 case CP0_REGISTER_15:
9c2149c8 8856 switch (sel) {
4466cd49 8857 case CP0_REG15__PRID:
7db13fae 8858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 8859 register_name = "PRid";
2423f660 8860 break;
4466cd49 8861 case CP0_REG15__EBASE:
d75c135e 8862 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8863 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 8864 register_name = "EBase";
2423f660 8865 break;
4466cd49 8866 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
8867 check_insn(ctx, ISA_MIPS32R2);
8868 CP0_CHECK(ctx->cmgcr);
8869 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 8870 register_name = "CMGCRBase";
c870e3f5 8871 break;
9c2149c8 8872 default:
f31b035a 8873 goto cp0_unimplemented;
876d4b07 8874 }
9c2149c8 8875 break;
04992c8c 8876 case CP0_REGISTER_16:
9c2149c8 8877 switch (sel) {
433efb4c 8878 case CP0_REG16__CONFIG:
7db13fae 8879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 8880 register_name = "Config";
9c2149c8 8881 break;
433efb4c 8882 case CP0_REG16__CONFIG1:
7db13fae 8883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 8884 register_name = "Config1";
9c2149c8 8885 break;
433efb4c 8886 case CP0_REG16__CONFIG2:
7db13fae 8887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 8888 register_name = "Config2";
9c2149c8 8889 break;
433efb4c 8890 case CP0_REG16__CONFIG3:
7db13fae 8891 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 8892 register_name = "Config3";
9c2149c8 8893 break;
433efb4c 8894 case CP0_REG16__CONFIG4:
faf1f68b 8895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 8896 register_name = "Config4";
faf1f68b 8897 break;
433efb4c 8898 case CP0_REG16__CONFIG5:
faf1f68b 8899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 8900 register_name = "Config5";
faf1f68b 8901 break;
05aa7e93 8902 /* 6,7 are implementation dependent */
433efb4c 8903 case CP0_REG16__CONFIG6:
7db13fae 8904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 8905 register_name = "Config6";
f0b3f3ae 8906 break;
433efb4c 8907 case CP0_REG16__CONFIG7:
7db13fae 8908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 8909 register_name = "Config7";
f0b3f3ae 8910 break;
9c2149c8 8911 default:
f31b035a 8912 goto cp0_unimplemented;
9c2149c8
TS
8913 }
8914 break;
04992c8c 8915 case CP0_REGISTER_17:
9c2149c8 8916 switch (sel) {
706ce142 8917 case CP0_REG17__LLADDR:
895c2d04 8918 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 8919 register_name = "LLAddr";
2423f660 8920 break;
706ce142 8921 case CP0_REG17__MAAR:
f6d4dd81
YK
8922 CP0_CHECK(ctx->mrp);
8923 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 8924 register_name = "MAAR";
f6d4dd81 8925 break;
706ce142 8926 case CP0_REG17__MAARI:
f6d4dd81
YK
8927 CP0_CHECK(ctx->mrp);
8928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 8929 register_name = "MAARI";
f6d4dd81 8930 break;
9c2149c8 8931 default:
f31b035a 8932 goto cp0_unimplemented;
9c2149c8
TS
8933 }
8934 break;
04992c8c 8935 case CP0_REGISTER_18:
9c2149c8 8936 switch (sel) {
e8dcfe82
AM
8937 case CP0_REG18__WATCHLO0:
8938 case CP0_REG18__WATCHLO1:
8939 case CP0_REG18__WATCHLO2:
8940 case CP0_REG18__WATCHLO3:
8941 case CP0_REG18__WATCHLO4:
8942 case CP0_REG18__WATCHLO5:
8943 case CP0_REG18__WATCHLO6:
8944 case CP0_REG18__WATCHLO7:
fa192d49 8945 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8946 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 8947 register_name = "WatchLo";
2423f660 8948 break;
9c2149c8 8949 default:
f31b035a 8950 goto cp0_unimplemented;
9c2149c8
TS
8951 }
8952 break;
04992c8c 8953 case CP0_REGISTER_19:
9c2149c8 8954 switch (sel) {
be274dc1
AM
8955 case CP0_REG19__WATCHHI0:
8956 case CP0_REG19__WATCHHI1:
8957 case CP0_REG19__WATCHHI2:
8958 case CP0_REG19__WATCHHI3:
8959 case CP0_REG19__WATCHHI4:
8960 case CP0_REG19__WATCHHI5:
8961 case CP0_REG19__WATCHHI6:
8962 case CP0_REG19__WATCHHI7:
fa192d49 8963 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 8964 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 8965 register_name = "WatchHi";
2423f660 8966 break;
9c2149c8 8967 default:
f31b035a 8968 goto cp0_unimplemented;
9c2149c8
TS
8969 }
8970 break;
04992c8c 8971 case CP0_REGISTER_20:
9c2149c8 8972 switch (sel) {
14f92b0b 8973 case CP0_REG20__XCONTEXT:
d75c135e 8974 check_insn(ctx, ISA_MIPS3);
7db13fae 8975 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8976 register_name = "XContext";
2423f660 8977 break;
9c2149c8 8978 default:
f31b035a 8979 goto cp0_unimplemented;
9c2149c8
TS
8980 }
8981 break;
04992c8c 8982 case CP0_REGISTER_21:
05aa7e93 8983 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8984 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8985 switch (sel) {
8986 case 0:
7db13fae 8987 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8988 register_name = "Framemask";
2423f660 8989 break;
9c2149c8 8990 default:
f31b035a 8991 goto cp0_unimplemented;
9c2149c8
TS
8992 }
8993 break;
04992c8c 8994 case CP0_REGISTER_22:
d9bea114 8995 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8996 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8997 break;
04992c8c 8998 case CP0_REGISTER_23:
9c2149c8 8999 switch (sel) {
4cbf4b6d 9000 case CP0_REG23__DEBUG:
895c2d04 9001 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 9002 register_name = "Debug";
2423f660 9003 break;
4cbf4b6d
AM
9004 case CP0_REG23__TRACECONTROL:
9005 /* PDtrace support */
9006 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 9007 register_name = "TraceControl";
3570d7f6 9008 goto cp0_unimplemented;
4cbf4b6d
AM
9009 case CP0_REG23__TRACECONTROL2:
9010 /* PDtrace support */
9011 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 9012 register_name = "TraceControl2";
3570d7f6 9013 goto cp0_unimplemented;
4cbf4b6d
AM
9014 case CP0_REG23__USERTRACEDATA1:
9015 /* PDtrace support */
9016 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9017 register_name = "UserTraceData1";
3570d7f6 9018 goto cp0_unimplemented;
4cbf4b6d
AM
9019 case CP0_REG23__TRACEIBPC:
9020 /* PDtrace support */
9021 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9022 register_name = "TraceIBPC";
9023 goto cp0_unimplemented;
9024 case CP0_REG23__TRACEDBPC:
9025 /* PDtrace support */
9026 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9027 register_name = "TraceDBPC";
3570d7f6 9028 goto cp0_unimplemented;
9c2149c8 9029 default:
f31b035a 9030 goto cp0_unimplemented;
9c2149c8
TS
9031 }
9032 break;
04992c8c 9033 case CP0_REGISTER_24:
9c2149c8 9034 switch (sel) {
8d7b4b6e 9035 case CP0_REG24__DEPC:
f0b3f3ae 9036 /* EJTAG support */
7db13fae 9037 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9038 register_name = "DEPC";
2423f660 9039 break;
9c2149c8 9040 default:
f31b035a 9041 goto cp0_unimplemented;
9c2149c8
TS
9042 }
9043 break;
04992c8c 9044 case CP0_REGISTER_25:
9c2149c8 9045 switch (sel) {
1176b328 9046 case CP0_REG25__PERFCTL0:
7db13fae 9047 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 9048 register_name = "Performance0";
9c2149c8 9049 break;
1176b328 9050 case CP0_REG25__PERFCNT0:
7480515f 9051 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 9052 register_name = "Performance1";
3570d7f6 9053 goto cp0_unimplemented;
1176b328 9054 case CP0_REG25__PERFCTL1:
7480515f 9055 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 9056 register_name = "Performance2";
3570d7f6 9057 goto cp0_unimplemented;
1176b328 9058 case CP0_REG25__PERFCNT1:
7480515f 9059 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 9060 register_name = "Performance3";
3570d7f6 9061 goto cp0_unimplemented;
1176b328 9062 case CP0_REG25__PERFCTL2:
7480515f 9063 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 9064 register_name = "Performance4";
3570d7f6 9065 goto cp0_unimplemented;
1176b328 9066 case CP0_REG25__PERFCNT2:
7480515f 9067 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 9068 register_name = "Performance5";
3570d7f6 9069 goto cp0_unimplemented;
1176b328 9070 case CP0_REG25__PERFCTL3:
7480515f 9071 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 9072 register_name = "Performance6";
3570d7f6 9073 goto cp0_unimplemented;
1176b328 9074 case CP0_REG25__PERFCNT3:
7480515f 9075 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 9076 register_name = "Performance7";
3570d7f6 9077 goto cp0_unimplemented;
9c2149c8 9078 default:
f31b035a 9079 goto cp0_unimplemented;
9c2149c8
TS
9080 }
9081 break;
04992c8c 9082 case CP0_REGISTER_26:
0d74a222 9083 switch (sel) {
dbbf08b2 9084 case CP0_REG26__ERRCTL:
0d74a222 9085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 9086 register_name = "ErrCtl";
0d74a222
LA
9087 break;
9088 default:
9089 goto cp0_unimplemented;
9090 }
da80682b 9091 break;
04992c8c 9092 case CP0_REGISTER_27:
9c2149c8
TS
9093 switch (sel) {
9094 /* ignored */
5a10873d 9095 case CP0_REG27__CACHERR:
d9bea114 9096 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 9097 register_name = "CacheErr";
2423f660 9098 break;
9c2149c8 9099 default:
f31b035a 9100 goto cp0_unimplemented;
9c2149c8
TS
9101 }
9102 break;
04992c8c 9103 case CP0_REGISTER_28:
9c2149c8 9104 switch (sel) {
a30e2f21
AM
9105 case CP0_REG28__TAGLO:
9106 case CP0_REG28__TAGLO1:
9107 case CP0_REG28__TAGLO2:
9108 case CP0_REG28__TAGLO3:
7db13fae 9109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 9110 register_name = "TagLo";
9c2149c8 9111 break;
a30e2f21
AM
9112 case CP0_REG28__DATALO:
9113 case CP0_REG28__DATALO1:
9114 case CP0_REG28__DATALO2:
9115 case CP0_REG28__DATALO3:
7db13fae 9116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 9117 register_name = "DataLo";
9c2149c8
TS
9118 break;
9119 default:
f31b035a 9120 goto cp0_unimplemented;
9c2149c8
TS
9121 }
9122 break;
04992c8c 9123 case CP0_REGISTER_29:
9c2149c8 9124 switch (sel) {
af4bb6da
AM
9125 case CP0_REG29__TAGHI:
9126 case CP0_REG29__TAGHI1:
9127 case CP0_REG29__TAGHI2:
9128 case CP0_REG29__TAGHI3:
7db13fae 9129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 9130 register_name = "TagHi";
9c2149c8 9131 break;
af4bb6da
AM
9132 case CP0_REG29__DATAHI:
9133 case CP0_REG29__DATAHI1:
9134 case CP0_REG29__DATAHI2:
9135 case CP0_REG29__DATAHI3:
7db13fae 9136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 9137 register_name = "DataHi";
9c2149c8
TS
9138 break;
9139 default:
f31b035a 9140 goto cp0_unimplemented;
9c2149c8
TS
9141 }
9142 break;
04992c8c 9143 case CP0_REGISTER_30:
9c2149c8 9144 switch (sel) {
4bcf121e 9145 case CP0_REG30__ERROREPC:
7db13fae 9146 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9147 register_name = "ErrorEPC";
2423f660 9148 break;
9c2149c8 9149 default:
f31b035a 9150 goto cp0_unimplemented;
9c2149c8
TS
9151 }
9152 break;
04992c8c 9153 case CP0_REGISTER_31:
9c2149c8 9154 switch (sel) {
14d92efd 9155 case CP0_REG31__DESAVE:
f0b3f3ae 9156 /* EJTAG support */
7db13fae 9157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9158 register_name = "DESAVE";
2423f660 9159 break;
14d92efd
AM
9160 case CP0_REG31__KSCRATCH1:
9161 case CP0_REG31__KSCRATCH2:
9162 case CP0_REG31__KSCRATCH3:
9163 case CP0_REG31__KSCRATCH4:
9164 case CP0_REG31__KSCRATCH5:
9165 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9166 CP0_CHECK(ctx->kscrexist & (1 << sel));
9167 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 9168 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9169 register_name = "KScratch";
e98c0d17 9170 break;
9c2149c8 9171 default:
f31b035a 9172 goto cp0_unimplemented;
9c2149c8
TS
9173 }
9174 break;
9175 default:
f31b035a 9176 goto cp0_unimplemented;
9c2149c8 9177 }
294fc2ea 9178 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
9179 return;
9180
f31b035a 9181cp0_unimplemented:
294fc2ea
AM
9182 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9183 register_name, reg, sel);
f31b035a 9184 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
9185}
9186
d75c135e 9187static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 9188{
294fc2ea 9189 const char *register_name = "invalid";
9c2149c8 9190
1f8929d2 9191 if (sel != 0) {
d75c135e 9192 check_insn(ctx, ISA_MIPS64);
1f8929d2 9193 }
e189e748 9194
eeb3bba8 9195 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9196 gen_io_start();
bd79255d 9197 }
2e70f6ef 9198
9c2149c8 9199 switch (reg) {
04992c8c 9200 case CP0_REGISTER_00:
9c2149c8 9201 switch (sel) {
1b142da5 9202 case CP0_REG00__INDEX:
895c2d04 9203 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 9204 register_name = "Index";
9c2149c8 9205 break;
1b142da5 9206 case CP0_REG00__MVPCONTROL:
f31b035a 9207 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9208 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 9209 register_name = "MVPControl";
ead9360e 9210 break;
1b142da5 9211 case CP0_REG00__MVPCONF0:
f31b035a 9212 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9213 /* ignored */
294fc2ea 9214 register_name = "MVPConf0";
ead9360e 9215 break;
1b142da5 9216 case CP0_REG00__MVPCONF1:
f31b035a 9217 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9218 /* ignored */
294fc2ea 9219 register_name = "MVPConf1";
ead9360e 9220 break;
1b142da5 9221 case CP0_REG00__VPCONTROL:
01bc435b
YK
9222 CP0_CHECK(ctx->vp);
9223 /* ignored */
294fc2ea 9224 register_name = "VPControl";
01bc435b 9225 break;
9c2149c8 9226 default:
f31b035a 9227 goto cp0_unimplemented;
9c2149c8
TS
9228 }
9229 break;
04992c8c 9230 case CP0_REGISTER_01:
9c2149c8 9231 switch (sel) {
30deb460 9232 case CP0_REG01__RANDOM:
2423f660 9233 /* ignored */
294fc2ea 9234 register_name = "Random";
2423f660 9235 break;
30deb460 9236 case CP0_REG01__VPECONTROL:
f31b035a 9237 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9238 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9239 register_name = "VPEControl";
ead9360e 9240 break;
30deb460 9241 case CP0_REG01__VPECONF0:
f31b035a 9242 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9243 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9244 register_name = "VPEConf0";
ead9360e 9245 break;
30deb460 9246 case CP0_REG01__VPECONF1:
f31b035a 9247 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9248 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9249 register_name = "VPEConf1";
ead9360e 9250 break;
30deb460 9251 case CP0_REG01__YQMASK:
f31b035a 9252 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9253 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9254 register_name = "YQMask";
ead9360e 9255 break;
30deb460 9256 case CP0_REG01__VPESCHEDULE:
f31b035a 9257 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9258 tcg_gen_st_tl(arg, cpu_env,
9259 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9260 register_name = "VPESchedule";
ead9360e 9261 break;
30deb460 9262 case CP0_REG01__VPESCHEFBACK:
f31b035a 9263 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9264 tcg_gen_st_tl(arg, cpu_env,
9265 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9266 register_name = "VPEScheFBack";
ead9360e 9267 break;
30deb460 9268 case CP0_REG01__VPEOPT:
f31b035a 9269 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9270 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9271 register_name = "VPEOpt";
ead9360e 9272 break;
9c2149c8 9273 default:
f31b035a 9274 goto cp0_unimplemented;
9c2149c8
TS
9275 }
9276 break;
04992c8c 9277 case CP0_REGISTER_02:
9c2149c8 9278 switch (sel) {
6d27d5bd 9279 case CP0_REG02__ENTRYLO0:
7207c7f9 9280 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9281 register_name = "EntryLo0";
2423f660 9282 break;
6d27d5bd 9283 case CP0_REG02__TCSTATUS:
f31b035a 9284 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9285 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9286 register_name = "TCStatus";
ead9360e 9287 break;
6d27d5bd 9288 case CP0_REG02__TCBIND:
f31b035a 9289 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9290 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9291 register_name = "TCBind";
ead9360e 9292 break;
6d27d5bd 9293 case CP0_REG02__TCRESTART:
f31b035a 9294 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9295 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9296 register_name = "TCRestart";
ead9360e 9297 break;
6d27d5bd 9298 case CP0_REG02__TCHALT:
f31b035a 9299 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9300 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9301 register_name = "TCHalt";
ead9360e 9302 break;
6d27d5bd 9303 case CP0_REG02__TCCONTEXT:
f31b035a 9304 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9305 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9306 register_name = "TCContext";
ead9360e 9307 break;
6d27d5bd 9308 case CP0_REG02__TCSCHEDULE:
f31b035a 9309 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9310 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9311 register_name = "TCSchedule";
ead9360e 9312 break;
6d27d5bd 9313 case CP0_REG02__TCSCHEFBACK:
f31b035a 9314 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9315 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9316 register_name = "TCScheFBack";
ead9360e 9317 break;
9c2149c8 9318 default:
f31b035a 9319 goto cp0_unimplemented;
9c2149c8
TS
9320 }
9321 break;
04992c8c 9322 case CP0_REGISTER_03:
9c2149c8 9323 switch (sel) {
acd37316 9324 case CP0_REG03__ENTRYLO1:
7207c7f9 9325 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9326 register_name = "EntryLo1";
2423f660 9327 break;
acd37316 9328 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9329 CP0_CHECK(ctx->vp);
9330 /* ignored */
294fc2ea 9331 register_name = "GlobalNumber";
01bc435b 9332 break;
9c2149c8 9333 default:
f31b035a 9334 goto cp0_unimplemented;
876d4b07 9335 }
9c2149c8 9336 break;
04992c8c 9337 case CP0_REGISTER_04:
9c2149c8 9338 switch (sel) {
020fe379 9339 case CP0_REG04__CONTEXT:
895c2d04 9340 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9341 register_name = "Context";
2423f660 9342 break;
020fe379
AM
9343 case CP0_REG04__CONTEXTCONFIG:
9344 /* SmartMIPS ASE */
9345 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 9346 register_name = "ContextConfig";
f31b035a 9347 goto cp0_unimplemented;
020fe379 9348 case CP0_REG04__USERLOCAL:
f31b035a
LA
9349 CP0_CHECK(ctx->ulri);
9350 tcg_gen_st_tl(arg, cpu_env,
9351 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9352 register_name = "UserLocal";
d279279e 9353 break;
9c2149c8 9354 default:
f31b035a 9355 goto cp0_unimplemented;
876d4b07 9356 }
9c2149c8 9357 break;
04992c8c 9358 case CP0_REGISTER_05:
9c2149c8 9359 switch (sel) {
a1e76353 9360 case CP0_REG05__PAGEMASK:
895c2d04 9361 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9362 register_name = "PageMask";
2423f660 9363 break;
a1e76353 9364 case CP0_REG05__PAGEGRAIN:
d75c135e 9365 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9366 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9367 register_name = "PageGrain";
2423f660 9368 break;
a1e76353 9369 case CP0_REG05__SEGCTL0:
cec56a73
JH
9370 CP0_CHECK(ctx->sc);
9371 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9372 register_name = "SegCtl0";
cec56a73 9373 break;
a1e76353 9374 case CP0_REG05__SEGCTL1:
cec56a73
JH
9375 CP0_CHECK(ctx->sc);
9376 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9377 register_name = "SegCtl1";
cec56a73 9378 break;
a1e76353 9379 case CP0_REG05__SEGCTL2:
cec56a73
JH
9380 CP0_CHECK(ctx->sc);
9381 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9382 register_name = "SegCtl2";
cec56a73 9383 break;
a1e76353 9384 case CP0_REG05__PWBASE:
5e31fdd5
YK
9385 check_pw(ctx);
9386 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9387 register_name = "PWBase";
5e31fdd5 9388 break;
a1e76353 9389 case CP0_REG05__PWFIELD:
fa75ad14
YK
9390 check_pw(ctx);
9391 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9392 register_name = "PWField";
fa75ad14 9393 break;
a1e76353 9394 case CP0_REG05__PWSIZE:
20b28ebc
YK
9395 check_pw(ctx);
9396 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9397 register_name = "PWSize";
20b28ebc 9398 break;
9c2149c8 9399 default:
f31b035a 9400 goto cp0_unimplemented;
876d4b07 9401 }
9c2149c8 9402 break;
04992c8c 9403 case CP0_REGISTER_06:
9c2149c8 9404 switch (sel) {
9023594b 9405 case CP0_REG06__WIRED:
895c2d04 9406 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9407 register_name = "Wired";
2423f660 9408 break;
9023594b 9409 case CP0_REG06__SRSCONF0:
d75c135e 9410 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9411 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9412 register_name = "SRSConf0";
ead9360e 9413 break;
9023594b 9414 case CP0_REG06__SRSCONF1:
d75c135e 9415 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9416 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9417 register_name = "SRSConf1";
ead9360e 9418 break;
9023594b 9419 case CP0_REG06__SRSCONF2:
d75c135e 9420 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9421 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9422 register_name = "SRSConf2";
ead9360e 9423 break;
9023594b 9424 case CP0_REG06__SRSCONF3:
d75c135e 9425 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9426 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9427 register_name = "SRSConf3";
ead9360e 9428 break;
9023594b 9429 case CP0_REG06__SRSCONF4:
d75c135e 9430 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9431 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9432 register_name = "SRSConf4";
ead9360e 9433 break;
9023594b 9434 case CP0_REG06__PWCTL:
103be64c
YK
9435 check_pw(ctx);
9436 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9437 register_name = "PWCtl";
103be64c 9438 break;
9c2149c8 9439 default:
f31b035a 9440 goto cp0_unimplemented;
876d4b07 9441 }
9c2149c8 9442 break;
04992c8c 9443 case CP0_REGISTER_07:
9c2149c8 9444 switch (sel) {
143a9875 9445 case CP0_REG07__HWRENA:
d75c135e 9446 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9447 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9448 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9449 register_name = "HWREna";
2423f660 9450 break;
9c2149c8 9451 default:
f31b035a 9452 goto cp0_unimplemented;
876d4b07 9453 }
9c2149c8 9454 break;
04992c8c 9455 case CP0_REGISTER_08:
aea14095 9456 switch (sel) {
67d167d2 9457 case CP0_REG08__BADVADDR:
aea14095 9458 /* ignored */
294fc2ea 9459 register_name = "BadVAddr";
aea14095 9460 break;
67d167d2 9461 case CP0_REG08__BADINSTR:
aea14095 9462 /* ignored */
294fc2ea 9463 register_name = "BadInstr";
aea14095 9464 break;
67d167d2 9465 case CP0_REG08__BADINSTRP:
aea14095 9466 /* ignored */
294fc2ea 9467 register_name = "BadInstrP";
aea14095 9468 break;
67d167d2 9469 case CP0_REG08__BADINSTRX:
25beba9b 9470 /* ignored */
294fc2ea 9471 register_name = "BadInstrX";
25beba9b 9472 break;
aea14095 9473 default:
f31b035a 9474 goto cp0_unimplemented;
aea14095 9475 }
9c2149c8 9476 break;
04992c8c 9477 case CP0_REGISTER_09:
9c2149c8 9478 switch (sel) {
e5a98a72 9479 case CP0_REG09__COUNT:
895c2d04 9480 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9481 register_name = "Count";
2423f660 9482 break;
e5a98a72 9483 case CP0_REG09__SAARI:
5fb2dcd1
YK
9484 CP0_CHECK(ctx->saar);
9485 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9486 register_name = "SAARI";
5fb2dcd1 9487 break;
e5a98a72 9488 case CP0_REG09__SAAR:
5fb2dcd1
YK
9489 CP0_CHECK(ctx->saar);
9490 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9491 register_name = "SAAR";
5fb2dcd1 9492 break;
9c2149c8 9493 default:
f31b035a 9494 goto cp0_unimplemented;
876d4b07
TS
9495 }
9496 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9497 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9498 break;
04992c8c 9499 case CP0_REGISTER_10:
9c2149c8 9500 switch (sel) {
860ffef0 9501 case CP0_REG10__ENTRYHI:
895c2d04 9502 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9503 register_name = "EntryHi";
2423f660 9504 break;
9c2149c8 9505 default:
f31b035a 9506 goto cp0_unimplemented;
876d4b07 9507 }
9c2149c8 9508 break;
04992c8c 9509 case CP0_REGISTER_11:
9c2149c8 9510 switch (sel) {
f5f3834f 9511 case CP0_REG11__COMPARE:
895c2d04 9512 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9513 register_name = "Compare";
2423f660 9514 break;
876d4b07 9515 /* 6,7 are implementation dependent */
9c2149c8 9516 default:
f31b035a 9517 goto cp0_unimplemented;
876d4b07 9518 }
de9a95f0 9519 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9520 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9521 break;
04992c8c 9522 case CP0_REGISTER_12:
9c2149c8 9523 switch (sel) {
2b084867 9524 case CP0_REG12__STATUS:
867abc7e 9525 save_cpu_state(ctx, 1);
895c2d04 9526 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 9527 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9528 gen_save_pc(ctx->base.pc_next + 4);
9529 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9530 register_name = "Status";
2423f660 9531 break;
2b084867 9532 case CP0_REG12__INTCTL:
d75c135e 9533 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9534 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 9535 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9536 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9537 register_name = "IntCtl";
2423f660 9538 break;
2b084867 9539 case CP0_REG12__SRSCTL:
d75c135e 9540 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9541 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 9542 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9543 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9544 register_name = "SRSCtl";
2423f660 9545 break;
2b084867 9546 case CP0_REG12__SRSMAP:
d75c135e 9547 check_insn(ctx, ISA_MIPS32R2);
7db13fae 9548 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 9549 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9550 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9551 register_name = "SRSMap";
2423f660
TS
9552 break;
9553 default:
f31b035a 9554 goto cp0_unimplemented;
876d4b07 9555 }
9c2149c8 9556 break;
04992c8c 9557 case CP0_REGISTER_13:
9c2149c8 9558 switch (sel) {
e3c7559d 9559 case CP0_REG13__CAUSE:
867abc7e 9560 save_cpu_state(ctx, 1);
895c2d04 9561 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
9562 /*
9563 * Stop translation as we may have triggered an interrupt.
b28425ba 9564 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
9565 * translated code to check for pending interrupts.
9566 */
eeb3bba8
EC
9567 gen_save_pc(ctx->base.pc_next + 4);
9568 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9569 register_name = "Cause";
2423f660 9570 break;
9c2149c8 9571 default:
f31b035a 9572 goto cp0_unimplemented;
876d4b07 9573 }
9c2149c8 9574 break;
04992c8c 9575 case CP0_REGISTER_14:
9c2149c8 9576 switch (sel) {
35e4b54d 9577 case CP0_REG14__EPC:
7db13fae 9578 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9579 register_name = "EPC";
2423f660 9580 break;
9c2149c8 9581 default:
f31b035a 9582 goto cp0_unimplemented;
876d4b07 9583 }
9c2149c8 9584 break;
04992c8c 9585 case CP0_REGISTER_15:
9c2149c8 9586 switch (sel) {
4466cd49 9587 case CP0_REG15__PRID:
2423f660 9588 /* ignored */
294fc2ea 9589 register_name = "PRid";
2423f660 9590 break;
4466cd49 9591 case CP0_REG15__EBASE:
d75c135e 9592 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9593 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 9594 register_name = "EBase";
2423f660 9595 break;
9c2149c8 9596 default:
f31b035a 9597 goto cp0_unimplemented;
876d4b07 9598 }
9c2149c8 9599 break;
04992c8c 9600 case CP0_REGISTER_16:
9c2149c8 9601 switch (sel) {
433efb4c 9602 case CP0_REG16__CONFIG:
895c2d04 9603 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 9604 register_name = "Config";
2423f660 9605 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9606 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9607 break;
433efb4c 9608 case CP0_REG16__CONFIG1:
1fc7bf6e 9609 /* ignored, read only */
294fc2ea 9610 register_name = "Config1";
9c2149c8 9611 break;
433efb4c 9612 case CP0_REG16__CONFIG2:
895c2d04 9613 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 9614 register_name = "Config2";
2423f660 9615 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9616 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9617 break;
433efb4c 9618 case CP0_REG16__CONFIG3:
90f12d73 9619 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 9620 register_name = "Config3";
90f12d73 9621 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9622 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9623 break;
433efb4c 9624 case CP0_REG16__CONFIG4:
faf1f68b 9625 /* currently ignored */
294fc2ea 9626 register_name = "Config4";
faf1f68b 9627 break;
433efb4c 9628 case CP0_REG16__CONFIG5:
faf1f68b 9629 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 9630 register_name = "Config5";
faf1f68b 9631 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9632 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9633 break;
9c2149c8
TS
9634 /* 6,7 are implementation dependent */
9635 default:
294fc2ea 9636 register_name = "Invalid config selector";
f31b035a 9637 goto cp0_unimplemented;
9c2149c8 9638 }
9c2149c8 9639 break;
04992c8c 9640 case CP0_REGISTER_17:
9c2149c8 9641 switch (sel) {
706ce142 9642 case CP0_REG17__LLADDR:
895c2d04 9643 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 9644 register_name = "LLAddr";
2423f660 9645 break;
706ce142 9646 case CP0_REG17__MAAR:
f6d4dd81
YK
9647 CP0_CHECK(ctx->mrp);
9648 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 9649 register_name = "MAAR";
f6d4dd81 9650 break;
706ce142 9651 case CP0_REG17__MAARI:
f6d4dd81
YK
9652 CP0_CHECK(ctx->mrp);
9653 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 9654 register_name = "MAARI";
f6d4dd81 9655 break;
9c2149c8 9656 default:
f31b035a 9657 goto cp0_unimplemented;
9c2149c8
TS
9658 }
9659 break;
04992c8c 9660 case CP0_REGISTER_18:
9c2149c8 9661 switch (sel) {
e8dcfe82
AM
9662 case CP0_REG18__WATCHLO0:
9663 case CP0_REG18__WATCHLO1:
9664 case CP0_REG18__WATCHLO2:
9665 case CP0_REG18__WATCHLO3:
9666 case CP0_REG18__WATCHLO4:
9667 case CP0_REG18__WATCHLO5:
9668 case CP0_REG18__WATCHLO6:
9669 case CP0_REG18__WATCHLO7:
fa192d49 9670 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9671 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 9672 register_name = "WatchLo";
2423f660 9673 break;
9c2149c8 9674 default:
f31b035a 9675 goto cp0_unimplemented;
9c2149c8
TS
9676 }
9677 break;
04992c8c 9678 case CP0_REGISTER_19:
9c2149c8 9679 switch (sel) {
be274dc1
AM
9680 case CP0_REG19__WATCHHI0:
9681 case CP0_REG19__WATCHHI1:
9682 case CP0_REG19__WATCHHI2:
9683 case CP0_REG19__WATCHHI3:
9684 case CP0_REG19__WATCHHI4:
9685 case CP0_REG19__WATCHHI5:
9686 case CP0_REG19__WATCHHI6:
9687 case CP0_REG19__WATCHHI7:
fa192d49 9688 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9689 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 9690 register_name = "WatchHi";
2423f660 9691 break;
9c2149c8 9692 default:
f31b035a 9693 goto cp0_unimplemented;
9c2149c8
TS
9694 }
9695 break;
04992c8c 9696 case CP0_REGISTER_20:
9c2149c8 9697 switch (sel) {
14f92b0b 9698 case CP0_REG20__XCONTEXT:
d75c135e 9699 check_insn(ctx, ISA_MIPS3);
895c2d04 9700 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 9701 register_name = "XContext";
2423f660 9702 break;
9c2149c8 9703 default:
f31b035a 9704 goto cp0_unimplemented;
9c2149c8
TS
9705 }
9706 break;
04992c8c 9707 case CP0_REGISTER_21:
9c2149c8 9708 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9709 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9710 switch (sel) {
9711 case 0:
895c2d04 9712 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 9713 register_name = "Framemask";
2423f660 9714 break;
9c2149c8 9715 default:
f31b035a 9716 goto cp0_unimplemented;
9c2149c8
TS
9717 }
9718 break;
04992c8c 9719 case CP0_REGISTER_22:
9c2149c8 9720 /* ignored */
294fc2ea 9721 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 9722 break;
04992c8c 9723 case CP0_REGISTER_23:
9c2149c8 9724 switch (sel) {
4cbf4b6d 9725 case CP0_REG23__DEBUG:
895c2d04 9726 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9727 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9728 gen_save_pc(ctx->base.pc_next + 4);
9729 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9730 register_name = "Debug";
2423f660 9731 break;
4cbf4b6d
AM
9732 case CP0_REG23__TRACECONTROL:
9733 /* PDtrace support */
9734 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 9735 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9736 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9737 register_name = "TraceControl";
3570d7f6 9738 goto cp0_unimplemented;
4cbf4b6d
AM
9739 case CP0_REG23__TRACECONTROL2:
9740 /* PDtrace support */
9741 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 9742 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9743 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9744 register_name = "TraceControl2";
3570d7f6 9745 goto cp0_unimplemented;
4cbf4b6d
AM
9746 case CP0_REG23__USERTRACEDATA1:
9747 /* PDtrace support */
9748 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 9749 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9750 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9751 register_name = "UserTraceData1";
3570d7f6 9752 goto cp0_unimplemented;
4cbf4b6d
AM
9753 case CP0_REG23__TRACEIBPC:
9754 /* PDtrace support */
9755 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9756 /* Stop translation as we may have switched the execution mode */
9757 ctx->base.is_jmp = DISAS_STOP;
9758 register_name = "TraceIBPC";
9759 goto cp0_unimplemented;
9760 case CP0_REG23__TRACEDBPC:
9761 /* PDtrace support */
9762 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 9763 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9764 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9765 register_name = "TraceDBPC";
3570d7f6 9766 goto cp0_unimplemented;
9c2149c8 9767 default:
f31b035a 9768 goto cp0_unimplemented;
9c2149c8 9769 }
9c2149c8 9770 break;
04992c8c 9771 case CP0_REGISTER_24:
9c2149c8 9772 switch (sel) {
8d7b4b6e 9773 case CP0_REG24__DEPC:
f1aa6320 9774 /* EJTAG support */
7db13fae 9775 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9776 register_name = "DEPC";
2423f660 9777 break;
9c2149c8 9778 default:
f31b035a 9779 goto cp0_unimplemented;
9c2149c8
TS
9780 }
9781 break;
04992c8c 9782 case CP0_REGISTER_25:
9c2149c8 9783 switch (sel) {
1176b328 9784 case CP0_REG25__PERFCTL0:
895c2d04 9785 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 9786 register_name = "Performance0";
2423f660 9787 break;
1176b328 9788 case CP0_REG25__PERFCNT0:
7480515f 9789 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 9790 register_name = "Performance1";
3570d7f6 9791 goto cp0_unimplemented;
1176b328 9792 case CP0_REG25__PERFCTL1:
7480515f 9793 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 9794 register_name = "Performance2";
3570d7f6 9795 goto cp0_unimplemented;
1176b328 9796 case CP0_REG25__PERFCNT1:
7480515f 9797 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 9798 register_name = "Performance3";
3570d7f6 9799 goto cp0_unimplemented;
1176b328 9800 case CP0_REG25__PERFCTL2:
7480515f 9801 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 9802 register_name = "Performance4";
3570d7f6 9803 goto cp0_unimplemented;
1176b328 9804 case CP0_REG25__PERFCNT2:
7480515f 9805 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 9806 register_name = "Performance5";
3570d7f6 9807 goto cp0_unimplemented;
1176b328 9808 case CP0_REG25__PERFCTL3:
7480515f 9809 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 9810 register_name = "Performance6";
3570d7f6 9811 goto cp0_unimplemented;
1176b328 9812 case CP0_REG25__PERFCNT3:
7480515f 9813 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 9814 register_name = "Performance7";
3570d7f6 9815 goto cp0_unimplemented;
9c2149c8 9816 default:
f31b035a 9817 goto cp0_unimplemented;
9c2149c8 9818 }
876d4b07 9819 break;
04992c8c 9820 case CP0_REGISTER_26:
0d74a222 9821 switch (sel) {
dbbf08b2 9822 case CP0_REG26__ERRCTL:
0d74a222 9823 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9824 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9825 register_name = "ErrCtl";
0d74a222
LA
9826 break;
9827 default:
9828 goto cp0_unimplemented;
9829 }
876d4b07 9830 break;
04992c8c 9831 case CP0_REGISTER_27:
9c2149c8 9832 switch (sel) {
5a10873d 9833 case CP0_REG27__CACHERR:
2423f660 9834 /* ignored */
294fc2ea 9835 register_name = "CacheErr";
2423f660 9836 break;
9c2149c8 9837 default:
f31b035a 9838 goto cp0_unimplemented;
9c2149c8 9839 }
876d4b07 9840 break;
04992c8c 9841 case CP0_REGISTER_28:
9c2149c8 9842 switch (sel) {
a30e2f21
AM
9843 case CP0_REG28__TAGLO:
9844 case CP0_REG28__TAGLO1:
9845 case CP0_REG28__TAGLO2:
9846 case CP0_REG28__TAGLO3:
895c2d04 9847 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 9848 register_name = "TagLo";
9c2149c8 9849 break;
a30e2f21
AM
9850 case CP0_REG28__DATALO:
9851 case CP0_REG28__DATALO1:
9852 case CP0_REG28__DATALO2:
9853 case CP0_REG28__DATALO3:
895c2d04 9854 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 9855 register_name = "DataLo";
9c2149c8
TS
9856 break;
9857 default:
f31b035a 9858 goto cp0_unimplemented;
9c2149c8
TS
9859 }
9860 break;
04992c8c 9861 case CP0_REGISTER_29:
9c2149c8 9862 switch (sel) {
af4bb6da
AM
9863 case CP0_REG29__TAGHI:
9864 case CP0_REG29__TAGHI1:
9865 case CP0_REG29__TAGHI2:
9866 case CP0_REG29__TAGHI3:
895c2d04 9867 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 9868 register_name = "TagHi";
9c2149c8 9869 break;
af4bb6da
AM
9870 case CP0_REG29__DATAHI:
9871 case CP0_REG29__DATAHI1:
9872 case CP0_REG29__DATAHI2:
9873 case CP0_REG29__DATAHI3:
895c2d04 9874 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 9875 register_name = "DataHi";
9c2149c8
TS
9876 break;
9877 default:
294fc2ea 9878 register_name = "invalid sel";
f31b035a 9879 goto cp0_unimplemented;
9c2149c8 9880 }
876d4b07 9881 break;
04992c8c 9882 case CP0_REGISTER_30:
9c2149c8 9883 switch (sel) {
4bcf121e 9884 case CP0_REG30__ERROREPC:
7db13fae 9885 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9886 register_name = "ErrorEPC";
2423f660 9887 break;
9c2149c8 9888 default:
f31b035a 9889 goto cp0_unimplemented;
9c2149c8
TS
9890 }
9891 break;
04992c8c 9892 case CP0_REGISTER_31:
9c2149c8 9893 switch (sel) {
14d92efd 9894 case CP0_REG31__DESAVE:
f1aa6320 9895 /* EJTAG support */
7db13fae 9896 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9897 register_name = "DESAVE";
2423f660 9898 break;
14d92efd
AM
9899 case CP0_REG31__KSCRATCH1:
9900 case CP0_REG31__KSCRATCH2:
9901 case CP0_REG31__KSCRATCH3:
9902 case CP0_REG31__KSCRATCH4:
9903 case CP0_REG31__KSCRATCH5:
9904 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9905 CP0_CHECK(ctx->kscrexist & (1 << sel));
9906 tcg_gen_st_tl(arg, cpu_env,
71375b59 9907 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9908 register_name = "KScratch";
e98c0d17 9909 break;
9c2149c8 9910 default:
f31b035a 9911 goto cp0_unimplemented;
9c2149c8 9912 }
9c2149c8
TS
9913 break;
9914 default:
f31b035a 9915 goto cp0_unimplemented;
9c2149c8 9916 }
294fc2ea 9917 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 9918
bf20dc07 9919 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9920 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
9921 /*
9922 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9923 * translated code to check for pending interrupts.
9924 */
eeb3bba8
EC
9925 gen_save_pc(ctx->base.pc_next + 4);
9926 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9927 }
9c2149c8
TS
9928 return;
9929
f31b035a 9930cp0_unimplemented:
294fc2ea
AM
9931 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9932 register_name, reg, sel);
9c2149c8 9933}
d26bc211 9934#endif /* TARGET_MIPS64 */
9c2149c8 9935
7db13fae 9936static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9937 int u, int sel, int h)
9938{
9939 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9940 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9941
9942 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9943 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9944 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 9945 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
9946 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9947 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 9948 tcg_gen_movi_tl(t0, -1);
1f8929d2 9949 } else if (u == 0) {
ead9360e 9950 switch (rt) {
5a25ce94
EI
9951 case 1:
9952 switch (sel) {
9953 case 1:
895c2d04 9954 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
9955 break;
9956 case 2:
895c2d04 9957 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9958 break;
9959 default:
9960 goto die;
9961 break;
9962 }
9963 break;
ead9360e
TS
9964 case 2:
9965 switch (sel) {
9966 case 1:
895c2d04 9967 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9968 break;
9969 case 2:
895c2d04 9970 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9971 break;
9972 case 3:
895c2d04 9973 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9974 break;
9975 case 4:
895c2d04 9976 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9977 break;
9978 case 5:
895c2d04 9979 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9980 break;
9981 case 6:
895c2d04 9982 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9983 break;
9984 case 7:
895c2d04 9985 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9986 break;
9987 default:
d75c135e 9988 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9989 break;
9990 }
9991 break;
9992 case 10:
9993 switch (sel) {
9994 case 0:
895c2d04 9995 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9996 break;
9997 default:
d75c135e 9998 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9999 break;
10000 }
f1fadbb2 10001 break;
ead9360e
TS
10002 case 12:
10003 switch (sel) {
10004 case 0:
895c2d04 10005 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
10006 break;
10007 default:
d75c135e 10008 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10009 break;
10010 }
f1fadbb2 10011 break;
5a25ce94
EI
10012 case 13:
10013 switch (sel) {
10014 case 0:
895c2d04 10015 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
10016 break;
10017 default:
10018 goto die;
10019 break;
10020 }
10021 break;
10022 case 14:
10023 switch (sel) {
10024 case 0:
895c2d04 10025 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
10026 break;
10027 default:
10028 goto die;
10029 break;
10030 }
10031 break;
10032 case 15:
10033 switch (sel) {
10034 case 1:
895c2d04 10035 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
10036 break;
10037 default:
10038 goto die;
10039 break;
10040 }
10041 break;
10042 case 16:
10043 switch (sel) {
c2e19f3c
AM
10044 case 0:
10045 case 1:
10046 case 2:
10047 case 3:
10048 case 4:
10049 case 5:
10050 case 6:
10051 case 7:
895c2d04 10052 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
10053 break;
10054 default:
10055 goto die;
10056 break;
10057 }
10058 break;
ead9360e
TS
10059 case 23:
10060 switch (sel) {
10061 case 0:
895c2d04 10062 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
10063 break;
10064 default:
d75c135e 10065 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10066 break;
10067 }
10068 break;
10069 default:
d75c135e 10070 gen_mfc0(ctx, t0, rt, sel);
ead9360e 10071 }
71375b59
AM
10072 } else {
10073 switch (sel) {
10074 /* GPR registers. */
ead9360e 10075 case 0:
71375b59 10076 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 10077 break;
71375b59 10078 /* Auxiliary CPU registers */
ead9360e 10079 case 1:
71375b59
AM
10080 switch (rt) {
10081 case 0:
10082 gen_helper_1e0i(mftlo, t0, 0);
10083 break;
10084 case 1:
10085 gen_helper_1e0i(mfthi, t0, 0);
10086 break;
10087 case 2:
10088 gen_helper_1e0i(mftacx, t0, 0);
10089 break;
10090 case 4:
10091 gen_helper_1e0i(mftlo, t0, 1);
10092 break;
10093 case 5:
10094 gen_helper_1e0i(mfthi, t0, 1);
10095 break;
10096 case 6:
10097 gen_helper_1e0i(mftacx, t0, 1);
10098 break;
10099 case 8:
10100 gen_helper_1e0i(mftlo, t0, 2);
10101 break;
10102 case 9:
10103 gen_helper_1e0i(mfthi, t0, 2);
10104 break;
10105 case 10:
10106 gen_helper_1e0i(mftacx, t0, 2);
10107 break;
10108 case 12:
10109 gen_helper_1e0i(mftlo, t0, 3);
10110 break;
10111 case 13:
10112 gen_helper_1e0i(mfthi, t0, 3);
10113 break;
10114 case 14:
10115 gen_helper_1e0i(mftacx, t0, 3);
10116 break;
10117 case 16:
10118 gen_helper_mftdsp(t0, cpu_env);
10119 break;
10120 default:
10121 goto die;
10122 }
ead9360e 10123 break;
71375b59 10124 /* Floating point (COP1). */
ead9360e 10125 case 2:
71375b59
AM
10126 /* XXX: For now we support only a single FPU context. */
10127 if (h == 0) {
10128 TCGv_i32 fp0 = tcg_temp_new_i32();
10129
10130 gen_load_fpr32(ctx, fp0, rt);
10131 tcg_gen_ext_i32_tl(t0, fp0);
10132 tcg_temp_free_i32(fp0);
10133 } else {
10134 TCGv_i32 fp0 = tcg_temp_new_i32();
10135
10136 gen_load_fpr32h(ctx, fp0, rt);
10137 tcg_gen_ext_i32_tl(t0, fp0);
10138 tcg_temp_free_i32(fp0);
10139 }
ead9360e 10140 break;
71375b59
AM
10141 case 3:
10142 /* XXX: For now we support only a single FPU context. */
10143 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 10144 break;
71375b59
AM
10145 /* COP2: Not implemented. */
10146 case 4:
ead9360e 10147 case 5:
71375b59 10148 /* fall through */
ead9360e
TS
10149 default:
10150 goto die;
10151 }
ead9360e 10152 }
b44a7fb1 10153 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
10154 gen_store_gpr(t0, rd);
10155 tcg_temp_free(t0);
ead9360e
TS
10156 return;
10157
10158die:
1a3fd9c3 10159 tcg_temp_free(t0);
d12d51d5 10160 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 10161 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10162}
10163
7db13fae 10164static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
10165 int u, int sel, int h)
10166{
10167 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10168 TCGv t0 = tcg_temp_local_new();
ead9360e 10169
1a3fd9c3 10170 gen_load_gpr(t0, rt);
ead9360e 10171 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10172 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10173 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
10174 /* NOP */
10175 ;
1f8929d2
AM
10176 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10177 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
10178 /* NOP */
10179 ;
1f8929d2 10180 } else if (u == 0) {
ead9360e 10181 switch (rd) {
5a25ce94
EI
10182 case 1:
10183 switch (sel) {
10184 case 1:
895c2d04 10185 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
10186 break;
10187 case 2:
895c2d04 10188 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
10189 break;
10190 default:
10191 goto die;
10192 break;
10193 }
10194 break;
ead9360e
TS
10195 case 2:
10196 switch (sel) {
10197 case 1:
895c2d04 10198 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
10199 break;
10200 case 2:
895c2d04 10201 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
10202 break;
10203 case 3:
895c2d04 10204 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
10205 break;
10206 case 4:
895c2d04 10207 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
10208 break;
10209 case 5:
895c2d04 10210 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
10211 break;
10212 case 6:
895c2d04 10213 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
10214 break;
10215 case 7:
895c2d04 10216 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
10217 break;
10218 default:
d75c135e 10219 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10220 break;
10221 }
10222 break;
10223 case 10:
10224 switch (sel) {
10225 case 0:
895c2d04 10226 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
10227 break;
10228 default:
d75c135e 10229 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10230 break;
10231 }
0d0304f2 10232 break;
ead9360e
TS
10233 case 12:
10234 switch (sel) {
10235 case 0:
895c2d04 10236 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
10237 break;
10238 default:
d75c135e 10239 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10240 break;
10241 }
0d0304f2 10242 break;
5a25ce94
EI
10243 case 13:
10244 switch (sel) {
10245 case 0:
895c2d04 10246 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
10247 break;
10248 default:
10249 goto die;
10250 break;
10251 }
10252 break;
10253 case 15:
10254 switch (sel) {
10255 case 1:
895c2d04 10256 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10257 break;
10258 default:
10259 goto die;
10260 break;
10261 }
10262 break;
ead9360e
TS
10263 case 23:
10264 switch (sel) {
10265 case 0:
895c2d04 10266 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10267 break;
10268 default:
d75c135e 10269 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10270 break;
10271 }
10272 break;
10273 default:
d75c135e 10274 gen_mtc0(ctx, t0, rd, sel);
ead9360e 10275 }
71375b59
AM
10276 } else {
10277 switch (sel) {
10278 /* GPR registers. */
ead9360e 10279 case 0:
71375b59 10280 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 10281 break;
71375b59 10282 /* Auxiliary CPU registers */
ead9360e 10283 case 1:
71375b59
AM
10284 switch (rd) {
10285 case 0:
10286 gen_helper_0e1i(mttlo, t0, 0);
10287 break;
10288 case 1:
10289 gen_helper_0e1i(mtthi, t0, 0);
10290 break;
10291 case 2:
10292 gen_helper_0e1i(mttacx, t0, 0);
10293 break;
10294 case 4:
10295 gen_helper_0e1i(mttlo, t0, 1);
10296 break;
10297 case 5:
10298 gen_helper_0e1i(mtthi, t0, 1);
10299 break;
10300 case 6:
10301 gen_helper_0e1i(mttacx, t0, 1);
10302 break;
10303 case 8:
10304 gen_helper_0e1i(mttlo, t0, 2);
10305 break;
10306 case 9:
10307 gen_helper_0e1i(mtthi, t0, 2);
10308 break;
10309 case 10:
10310 gen_helper_0e1i(mttacx, t0, 2);
10311 break;
10312 case 12:
10313 gen_helper_0e1i(mttlo, t0, 3);
10314 break;
10315 case 13:
10316 gen_helper_0e1i(mtthi, t0, 3);
10317 break;
10318 case 14:
10319 gen_helper_0e1i(mttacx, t0, 3);
10320 break;
10321 case 16:
10322 gen_helper_mttdsp(cpu_env, t0);
10323 break;
10324 default:
10325 goto die;
10326 }
ead9360e 10327 break;
71375b59 10328 /* Floating point (COP1). */
ead9360e 10329 case 2:
71375b59
AM
10330 /* XXX: For now we support only a single FPU context. */
10331 if (h == 0) {
10332 TCGv_i32 fp0 = tcg_temp_new_i32();
10333
10334 tcg_gen_trunc_tl_i32(fp0, t0);
10335 gen_store_fpr32(ctx, fp0, rd);
10336 tcg_temp_free_i32(fp0);
10337 } else {
10338 TCGv_i32 fp0 = tcg_temp_new_i32();
10339
10340 tcg_gen_trunc_tl_i32(fp0, t0);
10341 gen_store_fpr32h(ctx, fp0, rd);
10342 tcg_temp_free_i32(fp0);
10343 }
ead9360e 10344 break;
71375b59
AM
10345 case 3:
10346 /* XXX: For now we support only a single FPU context. */
10347 {
10348 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10349
10350 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10351 tcg_temp_free_i32(fs_tmp);
10352 }
10353 /* Stop translation as we may have changed hflags */
10354 ctx->base.is_jmp = DISAS_STOP;
ead9360e 10355 break;
71375b59
AM
10356 /* COP2: Not implemented. */
10357 case 4:
ead9360e 10358 case 5:
71375b59 10359 /* fall through */
ead9360e
TS
10360 default:
10361 goto die;
10362 }
ead9360e 10363 }
b44a7fb1 10364 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10365 tcg_temp_free(t0);
ead9360e
TS
10366 return;
10367
10368die:
1a3fd9c3 10369 tcg_temp_free(t0);
d12d51d5 10370 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10371 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10372}
10373
235785e8
AM
10374static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10375 int rt, int rd)
6af0bf9c 10376{
287c4b84 10377 const char *opn = "ldst";
6af0bf9c 10378
2e15497c 10379 check_cp0_enabled(ctx);
6af0bf9c
FB
10380 switch (opc) {
10381 case OPC_MFC0:
10382 if (rt == 0) {
ead9360e 10383 /* Treat as NOP. */
6af0bf9c
FB
10384 return;
10385 }
d75c135e 10386 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10387 opn = "mfc0";
10388 break;
10389 case OPC_MTC0:
1a3fd9c3 10390 {
1fc7bf6e 10391 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10392
10393 gen_load_gpr(t0, rt);
d75c135e 10394 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10395 tcg_temp_free(t0);
10396 }
6af0bf9c
FB
10397 opn = "mtc0";
10398 break;
d26bc211 10399#if defined(TARGET_MIPS64)
9c2149c8 10400 case OPC_DMFC0:
d75c135e 10401 check_insn(ctx, ISA_MIPS3);
9c2149c8 10402 if (rt == 0) {
ead9360e 10403 /* Treat as NOP. */
9c2149c8
TS
10404 return;
10405 }
d75c135e 10406 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10407 opn = "dmfc0";
10408 break;
10409 case OPC_DMTC0:
d75c135e 10410 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10411 {
1fc7bf6e 10412 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10413
10414 gen_load_gpr(t0, rt);
d75c135e 10415 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10416 tcg_temp_free(t0);
10417 }
9c2149c8
TS
10418 opn = "dmtc0";
10419 break;
534ce69f 10420#endif
5204ea79
LA
10421 case OPC_MFHC0:
10422 check_mvh(ctx);
10423 if (rt == 0) {
10424 /* Treat as NOP. */
10425 return;
10426 }
10427 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10428 opn = "mfhc0";
10429 break;
10430 case OPC_MTHC0:
10431 check_mvh(ctx);
10432 {
10433 TCGv t0 = tcg_temp_new();
10434 gen_load_gpr(t0, rt);
10435 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10436 tcg_temp_free(t0);
10437 }
10438 opn = "mthc0";
10439 break;
ead9360e 10440 case OPC_MFTR:
9affc1c5 10441 check_cp0_enabled(ctx);
ead9360e
TS
10442 if (rd == 0) {
10443 /* Treat as NOP. */
10444 return;
10445 }
6c5c1e20 10446 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10447 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10448 opn = "mftr";
10449 break;
10450 case OPC_MTTR:
9affc1c5 10451 check_cp0_enabled(ctx);
6c5c1e20 10452 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10453 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10454 opn = "mttr";
10455 break;
6af0bf9c 10456 case OPC_TLBWI:
6af0bf9c 10457 opn = "tlbwi";
1f8929d2 10458 if (!env->tlb->helper_tlbwi) {
29929e34 10459 goto die;
1f8929d2 10460 }
895c2d04 10461 gen_helper_tlbwi(cpu_env);
6af0bf9c 10462 break;
9456c2fb
LA
10463 case OPC_TLBINV:
10464 opn = "tlbinv";
10465 if (ctx->ie >= 2) {
10466 if (!env->tlb->helper_tlbinv) {
10467 goto die;
10468 }
10469 gen_helper_tlbinv(cpu_env);
10470 } /* treat as nop if TLBINV not supported */
10471 break;
10472 case OPC_TLBINVF:
10473 opn = "tlbinvf";
10474 if (ctx->ie >= 2) {
10475 if (!env->tlb->helper_tlbinvf) {
10476 goto die;
10477 }
10478 gen_helper_tlbinvf(cpu_env);
10479 } /* treat as nop if TLBINV not supported */
10480 break;
6af0bf9c 10481 case OPC_TLBWR:
6af0bf9c 10482 opn = "tlbwr";
1f8929d2 10483 if (!env->tlb->helper_tlbwr) {
29929e34 10484 goto die;
1f8929d2 10485 }
895c2d04 10486 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10487 break;
10488 case OPC_TLBP:
6af0bf9c 10489 opn = "tlbp";
1f8929d2 10490 if (!env->tlb->helper_tlbp) {
29929e34 10491 goto die;
1f8929d2 10492 }
895c2d04 10493 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10494 break;
10495 case OPC_TLBR:
6af0bf9c 10496 opn = "tlbr";
1f8929d2 10497 if (!env->tlb->helper_tlbr) {
29929e34 10498 goto die;
1f8929d2 10499 }
895c2d04 10500 gen_helper_tlbr(cpu_env);
6af0bf9c 10501 break;
ce9782f4 10502 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
10503 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10504 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10505 goto die;
ce9782f4
LA
10506 } else {
10507 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10508 if (ctx->opcode & (1 << bit_shift)) {
10509 /* OPC_ERETNC */
10510 opn = "eretnc";
10511 check_insn(ctx, ISA_MIPS32R5);
10512 gen_helper_eretnc(cpu_env);
10513 } else {
10514 /* OPC_ERET */
10515 opn = "eret";
10516 check_insn(ctx, ISA_MIPS2);
10517 gen_helper_eret(cpu_env);
10518 }
eeb3bba8 10519 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 10520 }
6af0bf9c
FB
10521 break;
10522 case OPC_DERET:
10523 opn = "deret";
d75c135e 10524 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
10525 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10526 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10527 goto die;
10528 }
6af0bf9c 10529 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 10530 MIPS_INVAL(opn);
9c708c7f 10531 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 10532 } else {
895c2d04 10533 gen_helper_deret(cpu_env);
eeb3bba8 10534 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
10535 }
10536 break;
4ad40f36
FB
10537 case OPC_WAIT:
10538 opn = "wait";
d75c135e 10539 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
10540 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10541 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10542 goto die;
10543 }
4ad40f36 10544 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 10545 ctx->base.pc_next += 4;
4ad40f36 10546 save_cpu_state(ctx, 1);
eeb3bba8 10547 ctx->base.pc_next -= 4;
895c2d04 10548 gen_helper_wait(cpu_env);
eeb3bba8 10549 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 10550 break;
6af0bf9c 10551 default:
29929e34 10552 die:
923617a3 10553 MIPS_INVAL(opn);
9c708c7f 10554 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
10555 return;
10556 }
2abf314d 10557 (void)opn; /* avoid a compiler warning */
6af0bf9c 10558}
f1aa6320 10559#endif /* !CONFIG_USER_ONLY */
6af0bf9c 10560
6ea83fed 10561/* CP1 Branches (before delay slot) */
d75c135e
AJ
10562static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10563 int32_t cc, int32_t offset)
6ea83fed
FB
10564{
10565 target_ulong btarget;
a7812ae4 10566 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 10567
339cd2a8 10568 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 10569 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
10570 goto out;
10571 }
10572
1f8929d2 10573 if (cc != 0) {
d75c135e 10574 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
1f8929d2 10575 }
e189e748 10576
eeb3bba8 10577 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 10578
7a387fff
TS
10579 switch (op) {
10580 case OPC_BC1F:
d94536f4
AJ
10581 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10582 tcg_gen_not_i32(t0, t0);
10583 tcg_gen_andi_i32(t0, t0, 1);
10584 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10585 goto not_likely;
7a387fff 10586 case OPC_BC1FL:
d94536f4
AJ
10587 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10588 tcg_gen_not_i32(t0, t0);
10589 tcg_gen_andi_i32(t0, t0, 1);
10590 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10591 goto likely;
7a387fff 10592 case OPC_BC1T:
d94536f4
AJ
10593 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10594 tcg_gen_andi_i32(t0, t0, 1);
10595 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10596 goto not_likely;
7a387fff 10597 case OPC_BC1TL:
d94536f4
AJ
10598 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10599 tcg_gen_andi_i32(t0, t0, 1);
10600 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10601 likely:
10602 ctx->hflags |= MIPS_HFLAG_BL;
10603 break;
5a5012ec 10604 case OPC_BC1FANY2:
a16336e4 10605 {
d94536f4
AJ
10606 TCGv_i32 t1 = tcg_temp_new_i32();
10607 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10608 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10609 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10610 tcg_temp_free_i32(t1);
d94536f4
AJ
10611 tcg_gen_andi_i32(t0, t0, 1);
10612 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10613 }
5a5012ec
TS
10614 goto not_likely;
10615 case OPC_BC1TANY2:
a16336e4 10616 {
d94536f4
AJ
10617 TCGv_i32 t1 = tcg_temp_new_i32();
10618 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10619 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
10620 tcg_gen_or_i32(t0, t0, t1);
10621 tcg_temp_free_i32(t1);
10622 tcg_gen_andi_i32(t0, t0, 1);
10623 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10624 }
5a5012ec
TS
10625 goto not_likely;
10626 case OPC_BC1FANY4:
a16336e4 10627 {
d94536f4
AJ
10628 TCGv_i32 t1 = tcg_temp_new_i32();
10629 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10630 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10631 tcg_gen_and_i32(t0, t0, t1);
71375b59 10632 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 10633 tcg_gen_and_i32(t0, t0, t1);
71375b59 10634 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 10635 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10636 tcg_temp_free_i32(t1);
d94536f4
AJ
10637 tcg_gen_andi_i32(t0, t0, 1);
10638 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10639 }
5a5012ec
TS
10640 goto not_likely;
10641 case OPC_BC1TANY4:
a16336e4 10642 {
d94536f4
AJ
10643 TCGv_i32 t1 = tcg_temp_new_i32();
10644 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10645 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 10646 tcg_gen_or_i32(t0, t0, t1);
71375b59 10647 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 10648 tcg_gen_or_i32(t0, t0, t1);
71375b59 10649 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
10650 tcg_gen_or_i32(t0, t0, t1);
10651 tcg_temp_free_i32(t1);
10652 tcg_gen_andi_i32(t0, t0, 1);
10653 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10654 }
5a5012ec
TS
10655 not_likely:
10656 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10657 break;
10658 default:
9d68ac14 10659 MIPS_INVAL("cp1 cond branch");
9c708c7f 10660 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10661 goto out;
6ea83fed 10662 }
6ea83fed 10663 ctx->btarget = btarget;
b231c103 10664 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10665 out:
a7812ae4 10666 tcg_temp_free_i32(t0);
6ea83fed
FB
10667}
10668
31837be3
YK
10669/* R6 CP1 Branches */
10670static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10671 int32_t ft, int32_t offset,
10672 int delayslot_size)
31837be3
YK
10673{
10674 target_ulong btarget;
31837be3
YK
10675 TCGv_i64 t0 = tcg_temp_new_i64();
10676
10677 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10678#ifdef MIPS_DEBUG_DISAS
339cd2a8 10679 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10680 "\n", ctx->base.pc_next);
31837be3 10681#endif
9c708c7f 10682 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10683 goto out;
10684 }
10685
10686 gen_load_fpr64(ctx, t0, ft);
10687 tcg_gen_andi_i64(t0, t0, 1);
10688
eeb3bba8 10689 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10690
10691 switch (op) {
10692 case OPC_BC1EQZ:
10693 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10694 ctx->hflags |= MIPS_HFLAG_BC;
10695 break;
10696 case OPC_BC1NEZ:
10697 /* t0 already set */
31837be3
YK
10698 ctx->hflags |= MIPS_HFLAG_BC;
10699 break;
10700 default:
9d68ac14 10701 MIPS_INVAL("cp1 cond branch");
9c708c7f 10702 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10703 goto out;
10704 }
10705
10706 tcg_gen_trunc_i64_tl(bcond, t0);
10707
31837be3 10708 ctx->btarget = btarget;
65935f07
YK
10709
10710 switch (delayslot_size) {
10711 case 2:
10712 ctx->hflags |= MIPS_HFLAG_BDS16;
10713 break;
10714 case 4:
10715 ctx->hflags |= MIPS_HFLAG_BDS32;
10716 break;
10717 }
31837be3
YK
10718
10719out:
10720 tcg_temp_free_i64(t0);
10721}
10722
6af0bf9c 10723/* Coprocessor 1 (FPU) */
5a5012ec 10724
5a5012ec
TS
10725#define FOP(func, fmt) (((fmt) << 21) | (func))
10726
bf4120ad
NF
10727enum fopcode {
10728 OPC_ADD_S = FOP(0, FMT_S),
10729 OPC_SUB_S = FOP(1, FMT_S),
10730 OPC_MUL_S = FOP(2, FMT_S),
10731 OPC_DIV_S = FOP(3, FMT_S),
10732 OPC_SQRT_S = FOP(4, FMT_S),
10733 OPC_ABS_S = FOP(5, FMT_S),
10734 OPC_MOV_S = FOP(6, FMT_S),
10735 OPC_NEG_S = FOP(7, FMT_S),
10736 OPC_ROUND_L_S = FOP(8, FMT_S),
10737 OPC_TRUNC_L_S = FOP(9, FMT_S),
10738 OPC_CEIL_L_S = FOP(10, FMT_S),
10739 OPC_FLOOR_L_S = FOP(11, FMT_S),
10740 OPC_ROUND_W_S = FOP(12, FMT_S),
10741 OPC_TRUNC_W_S = FOP(13, FMT_S),
10742 OPC_CEIL_W_S = FOP(14, FMT_S),
10743 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10744 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10745 OPC_MOVCF_S = FOP(17, FMT_S),
10746 OPC_MOVZ_S = FOP(18, FMT_S),
10747 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10748 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10749 OPC_RECIP_S = FOP(21, FMT_S),
10750 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10751 OPC_SELNEZ_S = FOP(23, FMT_S),
10752 OPC_MADDF_S = FOP(24, FMT_S),
10753 OPC_MSUBF_S = FOP(25, FMT_S),
10754 OPC_RINT_S = FOP(26, FMT_S),
10755 OPC_CLASS_S = FOP(27, FMT_S),
10756 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10757 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10758 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10759 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10760 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10761 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10762 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10763 OPC_RSQRT2_S = FOP(31, FMT_S),
10764 OPC_CVT_D_S = FOP(33, FMT_S),
10765 OPC_CVT_W_S = FOP(36, FMT_S),
10766 OPC_CVT_L_S = FOP(37, FMT_S),
10767 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
10768 OPC_CMP_F_S = FOP(48, FMT_S),
10769 OPC_CMP_UN_S = FOP(49, FMT_S),
10770 OPC_CMP_EQ_S = FOP(50, FMT_S),
10771 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10772 OPC_CMP_OLT_S = FOP(52, FMT_S),
10773 OPC_CMP_ULT_S = FOP(53, FMT_S),
10774 OPC_CMP_OLE_S = FOP(54, FMT_S),
10775 OPC_CMP_ULE_S = FOP(55, FMT_S),
10776 OPC_CMP_SF_S = FOP(56, FMT_S),
10777 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10778 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10779 OPC_CMP_NGL_S = FOP(59, FMT_S),
10780 OPC_CMP_LT_S = FOP(60, FMT_S),
10781 OPC_CMP_NGE_S = FOP(61, FMT_S),
10782 OPC_CMP_LE_S = FOP(62, FMT_S),
10783 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
10784
10785 OPC_ADD_D = FOP(0, FMT_D),
10786 OPC_SUB_D = FOP(1, FMT_D),
10787 OPC_MUL_D = FOP(2, FMT_D),
10788 OPC_DIV_D = FOP(3, FMT_D),
10789 OPC_SQRT_D = FOP(4, FMT_D),
10790 OPC_ABS_D = FOP(5, FMT_D),
10791 OPC_MOV_D = FOP(6, FMT_D),
10792 OPC_NEG_D = FOP(7, FMT_D),
10793 OPC_ROUND_L_D = FOP(8, FMT_D),
10794 OPC_TRUNC_L_D = FOP(9, FMT_D),
10795 OPC_CEIL_L_D = FOP(10, FMT_D),
10796 OPC_FLOOR_L_D = FOP(11, FMT_D),
10797 OPC_ROUND_W_D = FOP(12, FMT_D),
10798 OPC_TRUNC_W_D = FOP(13, FMT_D),
10799 OPC_CEIL_W_D = FOP(14, FMT_D),
10800 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10801 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10802 OPC_MOVCF_D = FOP(17, FMT_D),
10803 OPC_MOVZ_D = FOP(18, FMT_D),
10804 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10805 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10806 OPC_RECIP_D = FOP(21, FMT_D),
10807 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10808 OPC_SELNEZ_D = FOP(23, FMT_D),
10809 OPC_MADDF_D = FOP(24, FMT_D),
10810 OPC_MSUBF_D = FOP(25, FMT_D),
10811 OPC_RINT_D = FOP(26, FMT_D),
10812 OPC_CLASS_D = FOP(27, FMT_D),
10813 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10814 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10815 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10816 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10817 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10818 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10819 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10820 OPC_RSQRT2_D = FOP(31, FMT_D),
10821 OPC_CVT_S_D = FOP(32, FMT_D),
10822 OPC_CVT_W_D = FOP(36, FMT_D),
10823 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
10824 OPC_CMP_F_D = FOP(48, FMT_D),
10825 OPC_CMP_UN_D = FOP(49, FMT_D),
10826 OPC_CMP_EQ_D = FOP(50, FMT_D),
10827 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10828 OPC_CMP_OLT_D = FOP(52, FMT_D),
10829 OPC_CMP_ULT_D = FOP(53, FMT_D),
10830 OPC_CMP_OLE_D = FOP(54, FMT_D),
10831 OPC_CMP_ULE_D = FOP(55, FMT_D),
10832 OPC_CMP_SF_D = FOP(56, FMT_D),
10833 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10834 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10835 OPC_CMP_NGL_D = FOP(59, FMT_D),
10836 OPC_CMP_LT_D = FOP(60, FMT_D),
10837 OPC_CMP_NGE_D = FOP(61, FMT_D),
10838 OPC_CMP_LE_D = FOP(62, FMT_D),
10839 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
10840
10841 OPC_CVT_S_W = FOP(32, FMT_W),
10842 OPC_CVT_D_W = FOP(33, FMT_W),
10843 OPC_CVT_S_L = FOP(32, FMT_L),
10844 OPC_CVT_D_L = FOP(33, FMT_L),
10845 OPC_CVT_PS_PW = FOP(38, FMT_W),
10846
10847 OPC_ADD_PS = FOP(0, FMT_PS),
10848 OPC_SUB_PS = FOP(1, FMT_PS),
10849 OPC_MUL_PS = FOP(2, FMT_PS),
10850 OPC_DIV_PS = FOP(3, FMT_PS),
10851 OPC_ABS_PS = FOP(5, FMT_PS),
10852 OPC_MOV_PS = FOP(6, FMT_PS),
10853 OPC_NEG_PS = FOP(7, FMT_PS),
10854 OPC_MOVCF_PS = FOP(17, FMT_PS),
10855 OPC_MOVZ_PS = FOP(18, FMT_PS),
10856 OPC_MOVN_PS = FOP(19, FMT_PS),
10857 OPC_ADDR_PS = FOP(24, FMT_PS),
10858 OPC_MULR_PS = FOP(26, FMT_PS),
10859 OPC_RECIP2_PS = FOP(28, FMT_PS),
10860 OPC_RECIP1_PS = FOP(29, FMT_PS),
10861 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10862 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10863
10864 OPC_CVT_S_PU = FOP(32, FMT_PS),
10865 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10866 OPC_CVT_S_PL = FOP(40, FMT_PS),
10867 OPC_PLL_PS = FOP(44, FMT_PS),
10868 OPC_PLU_PS = FOP(45, FMT_PS),
10869 OPC_PUL_PS = FOP(46, FMT_PS),
10870 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
10871 OPC_CMP_F_PS = FOP(48, FMT_PS),
10872 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10873 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10874 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10875 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10876 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10877 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10878 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10879 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10880 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10881 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10882 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10883 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10884 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10885 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10886 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
10887};
10888
3f493883
YK
10889enum r6_f_cmp_op {
10890 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10891 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10892 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10893 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10894 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10895 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10896 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10897 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10898 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10899 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10900 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10901 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10902 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10903 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10904 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10905 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10906 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10907 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10908 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10909 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10910 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10911 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10912
10913 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10914 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10915 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10916 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10917 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10918 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10919 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10920 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10921 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10922 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10923 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10924 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10925 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10926 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10927 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10928 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10929 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10930 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10931 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10932 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10933 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10934 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10935};
235785e8
AM
10936
10937static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10938{
72c3a3ee 10939 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10940
10941 switch (opc) {
10942 case OPC_MFC1:
b6d96bed 10943 {
a7812ae4 10944 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10945
7c979afd 10946 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10947 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10948 tcg_temp_free_i32(fp0);
6958549d 10949 }
6c5c1e20 10950 gen_store_gpr(t0, rt);
6ea83fed
FB
10951 break;
10952 case OPC_MTC1:
6c5c1e20 10953 gen_load_gpr(t0, rt);
b6d96bed 10954 {
a7812ae4 10955 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10956
10957 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10958 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10959 tcg_temp_free_i32(fp0);
6958549d 10960 }
6ea83fed
FB
10961 break;
10962 case OPC_CFC1:
895c2d04 10963 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10964 gen_store_gpr(t0, rt);
6ea83fed
FB
10965 break;
10966 case OPC_CTC1:
6c5c1e20 10967 gen_load_gpr(t0, rt);
9c708c7f 10968 save_cpu_state(ctx, 0);
736d120a
PJ
10969 {
10970 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10971
10972 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10973 tcg_temp_free_i32(fs_tmp);
10974 }
4cf8a45f 10975 /* Stop translation as we may have changed hflags */
eeb3bba8 10976 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10977 break;
72c3a3ee 10978#if defined(TARGET_MIPS64)
9c2149c8 10979 case OPC_DMFC1:
72c3a3ee 10980 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10981 gen_store_gpr(t0, rt);
5a5012ec 10982 break;
9c2149c8 10983 case OPC_DMTC1:
6c5c1e20 10984 gen_load_gpr(t0, rt);
72c3a3ee 10985 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10986 break;
72c3a3ee 10987#endif
5a5012ec 10988 case OPC_MFHC1:
b6d96bed 10989 {
a7812ae4 10990 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10991
7f6613ce 10992 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10993 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10994 tcg_temp_free_i32(fp0);
6958549d 10995 }
6c5c1e20 10996 gen_store_gpr(t0, rt);
5a5012ec
TS
10997 break;
10998 case OPC_MTHC1:
6c5c1e20 10999 gen_load_gpr(t0, rt);
b6d96bed 11000 {
a7812ae4 11001 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
11002
11003 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 11004 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 11005 tcg_temp_free_i32(fp0);
6958549d 11006 }
5a5012ec 11007 break;
6ea83fed 11008 default:
9d68ac14 11009 MIPS_INVAL("cp1 move");
9c708c7f 11010 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 11011 goto out;
6ea83fed 11012 }
6c5c1e20
TS
11013
11014 out:
11015 tcg_temp_free(t0);
6ea83fed
FB
11016}
11017
235785e8 11018static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 11019{
42a268c2 11020 TCGLabel *l1;
e214b9bb 11021 TCGCond cond;
af58f9ca
AJ
11022 TCGv_i32 t0;
11023
11024 if (rd == 0) {
11025 /* Treat as NOP. */
11026 return;
11027 }
6ea83fed 11028
1f8929d2 11029 if (tf) {
e214b9bb 11030 cond = TCG_COND_EQ;
1f8929d2 11031 } else {
27848470 11032 cond = TCG_COND_NE;
1f8929d2 11033 }
27848470 11034
af58f9ca
AJ
11035 l1 = gen_new_label();
11036 t0 = tcg_temp_new_i32();
fa31af0e 11037 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 11038 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11039 tcg_temp_free_i32(t0);
af58f9ca
AJ
11040 if (rs == 0) {
11041 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11042 } else {
11043 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11044 }
e214b9bb 11045 gen_set_label(l1);
5a5012ec
TS
11046}
11047
7c979afd
LA
11048static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11049 int tf)
a16336e4 11050{
a16336e4 11051 int cond;
cbc37b28 11052 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 11053 TCGLabel *l1 = gen_new_label();
a16336e4 11054
1f8929d2 11055 if (tf) {
a16336e4 11056 cond = TCG_COND_EQ;
1f8929d2 11057 } else {
a16336e4 11058 cond = TCG_COND_NE;
1f8929d2 11059 }
a16336e4 11060
fa31af0e 11061 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11062 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11063 gen_load_fpr32(ctx, t0, fs);
11064 gen_store_fpr32(ctx, t0, fd);
a16336e4 11065 gen_set_label(l1);
cbc37b28 11066 tcg_temp_free_i32(t0);
5a5012ec 11067}
a16336e4 11068
235785e8
AM
11069static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11070 int tf)
a16336e4 11071{
a16336e4 11072 int cond;
cbc37b28
AJ
11073 TCGv_i32 t0 = tcg_temp_new_i32();
11074 TCGv_i64 fp0;
42a268c2 11075 TCGLabel *l1 = gen_new_label();
a16336e4 11076
1f8929d2 11077 if (tf) {
a16336e4 11078 cond = TCG_COND_EQ;
1f8929d2 11079 } else {
a16336e4 11080 cond = TCG_COND_NE;
1f8929d2 11081 }
a16336e4 11082
fa31af0e 11083 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11084 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11085 tcg_temp_free_i32(t0);
11f94258 11086 fp0 = tcg_temp_new_i64();
9bf3eb2c 11087 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 11088 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11089 tcg_temp_free_i64(fp0);
cbc37b28 11090 gen_set_label(l1);
a16336e4
TS
11091}
11092
7f6613ce
PJ
11093static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11094 int cc, int tf)
a16336e4
TS
11095{
11096 int cond;
cbc37b28 11097 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
11098 TCGLabel *l1 = gen_new_label();
11099 TCGLabel *l2 = gen_new_label();
a16336e4 11100
1f8929d2 11101 if (tf) {
a16336e4 11102 cond = TCG_COND_EQ;
1f8929d2 11103 } else {
a16336e4 11104 cond = TCG_COND_NE;
1f8929d2 11105 }
a16336e4 11106
fa31af0e 11107 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11108 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11109 gen_load_fpr32(ctx, t0, fs);
11110 gen_store_fpr32(ctx, t0, fd);
a16336e4 11111 gen_set_label(l1);
9bf3eb2c 11112
71375b59 11113 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 11114 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
11115 gen_load_fpr32h(ctx, t0, fs);
11116 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 11117 tcg_temp_free_i32(t0);
a16336e4 11118 gen_set_label(l2);
a16336e4
TS
11119}
11120
e7f16abb
LA
11121static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11122 int fs)
11123{
11124 TCGv_i32 t1 = tcg_const_i32(0);
11125 TCGv_i32 fp0 = tcg_temp_new_i32();
11126 TCGv_i32 fp1 = tcg_temp_new_i32();
11127 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11128 gen_load_fpr32(ctx, fp0, fd);
11129 gen_load_fpr32(ctx, fp1, ft);
11130 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
11131
11132 switch (op1) {
11133 case OPC_SEL_S:
11134 tcg_gen_andi_i32(fp0, fp0, 1);
11135 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11136 break;
11137 case OPC_SELEQZ_S:
11138 tcg_gen_andi_i32(fp1, fp1, 1);
11139 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11140 break;
11141 case OPC_SELNEZ_S:
11142 tcg_gen_andi_i32(fp1, fp1, 1);
11143 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11144 break;
11145 default:
11146 MIPS_INVAL("gen_sel_s");
9c708c7f 11147 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11148 break;
11149 }
11150
7c979afd 11151 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11152 tcg_temp_free_i32(fp2);
11153 tcg_temp_free_i32(fp1);
11154 tcg_temp_free_i32(fp0);
11155 tcg_temp_free_i32(t1);
11156}
11157
11158static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11159 int fs)
11160{
11161 TCGv_i64 t1 = tcg_const_i64(0);
11162 TCGv_i64 fp0 = tcg_temp_new_i64();
11163 TCGv_i64 fp1 = tcg_temp_new_i64();
11164 TCGv_i64 fp2 = tcg_temp_new_i64();
11165 gen_load_fpr64(ctx, fp0, fd);
11166 gen_load_fpr64(ctx, fp1, ft);
11167 gen_load_fpr64(ctx, fp2, fs);
11168
11169 switch (op1) {
11170 case OPC_SEL_D:
11171 tcg_gen_andi_i64(fp0, fp0, 1);
11172 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11173 break;
11174 case OPC_SELEQZ_D:
11175 tcg_gen_andi_i64(fp1, fp1, 1);
11176 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11177 break;
11178 case OPC_SELNEZ_D:
11179 tcg_gen_andi_i64(fp1, fp1, 1);
11180 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11181 break;
11182 default:
11183 MIPS_INVAL("gen_sel_d");
9c708c7f 11184 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11185 break;
11186 }
11187
11188 gen_store_fpr64(ctx, fp0, fd);
11189 tcg_temp_free_i64(fp2);
11190 tcg_temp_free_i64(fp1);
11191 tcg_temp_free_i64(fp0);
11192 tcg_temp_free_i64(t1);
11193}
6ea83fed 11194
235785e8
AM
11195static void gen_farith(DisasContext *ctx, enum fopcode op1,
11196 int ft, int fs, int fd, int cc)
6ea83fed 11197{
7a387fff 11198 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
11199 switch (op1) {
11200 case OPC_ADD_S:
b6d96bed 11201 {
a7812ae4
PB
11202 TCGv_i32 fp0 = tcg_temp_new_i32();
11203 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11204
7c979afd
LA
11205 gen_load_fpr32(ctx, fp0, fs);
11206 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11207 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11208 tcg_temp_free_i32(fp1);
7c979afd 11209 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11210 tcg_temp_free_i32(fp0);
b6d96bed 11211 }
5a5012ec 11212 break;
bf4120ad 11213 case OPC_SUB_S:
b6d96bed 11214 {
a7812ae4
PB
11215 TCGv_i32 fp0 = tcg_temp_new_i32();
11216 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11217
7c979afd
LA
11218 gen_load_fpr32(ctx, fp0, fs);
11219 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11220 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11221 tcg_temp_free_i32(fp1);
7c979afd 11222 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11223 tcg_temp_free_i32(fp0);
b6d96bed 11224 }
5a5012ec 11225 break;
bf4120ad 11226 case OPC_MUL_S:
b6d96bed 11227 {
a7812ae4
PB
11228 TCGv_i32 fp0 = tcg_temp_new_i32();
11229 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11230
7c979afd
LA
11231 gen_load_fpr32(ctx, fp0, fs);
11232 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11233 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11234 tcg_temp_free_i32(fp1);
7c979afd 11235 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11236 tcg_temp_free_i32(fp0);
b6d96bed 11237 }
5a5012ec 11238 break;
bf4120ad 11239 case OPC_DIV_S:
b6d96bed 11240 {
a7812ae4
PB
11241 TCGv_i32 fp0 = tcg_temp_new_i32();
11242 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11243
7c979afd
LA
11244 gen_load_fpr32(ctx, fp0, fs);
11245 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11246 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11247 tcg_temp_free_i32(fp1);
7c979afd 11248 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11249 tcg_temp_free_i32(fp0);
b6d96bed 11250 }
5a5012ec 11251 break;
bf4120ad 11252 case OPC_SQRT_S:
b6d96bed 11253 {
a7812ae4 11254 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11255
7c979afd 11256 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11257 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 11258 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11259 tcg_temp_free_i32(fp0);
b6d96bed 11260 }
5a5012ec 11261 break;
bf4120ad 11262 case OPC_ABS_S:
b6d96bed 11263 {
a7812ae4 11264 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11265
7c979afd 11266 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11267 if (ctx->abs2008) {
11268 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11269 } else {
11270 gen_helper_float_abs_s(fp0, fp0);
11271 }
7c979afd 11272 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11273 tcg_temp_free_i32(fp0);
b6d96bed 11274 }
5a5012ec 11275 break;
bf4120ad 11276 case OPC_MOV_S:
b6d96bed 11277 {
a7812ae4 11278 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11279
7c979afd
LA
11280 gen_load_fpr32(ctx, fp0, fs);
11281 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11282 tcg_temp_free_i32(fp0);
b6d96bed 11283 }
5a5012ec 11284 break;
bf4120ad 11285 case OPC_NEG_S:
b6d96bed 11286 {
a7812ae4 11287 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11288
7c979afd 11289 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11290 if (ctx->abs2008) {
11291 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11292 } else {
11293 gen_helper_float_chs_s(fp0, fp0);
11294 }
7c979afd 11295 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11296 tcg_temp_free_i32(fp0);
b6d96bed 11297 }
5a5012ec 11298 break;
bf4120ad 11299 case OPC_ROUND_L_S:
5e755519 11300 check_cp1_64bitmode(ctx);
b6d96bed 11301 {
a7812ae4
PB
11302 TCGv_i32 fp32 = tcg_temp_new_i32();
11303 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11304
7c979afd 11305 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11306 if (ctx->nan2008) {
11307 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11308 } else {
11309 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11310 }
a7812ae4 11311 tcg_temp_free_i32(fp32);
b6d96bed 11312 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11313 tcg_temp_free_i64(fp64);
b6d96bed 11314 }
5a5012ec 11315 break;
bf4120ad 11316 case OPC_TRUNC_L_S:
5e755519 11317 check_cp1_64bitmode(ctx);
b6d96bed 11318 {
a7812ae4
PB
11319 TCGv_i32 fp32 = tcg_temp_new_i32();
11320 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11321
7c979afd 11322 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11323 if (ctx->nan2008) {
11324 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11325 } else {
11326 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11327 }
a7812ae4 11328 tcg_temp_free_i32(fp32);
b6d96bed 11329 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11330 tcg_temp_free_i64(fp64);
b6d96bed 11331 }
5a5012ec 11332 break;
bf4120ad 11333 case OPC_CEIL_L_S:
5e755519 11334 check_cp1_64bitmode(ctx);
b6d96bed 11335 {
a7812ae4
PB
11336 TCGv_i32 fp32 = tcg_temp_new_i32();
11337 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11338
7c979afd 11339 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11340 if (ctx->nan2008) {
11341 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11342 } else {
11343 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11344 }
a7812ae4 11345 tcg_temp_free_i32(fp32);
b6d96bed 11346 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11347 tcg_temp_free_i64(fp64);
b6d96bed 11348 }
5a5012ec 11349 break;
bf4120ad 11350 case OPC_FLOOR_L_S:
5e755519 11351 check_cp1_64bitmode(ctx);
b6d96bed 11352 {
a7812ae4
PB
11353 TCGv_i32 fp32 = tcg_temp_new_i32();
11354 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11355
7c979afd 11356 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11357 if (ctx->nan2008) {
11358 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11359 } else {
11360 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11361 }
a7812ae4 11362 tcg_temp_free_i32(fp32);
b6d96bed 11363 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11364 tcg_temp_free_i64(fp64);
b6d96bed 11365 }
5a5012ec 11366 break;
bf4120ad 11367 case OPC_ROUND_W_S:
b6d96bed 11368 {
a7812ae4 11369 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11370
7c979afd 11371 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11372 if (ctx->nan2008) {
11373 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11374 } else {
11375 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11376 }
7c979afd 11377 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11378 tcg_temp_free_i32(fp0);
b6d96bed 11379 }
5a5012ec 11380 break;
bf4120ad 11381 case OPC_TRUNC_W_S:
b6d96bed 11382 {
a7812ae4 11383 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11384
7c979afd 11385 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11386 if (ctx->nan2008) {
11387 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11388 } else {
11389 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11390 }
7c979afd 11391 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11392 tcg_temp_free_i32(fp0);
b6d96bed 11393 }
5a5012ec 11394 break;
bf4120ad 11395 case OPC_CEIL_W_S:
b6d96bed 11396 {
a7812ae4 11397 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11398
7c979afd 11399 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11400 if (ctx->nan2008) {
11401 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11402 } else {
11403 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11404 }
7c979afd 11405 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11406 tcg_temp_free_i32(fp0);
b6d96bed 11407 }
5a5012ec 11408 break;
bf4120ad 11409 case OPC_FLOOR_W_S:
b6d96bed 11410 {
a7812ae4 11411 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11412
7c979afd 11413 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11414 if (ctx->nan2008) {
11415 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11416 } else {
11417 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11418 }
7c979afd 11419 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11420 tcg_temp_free_i32(fp0);
b6d96bed 11421 }
5a5012ec 11422 break;
e7f16abb
LA
11423 case OPC_SEL_S:
11424 check_insn(ctx, ISA_MIPS32R6);
11425 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11426 break;
11427 case OPC_SELEQZ_S:
11428 check_insn(ctx, ISA_MIPS32R6);
11429 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11430 break;
11431 case OPC_SELNEZ_S:
11432 check_insn(ctx, ISA_MIPS32R6);
11433 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11434 break;
bf4120ad 11435 case OPC_MOVCF_S:
fecd2646 11436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 11437 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11438 break;
bf4120ad 11439 case OPC_MOVZ_S:
fecd2646 11440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11441 {
42a268c2 11442 TCGLabel *l1 = gen_new_label();
c9297f4d 11443 TCGv_i32 fp0;
a16336e4 11444
c9297f4d
AJ
11445 if (ft != 0) {
11446 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11447 }
11448 fp0 = tcg_temp_new_i32();
7c979afd
LA
11449 gen_load_fpr32(ctx, fp0, fs);
11450 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11451 tcg_temp_free_i32(fp0);
a16336e4
TS
11452 gen_set_label(l1);
11453 }
5a5012ec 11454 break;
bf4120ad 11455 case OPC_MOVN_S:
fecd2646 11456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11457 {
42a268c2 11458 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11459 TCGv_i32 fp0;
11460
11461 if (ft != 0) {
11462 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11463 fp0 = tcg_temp_new_i32();
7c979afd
LA
11464 gen_load_fpr32(ctx, fp0, fs);
11465 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11466 tcg_temp_free_i32(fp0);
11467 gen_set_label(l1);
11468 }
a16336e4 11469 }
5a5012ec 11470 break;
bf4120ad 11471 case OPC_RECIP_S:
b6d96bed 11472 {
a7812ae4 11473 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11474
7c979afd 11475 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11476 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11477 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11478 tcg_temp_free_i32(fp0);
b6d96bed 11479 }
57fa1fb3 11480 break;
bf4120ad 11481 case OPC_RSQRT_S:
b6d96bed 11482 {
a7812ae4 11483 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11484
7c979afd 11485 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11486 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11487 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11488 tcg_temp_free_i32(fp0);
b6d96bed 11489 }
57fa1fb3 11490 break;
e7f16abb
LA
11491 case OPC_MADDF_S:
11492 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11493 {
a7812ae4
PB
11494 TCGv_i32 fp0 = tcg_temp_new_i32();
11495 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11496 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11497 gen_load_fpr32(ctx, fp0, fs);
11498 gen_load_fpr32(ctx, fp1, ft);
11499 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11500 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11501 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11502 tcg_temp_free_i32(fp2);
a7812ae4 11503 tcg_temp_free_i32(fp1);
a7812ae4 11504 tcg_temp_free_i32(fp0);
b6d96bed 11505 }
57fa1fb3 11506 break;
e7f16abb
LA
11507 case OPC_MSUBF_S:
11508 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11509 {
a7812ae4 11510 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11511 TCGv_i32 fp1 = tcg_temp_new_i32();
11512 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11513 gen_load_fpr32(ctx, fp0, fs);
11514 gen_load_fpr32(ctx, fp1, ft);
11515 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11516 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11517 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11518 tcg_temp_free_i32(fp2);
11519 tcg_temp_free_i32(fp1);
a7812ae4 11520 tcg_temp_free_i32(fp0);
b6d96bed 11521 }
57fa1fb3 11522 break;
e7f16abb
LA
11523 case OPC_RINT_S:
11524 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11525 {
a7812ae4 11526 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11527 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11528 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 11529 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11530 tcg_temp_free_i32(fp0);
b6d96bed 11531 }
57fa1fb3 11532 break;
e7f16abb
LA
11533 case OPC_CLASS_S:
11534 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11535 {
e7f16abb 11536 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11537 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 11538 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 11539 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 11540 tcg_temp_free_i32(fp0);
e7f16abb
LA
11541 }
11542 break;
11543 case OPC_MIN_S: /* OPC_RECIP2_S */
11544 if (ctx->insn_flags & ISA_MIPS32R6) {
11545 /* OPC_MIN_S */
a7812ae4
PB
11546 TCGv_i32 fp0 = tcg_temp_new_i32();
11547 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11548 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11549 gen_load_fpr32(ctx, fp0, fs);
11550 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11551 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 11552 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11553 tcg_temp_free_i32(fp2);
11554 tcg_temp_free_i32(fp1);
11555 tcg_temp_free_i32(fp0);
e7f16abb
LA
11556 } else {
11557 /* OPC_RECIP2_S */
11558 check_cp1_64bitmode(ctx);
11559 {
11560 TCGv_i32 fp0 = tcg_temp_new_i32();
11561 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11562
7c979afd
LA
11563 gen_load_fpr32(ctx, fp0, fs);
11564 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11565 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11566 tcg_temp_free_i32(fp1);
7c979afd 11567 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11568 tcg_temp_free_i32(fp0);
11569 }
e7f16abb
LA
11570 }
11571 break;
11572 case OPC_MINA_S: /* OPC_RECIP1_S */
11573 if (ctx->insn_flags & ISA_MIPS32R6) {
11574 /* OPC_MINA_S */
11575 TCGv_i32 fp0 = tcg_temp_new_i32();
11576 TCGv_i32 fp1 = tcg_temp_new_i32();
11577 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11578 gen_load_fpr32(ctx, fp0, fs);
11579 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11580 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 11581 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11582 tcg_temp_free_i32(fp2);
11583 tcg_temp_free_i32(fp1);
11584 tcg_temp_free_i32(fp0);
e7f16abb
LA
11585 } else {
11586 /* OPC_RECIP1_S */
11587 check_cp1_64bitmode(ctx);
11588 {
11589 TCGv_i32 fp0 = tcg_temp_new_i32();
11590
7c979afd 11591 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11592 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 11593 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11594 tcg_temp_free_i32(fp0);
11595 }
e7f16abb
LA
11596 }
11597 break;
11598 case OPC_MAX_S: /* OPC_RSQRT1_S */
11599 if (ctx->insn_flags & ISA_MIPS32R6) {
11600 /* OPC_MAX_S */
11601 TCGv_i32 fp0 = tcg_temp_new_i32();
11602 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11603 gen_load_fpr32(ctx, fp0, fs);
11604 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11605 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11606 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11607 tcg_temp_free_i32(fp1);
11608 tcg_temp_free_i32(fp0);
e7f16abb
LA
11609 } else {
11610 /* OPC_RSQRT1_S */
11611 check_cp1_64bitmode(ctx);
11612 {
11613 TCGv_i32 fp0 = tcg_temp_new_i32();
11614
7c979afd 11615 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11616 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11617 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11618 tcg_temp_free_i32(fp0);
11619 }
e7f16abb
LA
11620 }
11621 break;
11622 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11623 if (ctx->insn_flags & ISA_MIPS32R6) {
11624 /* OPC_MAXA_S */
11625 TCGv_i32 fp0 = tcg_temp_new_i32();
11626 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11627 gen_load_fpr32(ctx, fp0, fs);
11628 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11629 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11630 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11631 tcg_temp_free_i32(fp1);
a7812ae4 11632 tcg_temp_free_i32(fp0);
e7f16abb
LA
11633 } else {
11634 /* OPC_RSQRT2_S */
11635 check_cp1_64bitmode(ctx);
11636 {
11637 TCGv_i32 fp0 = tcg_temp_new_i32();
11638 TCGv_i32 fp1 = tcg_temp_new_i32();
11639
7c979afd
LA
11640 gen_load_fpr32(ctx, fp0, fs);
11641 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11642 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11643 tcg_temp_free_i32(fp1);
7c979afd 11644 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11645 tcg_temp_free_i32(fp0);
11646 }
b6d96bed 11647 }
57fa1fb3 11648 break;
bf4120ad 11649 case OPC_CVT_D_S:
5e755519 11650 check_cp1_registers(ctx, fd);
b6d96bed 11651 {
a7812ae4
PB
11652 TCGv_i32 fp32 = tcg_temp_new_i32();
11653 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11654
7c979afd 11655 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11656 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11657 tcg_temp_free_i32(fp32);
b6d96bed 11658 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11659 tcg_temp_free_i64(fp64);
b6d96bed 11660 }
5a5012ec 11661 break;
bf4120ad 11662 case OPC_CVT_W_S:
b6d96bed 11663 {
a7812ae4 11664 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11665
7c979afd 11666 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11667 if (ctx->nan2008) {
11668 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11669 } else {
11670 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11671 }
7c979afd 11672 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11673 tcg_temp_free_i32(fp0);
b6d96bed 11674 }
5a5012ec 11675 break;
bf4120ad 11676 case OPC_CVT_L_S:
5e755519 11677 check_cp1_64bitmode(ctx);
b6d96bed 11678 {
a7812ae4
PB
11679 TCGv_i32 fp32 = tcg_temp_new_i32();
11680 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11681
7c979afd 11682 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11683 if (ctx->nan2008) {
11684 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11685 } else {
11686 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11687 }
a7812ae4 11688 tcg_temp_free_i32(fp32);
b6d96bed 11689 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11690 tcg_temp_free_i64(fp64);
b6d96bed 11691 }
5a5012ec 11692 break;
bf4120ad 11693 case OPC_CVT_PS_S:
e29c9628 11694 check_ps(ctx);
b6d96bed 11695 {
a7812ae4
PB
11696 TCGv_i64 fp64 = tcg_temp_new_i64();
11697 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11698 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11699
7c979afd
LA
11700 gen_load_fpr32(ctx, fp32_0, fs);
11701 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11702 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11703 tcg_temp_free_i32(fp32_1);
11704 tcg_temp_free_i32(fp32_0);
36aa55dc 11705 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11706 tcg_temp_free_i64(fp64);
b6d96bed 11707 }
5a5012ec 11708 break;
bf4120ad
NF
11709 case OPC_CMP_F_S:
11710 case OPC_CMP_UN_S:
11711 case OPC_CMP_EQ_S:
11712 case OPC_CMP_UEQ_S:
11713 case OPC_CMP_OLT_S:
11714 case OPC_CMP_ULT_S:
11715 case OPC_CMP_OLE_S:
11716 case OPC_CMP_ULE_S:
11717 case OPC_CMP_SF_S:
11718 case OPC_CMP_NGLE_S:
11719 case OPC_CMP_SEQ_S:
11720 case OPC_CMP_NGL_S:
11721 case OPC_CMP_LT_S:
11722 case OPC_CMP_NGE_S:
11723 case OPC_CMP_LE_S:
11724 case OPC_CMP_NGT_S:
fecd2646 11725 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 11726 if (ctx->opcode & (1 << 6)) {
71375b59 11727 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 11728 } else {
71375b59 11729 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11730 }
5a5012ec 11731 break;
bf4120ad 11732 case OPC_ADD_D:
5e755519 11733 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11734 {
a7812ae4
PB
11735 TCGv_i64 fp0 = tcg_temp_new_i64();
11736 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11737
11738 gen_load_fpr64(ctx, fp0, fs);
11739 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11740 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11741 tcg_temp_free_i64(fp1);
b6d96bed 11742 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11743 tcg_temp_free_i64(fp0);
b6d96bed 11744 }
6ea83fed 11745 break;
bf4120ad 11746 case OPC_SUB_D:
5e755519 11747 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11748 {
a7812ae4
PB
11749 TCGv_i64 fp0 = tcg_temp_new_i64();
11750 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11751
11752 gen_load_fpr64(ctx, fp0, fs);
11753 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11754 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11755 tcg_temp_free_i64(fp1);
b6d96bed 11756 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11757 tcg_temp_free_i64(fp0);
b6d96bed 11758 }
6ea83fed 11759 break;
bf4120ad 11760 case OPC_MUL_D:
5e755519 11761 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11762 {
a7812ae4
PB
11763 TCGv_i64 fp0 = tcg_temp_new_i64();
11764 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11765
11766 gen_load_fpr64(ctx, fp0, fs);
11767 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11768 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11769 tcg_temp_free_i64(fp1);
b6d96bed 11770 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11771 tcg_temp_free_i64(fp0);
b6d96bed 11772 }
6ea83fed 11773 break;
bf4120ad 11774 case OPC_DIV_D:
5e755519 11775 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11776 {
a7812ae4
PB
11777 TCGv_i64 fp0 = tcg_temp_new_i64();
11778 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11779
11780 gen_load_fpr64(ctx, fp0, fs);
11781 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11782 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11783 tcg_temp_free_i64(fp1);
b6d96bed 11784 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11785 tcg_temp_free_i64(fp0);
b6d96bed 11786 }
6ea83fed 11787 break;
bf4120ad 11788 case OPC_SQRT_D:
5e755519 11789 check_cp1_registers(ctx, fs | fd);
b6d96bed 11790 {
a7812ae4 11791 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11792
11793 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11794 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11795 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11796 tcg_temp_free_i64(fp0);
b6d96bed 11797 }
6ea83fed 11798 break;
bf4120ad 11799 case OPC_ABS_D:
5e755519 11800 check_cp1_registers(ctx, fs | fd);
b6d96bed 11801 {
a7812ae4 11802 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11803
11804 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11805 if (ctx->abs2008) {
11806 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11807 } else {
11808 gen_helper_float_abs_d(fp0, fp0);
11809 }
b6d96bed 11810 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11811 tcg_temp_free_i64(fp0);
b6d96bed 11812 }
6ea83fed 11813 break;
bf4120ad 11814 case OPC_MOV_D:
5e755519 11815 check_cp1_registers(ctx, fs | fd);
b6d96bed 11816 {
a7812ae4 11817 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11818
11819 gen_load_fpr64(ctx, fp0, fs);
11820 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11821 tcg_temp_free_i64(fp0);
b6d96bed 11822 }
6ea83fed 11823 break;
bf4120ad 11824 case OPC_NEG_D:
5e755519 11825 check_cp1_registers(ctx, fs | fd);
b6d96bed 11826 {
a7812ae4 11827 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11828
11829 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11830 if (ctx->abs2008) {
11831 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11832 } else {
11833 gen_helper_float_chs_d(fp0, fp0);
11834 }
b6d96bed 11835 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11836 tcg_temp_free_i64(fp0);
b6d96bed 11837 }
6ea83fed 11838 break;
bf4120ad 11839 case OPC_ROUND_L_D:
5e755519 11840 check_cp1_64bitmode(ctx);
b6d96bed 11841 {
a7812ae4 11842 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11843
11844 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11845 if (ctx->nan2008) {
11846 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11847 } else {
11848 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11849 }
b6d96bed 11850 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11851 tcg_temp_free_i64(fp0);
b6d96bed 11852 }
5a5012ec 11853 break;
bf4120ad 11854 case OPC_TRUNC_L_D:
5e755519 11855 check_cp1_64bitmode(ctx);
b6d96bed 11856 {
a7812ae4 11857 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11858
11859 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11860 if (ctx->nan2008) {
11861 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11862 } else {
11863 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11864 }
b6d96bed 11865 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11866 tcg_temp_free_i64(fp0);
b6d96bed 11867 }
5a5012ec 11868 break;
bf4120ad 11869 case OPC_CEIL_L_D:
5e755519 11870 check_cp1_64bitmode(ctx);
b6d96bed 11871 {
a7812ae4 11872 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11873
11874 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11875 if (ctx->nan2008) {
11876 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11877 } else {
11878 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11879 }
b6d96bed 11880 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11881 tcg_temp_free_i64(fp0);
b6d96bed 11882 }
5a5012ec 11883 break;
bf4120ad 11884 case OPC_FLOOR_L_D:
5e755519 11885 check_cp1_64bitmode(ctx);
b6d96bed 11886 {
a7812ae4 11887 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11888
11889 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11890 if (ctx->nan2008) {
11891 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11892 } else {
11893 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11894 }
b6d96bed 11895 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11896 tcg_temp_free_i64(fp0);
b6d96bed 11897 }
5a5012ec 11898 break;
bf4120ad 11899 case OPC_ROUND_W_D:
5e755519 11900 check_cp1_registers(ctx, fs);
b6d96bed 11901 {
a7812ae4
PB
11902 TCGv_i32 fp32 = tcg_temp_new_i32();
11903 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11904
11905 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11906 if (ctx->nan2008) {
11907 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11908 } else {
11909 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11910 }
a7812ae4 11911 tcg_temp_free_i64(fp64);
7c979afd 11912 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11913 tcg_temp_free_i32(fp32);
b6d96bed 11914 }
6ea83fed 11915 break;
bf4120ad 11916 case OPC_TRUNC_W_D:
5e755519 11917 check_cp1_registers(ctx, fs);
b6d96bed 11918 {
a7812ae4
PB
11919 TCGv_i32 fp32 = tcg_temp_new_i32();
11920 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11921
11922 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11923 if (ctx->nan2008) {
11924 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11925 } else {
11926 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11927 }
a7812ae4 11928 tcg_temp_free_i64(fp64);
7c979afd 11929 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11930 tcg_temp_free_i32(fp32);
b6d96bed 11931 }
6ea83fed 11932 break;
bf4120ad 11933 case OPC_CEIL_W_D:
5e755519 11934 check_cp1_registers(ctx, fs);
b6d96bed 11935 {
a7812ae4
PB
11936 TCGv_i32 fp32 = tcg_temp_new_i32();
11937 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11938
11939 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11940 if (ctx->nan2008) {
11941 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11942 } else {
11943 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11944 }
a7812ae4 11945 tcg_temp_free_i64(fp64);
7c979afd 11946 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11947 tcg_temp_free_i32(fp32);
b6d96bed 11948 }
6ea83fed 11949 break;
bf4120ad 11950 case OPC_FLOOR_W_D:
5e755519 11951 check_cp1_registers(ctx, fs);
b6d96bed 11952 {
a7812ae4
PB
11953 TCGv_i32 fp32 = tcg_temp_new_i32();
11954 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11955
11956 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11957 if (ctx->nan2008) {
11958 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11959 } else {
11960 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11961 }
a7812ae4 11962 tcg_temp_free_i64(fp64);
7c979afd 11963 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11964 tcg_temp_free_i32(fp32);
b6d96bed 11965 }
6ea83fed 11966 break;
e7f16abb
LA
11967 case OPC_SEL_D:
11968 check_insn(ctx, ISA_MIPS32R6);
11969 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11970 break;
11971 case OPC_SELEQZ_D:
11972 check_insn(ctx, ISA_MIPS32R6);
11973 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11974 break;
11975 case OPC_SELNEZ_D:
11976 check_insn(ctx, ISA_MIPS32R6);
11977 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11978 break;
bf4120ad 11979 case OPC_MOVCF_D:
fecd2646 11980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 11981 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11982 break;
bf4120ad 11983 case OPC_MOVZ_D:
fecd2646 11984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11985 {
42a268c2 11986 TCGLabel *l1 = gen_new_label();
c9297f4d 11987 TCGv_i64 fp0;
a16336e4 11988
c9297f4d
AJ
11989 if (ft != 0) {
11990 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11991 }
11992 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11993 gen_load_fpr64(ctx, fp0, fs);
11994 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11995 tcg_temp_free_i64(fp0);
a16336e4
TS
11996 gen_set_label(l1);
11997 }
5a5012ec 11998 break;
bf4120ad 11999 case OPC_MOVN_D:
fecd2646 12000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 12001 {
42a268c2 12002 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
12003 TCGv_i64 fp0;
12004
12005 if (ft != 0) {
12006 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12007 fp0 = tcg_temp_new_i64();
12008 gen_load_fpr64(ctx, fp0, fs);
12009 gen_store_fpr64(ctx, fp0, fd);
12010 tcg_temp_free_i64(fp0);
12011 gen_set_label(l1);
12012 }
a16336e4 12013 }
6ea83fed 12014 break;
bf4120ad 12015 case OPC_RECIP_D:
ca6c7803 12016 check_cp1_registers(ctx, fs | fd);
b6d96bed 12017 {
a7812ae4 12018 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12019
12020 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12021 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 12022 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12023 tcg_temp_free_i64(fp0);
b6d96bed 12024 }
57fa1fb3 12025 break;
bf4120ad 12026 case OPC_RSQRT_D:
ca6c7803 12027 check_cp1_registers(ctx, fs | fd);
b6d96bed 12028 {
a7812ae4 12029 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12030
12031 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12032 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 12033 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12034 tcg_temp_free_i64(fp0);
b6d96bed 12035 }
57fa1fb3 12036 break;
e7f16abb
LA
12037 case OPC_MADDF_D:
12038 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12039 {
a7812ae4
PB
12040 TCGv_i64 fp0 = tcg_temp_new_i64();
12041 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 12042 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12043 gen_load_fpr64(ctx, fp0, fs);
12044 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12045 gen_load_fpr64(ctx, fp2, fd);
12046 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12047 gen_store_fpr64(ctx, fp2, fd);
12048 tcg_temp_free_i64(fp2);
a7812ae4 12049 tcg_temp_free_i64(fp1);
a7812ae4 12050 tcg_temp_free_i64(fp0);
b6d96bed 12051 }
57fa1fb3 12052 break;
e7f16abb
LA
12053 case OPC_MSUBF_D:
12054 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12055 {
a7812ae4 12056 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
12057 TCGv_i64 fp1 = tcg_temp_new_i64();
12058 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 12059 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
12060 gen_load_fpr64(ctx, fp1, ft);
12061 gen_load_fpr64(ctx, fp2, fd);
12062 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12063 gen_store_fpr64(ctx, fp2, fd);
12064 tcg_temp_free_i64(fp2);
12065 tcg_temp_free_i64(fp1);
a7812ae4 12066 tcg_temp_free_i64(fp0);
b6d96bed 12067 }
57fa1fb3 12068 break;
e7f16abb
LA
12069 case OPC_RINT_D:
12070 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12071 {
a7812ae4 12072 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12073 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 12074 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 12075 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12076 tcg_temp_free_i64(fp0);
b6d96bed 12077 }
57fa1fb3 12078 break;
e7f16abb
LA
12079 case OPC_CLASS_D:
12080 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 12081 {
e7f16abb
LA
12082 TCGv_i64 fp0 = tcg_temp_new_i64();
12083 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 12084 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
12085 gen_store_fpr64(ctx, fp0, fd);
12086 tcg_temp_free_i64(fp0);
e7f16abb
LA
12087 }
12088 break;
12089 case OPC_MIN_D: /* OPC_RECIP2_D */
12090 if (ctx->insn_flags & ISA_MIPS32R6) {
12091 /* OPC_MIN_D */
a7812ae4
PB
12092 TCGv_i64 fp0 = tcg_temp_new_i64();
12093 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
12094 gen_load_fpr64(ctx, fp0, fs);
12095 gen_load_fpr64(ctx, fp1, ft);
12096 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12097 gen_store_fpr64(ctx, fp1, fd);
12098 tcg_temp_free_i64(fp1);
12099 tcg_temp_free_i64(fp0);
e7f16abb
LA
12100 } else {
12101 /* OPC_RECIP2_D */
12102 check_cp1_64bitmode(ctx);
12103 {
12104 TCGv_i64 fp0 = tcg_temp_new_i64();
12105 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 12106
e7f16abb
LA
12107 gen_load_fpr64(ctx, fp0, fs);
12108 gen_load_fpr64(ctx, fp1, ft);
12109 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12110 tcg_temp_free_i64(fp1);
12111 gen_store_fpr64(ctx, fp0, fd);
12112 tcg_temp_free_i64(fp0);
12113 }
e7f16abb
LA
12114 }
12115 break;
12116 case OPC_MINA_D: /* OPC_RECIP1_D */
12117 if (ctx->insn_flags & ISA_MIPS32R6) {
12118 /* OPC_MINA_D */
12119 TCGv_i64 fp0 = tcg_temp_new_i64();
12120 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12121 gen_load_fpr64(ctx, fp0, fs);
12122 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12123 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12124 gen_store_fpr64(ctx, fp1, fd);
12125 tcg_temp_free_i64(fp1);
12126 tcg_temp_free_i64(fp0);
e7f16abb
LA
12127 } else {
12128 /* OPC_RECIP1_D */
12129 check_cp1_64bitmode(ctx);
12130 {
12131 TCGv_i64 fp0 = tcg_temp_new_i64();
12132
12133 gen_load_fpr64(ctx, fp0, fs);
12134 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12135 gen_store_fpr64(ctx, fp0, fd);
12136 tcg_temp_free_i64(fp0);
12137 }
e7f16abb
LA
12138 }
12139 break;
12140 case OPC_MAX_D: /* OPC_RSQRT1_D */
12141 if (ctx->insn_flags & ISA_MIPS32R6) {
12142 /* OPC_MAX_D */
12143 TCGv_i64 fp0 = tcg_temp_new_i64();
12144 TCGv_i64 fp1 = tcg_temp_new_i64();
12145 gen_load_fpr64(ctx, fp0, fs);
12146 gen_load_fpr64(ctx, fp1, ft);
12147 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12148 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 12149 tcg_temp_free_i64(fp1);
a7812ae4 12150 tcg_temp_free_i64(fp0);
e7f16abb
LA
12151 } else {
12152 /* OPC_RSQRT1_D */
12153 check_cp1_64bitmode(ctx);
12154 {
12155 TCGv_i64 fp0 = tcg_temp_new_i64();
12156
12157 gen_load_fpr64(ctx, fp0, fs);
12158 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12159 gen_store_fpr64(ctx, fp0, fd);
12160 tcg_temp_free_i64(fp0);
12161 }
e7f16abb
LA
12162 }
12163 break;
12164 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12165 if (ctx->insn_flags & ISA_MIPS32R6) {
12166 /* OPC_MAXA_D */
12167 TCGv_i64 fp0 = tcg_temp_new_i64();
12168 TCGv_i64 fp1 = tcg_temp_new_i64();
12169 gen_load_fpr64(ctx, fp0, fs);
12170 gen_load_fpr64(ctx, fp1, ft);
12171 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12172 gen_store_fpr64(ctx, fp1, fd);
12173 tcg_temp_free_i64(fp1);
12174 tcg_temp_free_i64(fp0);
e7f16abb
LA
12175 } else {
12176 /* OPC_RSQRT2_D */
12177 check_cp1_64bitmode(ctx);
12178 {
12179 TCGv_i64 fp0 = tcg_temp_new_i64();
12180 TCGv_i64 fp1 = tcg_temp_new_i64();
12181
12182 gen_load_fpr64(ctx, fp0, fs);
12183 gen_load_fpr64(ctx, fp1, ft);
12184 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12185 tcg_temp_free_i64(fp1);
12186 gen_store_fpr64(ctx, fp0, fd);
12187 tcg_temp_free_i64(fp0);
12188 }
b6d96bed 12189 }
57fa1fb3 12190 break;
bf4120ad
NF
12191 case OPC_CMP_F_D:
12192 case OPC_CMP_UN_D:
12193 case OPC_CMP_EQ_D:
12194 case OPC_CMP_UEQ_D:
12195 case OPC_CMP_OLT_D:
12196 case OPC_CMP_ULT_D:
12197 case OPC_CMP_OLE_D:
12198 case OPC_CMP_ULE_D:
12199 case OPC_CMP_SF_D:
12200 case OPC_CMP_NGLE_D:
12201 case OPC_CMP_SEQ_D:
12202 case OPC_CMP_NGL_D:
12203 case OPC_CMP_LT_D:
12204 case OPC_CMP_NGE_D:
12205 case OPC_CMP_LE_D:
12206 case OPC_CMP_NGT_D:
fecd2646 12207 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 12208 if (ctx->opcode & (1 << 6)) {
71375b59 12209 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 12210 } else {
71375b59 12211 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12212 }
6ea83fed 12213 break;
bf4120ad 12214 case OPC_CVT_S_D:
5e755519 12215 check_cp1_registers(ctx, fs);
b6d96bed 12216 {
a7812ae4
PB
12217 TCGv_i32 fp32 = tcg_temp_new_i32();
12218 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12219
12220 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12221 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 12222 tcg_temp_free_i64(fp64);
7c979afd 12223 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12224 tcg_temp_free_i32(fp32);
b6d96bed 12225 }
5a5012ec 12226 break;
bf4120ad 12227 case OPC_CVT_W_D:
5e755519 12228 check_cp1_registers(ctx, fs);
b6d96bed 12229 {
a7812ae4
PB
12230 TCGv_i32 fp32 = tcg_temp_new_i32();
12231 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12232
12233 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12234 if (ctx->nan2008) {
12235 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12236 } else {
12237 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12238 }
a7812ae4 12239 tcg_temp_free_i64(fp64);
7c979afd 12240 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12241 tcg_temp_free_i32(fp32);
b6d96bed 12242 }
5a5012ec 12243 break;
bf4120ad 12244 case OPC_CVT_L_D:
5e755519 12245 check_cp1_64bitmode(ctx);
b6d96bed 12246 {
a7812ae4 12247 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12248
12249 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12250 if (ctx->nan2008) {
12251 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12252 } else {
12253 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12254 }
b6d96bed 12255 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12256 tcg_temp_free_i64(fp0);
b6d96bed 12257 }
5a5012ec 12258 break;
bf4120ad 12259 case OPC_CVT_S_W:
b6d96bed 12260 {
a7812ae4 12261 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12262
7c979afd 12263 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12264 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 12265 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12266 tcg_temp_free_i32(fp0);
b6d96bed 12267 }
6ea83fed 12268 break;
bf4120ad 12269 case OPC_CVT_D_W:
5e755519 12270 check_cp1_registers(ctx, fd);
b6d96bed 12271 {
a7812ae4
PB
12272 TCGv_i32 fp32 = tcg_temp_new_i32();
12273 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12274
7c979afd 12275 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12276 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12277 tcg_temp_free_i32(fp32);
b6d96bed 12278 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12279 tcg_temp_free_i64(fp64);
b6d96bed 12280 }
5a5012ec 12281 break;
bf4120ad 12282 case OPC_CVT_S_L:
5e755519 12283 check_cp1_64bitmode(ctx);
b6d96bed 12284 {
a7812ae4
PB
12285 TCGv_i32 fp32 = tcg_temp_new_i32();
12286 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12287
12288 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12289 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12290 tcg_temp_free_i64(fp64);
7c979afd 12291 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12292 tcg_temp_free_i32(fp32);
b6d96bed 12293 }
5a5012ec 12294 break;
bf4120ad 12295 case OPC_CVT_D_L:
5e755519 12296 check_cp1_64bitmode(ctx);
b6d96bed 12297 {
a7812ae4 12298 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12299
12300 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12301 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12302 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12303 tcg_temp_free_i64(fp0);
b6d96bed 12304 }
5a5012ec 12305 break;
bf4120ad 12306 case OPC_CVT_PS_PW:
e29c9628 12307 check_ps(ctx);
b6d96bed 12308 {
a7812ae4 12309 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12310
12311 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12312 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12313 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12314 tcg_temp_free_i64(fp0);
b6d96bed 12315 }
5a5012ec 12316 break;
bf4120ad 12317 case OPC_ADD_PS:
e29c9628 12318 check_ps(ctx);
b6d96bed 12319 {
a7812ae4
PB
12320 TCGv_i64 fp0 = tcg_temp_new_i64();
12321 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12322
12323 gen_load_fpr64(ctx, fp0, fs);
12324 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12325 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12326 tcg_temp_free_i64(fp1);
b6d96bed 12327 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12328 tcg_temp_free_i64(fp0);
b6d96bed 12329 }
6ea83fed 12330 break;
bf4120ad 12331 case OPC_SUB_PS:
e29c9628 12332 check_ps(ctx);
b6d96bed 12333 {
a7812ae4
PB
12334 TCGv_i64 fp0 = tcg_temp_new_i64();
12335 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12336
12337 gen_load_fpr64(ctx, fp0, fs);
12338 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12339 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12340 tcg_temp_free_i64(fp1);
b6d96bed 12341 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12342 tcg_temp_free_i64(fp0);
b6d96bed 12343 }
6ea83fed 12344 break;
bf4120ad 12345 case OPC_MUL_PS:
e29c9628 12346 check_ps(ctx);
b6d96bed 12347 {
a7812ae4
PB
12348 TCGv_i64 fp0 = tcg_temp_new_i64();
12349 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12350
12351 gen_load_fpr64(ctx, fp0, fs);
12352 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12353 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12354 tcg_temp_free_i64(fp1);
b6d96bed 12355 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12356 tcg_temp_free_i64(fp0);
b6d96bed 12357 }
6ea83fed 12358 break;
bf4120ad 12359 case OPC_ABS_PS:
e29c9628 12360 check_ps(ctx);
b6d96bed 12361 {
a7812ae4 12362 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12363
12364 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12365 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12366 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12367 tcg_temp_free_i64(fp0);
b6d96bed 12368 }
6ea83fed 12369 break;
bf4120ad 12370 case OPC_MOV_PS:
e29c9628 12371 check_ps(ctx);
b6d96bed 12372 {
a7812ae4 12373 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12374
12375 gen_load_fpr64(ctx, fp0, fs);
12376 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12377 tcg_temp_free_i64(fp0);
b6d96bed 12378 }
6ea83fed 12379 break;
bf4120ad 12380 case OPC_NEG_PS:
e29c9628 12381 check_ps(ctx);
b6d96bed 12382 {
a7812ae4 12383 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12384
12385 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12386 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12387 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12388 tcg_temp_free_i64(fp0);
b6d96bed 12389 }
6ea83fed 12390 break;
bf4120ad 12391 case OPC_MOVCF_PS:
e29c9628 12392 check_ps(ctx);
7f6613ce 12393 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12394 break;
bf4120ad 12395 case OPC_MOVZ_PS:
e29c9628 12396 check_ps(ctx);
a16336e4 12397 {
42a268c2 12398 TCGLabel *l1 = gen_new_label();
30a3848b 12399 TCGv_i64 fp0;
a16336e4 12400
1f8929d2 12401 if (ft != 0) {
c9297f4d 12402 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 12403 }
c9297f4d
AJ
12404 fp0 = tcg_temp_new_i64();
12405 gen_load_fpr64(ctx, fp0, fs);
12406 gen_store_fpr64(ctx, fp0, fd);
12407 tcg_temp_free_i64(fp0);
a16336e4
TS
12408 gen_set_label(l1);
12409 }
6ea83fed 12410 break;
bf4120ad 12411 case OPC_MOVN_PS:
e29c9628 12412 check_ps(ctx);
a16336e4 12413 {
42a268c2 12414 TCGLabel *l1 = gen_new_label();
30a3848b 12415 TCGv_i64 fp0;
c9297f4d
AJ
12416
12417 if (ft != 0) {
12418 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12419 fp0 = tcg_temp_new_i64();
12420 gen_load_fpr64(ctx, fp0, fs);
12421 gen_store_fpr64(ctx, fp0, fd);
12422 tcg_temp_free_i64(fp0);
12423 gen_set_label(l1);
12424 }
a16336e4 12425 }
6ea83fed 12426 break;
bf4120ad 12427 case OPC_ADDR_PS:
e29c9628 12428 check_ps(ctx);
b6d96bed 12429 {
a7812ae4
PB
12430 TCGv_i64 fp0 = tcg_temp_new_i64();
12431 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12432
12433 gen_load_fpr64(ctx, fp0, ft);
12434 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12435 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12436 tcg_temp_free_i64(fp1);
b6d96bed 12437 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12438 tcg_temp_free_i64(fp0);
b6d96bed 12439 }
fbcc6828 12440 break;
bf4120ad 12441 case OPC_MULR_PS:
e29c9628 12442 check_ps(ctx);
b6d96bed 12443 {
a7812ae4
PB
12444 TCGv_i64 fp0 = tcg_temp_new_i64();
12445 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12446
12447 gen_load_fpr64(ctx, fp0, ft);
12448 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12449 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12450 tcg_temp_free_i64(fp1);
b6d96bed 12451 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12452 tcg_temp_free_i64(fp0);
b6d96bed 12453 }
57fa1fb3 12454 break;
bf4120ad 12455 case OPC_RECIP2_PS:
e29c9628 12456 check_ps(ctx);
b6d96bed 12457 {
a7812ae4
PB
12458 TCGv_i64 fp0 = tcg_temp_new_i64();
12459 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12460
12461 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12462 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12463 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12464 tcg_temp_free_i64(fp1);
b6d96bed 12465 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12466 tcg_temp_free_i64(fp0);
b6d96bed 12467 }
57fa1fb3 12468 break;
bf4120ad 12469 case OPC_RECIP1_PS:
e29c9628 12470 check_ps(ctx);
b6d96bed 12471 {
a7812ae4 12472 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12473
12474 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12475 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12476 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12477 tcg_temp_free_i64(fp0);
b6d96bed 12478 }
57fa1fb3 12479 break;
bf4120ad 12480 case OPC_RSQRT1_PS:
e29c9628 12481 check_ps(ctx);
b6d96bed 12482 {
a7812ae4 12483 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12484
12485 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12486 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12487 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12488 tcg_temp_free_i64(fp0);
b6d96bed 12489 }
57fa1fb3 12490 break;
bf4120ad 12491 case OPC_RSQRT2_PS:
e29c9628 12492 check_ps(ctx);
b6d96bed 12493 {
a7812ae4
PB
12494 TCGv_i64 fp0 = tcg_temp_new_i64();
12495 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12496
12497 gen_load_fpr64(ctx, fp0, fs);
12498 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12499 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12500 tcg_temp_free_i64(fp1);
b6d96bed 12501 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12502 tcg_temp_free_i64(fp0);
b6d96bed 12503 }
57fa1fb3 12504 break;
bf4120ad 12505 case OPC_CVT_S_PU:
5e755519 12506 check_cp1_64bitmode(ctx);
b6d96bed 12507 {
a7812ae4 12508 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12509
7f6613ce 12510 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12511 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12512 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12513 tcg_temp_free_i32(fp0);
b6d96bed 12514 }
dd016883 12515 break;
bf4120ad 12516 case OPC_CVT_PW_PS:
e29c9628 12517 check_ps(ctx);
b6d96bed 12518 {
a7812ae4 12519 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12520
12521 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12522 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 12523 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12524 tcg_temp_free_i64(fp0);
b6d96bed 12525 }
6ea83fed 12526 break;
bf4120ad 12527 case OPC_CVT_S_PL:
5e755519 12528 check_cp1_64bitmode(ctx);
b6d96bed 12529 {
a7812ae4 12530 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12531
7c979afd 12532 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12533 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 12534 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12535 tcg_temp_free_i32(fp0);
b6d96bed 12536 }
6ea83fed 12537 break;
bf4120ad 12538 case OPC_PLL_PS:
e29c9628 12539 check_ps(ctx);
b6d96bed 12540 {
a7812ae4
PB
12541 TCGv_i32 fp0 = tcg_temp_new_i32();
12542 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12543
7c979afd
LA
12544 gen_load_fpr32(ctx, fp0, fs);
12545 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 12546 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 12547 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
12548 tcg_temp_free_i32(fp0);
12549 tcg_temp_free_i32(fp1);
b6d96bed 12550 }
6ea83fed 12551 break;
bf4120ad 12552 case OPC_PLU_PS:
e29c9628 12553 check_ps(ctx);
b6d96bed 12554 {
a7812ae4
PB
12555 TCGv_i32 fp0 = tcg_temp_new_i32();
12556 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12557
7c979afd 12558 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 12559 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12560 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12561 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12562 tcg_temp_free_i32(fp0);
12563 tcg_temp_free_i32(fp1);
b6d96bed 12564 }
5a5012ec 12565 break;
bf4120ad 12566 case OPC_PUL_PS:
e29c9628 12567 check_ps(ctx);
b6d96bed 12568 {
a7812ae4
PB
12569 TCGv_i32 fp0 = tcg_temp_new_i32();
12570 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12571
7f6613ce 12572 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
12573 gen_load_fpr32(ctx, fp1, ft);
12574 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12575 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12576 tcg_temp_free_i32(fp0);
12577 tcg_temp_free_i32(fp1);
b6d96bed 12578 }
5a5012ec 12579 break;
bf4120ad 12580 case OPC_PUU_PS:
e29c9628 12581 check_ps(ctx);
b6d96bed 12582 {
a7812ae4
PB
12583 TCGv_i32 fp0 = tcg_temp_new_i32();
12584 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12585
7f6613ce
PJ
12586 gen_load_fpr32h(ctx, fp0, fs);
12587 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12588 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12589 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12590 tcg_temp_free_i32(fp0);
12591 tcg_temp_free_i32(fp1);
b6d96bed 12592 }
5a5012ec 12593 break;
bf4120ad
NF
12594 case OPC_CMP_F_PS:
12595 case OPC_CMP_UN_PS:
12596 case OPC_CMP_EQ_PS:
12597 case OPC_CMP_UEQ_PS:
12598 case OPC_CMP_OLT_PS:
12599 case OPC_CMP_ULT_PS:
12600 case OPC_CMP_OLE_PS:
12601 case OPC_CMP_ULE_PS:
12602 case OPC_CMP_SF_PS:
12603 case OPC_CMP_NGLE_PS:
12604 case OPC_CMP_SEQ_PS:
12605 case OPC_CMP_NGL_PS:
12606 case OPC_CMP_LT_PS:
12607 case OPC_CMP_NGE_PS:
12608 case OPC_CMP_LE_PS:
12609 case OPC_CMP_NGT_PS:
8153667c 12610 if (ctx->opcode & (1 << 6)) {
71375b59 12611 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 12612 } else {
71375b59 12613 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12614 }
6ea83fed 12615 break;
5a5012ec 12616 default:
9d68ac14 12617 MIPS_INVAL("farith");
9c708c7f 12618 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12619 return;
12620 }
6ea83fed 12621}
6af0bf9c 12622
5a5012ec 12623/* Coprocessor 3 (FPU) */
235785e8
AM
12624static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12625 int fd, int fs, int base, int index)
7a387fff 12626{
4e2474d6 12627 TCGv t0 = tcg_temp_new();
7a387fff 12628
93b12ccc 12629 if (base == 0) {
6c5c1e20 12630 gen_load_gpr(t0, index);
93b12ccc 12631 } else if (index == 0) {
6c5c1e20 12632 gen_load_gpr(t0, base);
93b12ccc 12633 } else {
05168674 12634 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12635 }
7480515f
AM
12636 /*
12637 * Don't do NOP if destination is zero: we must perform the actual
12638 * memory access.
12639 */
5a5012ec
TS
12640 switch (opc) {
12641 case OPC_LWXC1:
8c0ab41f 12642 check_cop1x(ctx);
b6d96bed 12643 {
a7812ae4 12644 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12645
5f68f5ae 12646 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12647 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12648 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12649 tcg_temp_free_i32(fp0);
b6d96bed 12650 }
5a5012ec
TS
12651 break;
12652 case OPC_LDXC1:
8c0ab41f
AJ
12653 check_cop1x(ctx);
12654 check_cp1_registers(ctx, fd);
b6d96bed 12655 {
a7812ae4 12656 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12657 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12658 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12659 tcg_temp_free_i64(fp0);
b6d96bed 12660 }
5a5012ec
TS
12661 break;
12662 case OPC_LUXC1:
8c0ab41f 12663 check_cp1_64bitmode(ctx);
6c5c1e20 12664 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12665 {
a7812ae4 12666 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12667
5f68f5ae 12668 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12669 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12670 tcg_temp_free_i64(fp0);
b6d96bed 12671 }
5a5012ec
TS
12672 break;
12673 case OPC_SWXC1:
8c0ab41f 12674 check_cop1x(ctx);
b6d96bed 12675 {
a7812ae4 12676 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12677 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12678 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12679 tcg_temp_free_i32(fp0);
b6d96bed 12680 }
5a5012ec
TS
12681 break;
12682 case OPC_SDXC1:
8c0ab41f
AJ
12683 check_cop1x(ctx);
12684 check_cp1_registers(ctx, fs);
b6d96bed 12685 {
a7812ae4 12686 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12687 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12688 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12689 tcg_temp_free_i64(fp0);
b6d96bed 12690 }
5a5012ec
TS
12691 break;
12692 case OPC_SUXC1:
8c0ab41f 12693 check_cp1_64bitmode(ctx);
6c5c1e20 12694 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12695 {
a7812ae4 12696 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12697 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12698 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12699 tcg_temp_free_i64(fp0);
b6d96bed 12700 }
5a5012ec 12701 break;
5a5012ec 12702 }
6c5c1e20 12703 tcg_temp_free(t0);
5a5012ec
TS
12704}
12705
235785e8
AM
12706static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12707 int fd, int fr, int fs, int ft)
5a5012ec 12708{
5a5012ec
TS
12709 switch (opc) {
12710 case OPC_ALNV_PS:
e29c9628 12711 check_ps(ctx);
a16336e4 12712 {
a7812ae4 12713 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12714 TCGv_i32 fp = tcg_temp_new_i32();
12715 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12716 TCGLabel *l1 = gen_new_label();
12717 TCGLabel *l2 = gen_new_label();
a16336e4 12718
6c5c1e20
TS
12719 gen_load_gpr(t0, fr);
12720 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12721
12722 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12723 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12724 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12725 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12726 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12727 tcg_gen_br(l2);
12728 gen_set_label(l1);
6c5c1e20
TS
12729 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12730 tcg_temp_free(t0);
a16336e4 12731#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12732 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12733 gen_load_fpr32h(ctx, fph, ft);
12734 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12735 gen_store_fpr32(ctx, fph, fd);
a16336e4 12736#else
7f6613ce 12737 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12738 gen_load_fpr32(ctx, fp, ft);
12739 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12740 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12741#endif
12742 gen_set_label(l2);
c905fdac
AJ
12743 tcg_temp_free_i32(fp);
12744 tcg_temp_free_i32(fph);
a16336e4 12745 }
5a5012ec
TS
12746 break;
12747 case OPC_MADD_S:
b8aa4598 12748 check_cop1x(ctx);
b6d96bed 12749 {
a7812ae4
PB
12750 TCGv_i32 fp0 = tcg_temp_new_i32();
12751 TCGv_i32 fp1 = tcg_temp_new_i32();
12752 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12753
7c979afd
LA
12754 gen_load_fpr32(ctx, fp0, fs);
12755 gen_load_fpr32(ctx, fp1, ft);
12756 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12757 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12758 tcg_temp_free_i32(fp0);
12759 tcg_temp_free_i32(fp1);
7c979afd 12760 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12761 tcg_temp_free_i32(fp2);
b6d96bed 12762 }
5a5012ec
TS
12763 break;
12764 case OPC_MADD_D:
b8aa4598
TS
12765 check_cop1x(ctx);
12766 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12767 {
a7812ae4
PB
12768 TCGv_i64 fp0 = tcg_temp_new_i64();
12769 TCGv_i64 fp1 = tcg_temp_new_i64();
12770 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12771
12772 gen_load_fpr64(ctx, fp0, fs);
12773 gen_load_fpr64(ctx, fp1, ft);
12774 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12775 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12776 tcg_temp_free_i64(fp0);
12777 tcg_temp_free_i64(fp1);
b6d96bed 12778 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12779 tcg_temp_free_i64(fp2);
b6d96bed 12780 }
5a5012ec
TS
12781 break;
12782 case OPC_MADD_PS:
e29c9628 12783 check_ps(ctx);
b6d96bed 12784 {
a7812ae4
PB
12785 TCGv_i64 fp0 = tcg_temp_new_i64();
12786 TCGv_i64 fp1 = tcg_temp_new_i64();
12787 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12788
12789 gen_load_fpr64(ctx, fp0, fs);
12790 gen_load_fpr64(ctx, fp1, ft);
12791 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12792 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12793 tcg_temp_free_i64(fp0);
12794 tcg_temp_free_i64(fp1);
b6d96bed 12795 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12796 tcg_temp_free_i64(fp2);
b6d96bed 12797 }
5a5012ec
TS
12798 break;
12799 case OPC_MSUB_S:
b8aa4598 12800 check_cop1x(ctx);
b6d96bed 12801 {
a7812ae4
PB
12802 TCGv_i32 fp0 = tcg_temp_new_i32();
12803 TCGv_i32 fp1 = tcg_temp_new_i32();
12804 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12805
7c979afd
LA
12806 gen_load_fpr32(ctx, fp0, fs);
12807 gen_load_fpr32(ctx, fp1, ft);
12808 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12809 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12810 tcg_temp_free_i32(fp0);
12811 tcg_temp_free_i32(fp1);
7c979afd 12812 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12813 tcg_temp_free_i32(fp2);
b6d96bed 12814 }
5a5012ec
TS
12815 break;
12816 case OPC_MSUB_D:
b8aa4598
TS
12817 check_cop1x(ctx);
12818 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12819 {
a7812ae4
PB
12820 TCGv_i64 fp0 = tcg_temp_new_i64();
12821 TCGv_i64 fp1 = tcg_temp_new_i64();
12822 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12823
12824 gen_load_fpr64(ctx, fp0, fs);
12825 gen_load_fpr64(ctx, fp1, ft);
12826 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12827 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12828 tcg_temp_free_i64(fp0);
12829 tcg_temp_free_i64(fp1);
b6d96bed 12830 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12831 tcg_temp_free_i64(fp2);
b6d96bed 12832 }
5a5012ec
TS
12833 break;
12834 case OPC_MSUB_PS:
e29c9628 12835 check_ps(ctx);
b6d96bed 12836 {
a7812ae4
PB
12837 TCGv_i64 fp0 = tcg_temp_new_i64();
12838 TCGv_i64 fp1 = tcg_temp_new_i64();
12839 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12840
12841 gen_load_fpr64(ctx, fp0, fs);
12842 gen_load_fpr64(ctx, fp1, ft);
12843 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12844 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12845 tcg_temp_free_i64(fp0);
12846 tcg_temp_free_i64(fp1);
b6d96bed 12847 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12848 tcg_temp_free_i64(fp2);
b6d96bed 12849 }
5a5012ec
TS
12850 break;
12851 case OPC_NMADD_S:
b8aa4598 12852 check_cop1x(ctx);
b6d96bed 12853 {
a7812ae4
PB
12854 TCGv_i32 fp0 = tcg_temp_new_i32();
12855 TCGv_i32 fp1 = tcg_temp_new_i32();
12856 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12857
7c979afd
LA
12858 gen_load_fpr32(ctx, fp0, fs);
12859 gen_load_fpr32(ctx, fp1, ft);
12860 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12861 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12862 tcg_temp_free_i32(fp0);
12863 tcg_temp_free_i32(fp1);
7c979afd 12864 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12865 tcg_temp_free_i32(fp2);
b6d96bed 12866 }
5a5012ec
TS
12867 break;
12868 case OPC_NMADD_D:
b8aa4598
TS
12869 check_cop1x(ctx);
12870 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12871 {
a7812ae4
PB
12872 TCGv_i64 fp0 = tcg_temp_new_i64();
12873 TCGv_i64 fp1 = tcg_temp_new_i64();
12874 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12875
12876 gen_load_fpr64(ctx, fp0, fs);
12877 gen_load_fpr64(ctx, fp1, ft);
12878 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12879 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12880 tcg_temp_free_i64(fp0);
12881 tcg_temp_free_i64(fp1);
b6d96bed 12882 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12883 tcg_temp_free_i64(fp2);
b6d96bed 12884 }
5a5012ec
TS
12885 break;
12886 case OPC_NMADD_PS:
e29c9628 12887 check_ps(ctx);
b6d96bed 12888 {
a7812ae4
PB
12889 TCGv_i64 fp0 = tcg_temp_new_i64();
12890 TCGv_i64 fp1 = tcg_temp_new_i64();
12891 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12892
12893 gen_load_fpr64(ctx, fp0, fs);
12894 gen_load_fpr64(ctx, fp1, ft);
12895 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12896 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12897 tcg_temp_free_i64(fp0);
12898 tcg_temp_free_i64(fp1);
b6d96bed 12899 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12900 tcg_temp_free_i64(fp2);
b6d96bed 12901 }
5a5012ec
TS
12902 break;
12903 case OPC_NMSUB_S:
b8aa4598 12904 check_cop1x(ctx);
b6d96bed 12905 {
a7812ae4
PB
12906 TCGv_i32 fp0 = tcg_temp_new_i32();
12907 TCGv_i32 fp1 = tcg_temp_new_i32();
12908 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12909
7c979afd
LA
12910 gen_load_fpr32(ctx, fp0, fs);
12911 gen_load_fpr32(ctx, fp1, ft);
12912 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12913 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12914 tcg_temp_free_i32(fp0);
12915 tcg_temp_free_i32(fp1);
7c979afd 12916 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12917 tcg_temp_free_i32(fp2);
b6d96bed 12918 }
5a5012ec
TS
12919 break;
12920 case OPC_NMSUB_D:
b8aa4598
TS
12921 check_cop1x(ctx);
12922 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12923 {
a7812ae4
PB
12924 TCGv_i64 fp0 = tcg_temp_new_i64();
12925 TCGv_i64 fp1 = tcg_temp_new_i64();
12926 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12927
12928 gen_load_fpr64(ctx, fp0, fs);
12929 gen_load_fpr64(ctx, fp1, ft);
12930 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12931 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12932 tcg_temp_free_i64(fp0);
12933 tcg_temp_free_i64(fp1);
b6d96bed 12934 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12935 tcg_temp_free_i64(fp2);
b6d96bed 12936 }
5a5012ec
TS
12937 break;
12938 case OPC_NMSUB_PS:
e29c9628 12939 check_ps(ctx);
b6d96bed 12940 {
a7812ae4
PB
12941 TCGv_i64 fp0 = tcg_temp_new_i64();
12942 TCGv_i64 fp1 = tcg_temp_new_i64();
12943 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12944
12945 gen_load_fpr64(ctx, fp0, fs);
12946 gen_load_fpr64(ctx, fp1, ft);
12947 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12948 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12949 tcg_temp_free_i64(fp0);
12950 tcg_temp_free_i64(fp1);
b6d96bed 12951 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12952 tcg_temp_free_i64(fp2);
b6d96bed 12953 }
5a5012ec 12954 break;
923617a3 12955 default:
9d68ac14 12956 MIPS_INVAL("flt3_arith");
9c708c7f 12957 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
12958 return;
12959 }
7a387fff
TS
12960}
12961
b00c7218 12962static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12963{
12964 TCGv t0;
12965
b3167288 12966#if !defined(CONFIG_USER_ONLY)
7480515f
AM
12967 /*
12968 * The Linux kernel will emulate rdhwr if it's not supported natively.
12969 * Therefore only check the ISA in system mode.
12970 */
d75c135e 12971 check_insn(ctx, ISA_MIPS32R2);
b3167288 12972#endif
26ebe468
NF
12973 t0 = tcg_temp_new();
12974
12975 switch (rd) {
12976 case 0:
895c2d04 12977 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12978 gen_store_gpr(t0, rt);
12979 break;
12980 case 1:
895c2d04 12981 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12982 gen_store_gpr(t0, rt);
12983 break;
12984 case 2:
eeb3bba8 12985 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12986 gen_io_start();
12987 }
895c2d04 12988 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 12989 gen_store_gpr(t0, rt);
7480515f
AM
12990 /*
12991 * Break the TB to be able to take timer interrupts immediately
12992 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12993 * we break completely out of translated code.
12994 */
eeb3bba8
EC
12995 gen_save_pc(ctx->base.pc_next + 4);
12996 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12997 break;
12998 case 3:
895c2d04 12999 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
13000 gen_store_gpr(t0, rt);
13001 break;
b00c7218
YK
13002 case 4:
13003 check_insn(ctx, ISA_MIPS32R6);
13004 if (sel != 0) {
7480515f
AM
13005 /*
13006 * Performance counter registers are not implemented other than
b00c7218
YK
13007 * control register 0.
13008 */
13009 generate_exception(ctx, EXCP_RI);
13010 }
13011 gen_helper_rdhwr_performance(t0, cpu_env);
13012 gen_store_gpr(t0, rt);
13013 break;
13014 case 5:
13015 check_insn(ctx, ISA_MIPS32R6);
13016 gen_helper_rdhwr_xnp(t0, cpu_env);
13017 gen_store_gpr(t0, rt);
13018 break;
26ebe468
NF
13019 case 29:
13020#if defined(CONFIG_USER_ONLY)
d279279e
PJ
13021 tcg_gen_ld_tl(t0, cpu_env,
13022 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
13023 gen_store_gpr(t0, rt);
13024 break;
13025#else
d279279e
PJ
13026 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13027 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13028 tcg_gen_ld_tl(t0, cpu_env,
13029 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13030 gen_store_gpr(t0, rt);
13031 } else {
9c708c7f 13032 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
13033 }
13034 break;
26ebe468
NF
13035#endif
13036 default: /* Invalid */
13037 MIPS_INVAL("rdhwr");
9c708c7f 13038 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
13039 break;
13040 }
13041 tcg_temp_free(t0);
13042}
13043
a5f53390
LA
13044static inline void clear_branch_hflags(DisasContext *ctx)
13045{
13046 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 13047 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
13048 save_cpu_state(ctx, 0);
13049 } else {
7480515f
AM
13050 /*
13051 * It is not safe to save ctx->hflags as hflags may be changed
13052 * in execution time by the instruction in delay / forbidden slot.
13053 */
a5f53390
LA
13054 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13055 }
13056}
13057
31837be3 13058static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
13059{
13060 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 13061 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 13062 /* Branches completion */
a5f53390 13063 clear_branch_hflags(ctx);
eeb3bba8 13064 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 13065 /* FIXME: Need to clear can_do_io. */
364d4831 13066 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 13067 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 13068 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 13069 break;
c9602061
NF
13070 case MIPS_HFLAG_B:
13071 /* unconditional branch */
364d4831
NF
13072 if (proc_hflags & MIPS_HFLAG_BX) {
13073 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13074 }
c9602061
NF
13075 gen_goto_tb(ctx, 0, ctx->btarget);
13076 break;
13077 case MIPS_HFLAG_BL:
13078 /* blikely taken case */
c9602061
NF
13079 gen_goto_tb(ctx, 0, ctx->btarget);
13080 break;
13081 case MIPS_HFLAG_BC:
13082 /* Conditional branch */
c9602061 13083 {
42a268c2 13084 TCGLabel *l1 = gen_new_label();
c9602061
NF
13085
13086 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 13087 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
13088 gen_set_label(l1);
13089 gen_goto_tb(ctx, 0, ctx->btarget);
13090 }
13091 break;
13092 case MIPS_HFLAG_BR:
13093 /* unconditional branch to register */
d75c135e 13094 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
13095 TCGv t0 = tcg_temp_new();
13096 TCGv_i32 t1 = tcg_temp_new_i32();
13097
13098 tcg_gen_andi_tl(t0, btarget, 0x1);
13099 tcg_gen_trunc_tl_i32(t1, t0);
13100 tcg_temp_free(t0);
13101 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13102 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13103 tcg_gen_or_i32(hflags, hflags, t1);
13104 tcg_temp_free_i32(t1);
13105
13106 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13107 } else {
13108 tcg_gen_mov_tl(cpu_PC, btarget);
13109 }
eeb3bba8 13110 if (ctx->base.singlestep_enabled) {
c9602061 13111 save_cpu_state(ctx, 0);
9c708c7f 13112 gen_helper_raise_exception_debug(cpu_env);
c9602061 13113 }
7f11636d 13114 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
13115 break;
13116 default:
a5f53390
LA
13117 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13118 abort();
c9602061
NF
13119 }
13120 }
13121}
13122
6893f074
YK
13123/* Compact Branches */
13124static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13125 int rs, int rt, int32_t offset)
13126{
13127 int bcond_compute = 0;
13128 TCGv t0 = tcg_temp_new();
13129 TCGv t1 = tcg_temp_new();
65935f07 13130 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
13131
13132 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13133#ifdef MIPS_DEBUG_DISAS
13134 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 13135 "\n", ctx->base.pc_next);
6893f074 13136#endif
9c708c7f 13137 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13138 goto out;
13139 }
13140
13141 /* Load needed operands and calculate btarget */
13142 switch (opc) {
13143 /* compact branch */
13144 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13145 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13146 gen_load_gpr(t0, rs);
13147 gen_load_gpr(t1, rt);
13148 bcond_compute = 1;
eeb3bba8 13149 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13150 if (rs <= rt && rs == 0) {
13151 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 13152 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13153 }
13154 break;
13155 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13156 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13157 gen_load_gpr(t0, rs);
13158 gen_load_gpr(t1, rt);
13159 bcond_compute = 1;
eeb3bba8 13160 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13161 break;
13162 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13163 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13164 if (rs == 0 || rs == rt) {
13165 /* OPC_BLEZALC, OPC_BGEZALC */
13166 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 13167 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13168 }
13169 gen_load_gpr(t0, rs);
13170 gen_load_gpr(t1, rt);
13171 bcond_compute = 1;
eeb3bba8 13172 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13173 break;
13174 case OPC_BC:
13175 case OPC_BALC:
eeb3bba8 13176 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13177 break;
13178 case OPC_BEQZC:
13179 case OPC_BNEZC:
13180 if (rs != 0) {
13181 /* OPC_BEQZC, OPC_BNEZC */
13182 gen_load_gpr(t0, rs);
13183 bcond_compute = 1;
eeb3bba8 13184 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13185 } else {
13186 /* OPC_JIC, OPC_JIALC */
13187 TCGv tbase = tcg_temp_new();
13188 TCGv toffset = tcg_temp_new();
13189
13190 gen_load_gpr(tbase, rt);
13191 tcg_gen_movi_tl(toffset, offset);
13192 gen_op_addr_add(ctx, btarget, tbase, toffset);
13193 tcg_temp_free(tbase);
13194 tcg_temp_free(toffset);
13195 }
13196 break;
13197 default:
13198 MIPS_INVAL("Compact branch/jump");
9c708c7f 13199 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13200 goto out;
13201 }
13202
13203 if (bcond_compute == 0) {
13204 /* Uncoditional compact branch */
13205 switch (opc) {
13206 case OPC_JIALC:
eeb3bba8 13207 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13208 /* Fallthrough */
13209 case OPC_JIC:
13210 ctx->hflags |= MIPS_HFLAG_BR;
13211 break;
13212 case OPC_BALC:
eeb3bba8 13213 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13214 /* Fallthrough */
13215 case OPC_BC:
13216 ctx->hflags |= MIPS_HFLAG_B;
13217 break;
13218 default:
13219 MIPS_INVAL("Compact branch/jump");
9c708c7f 13220 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13221 goto out;
13222 }
13223
13224 /* Generating branch here as compact branches don't have delay slot */
13225 gen_branch(ctx, 4);
13226 } else {
13227 /* Conditional compact branch */
13228 TCGLabel *fs = gen_new_label();
13229 save_cpu_state(ctx, 0);
13230
13231 switch (opc) {
13232 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13233 if (rs == 0 && rt != 0) {
13234 /* OPC_BLEZALC */
13235 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13236 } else if (rs != 0 && rt != 0 && rs == rt) {
13237 /* OPC_BGEZALC */
13238 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13239 } else {
13240 /* OPC_BGEUC */
13241 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13242 }
13243 break;
13244 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13245 if (rs == 0 && rt != 0) {
13246 /* OPC_BGTZALC */
13247 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13248 } else if (rs != 0 && rt != 0 && rs == rt) {
13249 /* OPC_BLTZALC */
13250 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13251 } else {
13252 /* OPC_BLTUC */
13253 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13254 }
13255 break;
13256 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13257 if (rs == 0 && rt != 0) {
13258 /* OPC_BLEZC */
13259 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13260 } else if (rs != 0 && rt != 0 && rs == rt) {
13261 /* OPC_BGEZC */
13262 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13263 } else {
13264 /* OPC_BGEC */
13265 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13266 }
13267 break;
13268 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13269 if (rs == 0 && rt != 0) {
13270 /* OPC_BGTZC */
13271 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13272 } else if (rs != 0 && rt != 0 && rs == rt) {
13273 /* OPC_BLTZC */
13274 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13275 } else {
13276 /* OPC_BLTC */
13277 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13278 }
13279 break;
13280 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13281 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13282 if (rs >= rt) {
13283 /* OPC_BOVC, OPC_BNVC */
13284 TCGv t2 = tcg_temp_new();
13285 TCGv t3 = tcg_temp_new();
13286 TCGv t4 = tcg_temp_new();
13287 TCGv input_overflow = tcg_temp_new();
13288
13289 gen_load_gpr(t0, rs);
13290 gen_load_gpr(t1, rt);
13291 tcg_gen_ext32s_tl(t2, t0);
13292 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13293 tcg_gen_ext32s_tl(t3, t1);
13294 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13295 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13296
13297 tcg_gen_add_tl(t4, t2, t3);
13298 tcg_gen_ext32s_tl(t4, t4);
13299 tcg_gen_xor_tl(t2, t2, t3);
13300 tcg_gen_xor_tl(t3, t4, t3);
13301 tcg_gen_andc_tl(t2, t3, t2);
13302 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13303 tcg_gen_or_tl(t4, t4, input_overflow);
13304 if (opc == OPC_BOVC) {
13305 /* OPC_BOVC */
13306 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13307 } else {
13308 /* OPC_BNVC */
13309 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13310 }
13311 tcg_temp_free(input_overflow);
13312 tcg_temp_free(t4);
13313 tcg_temp_free(t3);
13314 tcg_temp_free(t2);
13315 } else if (rs < rt && rs == 0) {
13316 /* OPC_BEQZALC, OPC_BNEZALC */
13317 if (opc == OPC_BEQZALC) {
13318 /* OPC_BEQZALC */
13319 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13320 } else {
13321 /* OPC_BNEZALC */
13322 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13323 }
13324 } else {
13325 /* OPC_BEQC, OPC_BNEC */
13326 if (opc == OPC_BEQC) {
13327 /* OPC_BEQC */
13328 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13329 } else {
13330 /* OPC_BNEC */
13331 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13332 }
13333 }
13334 break;
13335 case OPC_BEQZC:
13336 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13337 break;
13338 case OPC_BNEZC:
13339 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13340 break;
13341 default:
13342 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13343 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13344 goto out;
13345 }
13346
13347 /* Generating branch here as compact branches don't have delay slot */
13348 gen_goto_tb(ctx, 1, ctx->btarget);
13349 gen_set_label(fs);
13350
13351 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13352 }
13353
13354out:
13355 tcg_temp_free(t0);
13356 tcg_temp_free(t1);
13357}
13358
7a387fff 13359/* ISA extensions (ASEs) */
6af0bf9c 13360/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13361
13362/* MIPS16 major opcodes */
13363enum {
13364 M16_OPC_ADDIUSP = 0x00,
13365 M16_OPC_ADDIUPC = 0x01,
13366 M16_OPC_B = 0x02,
13367 M16_OPC_JAL = 0x03,
13368 M16_OPC_BEQZ = 0x04,
13369 M16_OPC_BNEQZ = 0x05,
13370 M16_OPC_SHIFT = 0x06,
13371 M16_OPC_LD = 0x07,
13372 M16_OPC_RRIA = 0x08,
13373 M16_OPC_ADDIU8 = 0x09,
13374 M16_OPC_SLTI = 0x0a,
13375 M16_OPC_SLTIU = 0x0b,
13376 M16_OPC_I8 = 0x0c,
13377 M16_OPC_LI = 0x0d,
13378 M16_OPC_CMPI = 0x0e,
13379 M16_OPC_SD = 0x0f,
13380 M16_OPC_LB = 0x10,
13381 M16_OPC_LH = 0x11,
13382 M16_OPC_LWSP = 0x12,
13383 M16_OPC_LW = 0x13,
13384 M16_OPC_LBU = 0x14,
13385 M16_OPC_LHU = 0x15,
13386 M16_OPC_LWPC = 0x16,
13387 M16_OPC_LWU = 0x17,
13388 M16_OPC_SB = 0x18,
13389 M16_OPC_SH = 0x19,
13390 M16_OPC_SWSP = 0x1a,
13391 M16_OPC_SW = 0x1b,
13392 M16_OPC_RRR = 0x1c,
13393 M16_OPC_RR = 0x1d,
13394 M16_OPC_EXTEND = 0x1e,
13395 M16_OPC_I64 = 0x1f
13396};
13397
13398/* I8 funct field */
13399enum {
13400 I8_BTEQZ = 0x0,
13401 I8_BTNEZ = 0x1,
13402 I8_SWRASP = 0x2,
13403 I8_ADJSP = 0x3,
13404 I8_SVRS = 0x4,
13405 I8_MOV32R = 0x5,
13406 I8_MOVR32 = 0x7
13407};
13408
13409/* RRR f field */
13410enum {
13411 RRR_DADDU = 0x0,
13412 RRR_ADDU = 0x1,
13413 RRR_DSUBU = 0x2,
13414 RRR_SUBU = 0x3
13415};
13416
13417/* RR funct field */
13418enum {
13419 RR_JR = 0x00,
13420 RR_SDBBP = 0x01,
13421 RR_SLT = 0x02,
13422 RR_SLTU = 0x03,
13423 RR_SLLV = 0x04,
13424 RR_BREAK = 0x05,
13425 RR_SRLV = 0x06,
13426 RR_SRAV = 0x07,
13427 RR_DSRL = 0x08,
13428 RR_CMP = 0x0a,
13429 RR_NEG = 0x0b,
13430 RR_AND = 0x0c,
13431 RR_OR = 0x0d,
13432 RR_XOR = 0x0e,
13433 RR_NOT = 0x0f,
13434 RR_MFHI = 0x10,
13435 RR_CNVT = 0x11,
13436 RR_MFLO = 0x12,
13437 RR_DSRA = 0x13,
13438 RR_DSLLV = 0x14,
13439 RR_DSRLV = 0x16,
13440 RR_DSRAV = 0x17,
13441 RR_MULT = 0x18,
13442 RR_MULTU = 0x19,
13443 RR_DIV = 0x1a,
13444 RR_DIVU = 0x1b,
13445 RR_DMULT = 0x1c,
13446 RR_DMULTU = 0x1d,
13447 RR_DDIV = 0x1e,
13448 RR_DDIVU = 0x1f
13449};
13450
13451/* I64 funct field */
13452enum {
13453 I64_LDSP = 0x0,
13454 I64_SDSP = 0x1,
13455 I64_SDRASP = 0x2,
13456 I64_DADJSP = 0x3,
13457 I64_LDPC = 0x4,
364d4831 13458 I64_DADDIU5 = 0x5,
6ea219d0
NF
13459 I64_DADDIUPC = 0x6,
13460 I64_DADDIUSP = 0x7
13461};
13462
13463/* RR ry field for CNVT */
13464enum {
13465 RR_RY_CNVT_ZEB = 0x0,
13466 RR_RY_CNVT_ZEH = 0x1,
13467 RR_RY_CNVT_ZEW = 0x2,
13468 RR_RY_CNVT_SEB = 0x4,
13469 RR_RY_CNVT_SEH = 0x5,
13470 RR_RY_CNVT_SEW = 0x6,
13471};
13472
235785e8 13473static int xlat(int r)
364d4831
NF
13474{
13475 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13476
13477 return map[r];
13478}
13479
235785e8
AM
13480static void gen_mips16_save(DisasContext *ctx,
13481 int xsregs, int aregs,
13482 int do_ra, int do_s0, int do_s1,
13483 int framesize)
364d4831
NF
13484{
13485 TCGv t0 = tcg_temp_new();
13486 TCGv t1 = tcg_temp_new();
c48245f0 13487 TCGv t2 = tcg_temp_new();
364d4831
NF
13488 int args, astatic;
13489
13490 switch (aregs) {
13491 case 0:
13492 case 1:
13493 case 2:
13494 case 3:
13495 case 11:
13496 args = 0;
13497 break;
13498 case 4:
13499 case 5:
13500 case 6:
13501 case 7:
13502 args = 1;
13503 break;
13504 case 8:
13505 case 9:
13506 case 10:
13507 args = 2;
13508 break;
13509 case 12:
13510 case 13:
13511 args = 3;
13512 break;
13513 case 14:
13514 args = 4;
13515 break;
13516 default:
9c708c7f 13517 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13518 return;
13519 }
13520
13521 switch (args) {
13522 case 4:
13523 gen_base_offset_addr(ctx, t0, 29, 12);
13524 gen_load_gpr(t1, 7);
5f68f5ae 13525 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13526 /* Fall through */
13527 case 3:
13528 gen_base_offset_addr(ctx, t0, 29, 8);
13529 gen_load_gpr(t1, 6);
5f68f5ae 13530 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13531 /* Fall through */
13532 case 2:
13533 gen_base_offset_addr(ctx, t0, 29, 4);
13534 gen_load_gpr(t1, 5);
5f68f5ae 13535 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13536 /* Fall through */
13537 case 1:
13538 gen_base_offset_addr(ctx, t0, 29, 0);
13539 gen_load_gpr(t1, 4);
5f68f5ae 13540 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13541 }
13542
13543 gen_load_gpr(t0, 29);
13544
5f68f5ae 13545#define DECR_AND_STORE(reg) do { \
c48245f0
MR
13546 tcg_gen_movi_tl(t2, -4); \
13547 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13548 gen_load_gpr(t1, reg); \
13549 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
13550 } while (0)
13551
13552 if (do_ra) {
13553 DECR_AND_STORE(31);
13554 }
13555
13556 switch (xsregs) {
13557 case 7:
13558 DECR_AND_STORE(30);
13559 /* Fall through */
13560 case 6:
13561 DECR_AND_STORE(23);
13562 /* Fall through */
13563 case 5:
13564 DECR_AND_STORE(22);
13565 /* Fall through */
13566 case 4:
13567 DECR_AND_STORE(21);
13568 /* Fall through */
13569 case 3:
13570 DECR_AND_STORE(20);
13571 /* Fall through */
13572 case 2:
13573 DECR_AND_STORE(19);
13574 /* Fall through */
13575 case 1:
13576 DECR_AND_STORE(18);
13577 }
13578
13579 if (do_s1) {
13580 DECR_AND_STORE(17);
13581 }
13582 if (do_s0) {
13583 DECR_AND_STORE(16);
13584 }
13585
13586 switch (aregs) {
13587 case 0:
13588 case 4:
13589 case 8:
13590 case 12:
13591 case 14:
13592 astatic = 0;
13593 break;
13594 case 1:
13595 case 5:
13596 case 9:
13597 case 13:
13598 astatic = 1;
13599 break;
13600 case 2:
13601 case 6:
13602 case 10:
13603 astatic = 2;
13604 break;
13605 case 3:
13606 case 7:
13607 astatic = 3;
13608 break;
13609 case 11:
13610 astatic = 4;
13611 break;
13612 default:
9c708c7f 13613 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13614 return;
13615 }
13616
13617 if (astatic > 0) {
13618 DECR_AND_STORE(7);
13619 if (astatic > 1) {
13620 DECR_AND_STORE(6);
13621 if (astatic > 2) {
13622 DECR_AND_STORE(5);
13623 if (astatic > 3) {
13624 DECR_AND_STORE(4);
13625 }
13626 }
13627 }
13628 }
13629#undef DECR_AND_STORE
13630
c48245f0
MR
13631 tcg_gen_movi_tl(t2, -framesize);
13632 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13633 tcg_temp_free(t0);
13634 tcg_temp_free(t1);
c48245f0 13635 tcg_temp_free(t2);
364d4831
NF
13636}
13637
235785e8
AM
13638static void gen_mips16_restore(DisasContext *ctx,
13639 int xsregs, int aregs,
13640 int do_ra, int do_s0, int do_s1,
13641 int framesize)
364d4831
NF
13642{
13643 int astatic;
13644 TCGv t0 = tcg_temp_new();
13645 TCGv t1 = tcg_temp_new();
c48245f0 13646 TCGv t2 = tcg_temp_new();
364d4831 13647
c48245f0
MR
13648 tcg_gen_movi_tl(t2, framesize);
13649 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13650
5f68f5ae 13651#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13652 tcg_gen_movi_tl(t2, -4); \
13653 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13654 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13655 gen_store_gpr(t1, reg); \
364d4831
NF
13656 } while (0)
13657
13658 if (do_ra) {
13659 DECR_AND_LOAD(31);
13660 }
13661
13662 switch (xsregs) {
13663 case 7:
13664 DECR_AND_LOAD(30);
13665 /* Fall through */
13666 case 6:
13667 DECR_AND_LOAD(23);
13668 /* Fall through */
13669 case 5:
13670 DECR_AND_LOAD(22);
13671 /* Fall through */
13672 case 4:
13673 DECR_AND_LOAD(21);
13674 /* Fall through */
13675 case 3:
13676 DECR_AND_LOAD(20);
13677 /* Fall through */
13678 case 2:
13679 DECR_AND_LOAD(19);
13680 /* Fall through */
13681 case 1:
13682 DECR_AND_LOAD(18);
13683 }
13684
13685 if (do_s1) {
13686 DECR_AND_LOAD(17);
13687 }
13688 if (do_s0) {
13689 DECR_AND_LOAD(16);
13690 }
13691
13692 switch (aregs) {
13693 case 0:
13694 case 4:
13695 case 8:
13696 case 12:
13697 case 14:
13698 astatic = 0;
13699 break;
13700 case 1:
13701 case 5:
13702 case 9:
13703 case 13:
13704 astatic = 1;
13705 break;
13706 case 2:
13707 case 6:
13708 case 10:
13709 astatic = 2;
13710 break;
13711 case 3:
13712 case 7:
13713 astatic = 3;
13714 break;
13715 case 11:
13716 astatic = 4;
13717 break;
13718 default:
9c708c7f 13719 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13720 return;
13721 }
13722
13723 if (astatic > 0) {
13724 DECR_AND_LOAD(7);
13725 if (astatic > 1) {
13726 DECR_AND_LOAD(6);
13727 if (astatic > 2) {
13728 DECR_AND_LOAD(5);
13729 if (astatic > 3) {
13730 DECR_AND_LOAD(4);
13731 }
13732 }
13733 }
13734 }
13735#undef DECR_AND_LOAD
13736
c48245f0
MR
13737 tcg_gen_movi_tl(t2, framesize);
13738 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13739 tcg_temp_free(t0);
13740 tcg_temp_free(t1);
c48245f0 13741 tcg_temp_free(t2);
364d4831
NF
13742}
13743
235785e8
AM
13744static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13745 int is_64_bit, int extended)
364d4831
NF
13746{
13747 TCGv t0;
13748
13749 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13750 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13751 return;
13752 }
13753
13754 t0 = tcg_temp_new();
13755
13756 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13757 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13758 if (!is_64_bit) {
13759 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13760 }
13761
13762 tcg_temp_free(t0);
13763}
13764
0d74a222
LA
13765static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13766 int16_t offset)
13767{
13768 TCGv_i32 t0 = tcg_const_i32(op);
13769 TCGv t1 = tcg_temp_new();
13770 gen_base_offset_addr(ctx, t1, base, offset);
13771 gen_helper_cache(cpu_env, t1, t0);
13772}
13773
364d4831 13774#if defined(TARGET_MIPS64)
235785e8
AM
13775static void decode_i64_mips16(DisasContext *ctx,
13776 int ry, int funct, int16_t offset,
13777 int extended)
364d4831
NF
13778{
13779 switch (funct) {
13780 case I64_LDSP:
d9224450 13781 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13782 check_mips_64(ctx);
13783 offset = extended ? offset : offset << 3;
d75c135e 13784 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13785 break;
13786 case I64_SDSP:
d9224450 13787 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13788 check_mips_64(ctx);
13789 offset = extended ? offset : offset << 3;
5c13fdfd 13790 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13791 break;
13792 case I64_SDRASP:
d9224450 13793 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13794 check_mips_64(ctx);
13795 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13796 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13797 break;
13798 case I64_DADJSP:
d9224450 13799 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13800 check_mips_64(ctx);
13801 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13802 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13803 break;
13804 case I64_LDPC:
d9224450
MR
13805 check_insn(ctx, ISA_MIPS3);
13806 check_mips_64(ctx);
364d4831 13807 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13808 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13809 } else {
13810 offset = extended ? offset : offset << 3;
d75c135e 13811 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13812 }
13813 break;
13814 case I64_DADDIU5:
d9224450 13815 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13816 check_mips_64(ctx);
13817 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13818 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13819 break;
13820 case I64_DADDIUPC:
d9224450 13821 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13822 check_mips_64(ctx);
13823 offset = extended ? offset : offset << 2;
13824 gen_addiupc(ctx, ry, offset, 1, extended);
13825 break;
13826 case I64_DADDIUSP:
d9224450 13827 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13828 check_mips_64(ctx);
13829 offset = extended ? offset : offset << 2;
d75c135e 13830 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13831 break;
13832 }
13833}
13834#endif
13835
235785e8 13836static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 13837{
eeb3bba8 13838 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13839 int op, rx, ry, funct, sa;
13840 int16_t imm, offset;
13841
13842 ctx->opcode = (ctx->opcode << 16) | extend;
13843 op = (ctx->opcode >> 11) & 0x1f;
13844 sa = (ctx->opcode >> 22) & 0x1f;
13845 funct = (ctx->opcode >> 8) & 0x7;
13846 rx = xlat((ctx->opcode >> 8) & 0x7);
13847 ry = xlat((ctx->opcode >> 5) & 0x7);
13848 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13849 | ((ctx->opcode >> 21) & 0x3f) << 5
13850 | (ctx->opcode & 0x1f));
13851
7480515f
AM
13852 /*
13853 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13854 * counterparts.
13855 */
364d4831
NF
13856 switch (op) {
13857 case M16_OPC_ADDIUSP:
d75c135e 13858 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13859 break;
13860 case M16_OPC_ADDIUPC:
13861 gen_addiupc(ctx, rx, imm, 0, 1);
13862 break;
13863 case M16_OPC_B:
b231c103 13864 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13865 /* No delay slot, so just process as a normal instruction */
13866 break;
13867 case M16_OPC_BEQZ:
b231c103 13868 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13869 /* No delay slot, so just process as a normal instruction */
13870 break;
13871 case M16_OPC_BNEQZ:
b231c103 13872 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13873 /* No delay slot, so just process as a normal instruction */
13874 break;
13875 case M16_OPC_SHIFT:
13876 switch (ctx->opcode & 0x3) {
13877 case 0x0:
d75c135e 13878 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13879 break;
13880 case 0x1:
13881#if defined(TARGET_MIPS64)
13882 check_mips_64(ctx);
d75c135e 13883 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13884#else
9c708c7f 13885 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13886#endif
13887 break;
13888 case 0x2:
d75c135e 13889 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13890 break;
13891 case 0x3:
d75c135e 13892 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13893 break;
13894 }
13895 break;
13896#if defined(TARGET_MIPS64)
13897 case M16_OPC_LD:
d9224450 13898 check_insn(ctx, ISA_MIPS3);
d75de749 13899 check_mips_64(ctx);
d75c135e 13900 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13901 break;
13902#endif
13903 case M16_OPC_RRIA:
13904 imm = ctx->opcode & 0xf;
13905 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13906 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13907 imm = (int16_t) (imm << 1) >> 1;
13908 if ((ctx->opcode >> 4) & 0x1) {
13909#if defined(TARGET_MIPS64)
13910 check_mips_64(ctx);
d75c135e 13911 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13912#else
9c708c7f 13913 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13914#endif
13915 } else {
d75c135e 13916 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13917 }
13918 break;
13919 case M16_OPC_ADDIU8:
d75c135e 13920 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13921 break;
13922 case M16_OPC_SLTI:
d75c135e 13923 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13924 break;
13925 case M16_OPC_SLTIU:
d75c135e 13926 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13927 break;
13928 case M16_OPC_I8:
13929 switch (funct) {
13930 case I8_BTEQZ:
b231c103 13931 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13932 break;
13933 case I8_BTNEZ:
b231c103 13934 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13935 break;
13936 case I8_SWRASP:
5c13fdfd 13937 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13938 break;
13939 case I8_ADJSP:
d75c135e 13940 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13941 break;
13942 case I8_SVRS:
d9224450 13943 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13944 {
13945 int xsregs = (ctx->opcode >> 24) & 0x7;
13946 int aregs = (ctx->opcode >> 16) & 0xf;
13947 int do_ra = (ctx->opcode >> 6) & 0x1;
13948 int do_s0 = (ctx->opcode >> 5) & 0x1;
13949 int do_s1 = (ctx->opcode >> 4) & 0x1;
13950 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13951 | (ctx->opcode & 0xf)) << 3;
13952
13953 if (ctx->opcode & (1 << 7)) {
13954 gen_mips16_save(ctx, xsregs, aregs,
13955 do_ra, do_s0, do_s1,
13956 framesize);
13957 } else {
13958 gen_mips16_restore(ctx, xsregs, aregs,
13959 do_ra, do_s0, do_s1,
13960 framesize);
13961 }
13962 }
13963 break;
13964 default:
9c708c7f 13965 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13966 break;
13967 }
13968 break;
13969 case M16_OPC_LI:
13970 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13971 break;
13972 case M16_OPC_CMPI:
13973 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13974 break;
13975#if defined(TARGET_MIPS64)
13976 case M16_OPC_SD:
d9224450
MR
13977 check_insn(ctx, ISA_MIPS3);
13978 check_mips_64(ctx);
5c13fdfd 13979 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13980 break;
13981#endif
13982 case M16_OPC_LB:
d75c135e 13983 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13984 break;
13985 case M16_OPC_LH:
d75c135e 13986 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13987 break;
13988 case M16_OPC_LWSP:
d75c135e 13989 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13990 break;
13991 case M16_OPC_LW:
d75c135e 13992 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13993 break;
13994 case M16_OPC_LBU:
d75c135e 13995 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13996 break;
13997 case M16_OPC_LHU:
d75c135e 13998 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13999 break;
14000 case M16_OPC_LWPC:
d75c135e 14001 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
14002 break;
14003#if defined(TARGET_MIPS64)
14004 case M16_OPC_LWU:
d9224450
MR
14005 check_insn(ctx, ISA_MIPS3);
14006 check_mips_64(ctx);
d75c135e 14007 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
14008 break;
14009#endif
14010 case M16_OPC_SB:
5c13fdfd 14011 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14012 break;
14013 case M16_OPC_SH:
5c13fdfd 14014 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
14015 break;
14016 case M16_OPC_SWSP:
5c13fdfd 14017 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
14018 break;
14019 case M16_OPC_SW:
5c13fdfd 14020 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
14021 break;
14022#if defined(TARGET_MIPS64)
14023 case M16_OPC_I64:
d75c135e 14024 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
14025 break;
14026#endif
14027 default:
9c708c7f 14028 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14029 break;
14030 }
14031
14032 return 4;
14033}
14034
3b3c1694
LA
14035static inline bool is_uhi(int sdbbp_code)
14036{
14037#ifdef CONFIG_USER_ONLY
14038 return false;
14039#else
14040 return semihosting_enabled() && sdbbp_code == 1;
14041#endif
14042}
14043
82ba4266
AB
14044#ifdef CONFIG_USER_ONLY
14045/* The above should dead-code away any calls to this..*/
14046static inline void gen_helper_do_semihosting(void *env)
14047{
14048 g_assert_not_reached();
14049}
14050#endif
14051
235785e8 14052static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
14053{
14054 int rx, ry;
14055 int sa;
14056 int op, cnvt_op, op1, offset;
14057 int funct;
14058 int n_bytes;
14059
14060 op = (ctx->opcode >> 11) & 0x1f;
14061 sa = (ctx->opcode >> 2) & 0x7;
14062 sa = sa == 0 ? 8 : sa;
14063 rx = xlat((ctx->opcode >> 8) & 0x7);
14064 cnvt_op = (ctx->opcode >> 5) & 0x7;
14065 ry = xlat((ctx->opcode >> 5) & 0x7);
14066 op1 = offset = ctx->opcode & 0x1f;
14067
14068 n_bytes = 2;
14069
14070 switch (op) {
14071 case M16_OPC_ADDIUSP:
14072 {
14073 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14074
d75c135e 14075 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
14076 }
14077 break;
14078 case M16_OPC_ADDIUPC:
14079 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14080 break;
14081 case M16_OPC_B:
14082 offset = (ctx->opcode & 0x7ff) << 1;
14083 offset = (int16_t)(offset << 4) >> 4;
b231c103 14084 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
14085 /* No delay slot, so just process as a normal instruction */
14086 break;
14087 case M16_OPC_JAL:
eeb3bba8 14088 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
14089 offset = (((ctx->opcode & 0x1f) << 21)
14090 | ((ctx->opcode >> 5) & 0x1f) << 16
14091 | offset) << 2;
b231c103
YK
14092 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14093 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 14094 n_bytes = 4;
364d4831
NF
14095 break;
14096 case M16_OPC_BEQZ:
b231c103
YK
14097 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14098 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14099 /* No delay slot, so just process as a normal instruction */
14100 break;
14101 case M16_OPC_BNEQZ:
b231c103
YK
14102 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14103 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14104 /* No delay slot, so just process as a normal instruction */
14105 break;
14106 case M16_OPC_SHIFT:
14107 switch (ctx->opcode & 0x3) {
14108 case 0x0:
d75c135e 14109 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
14110 break;
14111 case 0x1:
14112#if defined(TARGET_MIPS64)
d9224450 14113 check_insn(ctx, ISA_MIPS3);
364d4831 14114 check_mips_64(ctx);
d75c135e 14115 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 14116#else
9c708c7f 14117 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14118#endif
14119 break;
14120 case 0x2:
d75c135e 14121 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
14122 break;
14123 case 0x3:
d75c135e 14124 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
14125 break;
14126 }
14127 break;
14128#if defined(TARGET_MIPS64)
14129 case M16_OPC_LD:
d9224450 14130 check_insn(ctx, ISA_MIPS3);
364d4831 14131 check_mips_64(ctx);
d75c135e 14132 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
14133 break;
14134#endif
14135 case M16_OPC_RRIA:
14136 {
14137 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14138
14139 if ((ctx->opcode >> 4) & 1) {
14140#if defined(TARGET_MIPS64)
d9224450 14141 check_insn(ctx, ISA_MIPS3);
364d4831 14142 check_mips_64(ctx);
d75c135e 14143 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 14144#else
9c708c7f 14145 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14146#endif
14147 } else {
d75c135e 14148 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14149 }
14150 }
14151 break;
14152 case M16_OPC_ADDIU8:
14153 {
14154 int16_t imm = (int8_t) ctx->opcode;
14155
d75c135e 14156 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14157 }
14158 break;
14159 case M16_OPC_SLTI:
14160 {
14161 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14162 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14163 }
14164 break;
14165 case M16_OPC_SLTIU:
14166 {
14167 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14168 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14169 }
14170 break;
14171 case M16_OPC_I8:
14172 {
14173 int reg32;
14174
14175 funct = (ctx->opcode >> 8) & 0x7;
14176 switch (funct) {
14177 case I8_BTEQZ:
14178 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 14179 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14180 break;
14181 case I8_BTNEZ:
14182 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 14183 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14184 break;
14185 case I8_SWRASP:
5c13fdfd 14186 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
14187 break;
14188 case I8_ADJSP:
d75c135e 14189 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
14190 ((int8_t)ctx->opcode) << 3);
14191 break;
14192 case I8_SVRS:
d9224450 14193 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14194 {
14195 int do_ra = ctx->opcode & (1 << 6);
14196 int do_s0 = ctx->opcode & (1 << 5);
14197 int do_s1 = ctx->opcode & (1 << 4);
14198 int framesize = ctx->opcode & 0xf;
14199
14200 if (framesize == 0) {
14201 framesize = 128;
14202 } else {
14203 framesize = framesize << 3;
14204 }
14205
14206 if (ctx->opcode & (1 << 7)) {
14207 gen_mips16_save(ctx, 0, 0,
14208 do_ra, do_s0, do_s1, framesize);
14209 } else {
14210 gen_mips16_restore(ctx, 0, 0,
14211 do_ra, do_s0, do_s1, framesize);
14212 }
14213 }
14214 break;
14215 case I8_MOV32R:
14216 {
14217 int rz = xlat(ctx->opcode & 0x7);
14218
14219 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14220 ((ctx->opcode >> 5) & 0x7);
d75c135e 14221 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
14222 }
14223 break;
14224 case I8_MOVR32:
14225 reg32 = ctx->opcode & 0x1f;
d75c135e 14226 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
14227 break;
14228 default:
9c708c7f 14229 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14230 break;
14231 }
14232 }
14233 break;
14234 case M16_OPC_LI:
14235 {
14236 int16_t imm = (uint8_t) ctx->opcode;
14237
d75c135e 14238 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
14239 }
14240 break;
14241 case M16_OPC_CMPI:
14242 {
14243 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14244 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
14245 }
14246 break;
14247#if defined(TARGET_MIPS64)
14248 case M16_OPC_SD:
d9224450 14249 check_insn(ctx, ISA_MIPS3);
364d4831 14250 check_mips_64(ctx);
5c13fdfd 14251 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
14252 break;
14253#endif
14254 case M16_OPC_LB:
d75c135e 14255 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14256 break;
14257 case M16_OPC_LH:
d75c135e 14258 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
14259 break;
14260 case M16_OPC_LWSP:
d75c135e 14261 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14262 break;
14263 case M16_OPC_LW:
d75c135e 14264 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
14265 break;
14266 case M16_OPC_LBU:
d75c135e 14267 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14268 break;
14269 case M16_OPC_LHU:
d75c135e 14270 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
14271 break;
14272 case M16_OPC_LWPC:
d75c135e 14273 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 14274 break;
235785e8 14275#if defined(TARGET_MIPS64)
364d4831 14276 case M16_OPC_LWU:
d9224450 14277 check_insn(ctx, ISA_MIPS3);
364d4831 14278 check_mips_64(ctx);
d75c135e 14279 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
14280 break;
14281#endif
14282 case M16_OPC_SB:
5c13fdfd 14283 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14284 break;
14285 case M16_OPC_SH:
5c13fdfd 14286 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14287 break;
14288 case M16_OPC_SWSP:
5c13fdfd 14289 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14290 break;
14291 case M16_OPC_SW:
5c13fdfd 14292 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14293 break;
14294 case M16_OPC_RRR:
14295 {
14296 int rz = xlat((ctx->opcode >> 2) & 0x7);
14297 int mips32_op;
14298
14299 switch (ctx->opcode & 0x3) {
14300 case RRR_ADDU:
14301 mips32_op = OPC_ADDU;
14302 break;
14303 case RRR_SUBU:
14304 mips32_op = OPC_SUBU;
14305 break;
14306#if defined(TARGET_MIPS64)
14307 case RRR_DADDU:
14308 mips32_op = OPC_DADDU;
d9224450 14309 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14310 check_mips_64(ctx);
14311 break;
14312 case RRR_DSUBU:
14313 mips32_op = OPC_DSUBU;
d9224450 14314 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14315 check_mips_64(ctx);
14316 break;
14317#endif
14318 default:
9c708c7f 14319 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14320 goto done;
14321 }
14322
d75c135e 14323 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14324 done:
14325 ;
14326 }
14327 break;
14328 case M16_OPC_RR:
14329 switch (op1) {
14330 case RR_JR:
14331 {
14332 int nd = (ctx->opcode >> 7) & 0x1;
14333 int link = (ctx->opcode >> 6) & 0x1;
14334 int ra = (ctx->opcode >> 5) & 0x1;
14335
d9224450
MR
14336 if (nd) {
14337 check_insn(ctx, ISA_MIPS32);
14338 }
14339
364d4831 14340 if (link) {
b231c103 14341 op = OPC_JALR;
364d4831
NF
14342 } else {
14343 op = OPC_JR;
14344 }
14345
b231c103
YK
14346 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14347 (nd ? 0 : 2));
364d4831
NF
14348 }
14349 break;
14350 case RR_SDBBP:
3b3c1694
LA
14351 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14352 gen_helper_do_semihosting(cpu_env);
14353 } else {
7480515f
AM
14354 /*
14355 * XXX: not clear which exception should be raised
3b3c1694
LA
14356 * when in debug mode...
14357 */
14358 check_insn(ctx, ISA_MIPS32);
9c708c7f 14359 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14360 }
364d4831
NF
14361 break;
14362 case RR_SLT:
d75c135e 14363 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14364 break;
14365 case RR_SLTU:
d75c135e 14366 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14367 break;
14368 case RR_BREAK:
9c708c7f 14369 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14370 break;
14371 case RR_SLLV:
d75c135e 14372 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14373 break;
14374 case RR_SRLV:
d75c135e 14375 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14376 break;
14377 case RR_SRAV:
d75c135e 14378 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 14379 break;
235785e8 14380#if defined(TARGET_MIPS64)
364d4831 14381 case RR_DSRL:
d9224450 14382 check_insn(ctx, ISA_MIPS3);
364d4831 14383 check_mips_64(ctx);
d75c135e 14384 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14385 break;
14386#endif
14387 case RR_CMP:
d75c135e 14388 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14389 break;
14390 case RR_NEG:
d75c135e 14391 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14392 break;
14393 case RR_AND:
d75c135e 14394 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14395 break;
14396 case RR_OR:
d75c135e 14397 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14398 break;
14399 case RR_XOR:
d75c135e 14400 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14401 break;
14402 case RR_NOT:
d75c135e 14403 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14404 break;
14405 case RR_MFHI:
26135ead 14406 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14407 break;
14408 case RR_CNVT:
d9224450 14409 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14410 switch (cnvt_op) {
14411 case RR_RY_CNVT_ZEB:
14412 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14413 break;
14414 case RR_RY_CNVT_ZEH:
14415 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14416 break;
14417 case RR_RY_CNVT_SEB:
14418 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14419 break;
14420 case RR_RY_CNVT_SEH:
14421 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14422 break;
71375b59 14423#if defined(TARGET_MIPS64)
364d4831 14424 case RR_RY_CNVT_ZEW:
d9224450 14425 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14426 check_mips_64(ctx);
14427 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14428 break;
14429 case RR_RY_CNVT_SEW:
d9224450 14430 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14431 check_mips_64(ctx);
14432 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14433 break;
14434#endif
14435 default:
9c708c7f 14436 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14437 break;
14438 }
14439 break;
14440 case RR_MFLO:
26135ead 14441 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 14442 break;
235785e8 14443#if defined(TARGET_MIPS64)
364d4831 14444 case RR_DSRA:
d9224450 14445 check_insn(ctx, ISA_MIPS3);
364d4831 14446 check_mips_64(ctx);
d75c135e 14447 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14448 break;
14449 case RR_DSLLV:
d9224450 14450 check_insn(ctx, ISA_MIPS3);
364d4831 14451 check_mips_64(ctx);
d75c135e 14452 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14453 break;
14454 case RR_DSRLV:
d9224450 14455 check_insn(ctx, ISA_MIPS3);
364d4831 14456 check_mips_64(ctx);
d75c135e 14457 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14458 break;
14459 case RR_DSRAV:
d9224450 14460 check_insn(ctx, ISA_MIPS3);
364d4831 14461 check_mips_64(ctx);
d75c135e 14462 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14463 break;
14464#endif
14465 case RR_MULT:
26135ead 14466 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14467 break;
14468 case RR_MULTU:
26135ead 14469 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14470 break;
14471 case RR_DIV:
26135ead 14472 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14473 break;
14474 case RR_DIVU:
26135ead 14475 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 14476 break;
235785e8 14477#if defined(TARGET_MIPS64)
364d4831 14478 case RR_DMULT:
d9224450 14479 check_insn(ctx, ISA_MIPS3);
364d4831 14480 check_mips_64(ctx);
26135ead 14481 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14482 break;
14483 case RR_DMULTU:
d9224450 14484 check_insn(ctx, ISA_MIPS3);
364d4831 14485 check_mips_64(ctx);
26135ead 14486 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14487 break;
14488 case RR_DDIV:
d9224450 14489 check_insn(ctx, ISA_MIPS3);
364d4831 14490 check_mips_64(ctx);
26135ead 14491 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14492 break;
14493 case RR_DDIVU:
d9224450 14494 check_insn(ctx, ISA_MIPS3);
364d4831 14495 check_mips_64(ctx);
26135ead 14496 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14497 break;
14498#endif
14499 default:
9c708c7f 14500 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14501 break;
14502 }
14503 break;
14504 case M16_OPC_EXTEND:
240ce26a 14505 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14506 n_bytes = 4;
14507 break;
14508#if defined(TARGET_MIPS64)
14509 case M16_OPC_I64:
14510 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14511 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14512 break;
14513#endif
14514 default:
9c708c7f 14515 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14516 break;
14517 }
14518
14519 return n_bytes;
14520}
14521
211da992 14522/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 14523
211da992
CWR
14524/*
14525 * microMIPS32/microMIPS64 major opcodes
14526 *
14527 * 1. MIPS Architecture for Programmers Volume II-B:
14528 * The microMIPS32 Instruction Set (Revision 3.05)
14529 *
14530 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14531 *
14532 * 2. MIPS Architecture For Programmers Volume II-A:
14533 * The MIPS64 Instruction Set (Revision 3.51)
14534 */
6af0bf9c 14535
3c824109
NF
14536enum {
14537 POOL32A = 0x00,
14538 POOL16A = 0x01,
14539 LBU16 = 0x02,
14540 MOVE16 = 0x03,
14541 ADDI32 = 0x04,
3a1f4268
YK
14542 R6_LUI = 0x04,
14543 AUI = 0x04,
3c824109
NF
14544 LBU32 = 0x05,
14545 SB32 = 0x06,
14546 LB32 = 0x07,
14547
14548 POOL32B = 0x08,
14549 POOL16B = 0x09,
14550 LHU16 = 0x0a,
14551 ANDI16 = 0x0b,
14552 ADDIU32 = 0x0c,
14553 LHU32 = 0x0d,
14554 SH32 = 0x0e,
14555 LH32 = 0x0f,
14556
14557 POOL32I = 0x10,
14558 POOL16C = 0x11,
14559 LWSP16 = 0x12,
14560 POOL16D = 0x13,
14561 ORI32 = 0x14,
14562 POOL32F = 0x15,
211da992
CWR
14563 POOL32S = 0x16, /* MIPS64 */
14564 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
14565
14566 POOL32C = 0x18,
14567 LWGP16 = 0x19,
14568 LW16 = 0x1a,
14569 POOL16E = 0x1b,
14570 XORI32 = 0x1c,
14571 JALS32 = 0x1d,
3a1f4268
YK
14572 BOVC = 0x1d,
14573 BEQC = 0x1d,
14574 BEQZALC = 0x1d,
3c824109 14575 ADDIUPC = 0x1e,
3a1f4268
YK
14576 PCREL = 0x1e,
14577 BNVC = 0x1f,
14578 BNEC = 0x1f,
14579 BNEZALC = 0x1f,
3c824109 14580
3a1f4268
YK
14581 R6_BEQZC = 0x20,
14582 JIC = 0x20,
3c824109
NF
14583 POOL16F = 0x21,
14584 SB16 = 0x22,
14585 BEQZ16 = 0x23,
3a1f4268 14586 BEQZC16 = 0x23,
3c824109
NF
14587 SLTI32 = 0x24,
14588 BEQ32 = 0x25,
3a1f4268 14589 BC = 0x25,
3c824109
NF
14590 SWC132 = 0x26,
14591 LWC132 = 0x27,
14592
3a1f4268 14593 /* 0x29 is reserved */
3c824109 14594 RES_29 = 0x29,
3a1f4268
YK
14595 R6_BNEZC = 0x28,
14596 JIALC = 0x28,
3c824109
NF
14597 SH16 = 0x2a,
14598 BNEZ16 = 0x2b,
3a1f4268 14599 BNEZC16 = 0x2b,
3c824109
NF
14600 SLTIU32 = 0x2c,
14601 BNE32 = 0x2d,
3a1f4268 14602 BALC = 0x2d,
3c824109
NF
14603 SDC132 = 0x2e,
14604 LDC132 = 0x2f,
14605
3a1f4268 14606 /* 0x31 is reserved */
3c824109 14607 RES_31 = 0x31,
3a1f4268
YK
14608 BLEZALC = 0x30,
14609 BGEZALC = 0x30,
14610 BGEUC = 0x30,
3c824109
NF
14611 SWSP16 = 0x32,
14612 B16 = 0x33,
3a1f4268 14613 BC16 = 0x33,
3c824109
NF
14614 ANDI32 = 0x34,
14615 J32 = 0x35,
3a1f4268
YK
14616 BGTZC = 0x35,
14617 BLTZC = 0x35,
14618 BLTC = 0x35,
211da992
CWR
14619 SD32 = 0x36, /* MIPS64 */
14620 LD32 = 0x37, /* MIPS64 */
3c824109 14621
3a1f4268 14622 /* 0x39 is reserved */
3c824109 14623 RES_39 = 0x39,
3a1f4268
YK
14624 BGTZALC = 0x38,
14625 BLTZALC = 0x38,
14626 BLTUC = 0x38,
3c824109
NF
14627 SW16 = 0x3a,
14628 LI16 = 0x3b,
14629 JALX32 = 0x3c,
14630 JAL32 = 0x3d,
3a1f4268
YK
14631 BLEZC = 0x3d,
14632 BGEZC = 0x3d,
14633 BGEC = 0x3d,
3c824109
NF
14634 SW32 = 0x3e,
14635 LW32 = 0x3f
14636};
14637
3a1f4268
YK
14638/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14639enum {
14640 ADDIUPC_00 = 0x00,
c38a1d52
AR
14641 ADDIUPC_01 = 0x01,
14642 ADDIUPC_02 = 0x02,
14643 ADDIUPC_03 = 0x03,
14644 ADDIUPC_04 = 0x04,
14645 ADDIUPC_05 = 0x05,
14646 ADDIUPC_06 = 0x06,
3a1f4268
YK
14647 ADDIUPC_07 = 0x07,
14648 AUIPC = 0x1e,
14649 ALUIPC = 0x1f,
14650 LWPC_08 = 0x08,
c38a1d52
AR
14651 LWPC_09 = 0x09,
14652 LWPC_0A = 0x0A,
14653 LWPC_0B = 0x0B,
14654 LWPC_0C = 0x0C,
14655 LWPC_0D = 0x0D,
14656 LWPC_0E = 0x0E,
3a1f4268
YK
14657 LWPC_0F = 0x0F,
14658};
14659
3c824109
NF
14660/* POOL32A encoding of minor opcode field */
14661
14662enum {
7480515f
AM
14663 /*
14664 * These opcodes are distinguished only by bits 9..6; those bits are
14665 * what are recorded below.
14666 */
3c824109
NF
14667 SLL32 = 0x0,
14668 SRL32 = 0x1,
14669 SRA = 0x2,
14670 ROTR = 0x3,
3a1f4268
YK
14671 SELEQZ = 0x5,
14672 SELNEZ = 0x6,
b00c7218 14673 R6_RDHWR = 0x7,
3c824109
NF
14674
14675 SLLV = 0x0,
14676 SRLV = 0x1,
14677 SRAV = 0x2,
14678 ROTRV = 0x3,
14679 ADD = 0x4,
14680 ADDU32 = 0x5,
14681 SUB = 0x6,
14682 SUBU32 = 0x7,
14683 MUL = 0x8,
14684 AND = 0x9,
14685 OR32 = 0xa,
14686 NOR = 0xb,
14687 XOR32 = 0xc,
14688 SLT = 0xd,
14689 SLTU = 0xe,
14690
14691 MOVN = 0x0,
3a1f4268 14692 R6_MUL = 0x0,
3c824109 14693 MOVZ = 0x1,
3a1f4268
YK
14694 MUH = 0x1,
14695 MULU = 0x2,
14696 MUHU = 0x3,
3c824109 14697 LWXS = 0x4,
3a1f4268
YK
14698 R6_DIV = 0x4,
14699 MOD = 0x5,
14700 R6_DIVU = 0x6,
14701 MODU = 0x7,
3c824109
NF
14702
14703 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14704 BREAK32 = 0x07,
3c824109 14705 INS = 0x0c,
3a1f4268
YK
14706 LSA = 0x0f,
14707 ALIGN = 0x1f,
3c824109 14708 EXT = 0x2c,
bb238210
YK
14709 POOL32AXF = 0x3c,
14710 SIGRIE = 0x3f
3c824109
NF
14711};
14712
14713/* POOL32AXF encoding of minor opcode field extension */
14714
d132c79f
CWR
14715/*
14716 * 1. MIPS Architecture for Programmers Volume II-B:
14717 * The microMIPS32 Instruction Set (Revision 3.05)
14718 *
14719 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14720 *
14721 * 2. MIPS Architecture for Programmers VolumeIV-e:
14722 * The MIPS DSP Application-Specific Extension
14723 * to the microMIPS32 Architecture (Revision 2.34)
14724 *
14725 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14726 */
14727
3c824109
NF
14728enum {
14729 /* bits 11..6 */
14730 TEQ = 0x00,
14731 TGE = 0x08,
14732 TGEU = 0x10,
14733 TLT = 0x20,
14734 TLTU = 0x28,
14735 TNE = 0x30,
14736
14737 MFC0 = 0x03,
14738 MTC0 = 0x0b,
14739
d132c79f
CWR
14740 /* begin of microMIPS32 DSP */
14741
3c824109
NF
14742 /* bits 13..12 for 0x01 */
14743 MFHI_ACC = 0x0,
14744 MFLO_ACC = 0x1,
14745 MTHI_ACC = 0x2,
14746 MTLO_ACC = 0x3,
14747
14748 /* bits 13..12 for 0x2a */
14749 MADD_ACC = 0x0,
14750 MADDU_ACC = 0x1,
14751 MSUB_ACC = 0x2,
14752 MSUBU_ACC = 0x3,
14753
14754 /* bits 13..12 for 0x32 */
14755 MULT_ACC = 0x0,
6801038b 14756 MULTU_ACC = 0x1,
3c824109 14757
d132c79f
CWR
14758 /* end of microMIPS32 DSP */
14759
3c824109 14760 /* bits 15..12 for 0x2c */
3a1f4268 14761 BITSWAP = 0x0,
3c824109
NF
14762 SEB = 0x2,
14763 SEH = 0x3,
14764 CLO = 0x4,
14765 CLZ = 0x5,
14766 RDHWR = 0x6,
14767 WSBH = 0x7,
14768 MULT = 0x8,
14769 MULTU = 0x9,
14770 DIV = 0xa,
14771 DIVU = 0xb,
14772 MADD = 0xc,
14773 MADDU = 0xd,
14774 MSUB = 0xe,
14775 MSUBU = 0xf,
14776
14777 /* bits 15..12 for 0x34 */
14778 MFC2 = 0x4,
14779 MTC2 = 0x5,
14780 MFHC2 = 0x8,
14781 MTHC2 = 0x9,
14782 CFC2 = 0xc,
14783 CTC2 = 0xd,
14784
14785 /* bits 15..12 for 0x3c */
14786 JALR = 0x0,
14787 JR = 0x0, /* alias */
3a1f4268
YK
14788 JALRC = 0x0,
14789 JRC = 0x0,
3c824109 14790 JALR_HB = 0x1,
3a1f4268 14791 JALRC_HB = 0x1,
3c824109
NF
14792 JALRS = 0x4,
14793 JALRS_HB = 0x5,
14794
14795 /* bits 15..12 for 0x05 */
14796 RDPGPR = 0xe,
14797 WRPGPR = 0xf,
14798
14799 /* bits 15..12 for 0x0d */
14800 TLBP = 0x0,
14801 TLBR = 0x1,
14802 TLBWI = 0x2,
14803 TLBWR = 0x3,
e60ec063
YK
14804 TLBINV = 0x4,
14805 TLBINVF = 0x5,
3c824109
NF
14806 WAIT = 0x9,
14807 IRET = 0xd,
14808 DERET = 0xe,
14809 ERET = 0xf,
14810
14811 /* bits 15..12 for 0x15 */
14812 DMT = 0x0,
14813 DVPE = 0x1,
14814 EMT = 0x2,
14815 EVPE = 0x3,
14816
14817 /* bits 15..12 for 0x1d */
14818 DI = 0x4,
14819 EI = 0x5,
14820
14821 /* bits 15..12 for 0x2d */
14822 SYNC = 0x6,
14823 SYSCALL = 0x8,
14824 SDBBP = 0xd,
14825
14826 /* bits 15..12 for 0x35 */
14827 MFHI32 = 0x0,
14828 MFLO32 = 0x1,
14829 MTHI32 = 0x2,
14830 MTLO32 = 0x3,
14831};
14832
14833/* POOL32B encoding of minor opcode field (bits 15..12) */
14834
14835enum {
14836 LWC2 = 0x0,
14837 LWP = 0x1,
14838 LDP = 0x4,
14839 LWM32 = 0x5,
14840 CACHE = 0x6,
14841 LDM = 0x7,
14842 SWC2 = 0x8,
14843 SWP = 0x9,
14844 SDP = 0xc,
14845 SWM32 = 0xd,
14846 SDM = 0xf
14847};
14848
14849/* POOL32C encoding of minor opcode field (bits 15..12) */
14850
14851enum {
14852 LWL = 0x0,
14853 SWL = 0x8,
14854 LWR = 0x1,
14855 SWR = 0x9,
14856 PREF = 0x2,
8fffc646 14857 ST_EVA = 0xa,
3c824109
NF
14858 LL = 0x3,
14859 SC = 0xb,
14860 LDL = 0x4,
14861 SDL = 0xc,
14862 LDR = 0x5,
14863 SDR = 0xd,
8fffc646 14864 LD_EVA = 0x6,
3c824109
NF
14865 LWU = 0xe,
14866 LLD = 0x7,
14867 SCD = 0xf
14868};
14869
8fffc646
JH
14870/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14871
14872enum {
14873 LBUE = 0x0,
14874 LHUE = 0x1,
14875 LWLE = 0x2,
14876 LWRE = 0x3,
14877 LBE = 0x4,
14878 LHE = 0x5,
14879 LLE = 0x6,
14880 LWE = 0x7,
14881};
14882
14883/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14884
14885enum {
14886 SWLE = 0x0,
14887 SWRE = 0x1,
14888 PREFE = 0x2,
14889 CACHEE = 0x3,
14890 SBE = 0x4,
14891 SHE = 0x5,
14892 SCE = 0x6,
14893 SWE = 0x7,
14894};
14895
3c824109
NF
14896/* POOL32F encoding of minor opcode field (bits 5..0) */
14897
14898enum {
14899 /* These are the bit 7..6 values */
14900 ADD_FMT = 0x0,
3c824109
NF
14901
14902 SUB_FMT = 0x1,
3c824109
NF
14903
14904 MUL_FMT = 0x2,
14905
14906 DIV_FMT = 0x3,
14907
14908 /* These are the bit 8..6 values */
3a1f4268 14909 MOVN_FMT = 0x0,
3c824109
NF
14910 RSQRT2_FMT = 0x0,
14911 MOVF_FMT = 0x0,
3a1f4268
YK
14912 RINT_FMT = 0x0,
14913 SELNEZ_FMT = 0x0,
3c824109 14914
3a1f4268 14915 MOVZ_FMT = 0x1,
3c824109
NF
14916 LWXC1 = 0x1,
14917 MOVT_FMT = 0x1,
3a1f4268
YK
14918 CLASS_FMT = 0x1,
14919 SELEQZ_FMT = 0x1,
3c824109
NF
14920
14921 PLL_PS = 0x2,
14922 SWXC1 = 0x2,
3a1f4268 14923 SEL_FMT = 0x2,
3c824109
NF
14924
14925 PLU_PS = 0x3,
14926 LDXC1 = 0x3,
14927
3a1f4268 14928 MOVN_FMT_04 = 0x4,
3c824109
NF
14929 PUL_PS = 0x4,
14930 SDXC1 = 0x4,
14931 RECIP2_FMT = 0x4,
14932
3a1f4268 14933 MOVZ_FMT_05 = 0x05,
3c824109
NF
14934 PUU_PS = 0x5,
14935 LUXC1 = 0x5,
14936
14937 CVT_PS_S = 0x6,
14938 SUXC1 = 0x6,
14939 ADDR_PS = 0x6,
14940 PREFX = 0x6,
3a1f4268 14941 MADDF_FMT = 0x6,
3c824109
NF
14942
14943 MULR_PS = 0x7,
3a1f4268 14944 MSUBF_FMT = 0x7,
3c824109
NF
14945
14946 MADD_S = 0x01,
14947 MADD_D = 0x09,
14948 MADD_PS = 0x11,
14949 ALNV_PS = 0x19,
14950 MSUB_S = 0x21,
14951 MSUB_D = 0x29,
14952 MSUB_PS = 0x31,
14953
14954 NMADD_S = 0x02,
14955 NMADD_D = 0x0a,
14956 NMADD_PS = 0x12,
14957 NMSUB_S = 0x22,
14958 NMSUB_D = 0x2a,
14959 NMSUB_PS = 0x32,
14960
3a1f4268
YK
14961 MIN_FMT = 0x3,
14962 MAX_FMT = 0xb,
14963 MINA_FMT = 0x23,
14964 MAXA_FMT = 0x2b,
3c824109
NF
14965 POOL32FXF = 0x3b,
14966
14967 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14968 C_COND_FMT = 0x3c,
14969
14970 CMP_CONDN_S = 0x5,
14971 CMP_CONDN_D = 0x15
3c824109
NF
14972};
14973
14974/* POOL32Fxf encoding of minor opcode extension field */
14975
14976enum {
14977 CVT_L = 0x04,
14978 RSQRT_FMT = 0x08,
14979 FLOOR_L = 0x0c,
14980 CVT_PW_PS = 0x1c,
14981 CVT_W = 0x24,
14982 SQRT_FMT = 0x28,
14983 FLOOR_W = 0x2c,
14984 CVT_PS_PW = 0x3c,
14985 CFC1 = 0x40,
14986 RECIP_FMT = 0x48,
14987 CEIL_L = 0x4c,
14988 CTC1 = 0x60,
14989 CEIL_W = 0x6c,
14990 MFC1 = 0x80,
14991 CVT_S_PL = 0x84,
14992 TRUNC_L = 0x8c,
14993 MTC1 = 0xa0,
14994 CVT_S_PU = 0xa4,
14995 TRUNC_W = 0xac,
14996 MFHC1 = 0xc0,
14997 ROUND_L = 0xcc,
14998 MTHC1 = 0xe0,
14999 ROUND_W = 0xec,
15000
15001 MOV_FMT = 0x01,
15002 MOVF = 0x05,
15003 ABS_FMT = 0x0d,
15004 RSQRT1_FMT = 0x1d,
15005 MOVT = 0x25,
15006 NEG_FMT = 0x2d,
15007 CVT_D = 0x4d,
15008 RECIP1_FMT = 0x5d,
15009 CVT_S = 0x6d
15010};
15011
15012/* POOL32I encoding of minor opcode field (bits 25..21) */
15013
15014enum {
15015 BLTZ = 0x00,
15016 BLTZAL = 0x01,
15017 BGEZ = 0x02,
15018 BGEZAL = 0x03,
15019 BLEZ = 0x04,
15020 BNEZC = 0x05,
15021 BGTZ = 0x06,
15022 BEQZC = 0x07,
15023 TLTI = 0x08,
3a1f4268 15024 BC1EQZC = 0x08,
3c824109 15025 TGEI = 0x09,
3a1f4268 15026 BC1NEZC = 0x09,
3c824109 15027 TLTIU = 0x0a,
3a1f4268 15028 BC2EQZC = 0x0a,
3c824109 15029 TGEIU = 0x0b,
3a1f4268 15030 BC2NEZC = 0x0a,
3c824109 15031 TNEI = 0x0c,
3a1f4268 15032 R6_SYNCI = 0x0c,
3c824109
NF
15033 LUI = 0x0d,
15034 TEQI = 0x0e,
15035 SYNCI = 0x10,
15036 BLTZALS = 0x11,
15037 BGEZALS = 0x13,
15038 BC2F = 0x14,
15039 BC2T = 0x15,
15040 BPOSGE64 = 0x1a,
15041 BPOSGE32 = 0x1b,
15042 /* These overlap and are distinguished by bit16 of the instruction */
15043 BC1F = 0x1c,
15044 BC1T = 0x1d,
15045 BC1ANY2F = 0x1c,
15046 BC1ANY2T = 0x1d,
15047 BC1ANY4F = 0x1e,
15048 BC1ANY4T = 0x1f
15049};
15050
15051/* POOL16A encoding of minor opcode field */
15052
15053enum {
15054 ADDU16 = 0x0,
15055 SUBU16 = 0x1
15056};
15057
15058/* POOL16B encoding of minor opcode field */
15059
15060enum {
15061 SLL16 = 0x0,
15062 SRL16 = 0x1
15063};
15064
15065/* POOL16C encoding of minor opcode field */
15066
15067enum {
15068 NOT16 = 0x00,
15069 XOR16 = 0x04,
15070 AND16 = 0x08,
15071 OR16 = 0x0c,
15072 LWM16 = 0x10,
15073 SWM16 = 0x14,
15074 JR16 = 0x18,
15075 JRC16 = 0x1a,
15076 JALR16 = 0x1c,
15077 JALR16S = 0x1e,
15078 MFHI16 = 0x20,
15079 MFLO16 = 0x24,
15080 BREAK16 = 0x28,
15081 SDBBP16 = 0x2c,
15082 JRADDIUSP = 0x30
15083};
15084
3a1f4268
YK
15085/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15086
15087enum {
15088 R6_NOT16 = 0x00,
15089 R6_AND16 = 0x01,
15090 R6_LWM16 = 0x02,
15091 R6_JRC16 = 0x03,
15092 MOVEP = 0x04,
c38a1d52
AR
15093 MOVEP_05 = 0x05,
15094 MOVEP_06 = 0x06,
3a1f4268
YK
15095 MOVEP_07 = 0x07,
15096 R6_XOR16 = 0x08,
15097 R6_OR16 = 0x09,
15098 R6_SWM16 = 0x0a,
15099 JALRC16 = 0x0b,
15100 MOVEP_0C = 0x0c,
c38a1d52
AR
15101 MOVEP_0D = 0x0d,
15102 MOVEP_0E = 0x0e,
3a1f4268
YK
15103 MOVEP_0F = 0x0f,
15104 JRCADDIUSP = 0x13,
15105 R6_BREAK16 = 0x1b,
15106 R6_SDBBP16 = 0x3b
15107};
15108
3c824109
NF
15109/* POOL16D encoding of minor opcode field */
15110
15111enum {
15112 ADDIUS5 = 0x0,
15113 ADDIUSP = 0x1
15114};
15115
15116/* POOL16E encoding of minor opcode field */
15117
15118enum {
15119 ADDIUR2 = 0x0,
15120 ADDIUR1SP = 0x1
15121};
15122
235785e8 15123static int mmreg(int r)
3c824109
NF
15124{
15125 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15126
15127 return map[r];
15128}
15129
15130/* Used for 16-bit store instructions. */
235785e8 15131static int mmreg2(int r)
3c824109
NF
15132{
15133 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15134
15135 return map[r];
15136}
15137
15138#define uMIPS_RD(op) ((op >> 7) & 0x7)
15139#define uMIPS_RS(op) ((op >> 4) & 0x7)
15140#define uMIPS_RS2(op) uMIPS_RS(op)
15141#define uMIPS_RS1(op) ((op >> 1) & 0x7)
15142#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15143#define uMIPS_RS5(op) (op & 0x1f)
15144
15145/* Signed immediate */
15146#define SIMM(op, start, width) \
71375b59
AM
15147 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15148 << (32 - width)) \
15149 >> (32 - width))
3c824109 15150/* Zero-extended immediate */
71375b59 15151#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 15152
d75c135e 15153static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
15154{
15155 int rd = mmreg(uMIPS_RD(ctx->opcode));
15156
d75c135e 15157 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
15158}
15159
d75c135e 15160static void gen_addiur2(DisasContext *ctx)
3c824109
NF
15161{
15162 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15163 int rd = mmreg(uMIPS_RD(ctx->opcode));
15164 int rs = mmreg(uMIPS_RS(ctx->opcode));
15165
d75c135e 15166 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
15167}
15168
d75c135e 15169static void gen_addiusp(DisasContext *ctx)
3c824109
NF
15170{
15171 int encoded = ZIMM(ctx->opcode, 1, 9);
15172 int decoded;
15173
15174 if (encoded <= 1) {
15175 decoded = 256 + encoded;
15176 } else if (encoded <= 255) {
15177 decoded = encoded;
15178 } else if (encoded <= 509) {
15179 decoded = encoded - 512;
15180 } else {
15181 decoded = encoded - 768;
15182 }
15183
d75c135e 15184 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
15185}
15186
d75c135e 15187static void gen_addius5(DisasContext *ctx)
3c824109
NF
15188{
15189 int imm = SIMM(ctx->opcode, 1, 4);
15190 int rd = (ctx->opcode >> 5) & 0x1f;
15191
d75c135e 15192 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
15193}
15194
d75c135e 15195static void gen_andi16(DisasContext *ctx)
3c824109
NF
15196{
15197 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15198 31, 32, 63, 64, 255, 32768, 65535 };
15199 int rd = mmreg(uMIPS_RD(ctx->opcode));
15200 int rs = mmreg(uMIPS_RS(ctx->opcode));
15201 int encoded = ZIMM(ctx->opcode, 0, 4);
15202
d75c135e 15203 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
15204}
15205
235785e8
AM
15206static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15207 int base, int16_t offset)
3c824109
NF
15208{
15209 TCGv t0, t1;
15210 TCGv_i32 t2;
15211
15212 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 15213 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15214 return;
15215 }
15216
15217 t0 = tcg_temp_new();
15218
15219 gen_base_offset_addr(ctx, t0, base, offset);
15220
15221 t1 = tcg_const_tl(reglist);
15222 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 15223
3c824109
NF
15224 save_cpu_state(ctx, 1);
15225 switch (opc) {
15226 case LWM32:
895c2d04 15227 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
15228 break;
15229 case SWM32:
895c2d04 15230 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
15231 break;
15232#ifdef TARGET_MIPS64
15233 case LDM:
895c2d04 15234 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
15235 break;
15236 case SDM:
895c2d04 15237 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 15238 break;
6af0bf9c 15239#endif
3c824109 15240 }
3c824109 15241 tcg_temp_free(t0);
33087598 15242 tcg_temp_free(t1);
3c824109
NF
15243 tcg_temp_free_i32(t2);
15244}
6af0bf9c 15245
3c824109 15246
240ce26a 15247static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 15248{
3c824109
NF
15249 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15250 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 15251
3c824109
NF
15252 switch (((ctx->opcode) >> 4) & 0x3f) {
15253 case NOT16 + 0:
15254 case NOT16 + 1:
15255 case NOT16 + 2:
15256 case NOT16 + 3:
d75c135e 15257 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
15258 break;
15259 case XOR16 + 0:
15260 case XOR16 + 1:
15261 case XOR16 + 2:
15262 case XOR16 + 3:
d75c135e 15263 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
15264 break;
15265 case AND16 + 0:
15266 case AND16 + 1:
15267 case AND16 + 2:
15268 case AND16 + 3:
d75c135e 15269 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
15270 break;
15271 case OR16 + 0:
15272 case OR16 + 1:
15273 case OR16 + 2:
15274 case OR16 + 3:
d75c135e 15275 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
15276 break;
15277 case LWM16 + 0:
15278 case LWM16 + 1:
15279 case LWM16 + 2:
15280 case LWM16 + 3:
15281 {
15282 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15283 int offset = ZIMM(ctx->opcode, 0, 4);
15284
15285 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15286 29, offset << 2);
15287 }
15288 break;
15289 case SWM16 + 0:
15290 case SWM16 + 1:
15291 case SWM16 + 2:
15292 case SWM16 + 3:
15293 {
15294 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15295 int offset = ZIMM(ctx->opcode, 0, 4);
15296
15297 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15298 29, offset << 2);
15299 }
15300 break;
15301 case JR16 + 0:
15302 case JR16 + 1:
15303 {
15304 int reg = ctx->opcode & 0x1f;
15305
b231c103 15306 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15307 }
3c824109
NF
15308 break;
15309 case JRC16 + 0:
15310 case JRC16 + 1:
15311 {
15312 int reg = ctx->opcode & 0x1f;
b231c103 15313 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
15314 /*
15315 * Let normal delay slot handling in our caller take us
15316 * to the branch target.
15317 */
3c824109
NF
15318 }
15319 break;
15320 case JALR16 + 0:
15321 case JALR16 + 1:
b231c103
YK
15322 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15323 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15324 break;
3c824109
NF
15325 case JALR16S + 0:
15326 case JALR16S + 1:
b231c103
YK
15327 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15328 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15329 break;
15330 case MFHI16 + 0:
15331 case MFHI16 + 1:
26135ead 15332 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15333 break;
15334 case MFLO16 + 0:
15335 case MFLO16 + 1:
26135ead 15336 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15337 break;
15338 case BREAK16:
9c708c7f 15339 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15340 break;
15341 case SDBBP16:
3b3c1694
LA
15342 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15343 gen_helper_do_semihosting(cpu_env);
15344 } else {
7480515f
AM
15345 /*
15346 * XXX: not clear which exception should be raised
3b3c1694
LA
15347 * when in debug mode...
15348 */
15349 check_insn(ctx, ISA_MIPS32);
9c708c7f 15350 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15351 }
3c824109
NF
15352 break;
15353 case JRADDIUSP + 0:
15354 case JRADDIUSP + 1:
15355 {
15356 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15357 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15358 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
15359 /*
15360 * Let normal delay slot handling in our caller take us
15361 * to the branch target.
15362 */
3c824109
NF
15363 }
15364 break;
15365 default:
9c708c7f 15366 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15367 break;
15368 }
15369}
15370
ed7ce6c0
YK
15371static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15372 int enc_rs)
15373{
15374 int rd, rs, re, rt;
15375 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15376 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15377 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15378 rd = rd_enc[enc_dest];
15379 re = re_enc[enc_dest];
15380 rs = rs_rt_enc[enc_rs];
15381 rt = rs_rt_enc[enc_rt];
15382 if (rs) {
15383 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15384 } else {
15385 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15386 }
15387 if (rt) {
15388 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15389 } else {
15390 tcg_gen_movi_tl(cpu_gpr[re], 0);
15391 }
15392}
15393
15394static void gen_pool16c_r6_insn(DisasContext *ctx)
15395{
15396 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15397 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15398
15399 switch (ctx->opcode & 0xf) {
15400 case R6_NOT16:
15401 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15402 break;
15403 case R6_AND16:
15404 gen_logic(ctx, OPC_AND, rt, rt, rs);
15405 break;
15406 case R6_LWM16:
15407 {
15408 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15409 int offset = extract32(ctx->opcode, 4, 4);
15410 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15411 }
15412 break;
15413 case R6_JRC16: /* JRCADDIUSP */
15414 if ((ctx->opcode >> 4) & 1) {
15415 /* JRCADDIUSP */
15416 int imm = extract32(ctx->opcode, 5, 5);
15417 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15418 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15419 } else {
15420 /* JRC16 */
e1555d7d 15421 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15422 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15423 }
15424 break;
c38a1d52
AR
15425 case MOVEP:
15426 case MOVEP_05:
15427 case MOVEP_06:
15428 case MOVEP_07:
15429 case MOVEP_0C:
15430 case MOVEP_0D:
15431 case MOVEP_0E:
15432 case MOVEP_0F:
ed7ce6c0
YK
15433 {
15434 int enc_dest = uMIPS_RD(ctx->opcode);
15435 int enc_rt = uMIPS_RS2(ctx->opcode);
15436 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15437 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15438 }
15439 break;
15440 case R6_XOR16:
15441 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15442 break;
15443 case R6_OR16:
15444 gen_logic(ctx, OPC_OR, rt, rt, rs);
15445 break;
15446 case R6_SWM16:
15447 {
15448 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15449 int offset = extract32(ctx->opcode, 4, 4);
15450 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15451 }
15452 break;
15453 case JALRC16: /* BREAK16, SDBBP16 */
15454 switch (ctx->opcode & 0x3f) {
15455 case JALRC16:
15456 case JALRC16 + 0x20:
15457 /* JALRC16 */
15458 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15459 31, 0, 0);
15460 break;
15461 case R6_BREAK16:
15462 /* BREAK16 */
15463 generate_exception(ctx, EXCP_BREAK);
15464 break;
15465 case R6_SDBBP16:
15466 /* SDBBP16 */
060ebfef
LA
15467 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15468 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15469 } else {
060ebfef
LA
15470 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15471 generate_exception(ctx, EXCP_RI);
15472 } else {
15473 generate_exception(ctx, EXCP_DBp);
15474 }
ed7ce6c0
YK
15475 }
15476 break;
15477 }
15478 break;
15479 default:
15480 generate_exception(ctx, EXCP_RI);
15481 break;
15482 }
15483}
15484
235785e8 15485static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
15486{
15487 TCGv t0 = tcg_temp_new();
15488 TCGv t1 = tcg_temp_new();
15489
15490 gen_load_gpr(t0, base);
15491
15492 if (index != 0) {
15493 gen_load_gpr(t1, index);
15494 tcg_gen_shli_tl(t1, t1, 2);
15495 gen_op_addr_add(ctx, t0, t1, t0);
15496 }
15497
5f68f5ae 15498 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15499 gen_store_gpr(t1, rd);
15500
15501 tcg_temp_free(t0);
15502 tcg_temp_free(t1);
15503}
15504
235785e8
AM
15505static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15506 int base, int16_t offset)
3c824109 15507{
3c824109
NF
15508 TCGv t0, t1;
15509
36c6711b 15510 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15511 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15512 return;
15513 }
15514
3c824109
NF
15515 t0 = tcg_temp_new();
15516 t1 = tcg_temp_new();
8e9ade68 15517
3c824109
NF
15518 gen_base_offset_addr(ctx, t0, base, offset);
15519
15520 switch (opc) {
15521 case LWP:
36c6711b 15522 if (rd == base) {
9c708c7f 15523 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15524 return;
15525 }
5f68f5ae 15526 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15527 gen_store_gpr(t1, rd);
15528 tcg_gen_movi_tl(t1, 4);
15529 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15530 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 15531 gen_store_gpr(t1, rd + 1);
3c824109
NF
15532 break;
15533 case SWP:
3c824109 15534 gen_load_gpr(t1, rd);
5f68f5ae 15535 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15536 tcg_gen_movi_tl(t1, 4);
15537 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15538 gen_load_gpr(t1, rd + 1);
5f68f5ae 15539 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15540 break;
15541#ifdef TARGET_MIPS64
15542 case LDP:
36c6711b 15543 if (rd == base) {
9c708c7f 15544 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15545 return;
15546 }
5f68f5ae 15547 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15548 gen_store_gpr(t1, rd);
15549 tcg_gen_movi_tl(t1, 8);
15550 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15551 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 15552 gen_store_gpr(t1, rd + 1);
3c824109
NF
15553 break;
15554 case SDP:
3c824109 15555 gen_load_gpr(t1, rd);
5f68f5ae 15556 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15557 tcg_gen_movi_tl(t1, 8);
15558 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15559 gen_load_gpr(t1, rd + 1);
5f68f5ae 15560 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15561 break;
15562#endif
6af0bf9c 15563 }
3c824109
NF
15564 tcg_temp_free(t0);
15565 tcg_temp_free(t1);
15566}
618b0fe9 15567
d208ac0c
LA
15568static void gen_sync(int stype)
15569{
15570 TCGBar tcg_mo = TCG_BAR_SC;
15571
15572 switch (stype) {
15573 case 0x4: /* SYNC_WMB */
15574 tcg_mo |= TCG_MO_ST_ST;
15575 break;
15576 case 0x10: /* SYNC_MB */
15577 tcg_mo |= TCG_MO_ALL;
15578 break;
15579 case 0x11: /* SYNC_ACQUIRE */
15580 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15581 break;
15582 case 0x12: /* SYNC_RELEASE */
15583 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15584 break;
15585 case 0x13: /* SYNC_RMB */
15586 tcg_mo |= TCG_MO_LD_LD;
15587 break;
15588 default:
15589 tcg_mo |= TCG_MO_ALL;
15590 break;
15591 }
15592
15593 tcg_gen_mb(tcg_mo);
15594}
15595
235785e8 15596static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
15597{
15598 int extension = (ctx->opcode >> 6) & 0x3f;
15599 int minor = (ctx->opcode >> 12) & 0xf;
15600 uint32_t mips32_op;
15601
15602 switch (extension) {
15603 case TEQ:
15604 mips32_op = OPC_TEQ;
15605 goto do_trap;
15606 case TGE:
15607 mips32_op = OPC_TGE;
15608 goto do_trap;
15609 case TGEU:
15610 mips32_op = OPC_TGEU;
15611 goto do_trap;
15612 case TLT:
15613 mips32_op = OPC_TLT;
15614 goto do_trap;
15615 case TLTU:
15616 mips32_op = OPC_TLTU;
15617 goto do_trap;
15618 case TNE:
15619 mips32_op = OPC_TNE;
15620 do_trap:
15621 gen_trap(ctx, mips32_op, rs, rt, -1);
15622 break;
15623#ifndef CONFIG_USER_ONLY
15624 case MFC0:
15625 case MFC0 + 32:
2e15497c 15626 check_cp0_enabled(ctx);
3c824109
NF
15627 if (rt == 0) {
15628 /* Treat as NOP. */
15629 break;
15630 }
d75c135e 15631 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15632 break;
15633 case MTC0:
15634 case MTC0 + 32:
2e15497c 15635 check_cp0_enabled(ctx);
3c824109
NF
15636 {
15637 TCGv t0 = tcg_temp_new();
618b0fe9 15638
3c824109 15639 gen_load_gpr(t0, rt);
d75c135e 15640 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15641 tcg_temp_free(t0);
15642 }
15643 break;
15644#endif
a1fc6246
LA
15645 case 0x2a:
15646 switch (minor & 3) {
15647 case MADD_ACC:
15648 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15649 break;
15650 case MADDU_ACC:
15651 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15652 break;
15653 case MSUB_ACC:
15654 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15655 break;
15656 case MSUBU_ACC:
15657 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15658 break;
15659 default:
15660 goto pool32axf_invalid;
15661 }
15662 break;
15663 case 0x32:
15664 switch (minor & 3) {
15665 case MULT_ACC:
15666 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15667 break;
15668 case MULTU_ACC:
15669 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15670 break;
15671 default:
15672 goto pool32axf_invalid;
15673 }
15674 break;
3c824109
NF
15675 case 0x2c:
15676 switch (minor) {
e0332095
YK
15677 case BITSWAP:
15678 check_insn(ctx, ISA_MIPS32R6);
15679 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15680 break;
3c824109
NF
15681 case SEB:
15682 gen_bshfl(ctx, OPC_SEB, rs, rt);
15683 break;
15684 case SEH:
15685 gen_bshfl(ctx, OPC_SEH, rs, rt);
15686 break;
15687 case CLO:
15688 mips32_op = OPC_CLO;
15689 goto do_cl;
15690 case CLZ:
15691 mips32_op = OPC_CLZ;
15692 do_cl:
d75c135e 15693 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15694 gen_cl(ctx, mips32_op, rt, rs);
15695 break;
15696 case RDHWR:
b00c7218
YK
15697 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15698 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15699 break;
15700 case WSBH:
15701 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15702 break;
15703 case MULT:
9e8f441a 15704 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15705 mips32_op = OPC_MULT;
26135ead 15706 goto do_mul;
3c824109 15707 case MULTU:
9e8f441a 15708 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15709 mips32_op = OPC_MULTU;
26135ead 15710 goto do_mul;
3c824109 15711 case DIV:
9e8f441a 15712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15713 mips32_op = OPC_DIV;
26135ead 15714 goto do_div;
3c824109 15715 case DIVU:
9e8f441a 15716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15717 mips32_op = OPC_DIVU;
26135ead
RS
15718 goto do_div;
15719 do_div:
15720 check_insn(ctx, ISA_MIPS32);
15721 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15722 break;
3c824109 15723 case MADD:
9e8f441a 15724 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15725 mips32_op = OPC_MADD;
26135ead 15726 goto do_mul;
3c824109 15727 case MADDU:
9e8f441a 15728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15729 mips32_op = OPC_MADDU;
26135ead 15730 goto do_mul;
3c824109 15731 case MSUB:
9e8f441a 15732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15733 mips32_op = OPC_MSUB;
26135ead 15734 goto do_mul;
3c824109 15735 case MSUBU:
9e8f441a 15736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15737 mips32_op = OPC_MSUBU;
26135ead 15738 do_mul:
d75c135e 15739 check_insn(ctx, ISA_MIPS32);
a1fc6246 15740 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15741 break;
15742 default:
15743 goto pool32axf_invalid;
15744 }
15745 break;
15746 case 0x34:
15747 switch (minor) {
15748 case MFC2:
15749 case MTC2:
15750 case MFHC2:
15751 case MTHC2:
15752 case CFC2:
15753 case CTC2:
15754 generate_exception_err(ctx, EXCP_CpU, 2);
15755 break;
15756 default:
15757 goto pool32axf_invalid;
15758 }
15759 break;
15760 case 0x3c:
15761 switch (minor) {
65935f07
YK
15762 case JALR: /* JALRC */
15763 case JALR_HB: /* JALRC_HB */
15764 if (ctx->insn_flags & ISA_MIPS32R6) {
15765 /* JALRC, JALRC_HB */
15766 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15767 } else {
15768 /* JALR, JALR_HB */
15769 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15770 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15771 }
3c824109
NF
15772 break;
15773 case JALRS:
15774 case JALRS_HB:
9e8f441a 15775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15776 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15777 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15778 break;
15779 default:
15780 goto pool32axf_invalid;
15781 }
15782 break;
15783 case 0x05:
15784 switch (minor) {
15785 case RDPGPR:
2e15497c 15786 check_cp0_enabled(ctx);
d75c135e 15787 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15788 gen_load_srsgpr(rs, rt);
3c824109
NF
15789 break;
15790 case WRPGPR:
2e15497c 15791 check_cp0_enabled(ctx);
d75c135e 15792 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15793 gen_store_srsgpr(rs, rt);
3c824109
NF
15794 break;
15795 default:
15796 goto pool32axf_invalid;
15797 }
15798 break;
15799#ifndef CONFIG_USER_ONLY
15800 case 0x0d:
15801 switch (minor) {
15802 case TLBP:
15803 mips32_op = OPC_TLBP;
15804 goto do_cp0;
15805 case TLBR:
15806 mips32_op = OPC_TLBR;
15807 goto do_cp0;
15808 case TLBWI:
15809 mips32_op = OPC_TLBWI;
15810 goto do_cp0;
15811 case TLBWR:
15812 mips32_op = OPC_TLBWR;
15813 goto do_cp0;
e60ec063
YK
15814 case TLBINV:
15815 mips32_op = OPC_TLBINV;
15816 goto do_cp0;
15817 case TLBINVF:
15818 mips32_op = OPC_TLBINVF;
15819 goto do_cp0;
3c824109
NF
15820 case WAIT:
15821 mips32_op = OPC_WAIT;
15822 goto do_cp0;
15823 case DERET:
15824 mips32_op = OPC_DERET;
15825 goto do_cp0;
15826 case ERET:
15827 mips32_op = OPC_ERET;
15828 do_cp0:
15829 gen_cp0(env, ctx, mips32_op, rt, rs);
15830 break;
15831 default:
15832 goto pool32axf_invalid;
15833 }
15834 break;
15835 case 0x1d:
15836 switch (minor) {
15837 case DI:
2e15497c 15838 check_cp0_enabled(ctx);
3c824109
NF
15839 {
15840 TCGv t0 = tcg_temp_new();
15841
15842 save_cpu_state(ctx, 1);
895c2d04 15843 gen_helper_di(t0, cpu_env);
3c824109 15844 gen_store_gpr(t0, rs);
71375b59
AM
15845 /*
15846 * Stop translation as we may have switched the execution
15847 * mode.
15848 */
eeb3bba8 15849 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15850 tcg_temp_free(t0);
15851 }
15852 break;
15853 case EI:
2e15497c 15854 check_cp0_enabled(ctx);
3c824109
NF
15855 {
15856 TCGv t0 = tcg_temp_new();
15857
15858 save_cpu_state(ctx, 1);
895c2d04 15859 gen_helper_ei(t0, cpu_env);
3c824109 15860 gen_store_gpr(t0, rs);
7480515f
AM
15861 /*
15862 * DISAS_STOP isn't sufficient, we need to ensure we break out
15863 * of translated code to check for pending interrupts.
15864 */
eeb3bba8
EC
15865 gen_save_pc(ctx->base.pc_next + 4);
15866 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15867 tcg_temp_free(t0);
15868 }
15869 break;
15870 default:
15871 goto pool32axf_invalid;
15872 }
15873 break;
15874#endif
15875 case 0x2d:
15876 switch (minor) {
15877 case SYNC:
d208ac0c 15878 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15879 break;
15880 case SYSCALL:
9c708c7f 15881 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15882 break;
15883 case SDBBP:
3b3c1694
LA
15884 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15885 gen_helper_do_semihosting(cpu_env);
15886 } else {
15887 check_insn(ctx, ISA_MIPS32);
e0332095 15888 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15889 generate_exception_end(ctx, EXCP_RI);
e0332095 15890 } else {
9c708c7f 15891 generate_exception_end(ctx, EXCP_DBp);
e0332095 15892 }
3b3c1694 15893 }
3c824109
NF
15894 break;
15895 default:
15896 goto pool32axf_invalid;
15897 }
15898 break;
a1fc6246 15899 case 0x01:
26135ead 15900 switch (minor & 3) {
a1fc6246 15901 case MFHI_ACC:
26135ead 15902 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15903 break;
a1fc6246 15904 case MFLO_ACC:
26135ead 15905 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15906 break;
a1fc6246 15907 case MTHI_ACC:
26135ead 15908 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15909 break;
a1fc6246 15910 case MTLO_ACC:
26135ead 15911 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15912 break;
15913 default:
15914 goto pool32axf_invalid;
15915 }
15916 break;
a1fc6246 15917 case 0x35:
9e8f441a 15918 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15919 switch (minor) {
15920 case MFHI32:
15921 gen_HILO(ctx, OPC_MFHI, 0, rs);
15922 break;
15923 case MFLO32:
15924 gen_HILO(ctx, OPC_MFLO, 0, rs);
15925 break;
15926 case MTHI32:
15927 gen_HILO(ctx, OPC_MTHI, 0, rs);
15928 break;
15929 case MTLO32:
15930 gen_HILO(ctx, OPC_MTLO, 0, rs);
15931 break;
15932 default:
15933 goto pool32axf_invalid;
15934 }
15935 break;
3c824109
NF
15936 default:
15937 pool32axf_invalid:
15938 MIPS_INVAL("pool32axf");
9c708c7f 15939 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15940 break;
15941 }
15942}
15943
7480515f
AM
15944/*
15945 * Values for microMIPS fmt field. Variable-width, depending on which
15946 * formats the instruction supports.
15947 */
3c824109
NF
15948enum {
15949 FMT_SD_S = 0,
15950 FMT_SD_D = 1,
15951
15952 FMT_SDPS_S = 0,
15953 FMT_SDPS_D = 1,
15954 FMT_SDPS_PS = 2,
15955
15956 FMT_SWL_S = 0,
15957 FMT_SWL_W = 1,
15958 FMT_SWL_L = 2,
15959
15960 FMT_DWL_D = 0,
15961 FMT_DWL_W = 1,
15962 FMT_DWL_L = 2
15963};
15964
d75c135e 15965static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
15966{
15967 int extension = (ctx->opcode >> 6) & 0x3ff;
15968 uint32_t mips32_op;
15969
71375b59
AM
15970#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15971#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15972#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
15973
15974 switch (extension) {
15975 case FLOAT_1BIT_FMT(CFC1, 0):
15976 mips32_op = OPC_CFC1;
15977 goto do_cp1;
15978 case FLOAT_1BIT_FMT(CTC1, 0):
15979 mips32_op = OPC_CTC1;
15980 goto do_cp1;
15981 case FLOAT_1BIT_FMT(MFC1, 0):
15982 mips32_op = OPC_MFC1;
15983 goto do_cp1;
15984 case FLOAT_1BIT_FMT(MTC1, 0):
15985 mips32_op = OPC_MTC1;
15986 goto do_cp1;
15987 case FLOAT_1BIT_FMT(MFHC1, 0):
15988 mips32_op = OPC_MFHC1;
15989 goto do_cp1;
15990 case FLOAT_1BIT_FMT(MTHC1, 0):
15991 mips32_op = OPC_MTHC1;
15992 do_cp1:
15993 gen_cp1(ctx, mips32_op, rt, rs);
15994 break;
15995
15996 /* Reciprocal square root */
15997 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15998 mips32_op = OPC_RSQRT_S;
15999 goto do_unaryfp;
16000 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16001 mips32_op = OPC_RSQRT_D;
16002 goto do_unaryfp;
16003
16004 /* Square root */
16005 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16006 mips32_op = OPC_SQRT_S;
16007 goto do_unaryfp;
16008 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16009 mips32_op = OPC_SQRT_D;
16010 goto do_unaryfp;
16011
16012 /* Reciprocal */
16013 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16014 mips32_op = OPC_RECIP_S;
16015 goto do_unaryfp;
16016 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16017 mips32_op = OPC_RECIP_D;
16018 goto do_unaryfp;
16019
16020 /* Floor */
16021 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16022 mips32_op = OPC_FLOOR_L_S;
16023 goto do_unaryfp;
16024 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16025 mips32_op = OPC_FLOOR_L_D;
16026 goto do_unaryfp;
16027 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16028 mips32_op = OPC_FLOOR_W_S;
16029 goto do_unaryfp;
16030 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16031 mips32_op = OPC_FLOOR_W_D;
16032 goto do_unaryfp;
16033
16034 /* Ceiling */
16035 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16036 mips32_op = OPC_CEIL_L_S;
16037 goto do_unaryfp;
16038 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16039 mips32_op = OPC_CEIL_L_D;
16040 goto do_unaryfp;
16041 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16042 mips32_op = OPC_CEIL_W_S;
16043 goto do_unaryfp;
16044 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16045 mips32_op = OPC_CEIL_W_D;
16046 goto do_unaryfp;
16047
16048 /* Truncation */
16049 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16050 mips32_op = OPC_TRUNC_L_S;
16051 goto do_unaryfp;
16052 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16053 mips32_op = OPC_TRUNC_L_D;
16054 goto do_unaryfp;
16055 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16056 mips32_op = OPC_TRUNC_W_S;
16057 goto do_unaryfp;
16058 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16059 mips32_op = OPC_TRUNC_W_D;
16060 goto do_unaryfp;
16061
16062 /* Round */
16063 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16064 mips32_op = OPC_ROUND_L_S;
16065 goto do_unaryfp;
16066 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16067 mips32_op = OPC_ROUND_L_D;
16068 goto do_unaryfp;
16069 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16070 mips32_op = OPC_ROUND_W_S;
16071 goto do_unaryfp;
16072 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16073 mips32_op = OPC_ROUND_W_D;
16074 goto do_unaryfp;
16075
16076 /* Integer to floating-point conversion */
16077 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16078 mips32_op = OPC_CVT_L_S;
16079 goto do_unaryfp;
16080 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16081 mips32_op = OPC_CVT_L_D;
16082 goto do_unaryfp;
16083 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16084 mips32_op = OPC_CVT_W_S;
16085 goto do_unaryfp;
16086 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16087 mips32_op = OPC_CVT_W_D;
16088 goto do_unaryfp;
16089
16090 /* Paired-foo conversions */
16091 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16092 mips32_op = OPC_CVT_S_PL;
16093 goto do_unaryfp;
16094 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16095 mips32_op = OPC_CVT_S_PU;
16096 goto do_unaryfp;
16097 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16098 mips32_op = OPC_CVT_PW_PS;
16099 goto do_unaryfp;
16100 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16101 mips32_op = OPC_CVT_PS_PW;
16102 goto do_unaryfp;
16103
16104 /* Floating-point moves */
16105 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16106 mips32_op = OPC_MOV_S;
16107 goto do_unaryfp;
16108 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16109 mips32_op = OPC_MOV_D;
16110 goto do_unaryfp;
16111 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16112 mips32_op = OPC_MOV_PS;
16113 goto do_unaryfp;
16114
16115 /* Absolute value */
16116 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16117 mips32_op = OPC_ABS_S;
16118 goto do_unaryfp;
16119 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16120 mips32_op = OPC_ABS_D;
16121 goto do_unaryfp;
16122 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16123 mips32_op = OPC_ABS_PS;
16124 goto do_unaryfp;
16125
16126 /* Negation */
16127 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16128 mips32_op = OPC_NEG_S;
16129 goto do_unaryfp;
16130 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16131 mips32_op = OPC_NEG_D;
16132 goto do_unaryfp;
16133 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16134 mips32_op = OPC_NEG_PS;
16135 goto do_unaryfp;
16136
16137 /* Reciprocal square root step */
16138 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16139 mips32_op = OPC_RSQRT1_S;
16140 goto do_unaryfp;
16141 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16142 mips32_op = OPC_RSQRT1_D;
16143 goto do_unaryfp;
16144 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16145 mips32_op = OPC_RSQRT1_PS;
16146 goto do_unaryfp;
16147
16148 /* Reciprocal step */
16149 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16150 mips32_op = OPC_RECIP1_S;
16151 goto do_unaryfp;
16152 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16153 mips32_op = OPC_RECIP1_S;
16154 goto do_unaryfp;
16155 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16156 mips32_op = OPC_RECIP1_PS;
16157 goto do_unaryfp;
16158
16159 /* Conversions from double */
16160 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16161 mips32_op = OPC_CVT_D_S;
16162 goto do_unaryfp;
16163 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16164 mips32_op = OPC_CVT_D_W;
16165 goto do_unaryfp;
16166 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16167 mips32_op = OPC_CVT_D_L;
16168 goto do_unaryfp;
16169
16170 /* Conversions from single */
16171 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16172 mips32_op = OPC_CVT_S_D;
16173 goto do_unaryfp;
16174 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16175 mips32_op = OPC_CVT_S_W;
16176 goto do_unaryfp;
16177 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16178 mips32_op = OPC_CVT_S_L;
16179 do_unaryfp:
16180 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16181 break;
16182
16183 /* Conditional moves on floating-point codes */
16184 case COND_FLOAT_MOV(MOVT, 0):
16185 case COND_FLOAT_MOV(MOVT, 1):
16186 case COND_FLOAT_MOV(MOVT, 2):
16187 case COND_FLOAT_MOV(MOVT, 3):
16188 case COND_FLOAT_MOV(MOVT, 4):
16189 case COND_FLOAT_MOV(MOVT, 5):
16190 case COND_FLOAT_MOV(MOVT, 6):
16191 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 16192 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16193 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16194 break;
16195 case COND_FLOAT_MOV(MOVF, 0):
16196 case COND_FLOAT_MOV(MOVF, 1):
16197 case COND_FLOAT_MOV(MOVF, 2):
16198 case COND_FLOAT_MOV(MOVF, 3):
16199 case COND_FLOAT_MOV(MOVF, 4):
16200 case COND_FLOAT_MOV(MOVF, 5):
16201 case COND_FLOAT_MOV(MOVF, 6):
16202 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 16203 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16204 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16205 break;
16206 default:
16207 MIPS_INVAL("pool32fxf");
9c708c7f 16208 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16209 break;
16210 }
16211}
16212
f60eeb0c 16213static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16214{
16215 int32_t offset;
16216 uint16_t insn;
16217 int rt, rs, rd, rr;
16218 int16_t imm;
8fffc646 16219 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
16220 uint32_t cond, fmt, cc;
16221
eeb3bba8 16222 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
16223 ctx->opcode = (ctx->opcode << 16) | insn;
16224
16225 rt = (ctx->opcode >> 21) & 0x1f;
16226 rs = (ctx->opcode >> 16) & 0x1f;
16227 rd = (ctx->opcode >> 11) & 0x1f;
16228 rr = (ctx->opcode >> 6) & 0x1f;
16229 imm = (int16_t) ctx->opcode;
16230
16231 op = (ctx->opcode >> 26) & 0x3f;
16232 switch (op) {
16233 case POOL32A:
16234 minor = ctx->opcode & 0x3f;
16235 switch (minor) {
16236 case 0x00:
16237 minor = (ctx->opcode >> 6) & 0xf;
16238 switch (minor) {
16239 case SLL32:
16240 mips32_op = OPC_SLL;
16241 goto do_shifti;
16242 case SRA:
16243 mips32_op = OPC_SRA;
16244 goto do_shifti;
16245 case SRL32:
16246 mips32_op = OPC_SRL;
16247 goto do_shifti;
16248 case ROTR:
16249 mips32_op = OPC_ROTR;
16250 do_shifti:
d75c135e 16251 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 16252 break;
e0332095
YK
16253 case SELEQZ:
16254 check_insn(ctx, ISA_MIPS32R6);
16255 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16256 break;
16257 case SELNEZ:
16258 check_insn(ctx, ISA_MIPS32R6);
16259 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16260 break;
b00c7218
YK
16261 case R6_RDHWR:
16262 check_insn(ctx, ISA_MIPS32R6);
16263 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16264 break;
3c824109
NF
16265 default:
16266 goto pool32a_invalid;
16267 }
16268 break;
16269 case 0x10:
16270 minor = (ctx->opcode >> 6) & 0xf;
16271 switch (minor) {
16272 /* Arithmetic */
16273 case ADD:
16274 mips32_op = OPC_ADD;
16275 goto do_arith;
16276 case ADDU32:
16277 mips32_op = OPC_ADDU;
16278 goto do_arith;
16279 case SUB:
16280 mips32_op = OPC_SUB;
16281 goto do_arith;
16282 case SUBU32:
16283 mips32_op = OPC_SUBU;
16284 goto do_arith;
16285 case MUL:
9e8f441a 16286 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16287 mips32_op = OPC_MUL;
16288 do_arith:
d75c135e 16289 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16290 break;
16291 /* Shifts */
16292 case SLLV:
16293 mips32_op = OPC_SLLV;
16294 goto do_shift;
16295 case SRLV:
16296 mips32_op = OPC_SRLV;
16297 goto do_shift;
16298 case SRAV:
16299 mips32_op = OPC_SRAV;
16300 goto do_shift;
16301 case ROTRV:
16302 mips32_op = OPC_ROTRV;
16303 do_shift:
d75c135e 16304 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16305 break;
16306 /* Logical operations */
16307 case AND:
16308 mips32_op = OPC_AND;
16309 goto do_logic;
16310 case OR32:
16311 mips32_op = OPC_OR;
16312 goto do_logic;
16313 case NOR:
16314 mips32_op = OPC_NOR;
16315 goto do_logic;
16316 case XOR32:
16317 mips32_op = OPC_XOR;
16318 do_logic:
d75c135e 16319 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16320 break;
16321 /* Set less than */
16322 case SLT:
16323 mips32_op = OPC_SLT;
16324 goto do_slt;
16325 case SLTU:
16326 mips32_op = OPC_SLTU;
16327 do_slt:
d75c135e 16328 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16329 break;
16330 default:
16331 goto pool32a_invalid;
16332 }
16333 break;
16334 case 0x18:
16335 minor = (ctx->opcode >> 6) & 0xf;
16336 switch (minor) {
16337 /* Conditional moves */
e0332095
YK
16338 case MOVN: /* MUL */
16339 if (ctx->insn_flags & ISA_MIPS32R6) {
16340 /* MUL */
16341 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16342 } else {
16343 /* MOVN */
16344 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16345 }
16346 break;
16347 case MOVZ: /* MUH */
16348 if (ctx->insn_flags & ISA_MIPS32R6) {
16349 /* MUH */
16350 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16351 } else {
16352 /* MOVZ */
16353 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16354 }
16355 break;
16356 case MULU:
16357 check_insn(ctx, ISA_MIPS32R6);
16358 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16359 break;
16360 case MUHU:
16361 check_insn(ctx, ISA_MIPS32R6);
16362 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16363 break;
16364 case LWXS: /* DIV */
16365 if (ctx->insn_flags & ISA_MIPS32R6) {
16366 /* DIV */
16367 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16368 } else {
16369 /* LWXS */
16370 gen_ldxs(ctx, rs, rt, rd);
16371 }
16372 break;
16373 case MOD:
16374 check_insn(ctx, ISA_MIPS32R6);
16375 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16376 break;
16377 case R6_DIVU:
16378 check_insn(ctx, ISA_MIPS32R6);
16379 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16380 break;
e0332095
YK
16381 case MODU:
16382 check_insn(ctx, ISA_MIPS32R6);
16383 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16384 break;
16385 default:
16386 goto pool32a_invalid;
16387 }
16388 break;
16389 case INS:
16390 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16391 return;
e0332095
YK
16392 case LSA:
16393 check_insn(ctx, ISA_MIPS32R6);
16394 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16395 extract32(ctx->opcode, 9, 2));
16396 break;
16397 case ALIGN:
16398 check_insn(ctx, ISA_MIPS32R6);
821f2008 16399 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16400 break;
3c824109
NF
16401 case EXT:
16402 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16403 return;
16404 case POOL32AXF:
240ce26a 16405 gen_pool32axf(env, ctx, rt, rs);
3c824109 16406 break;
dbd8af98 16407 case BREAK32:
9c708c7f 16408 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16409 break;
bb238210
YK
16410 case SIGRIE:
16411 check_insn(ctx, ISA_MIPS32R6);
16412 generate_exception_end(ctx, EXCP_RI);
16413 break;
3c824109
NF
16414 default:
16415 pool32a_invalid:
16416 MIPS_INVAL("pool32a");
9c708c7f 16417 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16418 break;
16419 }
16420 break;
16421 case POOL32B:
16422 minor = (ctx->opcode >> 12) & 0xf;
16423 switch (minor) {
16424 case CACHE:
2e15497c 16425 check_cp0_enabled(ctx);
0d74a222
LA
16426 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16427 gen_cache_operation(ctx, rt, rs, imm);
16428 }
3c824109
NF
16429 break;
16430 case LWC2:
16431 case SWC2:
16432 /* COP2: Not implemented. */
16433 generate_exception_err(ctx, EXCP_CpU, 2);
16434 break;
3c824109
NF
16435#ifdef TARGET_MIPS64
16436 case LDP:
16437 case SDP:
d9224450
MR
16438 check_insn(ctx, ISA_MIPS3);
16439 check_mips_64(ctx);
3c824109 16440#endif
146dd620 16441 /* fall through */
d9224450
MR
16442 case LWP:
16443 case SWP:
3c824109
NF
16444 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16445 break;
3c824109
NF
16446#ifdef TARGET_MIPS64
16447 case LDM:
16448 case SDM:
d9224450
MR
16449 check_insn(ctx, ISA_MIPS3);
16450 check_mips_64(ctx);
3c824109 16451#endif
146dd620 16452 /* fall through */
d9224450
MR
16453 case LWM32:
16454 case SWM32:
3c824109
NF
16455 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16456 break;
16457 default:
16458 MIPS_INVAL("pool32b");
9c708c7f 16459 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16460 break;
16461 }
16462 break;
16463 case POOL32F:
5ab5c041 16464 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16465 minor = ctx->opcode & 0x3f;
16466 check_cp1_enabled(ctx);
16467 switch (minor) {
16468 case ALNV_PS:
9e8f441a 16469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16470 mips32_op = OPC_ALNV_PS;
16471 goto do_madd;
16472 case MADD_S:
9e8f441a 16473 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16474 mips32_op = OPC_MADD_S;
16475 goto do_madd;
16476 case MADD_D:
9e8f441a 16477 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16478 mips32_op = OPC_MADD_D;
16479 goto do_madd;
16480 case MADD_PS:
9e8f441a 16481 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16482 mips32_op = OPC_MADD_PS;
16483 goto do_madd;
16484 case MSUB_S:
9e8f441a 16485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16486 mips32_op = OPC_MSUB_S;
16487 goto do_madd;
16488 case MSUB_D:
9e8f441a 16489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16490 mips32_op = OPC_MSUB_D;
16491 goto do_madd;
16492 case MSUB_PS:
9e8f441a 16493 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16494 mips32_op = OPC_MSUB_PS;
16495 goto do_madd;
16496 case NMADD_S:
9e8f441a 16497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16498 mips32_op = OPC_NMADD_S;
16499 goto do_madd;
16500 case NMADD_D:
9e8f441a 16501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16502 mips32_op = OPC_NMADD_D;
16503 goto do_madd;
16504 case NMADD_PS:
9e8f441a 16505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16506 mips32_op = OPC_NMADD_PS;
16507 goto do_madd;
16508 case NMSUB_S:
9e8f441a 16509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16510 mips32_op = OPC_NMSUB_S;
16511 goto do_madd;
16512 case NMSUB_D:
9e8f441a 16513 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16514 mips32_op = OPC_NMSUB_D;
16515 goto do_madd;
16516 case NMSUB_PS:
9e8f441a 16517 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16518 mips32_op = OPC_NMSUB_PS;
16519 do_madd:
16520 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16521 break;
16522 case CABS_COND_FMT:
9e8f441a 16523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16524 cond = (ctx->opcode >> 6) & 0xf;
16525 cc = (ctx->opcode >> 13) & 0x7;
16526 fmt = (ctx->opcode >> 10) & 0x3;
16527 switch (fmt) {
16528 case 0x0:
16529 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16530 break;
16531 case 0x1:
16532 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16533 break;
16534 case 0x2:
16535 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16536 break;
16537 default:
16538 goto pool32f_invalid;
16539 }
16540 break;
16541 case C_COND_FMT:
9e8f441a 16542 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16543 cond = (ctx->opcode >> 6) & 0xf;
16544 cc = (ctx->opcode >> 13) & 0x7;
16545 fmt = (ctx->opcode >> 10) & 0x3;
16546 switch (fmt) {
16547 case 0x0:
16548 gen_cmp_s(ctx, cond, rt, rs, cc);
16549 break;
16550 case 0x1:
16551 gen_cmp_d(ctx, cond, rt, rs, cc);
16552 break;
16553 case 0x2:
16554 gen_cmp_ps(ctx, cond, rt, rs, cc);
16555 break;
16556 default:
16557 goto pool32f_invalid;
16558 }
16559 break;
2a24a7ba
YK
16560 case CMP_CONDN_S:
16561 check_insn(ctx, ISA_MIPS32R6);
16562 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16563 break;
16564 case CMP_CONDN_D:
16565 check_insn(ctx, ISA_MIPS32R6);
16566 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16567 break;
3c824109 16568 case POOL32FXF:
d75c135e 16569 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
16570 break;
16571 case 0x00:
16572 /* PLL foo */
16573 switch ((ctx->opcode >> 6) & 0x7) {
16574 case PLL_PS:
16575 mips32_op = OPC_PLL_PS;
16576 goto do_ps;
16577 case PLU_PS:
16578 mips32_op = OPC_PLU_PS;
16579 goto do_ps;
16580 case PUL_PS:
16581 mips32_op = OPC_PUL_PS;
16582 goto do_ps;
16583 case PUU_PS:
16584 mips32_op = OPC_PUU_PS;
16585 goto do_ps;
16586 case CVT_PS_S:
9e8f441a 16587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16588 mips32_op = OPC_CVT_PS_S;
16589 do_ps:
16590 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16591 break;
16592 default:
16593 goto pool32f_invalid;
16594 }
16595 break;
2a24a7ba
YK
16596 case MIN_FMT:
16597 check_insn(ctx, ISA_MIPS32R6);
16598 switch ((ctx->opcode >> 9) & 0x3) {
16599 case FMT_SDPS_S:
16600 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16601 break;
16602 case FMT_SDPS_D:
16603 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16604 break;
16605 default:
16606 goto pool32f_invalid;
16607 }
16608 break;
3c824109
NF
16609 case 0x08:
16610 /* [LS][WDU]XC1 */
16611 switch ((ctx->opcode >> 6) & 0x7) {
16612 case LWXC1:
9e8f441a 16613 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16614 mips32_op = OPC_LWXC1;
16615 goto do_ldst_cp1;
16616 case SWXC1:
9e8f441a 16617 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16618 mips32_op = OPC_SWXC1;
16619 goto do_ldst_cp1;
16620 case LDXC1:
9e8f441a 16621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16622 mips32_op = OPC_LDXC1;
16623 goto do_ldst_cp1;
16624 case SDXC1:
9e8f441a 16625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16626 mips32_op = OPC_SDXC1;
16627 goto do_ldst_cp1;
16628 case LUXC1:
9e8f441a 16629 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16630 mips32_op = OPC_LUXC1;
16631 goto do_ldst_cp1;
16632 case SUXC1:
9e8f441a 16633 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16634 mips32_op = OPC_SUXC1;
16635 do_ldst_cp1:
16636 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16637 break;
16638 default:
16639 goto pool32f_invalid;
16640 }
16641 break;
2a24a7ba
YK
16642 case MAX_FMT:
16643 check_insn(ctx, ISA_MIPS32R6);
16644 switch ((ctx->opcode >> 9) & 0x3) {
16645 case FMT_SDPS_S:
16646 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16647 break;
16648 case FMT_SDPS_D:
16649 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16650 break;
16651 default:
16652 goto pool32f_invalid;
16653 }
16654 break;
3c824109
NF
16655 case 0x18:
16656 /* 3D insns */
9e8f441a 16657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16658 fmt = (ctx->opcode >> 9) & 0x3;
16659 switch ((ctx->opcode >> 6) & 0x7) {
16660 case RSQRT2_FMT:
16661 switch (fmt) {
16662 case FMT_SDPS_S:
16663 mips32_op = OPC_RSQRT2_S;
16664 goto do_3d;
16665 case FMT_SDPS_D:
16666 mips32_op = OPC_RSQRT2_D;
16667 goto do_3d;
16668 case FMT_SDPS_PS:
16669 mips32_op = OPC_RSQRT2_PS;
16670 goto do_3d;
16671 default:
16672 goto pool32f_invalid;
16673 }
16674 break;
16675 case RECIP2_FMT:
16676 switch (fmt) {
16677 case FMT_SDPS_S:
16678 mips32_op = OPC_RECIP2_S;
16679 goto do_3d;
16680 case FMT_SDPS_D:
16681 mips32_op = OPC_RECIP2_D;
16682 goto do_3d;
16683 case FMT_SDPS_PS:
16684 mips32_op = OPC_RECIP2_PS;
16685 goto do_3d;
16686 default:
16687 goto pool32f_invalid;
16688 }
16689 break;
16690 case ADDR_PS:
16691 mips32_op = OPC_ADDR_PS;
16692 goto do_3d;
16693 case MULR_PS:
16694 mips32_op = OPC_MULR_PS;
16695 do_3d:
16696 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16697 break;
16698 default:
16699 goto pool32f_invalid;
16700 }
16701 break;
16702 case 0x20:
2a24a7ba 16703 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16704 cc = (ctx->opcode >> 13) & 0x7;
16705 fmt = (ctx->opcode >> 9) & 0x3;
16706 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16707 case MOVF_FMT: /* RINT_FMT */
16708 if (ctx->insn_flags & ISA_MIPS32R6) {
16709 /* RINT_FMT */
16710 switch (fmt) {
16711 case FMT_SDPS_S:
16712 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16713 break;
16714 case FMT_SDPS_D:
16715 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16716 break;
16717 default:
16718 goto pool32f_invalid;
16719 }
16720 } else {
16721 /* MOVF_FMT */
16722 switch (fmt) {
16723 case FMT_SDPS_S:
16724 gen_movcf_s(ctx, rs, rt, cc, 0);
16725 break;
16726 case FMT_SDPS_D:
16727 gen_movcf_d(ctx, rs, rt, cc, 0);
16728 break;
16729 case FMT_SDPS_PS:
16730 check_ps(ctx);
16731 gen_movcf_ps(ctx, rs, rt, cc, 0);
16732 break;
16733 default:
16734 goto pool32f_invalid;
16735 }
3c824109
NF
16736 }
16737 break;
2a24a7ba
YK
16738 case MOVT_FMT: /* CLASS_FMT */
16739 if (ctx->insn_flags & ISA_MIPS32R6) {
16740 /* CLASS_FMT */
16741 switch (fmt) {
16742 case FMT_SDPS_S:
16743 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16744 break;
16745 case FMT_SDPS_D:
16746 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16747 break;
16748 default:
16749 goto pool32f_invalid;
16750 }
16751 } else {
16752 /* MOVT_FMT */
16753 switch (fmt) {
16754 case FMT_SDPS_S:
16755 gen_movcf_s(ctx, rs, rt, cc, 1);
16756 break;
16757 case FMT_SDPS_D:
16758 gen_movcf_d(ctx, rs, rt, cc, 1);
16759 break;
16760 case FMT_SDPS_PS:
16761 check_ps(ctx);
16762 gen_movcf_ps(ctx, rs, rt, cc, 1);
16763 break;
16764 default:
16765 goto pool32f_invalid;
16766 }
3c824109
NF
16767 }
16768 break;
16769 case PREFX:
9e8f441a 16770 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16771 break;
16772 default:
16773 goto pool32f_invalid;
16774 }
16775 break;
16776#define FINSN_3ARG_SDPS(prfx) \
16777 switch ((ctx->opcode >> 8) & 0x3) { \
16778 case FMT_SDPS_S: \
16779 mips32_op = OPC_##prfx##_S; \
16780 goto do_fpop; \
16781 case FMT_SDPS_D: \
16782 mips32_op = OPC_##prfx##_D; \
16783 goto do_fpop; \
16784 case FMT_SDPS_PS: \
e29c9628 16785 check_ps(ctx); \
3c824109
NF
16786 mips32_op = OPC_##prfx##_PS; \
16787 goto do_fpop; \
16788 default: \
16789 goto pool32f_invalid; \
16790 }
2a24a7ba
YK
16791 case MINA_FMT:
16792 check_insn(ctx, ISA_MIPS32R6);
16793 switch ((ctx->opcode >> 9) & 0x3) {
16794 case FMT_SDPS_S:
16795 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16796 break;
16797 case FMT_SDPS_D:
16798 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16799 break;
16800 default:
16801 goto pool32f_invalid;
16802 }
16803 break;
16804 case MAXA_FMT:
16805 check_insn(ctx, ISA_MIPS32R6);
16806 switch ((ctx->opcode >> 9) & 0x3) {
16807 case FMT_SDPS_S:
16808 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16809 break;
16810 case FMT_SDPS_D:
16811 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16812 break;
16813 default:
16814 goto pool32f_invalid;
16815 }
16816 break;
3c824109
NF
16817 case 0x30:
16818 /* regular FP ops */
16819 switch ((ctx->opcode >> 6) & 0x3) {
16820 case ADD_FMT:
16821 FINSN_3ARG_SDPS(ADD);
16822 break;
16823 case SUB_FMT:
16824 FINSN_3ARG_SDPS(SUB);
16825 break;
16826 case MUL_FMT:
16827 FINSN_3ARG_SDPS(MUL);
16828 break;
16829 case DIV_FMT:
16830 fmt = (ctx->opcode >> 8) & 0x3;
16831 if (fmt == 1) {
16832 mips32_op = OPC_DIV_D;
16833 } else if (fmt == 0) {
16834 mips32_op = OPC_DIV_S;
16835 } else {
16836 goto pool32f_invalid;
16837 }
16838 goto do_fpop;
16839 default:
16840 goto pool32f_invalid;
16841 }
16842 break;
16843 case 0x38:
16844 /* cmovs */
2a24a7ba 16845 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16846 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16847 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16848 /* SELEQZ_FMT */
2a24a7ba
YK
16849 switch ((ctx->opcode >> 9) & 0x3) {
16850 case FMT_SDPS_S:
fdac60cd 16851 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16852 break;
16853 case FMT_SDPS_D:
fdac60cd 16854 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16855 break;
16856 default:
16857 goto pool32f_invalid;
16858 }
16859 } else {
16860 /* MOVN_FMT */
16861 FINSN_3ARG_SDPS(MOVN);
16862 }
16863 break;
16864 case MOVN_FMT_04:
16865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16866 FINSN_3ARG_SDPS(MOVN);
16867 break;
fdac60cd 16868 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16869 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16870 /* SELNEZ_FMT */
2a24a7ba
YK
16871 switch ((ctx->opcode >> 9) & 0x3) {
16872 case FMT_SDPS_S:
fdac60cd 16873 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16874 break;
16875 case FMT_SDPS_D:
fdac60cd 16876 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16877 break;
16878 default:
16879 goto pool32f_invalid;
16880 }
16881 } else {
16882 /* MOVZ_FMT */
16883 FINSN_3ARG_SDPS(MOVZ);
16884 }
16885 break;
16886 case MOVZ_FMT_05:
16887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16888 FINSN_3ARG_SDPS(MOVZ);
16889 break;
2a24a7ba
YK
16890 case SEL_FMT:
16891 check_insn(ctx, ISA_MIPS32R6);
16892 switch ((ctx->opcode >> 9) & 0x3) {
16893 case FMT_SDPS_S:
16894 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16895 break;
16896 case FMT_SDPS_D:
16897 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16898 break;
16899 default:
16900 goto pool32f_invalid;
16901 }
16902 break;
16903 case MADDF_FMT:
16904 check_insn(ctx, ISA_MIPS32R6);
16905 switch ((ctx->opcode >> 9) & 0x3) {
16906 case FMT_SDPS_S:
16907 mips32_op = OPC_MADDF_S;
16908 goto do_fpop;
16909 case FMT_SDPS_D:
16910 mips32_op = OPC_MADDF_D;
16911 goto do_fpop;
16912 default:
16913 goto pool32f_invalid;
16914 }
16915 break;
16916 case MSUBF_FMT:
16917 check_insn(ctx, ISA_MIPS32R6);
16918 switch ((ctx->opcode >> 9) & 0x3) {
16919 case FMT_SDPS_S:
16920 mips32_op = OPC_MSUBF_S;
16921 goto do_fpop;
16922 case FMT_SDPS_D:
16923 mips32_op = OPC_MSUBF_D;
16924 goto do_fpop;
16925 default:
16926 goto pool32f_invalid;
16927 }
16928 break;
3c824109
NF
16929 default:
16930 goto pool32f_invalid;
16931 }
16932 break;
16933 do_fpop:
16934 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16935 break;
16936 default:
16937 pool32f_invalid:
16938 MIPS_INVAL("pool32f");
9c708c7f 16939 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16940 break;
16941 }
16942 } else {
16943 generate_exception_err(ctx, EXCP_CpU, 1);
16944 }
16945 break;
16946 case POOL32I:
16947 minor = (ctx->opcode >> 21) & 0x1f;
16948 switch (minor) {
16949 case BLTZ:
9e8f441a 16950 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16951 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16952 break;
3c824109 16953 case BLTZAL:
9e8f441a 16954 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16955 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16956 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16957 break;
3c824109 16958 case BLTZALS:
9e8f441a 16959 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16960 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16961 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16962 break;
3c824109 16963 case BGEZ:
9e8f441a 16964 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16965 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16966 break;
3c824109 16967 case BGEZAL:
9e8f441a 16968 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16969 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16970 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16971 break;
3c824109 16972 case BGEZALS:
9e8f441a 16973 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16974 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16975 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16976 break;
3c824109 16977 case BLEZ:
9e8f441a 16978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16979 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16980 break;
3c824109 16981 case BGTZ:
9e8f441a 16982 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 16983 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16984 break;
16985
16986 /* Traps */
65935f07
YK
16987 case TLTI: /* BC1EQZC */
16988 if (ctx->insn_flags & ISA_MIPS32R6) {
16989 /* BC1EQZC */
16990 check_cp1_enabled(ctx);
16991 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16992 } else {
16993 /* TLTI */
16994 mips32_op = OPC_TLTI;
16995 goto do_trapi;
16996 }
16997 break;
16998 case TGEI: /* BC1NEZC */
16999 if (ctx->insn_flags & ISA_MIPS32R6) {
17000 /* BC1NEZC */
17001 check_cp1_enabled(ctx);
17002 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17003 } else {
17004 /* TGEI */
17005 mips32_op = OPC_TGEI;
17006 goto do_trapi;
17007 }
17008 break;
3c824109 17009 case TLTIU:
9e8f441a 17010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17011 mips32_op = OPC_TLTIU;
17012 goto do_trapi;
17013 case TGEIU:
9e8f441a 17014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17015 mips32_op = OPC_TGEIU;
17016 goto do_trapi;
3b4a5489
YK
17017 case TNEI: /* SYNCI */
17018 if (ctx->insn_flags & ISA_MIPS32R6) {
17019 /* SYNCI */
7480515f
AM
17020 /*
17021 * Break the TB to be able to sync copied instructions
17022 * immediately.
17023 */
eeb3bba8 17024 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
17025 } else {
17026 /* TNEI */
17027 mips32_op = OPC_TNEI;
17028 goto do_trapi;
17029 }
17030 break;
3c824109 17031 case TEQI:
9e8f441a 17032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17033 mips32_op = OPC_TEQI;
17034 do_trapi:
17035 gen_trap(ctx, mips32_op, rs, -1, imm);
17036 break;
17037
17038 case BNEZC:
17039 case BEQZC:
9e8f441a 17040 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17041 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 17042 4, rs, 0, imm << 1, 0);
7480515f
AM
17043 /*
17044 * Compact branches don't have a delay slot, so just let
17045 * the normal delay slot handling take us to the branch
17046 * target.
17047 */
3c824109
NF
17048 break;
17049 case LUI:
9e8f441a 17050 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 17051 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
17052 break;
17053 case SYNCI:
9e8f441a 17054 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7480515f
AM
17055 /*
17056 * Break the TB to be able to sync copied instructions
17057 * immediately.
17058 */
eeb3bba8 17059 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
17060 break;
17061 case BC2F:
17062 case BC2T:
9e8f441a 17063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17064 /* COP2: Not implemented. */
17065 generate_exception_err(ctx, EXCP_CpU, 2);
17066 break;
17067 case BC1F:
9e8f441a 17068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17069 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17070 goto do_cp1branch;
17071 case BC1T:
9e8f441a 17072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17073 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17074 goto do_cp1branch;
17075 case BC1ANY4F:
9e8f441a 17076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17077 mips32_op = OPC_BC1FANY4;
17078 goto do_cp1mips3d;
17079 case BC1ANY4T:
9e8f441a 17080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
17081 mips32_op = OPC_BC1TANY4;
17082 do_cp1mips3d:
17083 check_cop1x(ctx);
d75c135e 17084 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
17085 /* Fall through */
17086 do_cp1branch:
272f458d
MR
17087 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17088 check_cp1_enabled(ctx);
17089 gen_compute_branch1(ctx, mips32_op,
17090 (ctx->opcode >> 18) & 0x7, imm << 1);
17091 } else {
17092 generate_exception_err(ctx, EXCP_CpU, 1);
17093 }
3c824109
NF
17094 break;
17095 case BPOSGE64:
17096 case BPOSGE32:
17097 /* MIPS DSP: not implemented */
17098 /* Fall through */
17099 default:
17100 MIPS_INVAL("pool32i");
9c708c7f 17101 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17102 break;
17103 }
17104 break;
17105 case POOL32C:
17106 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
17107 offset = sextract32(ctx->opcode, 0,
17108 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
17109 switch (minor) {
17110 case LWL:
9e8f441a 17111 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17112 mips32_op = OPC_LWL;
5c13fdfd 17113 goto do_ld_lr;
3c824109 17114 case SWL:
9e8f441a 17115 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17116 mips32_op = OPC_SWL;
5c13fdfd 17117 goto do_st_lr;
3c824109 17118 case LWR:
9e8f441a 17119 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17120 mips32_op = OPC_LWR;
5c13fdfd 17121 goto do_ld_lr;
3c824109 17122 case SWR:
9e8f441a 17123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17124 mips32_op = OPC_SWR;
5c13fdfd 17125 goto do_st_lr;
3c824109
NF
17126#if defined(TARGET_MIPS64)
17127 case LDL:
d9224450
MR
17128 check_insn(ctx, ISA_MIPS3);
17129 check_mips_64(ctx);
9e8f441a 17130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17131 mips32_op = OPC_LDL;
5c13fdfd 17132 goto do_ld_lr;
3c824109 17133 case SDL:
d9224450
MR
17134 check_insn(ctx, ISA_MIPS3);
17135 check_mips_64(ctx);
9e8f441a 17136 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17137 mips32_op = OPC_SDL;
5c13fdfd 17138 goto do_st_lr;
3c824109 17139 case LDR:
d9224450
MR
17140 check_insn(ctx, ISA_MIPS3);
17141 check_mips_64(ctx);
9e8f441a 17142 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17143 mips32_op = OPC_LDR;
5c13fdfd 17144 goto do_ld_lr;
3c824109 17145 case SDR:
d9224450
MR
17146 check_insn(ctx, ISA_MIPS3);
17147 check_mips_64(ctx);
9e8f441a 17148 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17149 mips32_op = OPC_SDR;
5c13fdfd 17150 goto do_st_lr;
3c824109 17151 case LWU:
d9224450
MR
17152 check_insn(ctx, ISA_MIPS3);
17153 check_mips_64(ctx);
3c824109 17154 mips32_op = OPC_LWU;
5c13fdfd 17155 goto do_ld_lr;
3c824109 17156 case LLD:
d9224450
MR
17157 check_insn(ctx, ISA_MIPS3);
17158 check_mips_64(ctx);
3c824109 17159 mips32_op = OPC_LLD;
5c13fdfd 17160 goto do_ld_lr;
3c824109
NF
17161#endif
17162 case LL:
17163 mips32_op = OPC_LL;
5c13fdfd
AJ
17164 goto do_ld_lr;
17165 do_ld_lr:
3b4a5489 17166 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
17167 break;
17168 do_st_lr:
8fffc646 17169 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
17170 break;
17171 case SC:
33a07fa2 17172 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
17173 break;
17174#if defined(TARGET_MIPS64)
17175 case SCD:
d9224450
MR
17176 check_insn(ctx, ISA_MIPS3);
17177 check_mips_64(ctx);
33a07fa2 17178 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
17179 break;
17180#endif
8fffc646
JH
17181 case LD_EVA:
17182 if (!ctx->eva) {
17183 MIPS_INVAL("pool32c ld-eva");
17184 generate_exception_end(ctx, EXCP_RI);
17185 break;
17186 }
17187 check_cp0_enabled(ctx);
17188
17189 minor2 = (ctx->opcode >> 9) & 0x7;
17190 offset = sextract32(ctx->opcode, 0, 9);
17191 switch (minor2) {
17192 case LBUE:
17193 mips32_op = OPC_LBUE;
17194 goto do_ld_lr;
17195 case LHUE:
17196 mips32_op = OPC_LHUE;
17197 goto do_ld_lr;
17198 case LWLE:
17199 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17200 mips32_op = OPC_LWLE;
17201 goto do_ld_lr;
17202 case LWRE:
17203 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17204 mips32_op = OPC_LWRE;
17205 goto do_ld_lr;
17206 case LBE:
17207 mips32_op = OPC_LBE;
17208 goto do_ld_lr;
17209 case LHE:
17210 mips32_op = OPC_LHE;
17211 goto do_ld_lr;
17212 case LLE:
17213 mips32_op = OPC_LLE;
17214 goto do_ld_lr;
17215 case LWE:
17216 mips32_op = OPC_LWE;
17217 goto do_ld_lr;
17218 };
17219 break;
17220 case ST_EVA:
17221 if (!ctx->eva) {
17222 MIPS_INVAL("pool32c st-eva");
17223 generate_exception_end(ctx, EXCP_RI);
17224 break;
17225 }
17226 check_cp0_enabled(ctx);
17227
17228 minor2 = (ctx->opcode >> 9) & 0x7;
17229 offset = sextract32(ctx->opcode, 0, 9);
17230 switch (minor2) {
17231 case SWLE:
17232 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17233 mips32_op = OPC_SWLE;
17234 goto do_st_lr;
17235 case SWRE:
17236 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17237 mips32_op = OPC_SWRE;
17238 goto do_st_lr;
17239 case PREFE:
17240 /* Treat as no-op */
17241 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17242 /* hint codes 24-31 are reserved and signal RI */
17243 generate_exception(ctx, EXCP_RI);
17244 }
17245 break;
17246 case CACHEE:
17247 /* Treat as no-op */
17248 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17249 gen_cache_operation(ctx, rt, rs, offset);
17250 }
17251 break;
17252 case SBE:
17253 mips32_op = OPC_SBE;
17254 goto do_st_lr;
17255 case SHE:
17256 mips32_op = OPC_SHE;
17257 goto do_st_lr;
17258 case SCE:
33a07fa2 17259 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
17260 break;
17261 case SWE:
17262 mips32_op = OPC_SWE;
17263 goto do_st_lr;
17264 };
17265 break;
3c824109
NF
17266 case PREF:
17267 /* Treat as no-op */
3b4a5489
YK
17268 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17269 /* hint codes 24-31 are reserved and signal RI */
17270 generate_exception(ctx, EXCP_RI);
17271 }
3c824109
NF
17272 break;
17273 default:
17274 MIPS_INVAL("pool32c");
9c708c7f 17275 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17276 break;
17277 }
17278 break;
ab39ee45
YK
17279 case ADDI32: /* AUI, LUI */
17280 if (ctx->insn_flags & ISA_MIPS32R6) {
17281 /* AUI, LUI */
17282 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17283 } else {
17284 /* ADDI32 */
17285 mips32_op = OPC_ADDI;
17286 goto do_addi;
17287 }
17288 break;
3c824109
NF
17289 case ADDIU32:
17290 mips32_op = OPC_ADDIU;
17291 do_addi:
d75c135e 17292 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17293 break;
17294
17295 /* Logical operations */
17296 case ORI32:
17297 mips32_op = OPC_ORI;
17298 goto do_logici;
17299 case XORI32:
17300 mips32_op = OPC_XORI;
17301 goto do_logici;
17302 case ANDI32:
17303 mips32_op = OPC_ANDI;
17304 do_logici:
d75c135e 17305 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17306 break;
17307
17308 /* Set less than immediate */
17309 case SLTI32:
17310 mips32_op = OPC_SLTI;
17311 goto do_slti;
17312 case SLTIU32:
17313 mips32_op = OPC_SLTIU;
17314 do_slti:
d75c135e 17315 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17316 break;
17317 case JALX32:
9e8f441a 17318 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17319 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17320 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17321 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17322 break;
65935f07
YK
17323 case JALS32: /* BOVC, BEQC, BEQZALC */
17324 if (ctx->insn_flags & ISA_MIPS32R6) {
17325 if (rs >= rt) {
17326 /* BOVC */
17327 mips32_op = OPC_BOVC;
17328 } else if (rs < rt && rs == 0) {
17329 /* BEQZALC */
17330 mips32_op = OPC_BEQZALC;
17331 } else {
17332 /* BEQC */
17333 mips32_op = OPC_BEQC;
17334 }
17335 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17336 } else {
17337 /* JALS32 */
17338 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17339 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17340 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17341 }
3c824109 17342 break;
65935f07
YK
17343 case BEQ32: /* BC */
17344 if (ctx->insn_flags & ISA_MIPS32R6) {
17345 /* BC */
17346 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17347 sextract32(ctx->opcode << 1, 0, 27));
17348 } else {
17349 /* BEQ32 */
17350 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17351 }
3c824109 17352 break;
65935f07
YK
17353 case BNE32: /* BALC */
17354 if (ctx->insn_flags & ISA_MIPS32R6) {
17355 /* BALC */
17356 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17357 sextract32(ctx->opcode << 1, 0, 27));
17358 } else {
17359 /* BNE32 */
17360 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17361 }
3c824109 17362 break;
65935f07
YK
17363 case J32: /* BGTZC, BLTZC, BLTC */
17364 if (ctx->insn_flags & ISA_MIPS32R6) {
17365 if (rs == 0 && rt != 0) {
17366 /* BGTZC */
17367 mips32_op = OPC_BGTZC;
17368 } else if (rs != 0 && rt != 0 && rs == rt) {
17369 /* BLTZC */
17370 mips32_op = OPC_BLTZC;
17371 } else {
17372 /* BLTC */
17373 mips32_op = OPC_BLTC;
17374 }
17375 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17376 } else {
17377 /* J32 */
17378 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17379 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17380 }
3c824109 17381 break;
65935f07
YK
17382 case JAL32: /* BLEZC, BGEZC, BGEC */
17383 if (ctx->insn_flags & ISA_MIPS32R6) {
17384 if (rs == 0 && rt != 0) {
17385 /* BLEZC */
17386 mips32_op = OPC_BLEZC;
17387 } else if (rs != 0 && rt != 0 && rs == rt) {
17388 /* BGEZC */
17389 mips32_op = OPC_BGEZC;
17390 } else {
17391 /* BGEC */
17392 mips32_op = OPC_BGEC;
17393 }
17394 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17395 } else {
17396 /* JAL32 */
17397 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17398 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17399 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17400 }
3c824109
NF
17401 break;
17402 /* Floating point (COP1) */
17403 case LWC132:
17404 mips32_op = OPC_LWC1;
17405 goto do_cop1;
17406 case LDC132:
17407 mips32_op = OPC_LDC1;
17408 goto do_cop1;
17409 case SWC132:
17410 mips32_op = OPC_SWC1;
17411 goto do_cop1;
17412 case SDC132:
17413 mips32_op = OPC_SDC1;
17414 do_cop1:
5ab5c041 17415 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17416 break;
ab39ee45
YK
17417 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17418 if (ctx->insn_flags & ISA_MIPS32R6) {
17419 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17420 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17421 case ADDIUPC_00:
17422 case ADDIUPC_01:
17423 case ADDIUPC_02:
17424 case ADDIUPC_03:
17425 case ADDIUPC_04:
17426 case ADDIUPC_05:
17427 case ADDIUPC_06:
17428 case ADDIUPC_07:
eeb3bba8 17429 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17430 break;
17431 case AUIPC:
eeb3bba8 17432 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17433 break;
17434 case ALUIPC:
eeb3bba8 17435 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17436 break;
c38a1d52
AR
17437 case LWPC_08:
17438 case LWPC_09:
17439 case LWPC_0A:
17440 case LWPC_0B:
17441 case LWPC_0C:
17442 case LWPC_0D:
17443 case LWPC_0E:
17444 case LWPC_0F:
eeb3bba8 17445 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17446 break;
17447 default:
17448 generate_exception(ctx, EXCP_RI);
17449 break;
17450 }
17451 } else {
17452 /* ADDIUPC */
3c824109 17453 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17454 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17455
17456 gen_addiupc(ctx, reg, offset, 0, 0);
17457 }
17458 break;
65935f07
YK
17459 case BNVC: /* BNEC, BNEZALC */
17460 check_insn(ctx, ISA_MIPS32R6);
17461 if (rs >= rt) {
17462 /* BNVC */
17463 mips32_op = OPC_BNVC;
17464 } else if (rs < rt && rs == 0) {
17465 /* BNEZALC */
17466 mips32_op = OPC_BNEZALC;
17467 } else {
17468 /* BNEC */
17469 mips32_op = OPC_BNEC;
17470 }
17471 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17472 break;
17473 case R6_BNEZC: /* JIALC */
17474 check_insn(ctx, ISA_MIPS32R6);
17475 if (rt != 0) {
17476 /* BNEZC */
17477 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17478 sextract32(ctx->opcode << 1, 0, 22));
17479 } else {
17480 /* JIALC */
17481 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17482 }
17483 break;
17484 case R6_BEQZC: /* JIC */
17485 check_insn(ctx, ISA_MIPS32R6);
17486 if (rt != 0) {
17487 /* BEQZC */
17488 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17489 sextract32(ctx->opcode << 1, 0, 22));
17490 } else {
17491 /* JIC */
17492 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17493 }
17494 break;
17495 case BLEZALC: /* BGEZALC, BGEUC */
17496 check_insn(ctx, ISA_MIPS32R6);
17497 if (rs == 0 && rt != 0) {
17498 /* BLEZALC */
17499 mips32_op = OPC_BLEZALC;
17500 } else if (rs != 0 && rt != 0 && rs == rt) {
17501 /* BGEZALC */
17502 mips32_op = OPC_BGEZALC;
17503 } else {
17504 /* BGEUC */
17505 mips32_op = OPC_BGEUC;
17506 }
17507 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17508 break;
17509 case BGTZALC: /* BLTZALC, BLTUC */
17510 check_insn(ctx, ISA_MIPS32R6);
17511 if (rs == 0 && rt != 0) {
17512 /* BGTZALC */
17513 mips32_op = OPC_BGTZALC;
17514 } else if (rs != 0 && rt != 0 && rs == rt) {
17515 /* BLTZALC */
17516 mips32_op = OPC_BLTZALC;
17517 } else {
17518 /* BLTUC */
17519 mips32_op = OPC_BLTUC;
17520 }
17521 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17522 break;
3c824109
NF
17523 /* Loads and stores */
17524 case LB32:
17525 mips32_op = OPC_LB;
5c13fdfd 17526 goto do_ld;
3c824109
NF
17527 case LBU32:
17528 mips32_op = OPC_LBU;
5c13fdfd 17529 goto do_ld;
3c824109
NF
17530 case LH32:
17531 mips32_op = OPC_LH;
5c13fdfd 17532 goto do_ld;
3c824109
NF
17533 case LHU32:
17534 mips32_op = OPC_LHU;
5c13fdfd 17535 goto do_ld;
3c824109
NF
17536 case LW32:
17537 mips32_op = OPC_LW;
5c13fdfd 17538 goto do_ld;
3c824109
NF
17539#ifdef TARGET_MIPS64
17540 case LD32:
d9224450
MR
17541 check_insn(ctx, ISA_MIPS3);
17542 check_mips_64(ctx);
3c824109 17543 mips32_op = OPC_LD;
5c13fdfd 17544 goto do_ld;
3c824109 17545 case SD32:
d9224450
MR
17546 check_insn(ctx, ISA_MIPS3);
17547 check_mips_64(ctx);
3c824109 17548 mips32_op = OPC_SD;
5c13fdfd 17549 goto do_st;
3c824109
NF
17550#endif
17551 case SB32:
17552 mips32_op = OPC_SB;
5c13fdfd 17553 goto do_st;
3c824109
NF
17554 case SH32:
17555 mips32_op = OPC_SH;
5c13fdfd 17556 goto do_st;
3c824109
NF
17557 case SW32:
17558 mips32_op = OPC_SW;
5c13fdfd
AJ
17559 goto do_st;
17560 do_ld:
d75c135e 17561 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
17562 break;
17563 do_st:
17564 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17565 break;
17566 default:
9c708c7f 17567 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17568 break;
17569 }
17570}
17571
235785e8 17572static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
17573{
17574 uint32_t op;
17575
17576 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
17577 if (ctx->base.pc_next & 0x1) {
17578 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 17579 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
17580 return 2;
17581 }
17582
17583 op = (ctx->opcode >> 10) & 0x3f;
17584 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
17585 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17586 switch (op & 0x7) { /* MSB-3..MSB-5 */
17587 case 0:
17588 /* POOL32A, POOL32B, POOL32I, POOL32C */
17589 case 4:
17590 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17591 case 5:
17592 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17593 case 6:
17594 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17595 case 7:
17596 /* LB32, LH32, LWC132, LDC132, LW32 */
17597 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 17598 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17599 return 2;
17600 }
17601 break;
b231c103
YK
17602 case 1:
17603 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17604 case 2:
17605 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17606 case 3:
17607 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17608 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 17609 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17610 return 2;
17611 }
17612 break;
3c824109
NF
17613 }
17614 }
b231c103 17615
3c824109
NF
17616 switch (op) {
17617 case POOL16A:
17618 {
17619 int rd = mmreg(uMIPS_RD(ctx->opcode));
17620 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17621 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17622 uint32_t opc = 0;
17623
17624 switch (ctx->opcode & 0x1) {
17625 case ADDU16:
17626 opc = OPC_ADDU;
17627 break;
17628 case SUBU16:
17629 opc = OPC_SUBU;
17630 break;
17631 }
ed7ce6c0 17632 if (ctx->insn_flags & ISA_MIPS32R6) {
7480515f
AM
17633 /*
17634 * In the Release 6, the register number location in
ed7ce6c0
YK
17635 * the instruction encoding has changed.
17636 */
17637 gen_arith(ctx, opc, rs1, rd, rs2);
17638 } else {
17639 gen_arith(ctx, opc, rd, rs1, rs2);
17640 }
3c824109
NF
17641 }
17642 break;
17643 case POOL16B:
17644 {
17645 int rd = mmreg(uMIPS_RD(ctx->opcode));
17646 int rs = mmreg(uMIPS_RS(ctx->opcode));
17647 int amount = (ctx->opcode >> 1) & 0x7;
17648 uint32_t opc = 0;
17649 amount = amount == 0 ? 8 : amount;
17650
17651 switch (ctx->opcode & 0x1) {
17652 case SLL16:
17653 opc = OPC_SLL;
17654 break;
17655 case SRL16:
17656 opc = OPC_SRL;
17657 break;
17658 }
17659
d75c135e 17660 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17661 }
17662 break;
17663 case POOL16C:
ed7ce6c0
YK
17664 if (ctx->insn_flags & ISA_MIPS32R6) {
17665 gen_pool16c_r6_insn(ctx);
17666 } else {
17667 gen_pool16c_insn(ctx);
17668 }
3c824109
NF
17669 break;
17670 case LWGP16:
17671 {
17672 int rd = mmreg(uMIPS_RD(ctx->opcode));
17673 int rb = 28; /* GP */
17674 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17675
d75c135e 17676 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17677 }
17678 break;
17679 case POOL16F:
9e8f441a 17680 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17681 if (ctx->opcode & 1) {
9c708c7f 17682 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17683 } else {
17684 /* MOVEP */
17685 int enc_dest = uMIPS_RD(ctx->opcode);
17686 int enc_rt = uMIPS_RS2(ctx->opcode);
17687 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17688 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17689 }
17690 break;
17691 case LBU16:
17692 {
17693 int rd = mmreg(uMIPS_RD(ctx->opcode));
17694 int rb = mmreg(uMIPS_RS(ctx->opcode));
17695 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17696 offset = (offset == 0xf ? -1 : offset);
17697
d75c135e 17698 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17699 }
17700 break;
17701 case LHU16:
17702 {
17703 int rd = mmreg(uMIPS_RD(ctx->opcode));
17704 int rb = mmreg(uMIPS_RS(ctx->opcode));
17705 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17706
d75c135e 17707 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17708 }
17709 break;
17710 case LWSP16:
17711 {
17712 int rd = (ctx->opcode >> 5) & 0x1f;
17713 int rb = 29; /* SP */
17714 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17715
d75c135e 17716 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17717 }
17718 break;
17719 case LW16:
17720 {
17721 int rd = mmreg(uMIPS_RD(ctx->opcode));
17722 int rb = mmreg(uMIPS_RS(ctx->opcode));
17723 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17724
d75c135e 17725 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17726 }
17727 break;
17728 case SB16:
17729 {
17730 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17731 int rb = mmreg(uMIPS_RS(ctx->opcode));
17732 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17733
5c13fdfd 17734 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17735 }
17736 break;
17737 case SH16:
17738 {
17739 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17740 int rb = mmreg(uMIPS_RS(ctx->opcode));
17741 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17742
5c13fdfd 17743 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17744 }
17745 break;
17746 case SWSP16:
17747 {
17748 int rd = (ctx->opcode >> 5) & 0x1f;
17749 int rb = 29; /* SP */
17750 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17751
5c13fdfd 17752 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17753 }
17754 break;
17755 case SW16:
17756 {
17757 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17758 int rb = mmreg(uMIPS_RS(ctx->opcode));
17759 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17760
5c13fdfd 17761 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17762 }
17763 break;
17764 case MOVE16:
17765 {
17766 int rd = uMIPS_RD5(ctx->opcode);
17767 int rs = uMIPS_RS5(ctx->opcode);
17768
7215d7e7 17769 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17770 }
17771 break;
17772 case ANDI16:
d75c135e 17773 gen_andi16(ctx);
3c824109
NF
17774 break;
17775 case POOL16D:
17776 switch (ctx->opcode & 0x1) {
17777 case ADDIUS5:
d75c135e 17778 gen_addius5(ctx);
3c824109
NF
17779 break;
17780 case ADDIUSP:
d75c135e 17781 gen_addiusp(ctx);
3c824109
NF
17782 break;
17783 }
17784 break;
17785 case POOL16E:
17786 switch (ctx->opcode & 0x1) {
17787 case ADDIUR2:
d75c135e 17788 gen_addiur2(ctx);
3c824109
NF
17789 break;
17790 case ADDIUR1SP:
d75c135e 17791 gen_addiur1sp(ctx);
3c824109
NF
17792 break;
17793 }
17794 break;
65935f07 17795 case B16: /* BC16 */
3c824109 17796 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17797 sextract32(ctx->opcode, 0, 10) << 1,
17798 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17799 break;
65935f07
YK
17800 case BNEZ16: /* BNEZC16 */
17801 case BEQZ16: /* BEQZC16 */
3c824109
NF
17802 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17803 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17804 0, sextract32(ctx->opcode, 0, 7) << 1,
17805 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17806
3c824109
NF
17807 break;
17808 case LI16:
17809 {
17810 int reg = mmreg(uMIPS_RD(ctx->opcode));
17811 int imm = ZIMM(ctx->opcode, 0, 7);
17812
17813 imm = (imm == 0x7f ? -1 : imm);
17814 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17815 }
17816 break;
3c824109 17817 case RES_29:
3c824109 17818 case RES_31:
3c824109 17819 case RES_39:
9c708c7f 17820 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17821 break;
17822 default:
f60eeb0c 17823 decode_micromips32_opc(env, ctx);
3c824109
NF
17824 return 4;
17825 }
17826
17827 return 2;
17828}
17829
261c95a0
YK
17830/*
17831 *
17832 * nanoMIPS opcodes
17833 *
17834 */
17835
17836/* MAJOR, P16, and P32 pools opcodes */
17837enum {
17838 NM_P_ADDIU = 0x00,
17839 NM_ADDIUPC = 0x01,
17840 NM_MOVE_BALC = 0x02,
17841 NM_P16_MV = 0x04,
17842 NM_LW16 = 0x05,
17843 NM_BC16 = 0x06,
17844 NM_P16_SR = 0x07,
17845
17846 NM_POOL32A = 0x08,
17847 NM_P_BAL = 0x0a,
17848 NM_P16_SHIFT = 0x0c,
17849 NM_LWSP16 = 0x0d,
17850 NM_BALC16 = 0x0e,
17851 NM_P16_4X4 = 0x0f,
17852
17853 NM_P_GP_W = 0x10,
17854 NM_P_GP_BH = 0x11,
17855 NM_P_J = 0x12,
17856 NM_P16C = 0x14,
17857 NM_LWGP16 = 0x15,
17858 NM_P16_LB = 0x17,
17859
17860 NM_P48I = 0x18,
17861 NM_P16_A1 = 0x1c,
17862 NM_LW4X4 = 0x1d,
17863 NM_P16_LH = 0x1f,
17864
17865 NM_P_U12 = 0x20,
17866 NM_P_LS_U12 = 0x21,
17867 NM_P_BR1 = 0x22,
17868 NM_P16_A2 = 0x24,
17869 NM_SW16 = 0x25,
17870 NM_BEQZC16 = 0x26,
17871
17872 NM_POOL32F = 0x28,
17873 NM_P_LS_S9 = 0x29,
17874 NM_P_BR2 = 0x2a,
17875
17876 NM_P16_ADDU = 0x2c,
17877 NM_SWSP16 = 0x2d,
17878 NM_BNEZC16 = 0x2e,
17879 NM_MOVEP = 0x2f,
17880
17881 NM_POOL32S = 0x30,
17882 NM_P_BRI = 0x32,
17883 NM_LI16 = 0x34,
17884 NM_SWGP16 = 0x35,
17885 NM_P16_BR = 0x36,
17886
17887 NM_P_LUI = 0x38,
17888 NM_ANDI16 = 0x3c,
17889 NM_SW4X4 = 0x3d,
17890 NM_MOVEPREV = 0x3f,
17891};
17892
17893/* POOL32A instruction pool */
17894enum {
17895 NM_POOL32A0 = 0x00,
17896 NM_SPECIAL2 = 0x01,
17897 NM_COP2_1 = 0x02,
17898 NM_UDI = 0x03,
17899 NM_POOL32A5 = 0x05,
17900 NM_POOL32A7 = 0x07,
17901};
17902
17903/* P.GP.W instruction pool */
17904enum {
17905 NM_ADDIUGP_W = 0x00,
17906 NM_LWGP = 0x02,
17907 NM_SWGP = 0x03,
17908};
17909
17910/* P48I instruction pool */
17911enum {
17912 NM_LI48 = 0x00,
17913 NM_ADDIU48 = 0x01,
17914 NM_ADDIUGP48 = 0x02,
17915 NM_ADDIUPC48 = 0x03,
17916 NM_LWPC48 = 0x0b,
17917 NM_SWPC48 = 0x0f,
17918};
17919
17920/* P.U12 instruction pool */
17921enum {
17922 NM_ORI = 0x00,
17923 NM_XORI = 0x01,
17924 NM_ANDI = 0x02,
17925 NM_P_SR = 0x03,
17926 NM_SLTI = 0x04,
17927 NM_SLTIU = 0x05,
17928 NM_SEQI = 0x06,
17929 NM_ADDIUNEG = 0x08,
17930 NM_P_SHIFT = 0x0c,
17931 NM_P_ROTX = 0x0d,
17932 NM_P_INS = 0x0e,
17933 NM_P_EXT = 0x0f,
17934};
17935
17936/* POOL32F instruction pool */
17937enum {
17938 NM_POOL32F_0 = 0x00,
17939 NM_POOL32F_3 = 0x03,
17940 NM_POOL32F_5 = 0x05,
17941};
17942
17943/* POOL32S instruction pool */
17944enum {
17945 NM_POOL32S_0 = 0x00,
17946 NM_POOL32S_4 = 0x04,
17947};
17948
17949/* P.LUI instruction pool */
17950enum {
17951 NM_LUI = 0x00,
17952 NM_ALUIPC = 0x01,
17953};
17954
17955/* P.GP.BH instruction pool */
17956enum {
17957 NM_LBGP = 0x00,
17958 NM_SBGP = 0x01,
17959 NM_LBUGP = 0x02,
17960 NM_ADDIUGP_B = 0x03,
17961 NM_P_GP_LH = 0x04,
17962 NM_P_GP_SH = 0x05,
17963 NM_P_GP_CP1 = 0x06,
17964};
17965
17966/* P.LS.U12 instruction pool */
17967enum {
17968 NM_LB = 0x00,
17969 NM_SB = 0x01,
17970 NM_LBU = 0x02,
17971 NM_P_PREFU12 = 0x03,
17972 NM_LH = 0x04,
17973 NM_SH = 0x05,
17974 NM_LHU = 0x06,
17975 NM_LWU = 0x07,
17976 NM_LW = 0x08,
17977 NM_SW = 0x09,
17978 NM_LWC1 = 0x0a,
17979 NM_SWC1 = 0x0b,
17980 NM_LDC1 = 0x0e,
17981 NM_SDC1 = 0x0f,
17982};
17983
17984/* P.LS.S9 instruction pool */
17985enum {
17986 NM_P_LS_S0 = 0x00,
17987 NM_P_LS_S1 = 0x01,
17988 NM_P_LS_E0 = 0x02,
17989 NM_P_LS_WM = 0x04,
17990 NM_P_LS_UAWM = 0x05,
17991};
17992
17993/* P.BAL instruction pool */
17994enum {
17995 NM_BC = 0x00,
17996 NM_BALC = 0x01,
17997};
17998
17999/* P.J instruction pool */
18000enum {
18001 NM_JALRC = 0x00,
18002 NM_JALRC_HB = 0x01,
18003 NM_P_BALRSC = 0x08,
18004};
18005
18006/* P.BR1 instruction pool */
18007enum {
18008 NM_BEQC = 0x00,
18009 NM_P_BR3A = 0x01,
18010 NM_BGEC = 0x02,
18011 NM_BGEUC = 0x03,
18012};
18013
18014/* P.BR2 instruction pool */
18015enum {
18016 NM_BNEC = 0x00,
18017 NM_BLTC = 0x02,
18018 NM_BLTUC = 0x03,
18019};
18020
18021/* P.BRI instruction pool */
18022enum {
18023 NM_BEQIC = 0x00,
18024 NM_BBEQZC = 0x01,
18025 NM_BGEIC = 0x02,
18026 NM_BGEIUC = 0x03,
18027 NM_BNEIC = 0x04,
18028 NM_BBNEZC = 0x05,
18029 NM_BLTIC = 0x06,
18030 NM_BLTIUC = 0x07,
18031};
18032
18033/* P16.SHIFT instruction pool */
18034enum {
18035 NM_SLL16 = 0x00,
18036 NM_SRL16 = 0x01,
18037};
18038
18039/* POOL16C instruction pool */
18040enum {
18041 NM_POOL16C_0 = 0x00,
18042 NM_LWXS16 = 0x01,
18043};
18044
18045/* P16.A1 instruction pool */
18046enum {
18047 NM_ADDIUR1SP = 0x01,
18048};
18049
18050/* P16.A2 instruction pool */
18051enum {
18052 NM_ADDIUR2 = 0x00,
18053 NM_P_ADDIURS5 = 0x01,
18054};
18055
18056/* P16.ADDU instruction pool */
18057enum {
18058 NM_ADDU16 = 0x00,
18059 NM_SUBU16 = 0x01,
18060};
18061
18062/* P16.SR instruction pool */
18063enum {
18064 NM_SAVE16 = 0x00,
18065 NM_RESTORE_JRC16 = 0x01,
18066};
18067
18068/* P16.4X4 instruction pool */
18069enum {
18070 NM_ADDU4X4 = 0x00,
18071 NM_MUL4X4 = 0x01,
18072};
18073
18074/* P16.LB instruction pool */
18075enum {
18076 NM_LB16 = 0x00,
18077 NM_SB16 = 0x01,
18078 NM_LBU16 = 0x02,
18079};
18080
18081/* P16.LH instruction pool */
18082enum {
18083 NM_LH16 = 0x00,
18084 NM_SH16 = 0x01,
18085 NM_LHU16 = 0x02,
18086};
18087
18088/* P.RI instruction pool */
18089enum {
18090 NM_SIGRIE = 0x00,
18091 NM_P_SYSCALL = 0x01,
18092 NM_BREAK = 0x02,
18093 NM_SDBBP = 0x03,
18094};
18095
18096/* POOL32A0 instruction pool */
18097enum {
18098 NM_P_TRAP = 0x00,
18099 NM_SEB = 0x01,
18100 NM_SLLV = 0x02,
18101 NM_MUL = 0x03,
18102 NM_MFC0 = 0x06,
18103 NM_MFHC0 = 0x07,
18104 NM_SEH = 0x09,
18105 NM_SRLV = 0x0a,
18106 NM_MUH = 0x0b,
18107 NM_MTC0 = 0x0e,
18108 NM_MTHC0 = 0x0f,
18109 NM_SRAV = 0x12,
18110 NM_MULU = 0x13,
18111 NM_ROTRV = 0x1a,
18112 NM_MUHU = 0x1b,
18113 NM_ADD = 0x22,
18114 NM_DIV = 0x23,
18115 NM_ADDU = 0x2a,
18116 NM_MOD = 0x2b,
18117 NM_SUB = 0x32,
18118 NM_DIVU = 0x33,
18119 NM_RDHWR = 0x38,
18120 NM_SUBU = 0x3a,
18121 NM_MODU = 0x3b,
18122 NM_P_CMOVE = 0x42,
18123 NM_FORK = 0x45,
18124 NM_MFTR = 0x46,
18125 NM_MFHTR = 0x47,
18126 NM_AND = 0x4a,
18127 NM_YIELD = 0x4d,
18128 NM_MTTR = 0x4e,
18129 NM_MTHTR = 0x4f,
18130 NM_OR = 0x52,
18131 NM_D_E_MT_VPE = 0x56,
18132 NM_NOR = 0x5a,
18133 NM_XOR = 0x62,
18134 NM_SLT = 0x6a,
18135 NM_P_SLTU = 0x72,
18136 NM_SOV = 0x7a,
18137};
18138
ba1e8117
AM
18139/* CRC32 instruction pool */
18140enum {
18141 NM_CRC32B = 0x00,
18142 NM_CRC32H = 0x01,
18143 NM_CRC32W = 0x02,
18144 NM_CRC32CB = 0x04,
18145 NM_CRC32CH = 0x05,
18146 NM_CRC32CW = 0x06,
18147};
18148
b3979b6f
SM
18149/* POOL32A5 instruction pool */
18150enum {
18151 NM_CMP_EQ_PH = 0x00,
18152 NM_CMP_LT_PH = 0x08,
18153 NM_CMP_LE_PH = 0x10,
18154 NM_CMPGU_EQ_QB = 0x18,
18155 NM_CMPGU_LT_QB = 0x20,
18156 NM_CMPGU_LE_QB = 0x28,
18157 NM_CMPGDU_EQ_QB = 0x30,
18158 NM_CMPGDU_LT_QB = 0x38,
18159 NM_CMPGDU_LE_QB = 0x40,
18160 NM_CMPU_EQ_QB = 0x48,
18161 NM_CMPU_LT_QB = 0x50,
18162 NM_CMPU_LE_QB = 0x58,
18163 NM_ADDQ_S_W = 0x60,
18164 NM_SUBQ_S_W = 0x68,
18165 NM_ADDSC = 0x70,
18166 NM_ADDWC = 0x78,
18167
18168 NM_ADDQ_S_PH = 0x01,
18169 NM_ADDQH_R_PH = 0x09,
18170 NM_ADDQH_R_W = 0x11,
18171 NM_ADDU_S_QB = 0x19,
18172 NM_ADDU_S_PH = 0x21,
18173 NM_ADDUH_R_QB = 0x29,
18174 NM_SHRAV_R_PH = 0x31,
18175 NM_SHRAV_R_QB = 0x39,
18176 NM_SUBQ_S_PH = 0x41,
18177 NM_SUBQH_R_PH = 0x49,
18178 NM_SUBQH_R_W = 0x51,
18179 NM_SUBU_S_QB = 0x59,
18180 NM_SUBU_S_PH = 0x61,
18181 NM_SUBUH_R_QB = 0x69,
18182 NM_SHLLV_S_PH = 0x71,
18183 NM_PRECR_SRA_R_PH_W = 0x79,
18184
18185 NM_MULEU_S_PH_QBL = 0x12,
18186 NM_MULEU_S_PH_QBR = 0x1a,
18187 NM_MULQ_RS_PH = 0x22,
18188 NM_MULQ_S_PH = 0x2a,
18189 NM_MULQ_RS_W = 0x32,
18190 NM_MULQ_S_W = 0x3a,
18191 NM_APPEND = 0x42,
18192 NM_MODSUB = 0x52,
18193 NM_SHRAV_R_W = 0x5a,
18194 NM_SHRLV_PH = 0x62,
18195 NM_SHRLV_QB = 0x6a,
18196 NM_SHLLV_QB = 0x72,
18197 NM_SHLLV_S_W = 0x7a,
18198
18199 NM_SHILO = 0x03,
18200
18201 NM_MULEQ_S_W_PHL = 0x04,
18202 NM_MULEQ_S_W_PHR = 0x0c,
18203
18204 NM_MUL_S_PH = 0x05,
18205 NM_PRECR_QB_PH = 0x0d,
18206 NM_PRECRQ_QB_PH = 0x15,
18207 NM_PRECRQ_PH_W = 0x1d,
18208 NM_PRECRQ_RS_PH_W = 0x25,
18209 NM_PRECRQU_S_QB_PH = 0x2d,
18210 NM_PACKRL_PH = 0x35,
18211 NM_PICK_QB = 0x3d,
18212 NM_PICK_PH = 0x45,
18213
18214 NM_SHRA_R_W = 0x5e,
18215 NM_SHRA_R_PH = 0x66,
18216 NM_SHLL_S_PH = 0x76,
18217 NM_SHLL_S_W = 0x7e,
18218
18219 NM_REPL_PH = 0x07
18220};
18221
261c95a0
YK
18222/* POOL32A7 instruction pool */
18223enum {
18224 NM_P_LSX = 0x00,
18225 NM_LSA = 0x01,
18226 NM_EXTW = 0x03,
18227 NM_POOL32AXF = 0x07,
18228};
18229
18230/* P.SR instruction pool */
18231enum {
18232 NM_PP_SR = 0x00,
18233 NM_P_SR_F = 0x01,
18234};
18235
18236/* P.SHIFT instruction pool */
18237enum {
18238 NM_P_SLL = 0x00,
18239 NM_SRL = 0x02,
18240 NM_SRA = 0x04,
18241 NM_ROTR = 0x06,
18242};
18243
18244/* P.ROTX instruction pool */
18245enum {
18246 NM_ROTX = 0x00,
18247};
18248
18249/* P.INS instruction pool */
18250enum {
18251 NM_INS = 0x00,
18252};
18253
18254/* P.EXT instruction pool */
18255enum {
18256 NM_EXT = 0x00,
18257};
18258
18259/* POOL32F_0 (fmt) instruction pool */
18260enum {
18261 NM_RINT_S = 0x04,
18262 NM_RINT_D = 0x44,
18263 NM_ADD_S = 0x06,
18264 NM_SELEQZ_S = 0x07,
18265 NM_SELEQZ_D = 0x47,
18266 NM_CLASS_S = 0x0c,
18267 NM_CLASS_D = 0x4c,
18268 NM_SUB_S = 0x0e,
18269 NM_SELNEZ_S = 0x0f,
18270 NM_SELNEZ_D = 0x4f,
18271 NM_MUL_S = 0x16,
18272 NM_SEL_S = 0x17,
18273 NM_SEL_D = 0x57,
18274 NM_DIV_S = 0x1e,
18275 NM_ADD_D = 0x26,
18276 NM_SUB_D = 0x2e,
18277 NM_MUL_D = 0x36,
18278 NM_MADDF_S = 0x37,
18279 NM_MADDF_D = 0x77,
18280 NM_DIV_D = 0x3e,
18281 NM_MSUBF_S = 0x3f,
18282 NM_MSUBF_D = 0x7f,
18283};
18284
18285/* POOL32F_3 instruction pool */
18286enum {
18287 NM_MIN_FMT = 0x00,
18288 NM_MAX_FMT = 0x01,
18289 NM_MINA_FMT = 0x04,
18290 NM_MAXA_FMT = 0x05,
18291 NM_POOL32FXF = 0x07,
18292};
18293
18294/* POOL32F_5 instruction pool */
18295enum {
18296 NM_CMP_CONDN_S = 0x00,
18297 NM_CMP_CONDN_D = 0x02,
18298};
18299
18300/* P.GP.LH instruction pool */
18301enum {
18302 NM_LHGP = 0x00,
18303 NM_LHUGP = 0x01,
18304};
18305
18306/* P.GP.SH instruction pool */
18307enum {
18308 NM_SHGP = 0x00,
18309};
18310
18311/* P.GP.CP1 instruction pool */
18312enum {
18313 NM_LWC1GP = 0x00,
18314 NM_SWC1GP = 0x01,
18315 NM_LDC1GP = 0x02,
18316 NM_SDC1GP = 0x03,
18317};
18318
18319/* P.LS.S0 instruction pool */
18320enum {
18321 NM_LBS9 = 0x00,
18322 NM_LHS9 = 0x04,
18323 NM_LWS9 = 0x08,
18324 NM_LDS9 = 0x0c,
18325
18326 NM_SBS9 = 0x01,
18327 NM_SHS9 = 0x05,
18328 NM_SWS9 = 0x09,
18329 NM_SDS9 = 0x0d,
18330
18331 NM_LBUS9 = 0x02,
18332 NM_LHUS9 = 0x06,
18333 NM_LWC1S9 = 0x0a,
18334 NM_LDC1S9 = 0x0e,
18335
18336 NM_P_PREFS9 = 0x03,
18337 NM_LWUS9 = 0x07,
18338 NM_SWC1S9 = 0x0b,
18339 NM_SDC1S9 = 0x0f,
18340};
18341
18342/* P.LS.S1 instruction pool */
18343enum {
18344 NM_ASET_ACLR = 0x02,
18345 NM_UALH = 0x04,
18346 NM_UASH = 0x05,
18347 NM_CACHE = 0x07,
18348 NM_P_LL = 0x0a,
18349 NM_P_SC = 0x0b,
18350};
18351
0d30b3bb
DN
18352/* P.LS.E0 instruction pool */
18353enum {
18354 NM_LBE = 0x00,
18355 NM_SBE = 0x01,
18356 NM_LBUE = 0x02,
18357 NM_P_PREFE = 0x03,
18358 NM_LHE = 0x04,
18359 NM_SHE = 0x05,
18360 NM_LHUE = 0x06,
18361 NM_CACHEE = 0x07,
18362 NM_LWE = 0x08,
18363 NM_SWE = 0x09,
18364 NM_P_LLE = 0x0a,
18365 NM_P_SCE = 0x0b,
18366};
18367
18368/* P.PREFE instruction pool */
18369enum {
18370 NM_SYNCIE = 0x00,
18371 NM_PREFE = 0x01,
18372};
18373
18374/* P.LLE instruction pool */
18375enum {
18376 NM_LLE = 0x00,
18377 NM_LLWPE = 0x01,
18378};
18379
18380/* P.SCE instruction pool */
18381enum {
18382 NM_SCE = 0x00,
18383 NM_SCWPE = 0x01,
18384};
18385
261c95a0
YK
18386/* P.LS.WM instruction pool */
18387enum {
18388 NM_LWM = 0x00,
18389 NM_SWM = 0x01,
18390};
18391
18392/* P.LS.UAWM instruction pool */
18393enum {
18394 NM_UALWM = 0x00,
18395 NM_UASWM = 0x01,
18396};
18397
18398/* P.BR3A instruction pool */
18399enum {
18400 NM_BC1EQZC = 0x00,
18401 NM_BC1NEZC = 0x01,
18402 NM_BC2EQZC = 0x02,
18403 NM_BC2NEZC = 0x03,
18404 NM_BPOSGE32C = 0x04,
18405};
18406
18407/* P16.RI instruction pool */
18408enum {
18409 NM_P16_SYSCALL = 0x01,
18410 NM_BREAK16 = 0x02,
18411 NM_SDBBP16 = 0x03,
18412};
18413
18414/* POOL16C_0 instruction pool */
18415enum {
18416 NM_POOL16C_00 = 0x00,
18417};
18418
18419/* P16.JRC instruction pool */
18420enum {
18421 NM_JRC = 0x00,
18422 NM_JALRC16 = 0x01,
18423};
18424
18425/* P.SYSCALL instruction pool */
18426enum {
18427 NM_SYSCALL = 0x00,
18428 NM_HYPCALL = 0x01,
18429};
18430
18431/* P.TRAP instruction pool */
18432enum {
18433 NM_TEQ = 0x00,
18434 NM_TNE = 0x01,
18435};
18436
18437/* P.CMOVE instruction pool */
18438enum {
18439 NM_MOVZ = 0x00,
18440 NM_MOVN = 0x01,
18441};
18442
18443/* POOL32Axf instruction pool */
18444enum {
b3979b6f
SM
18445 NM_POOL32AXF_1 = 0x01,
18446 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18447 NM_POOL32AXF_4 = 0x04,
18448 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18449 NM_POOL32AXF_7 = 0x07,
18450};
18451
18452/* POOL32Axf_1 instruction pool */
18453enum {
18454 NM_POOL32AXF_1_0 = 0x00,
18455 NM_POOL32AXF_1_1 = 0x01,
18456 NM_POOL32AXF_1_3 = 0x03,
18457 NM_POOL32AXF_1_4 = 0x04,
18458 NM_POOL32AXF_1_5 = 0x05,
18459 NM_POOL32AXF_1_7 = 0x07,
18460};
18461
18462/* POOL32Axf_2 instruction pool */
18463enum {
18464 NM_POOL32AXF_2_0_7 = 0x00,
18465 NM_POOL32AXF_2_8_15 = 0x01,
18466 NM_POOL32AXF_2_16_23 = 0x02,
18467 NM_POOL32AXF_2_24_31 = 0x03,
18468};
18469
18470/* POOL32Axf_7 instruction pool */
18471enum {
18472 NM_SHRA_R_QB = 0x0,
18473 NM_SHRL_PH = 0x1,
18474 NM_REPL_QB = 0x2,
18475};
18476
18477/* POOL32Axf_1_0 instruction pool */
18478enum {
18479 NM_MFHI = 0x0,
18480 NM_MFLO = 0x1,
18481 NM_MTHI = 0x2,
18482 NM_MTLO = 0x3,
18483};
18484
18485/* POOL32Axf_1_1 instruction pool */
18486enum {
18487 NM_MTHLIP = 0x0,
18488 NM_SHILOV = 0x1,
18489};
18490
18491/* POOL32Axf_1_3 instruction pool */
18492enum {
18493 NM_RDDSP = 0x0,
18494 NM_WRDSP = 0x1,
18495 NM_EXTP = 0x2,
18496 NM_EXTPDP = 0x3,
18497};
18498
18499/* POOL32Axf_1_4 instruction pool */
18500enum {
18501 NM_SHLL_QB = 0x0,
18502 NM_SHRL_QB = 0x1,
18503};
18504
18505/* POOL32Axf_1_5 instruction pool */
18506enum {
18507 NM_MAQ_S_W_PHR = 0x0,
18508 NM_MAQ_S_W_PHL = 0x1,
18509 NM_MAQ_SA_W_PHR = 0x2,
18510 NM_MAQ_SA_W_PHL = 0x3,
18511};
18512
18513/* POOL32Axf_1_7 instruction pool */
18514enum {
18515 NM_EXTR_W = 0x0,
18516 NM_EXTR_R_W = 0x1,
18517 NM_EXTR_RS_W = 0x2,
18518 NM_EXTR_S_H = 0x3,
18519};
18520
18521/* POOL32Axf_2_0_7 instruction pool */
18522enum {
18523 NM_DPA_W_PH = 0x0,
18524 NM_DPAQ_S_W_PH = 0x1,
18525 NM_DPS_W_PH = 0x2,
18526 NM_DPSQ_S_W_PH = 0x3,
18527 NM_BALIGN = 0x4,
18528 NM_MADD = 0x5,
18529 NM_MULT = 0x6,
18530 NM_EXTRV_W = 0x7,
18531};
18532
18533/* POOL32Axf_2_8_15 instruction pool */
18534enum {
18535 NM_DPAX_W_PH = 0x0,
18536 NM_DPAQ_SA_L_W = 0x1,
18537 NM_DPSX_W_PH = 0x2,
18538 NM_DPSQ_SA_L_W = 0x3,
18539 NM_MADDU = 0x5,
18540 NM_MULTU = 0x6,
18541 NM_EXTRV_R_W = 0x7,
18542};
18543
18544/* POOL32Axf_2_16_23 instruction pool */
18545enum {
18546 NM_DPAU_H_QBL = 0x0,
18547 NM_DPAQX_S_W_PH = 0x1,
18548 NM_DPSU_H_QBL = 0x2,
18549 NM_DPSQX_S_W_PH = 0x3,
18550 NM_EXTPV = 0x4,
18551 NM_MSUB = 0x5,
18552 NM_MULSA_W_PH = 0x6,
18553 NM_EXTRV_RS_W = 0x7,
18554};
18555
18556/* POOL32Axf_2_24_31 instruction pool */
18557enum {
18558 NM_DPAU_H_QBR = 0x0,
18559 NM_DPAQX_SA_W_PH = 0x1,
18560 NM_DPSU_H_QBR = 0x2,
18561 NM_DPSQX_SA_W_PH = 0x3,
18562 NM_EXTPDPV = 0x4,
18563 NM_MSUBU = 0x5,
18564 NM_MULSAQ_S_W_PH = 0x6,
18565 NM_EXTRV_S_H = 0x7,
261c95a0
YK
18566};
18567
18568/* POOL32Axf_{4, 5} instruction pool */
18569enum {
18570 NM_CLO = 0x25,
18571 NM_CLZ = 0x2d,
18572
18573 NM_TLBP = 0x01,
18574 NM_TLBR = 0x09,
18575 NM_TLBWI = 0x11,
18576 NM_TLBWR = 0x19,
18577 NM_TLBINV = 0x03,
18578 NM_TLBINVF = 0x0b,
18579 NM_DI = 0x23,
18580 NM_EI = 0x2b,
18581 NM_RDPGPR = 0x70,
18582 NM_WRPGPR = 0x78,
18583 NM_WAIT = 0x61,
18584 NM_DERET = 0x71,
18585 NM_ERETX = 0x79,
b3979b6f
SM
18586
18587 /* nanoMIPS DSP instructions */
18588 NM_ABSQ_S_QB = 0x00,
18589 NM_ABSQ_S_PH = 0x08,
18590 NM_ABSQ_S_W = 0x10,
18591 NM_PRECEQ_W_PHL = 0x28,
18592 NM_PRECEQ_W_PHR = 0x30,
18593 NM_PRECEQU_PH_QBL = 0x38,
18594 NM_PRECEQU_PH_QBR = 0x48,
18595 NM_PRECEU_PH_QBL = 0x58,
18596 NM_PRECEU_PH_QBR = 0x68,
18597 NM_PRECEQU_PH_QBLA = 0x39,
18598 NM_PRECEQU_PH_QBRA = 0x49,
18599 NM_PRECEU_PH_QBLA = 0x59,
18600 NM_PRECEU_PH_QBRA = 0x69,
18601 NM_REPLV_PH = 0x01,
18602 NM_REPLV_QB = 0x09,
18603 NM_BITREV = 0x18,
18604 NM_INSV = 0x20,
18605 NM_RADDU_W_QB = 0x78,
18606
18607 NM_BITSWAP = 0x05,
18608 NM_WSBH = 0x3d,
261c95a0
YK
18609};
18610
18611/* PP.SR instruction pool */
18612enum {
18613 NM_SAVE = 0x00,
18614 NM_RESTORE = 0x02,
18615 NM_RESTORE_JRC = 0x03,
18616};
18617
18618/* P.SR.F instruction pool */
18619enum {
18620 NM_SAVEF = 0x00,
18621 NM_RESTOREF = 0x01,
18622};
18623
18624/* P16.SYSCALL instruction pool */
18625enum {
18626 NM_SYSCALL16 = 0x00,
18627 NM_HYPCALL16 = 0x01,
18628};
18629
18630/* POOL16C_00 instruction pool */
18631enum {
18632 NM_NOT16 = 0x00,
18633 NM_XOR16 = 0x01,
18634 NM_AND16 = 0x02,
18635 NM_OR16 = 0x03,
18636};
18637
18638/* PP.LSX and PP.LSXS instruction pool */
18639enum {
18640 NM_LBX = 0x00,
18641 NM_LHX = 0x04,
18642 NM_LWX = 0x08,
18643 NM_LDX = 0x0c,
18644
18645 NM_SBX = 0x01,
18646 NM_SHX = 0x05,
18647 NM_SWX = 0x09,
18648 NM_SDX = 0x0d,
18649
18650 NM_LBUX = 0x02,
18651 NM_LHUX = 0x06,
18652 NM_LWC1X = 0x0a,
18653 NM_LDC1X = 0x0e,
18654
18655 NM_LWUX = 0x07,
18656 NM_SWC1X = 0x0b,
18657 NM_SDC1X = 0x0f,
18658
18659 NM_LHXS = 0x04,
18660 NM_LWXS = 0x08,
18661 NM_LDXS = 0x0c,
18662
18663 NM_SHXS = 0x05,
18664 NM_SWXS = 0x09,
18665 NM_SDXS = 0x0d,
18666
18667 NM_LHUXS = 0x06,
18668 NM_LWC1XS = 0x0a,
18669 NM_LDC1XS = 0x0e,
18670
18671 NM_LWUXS = 0x07,
18672 NM_SWC1XS = 0x0b,
18673 NM_SDC1XS = 0x0f,
18674};
18675
18676/* ERETx instruction pool */
18677enum {
18678 NM_ERET = 0x00,
18679 NM_ERETNC = 0x01,
18680};
18681
18682/* POOL32FxF_{0, 1} insturction pool */
18683enum {
18684 NM_CFC1 = 0x40,
18685 NM_CTC1 = 0x60,
18686 NM_MFC1 = 0x80,
18687 NM_MTC1 = 0xa0,
18688 NM_MFHC1 = 0xc0,
18689 NM_MTHC1 = 0xe0,
18690
18691 NM_CVT_S_PL = 0x84,
18692 NM_CVT_S_PU = 0xa4,
18693
18694 NM_CVT_L_S = 0x004,
18695 NM_CVT_L_D = 0x104,
18696 NM_CVT_W_S = 0x024,
18697 NM_CVT_W_D = 0x124,
18698
18699 NM_RSQRT_S = 0x008,
18700 NM_RSQRT_D = 0x108,
18701
18702 NM_SQRT_S = 0x028,
18703 NM_SQRT_D = 0x128,
18704
18705 NM_RECIP_S = 0x048,
18706 NM_RECIP_D = 0x148,
18707
18708 NM_FLOOR_L_S = 0x00c,
18709 NM_FLOOR_L_D = 0x10c,
18710
18711 NM_FLOOR_W_S = 0x02c,
18712 NM_FLOOR_W_D = 0x12c,
18713
18714 NM_CEIL_L_S = 0x04c,
18715 NM_CEIL_L_D = 0x14c,
18716 NM_CEIL_W_S = 0x06c,
18717 NM_CEIL_W_D = 0x16c,
18718 NM_TRUNC_L_S = 0x08c,
18719 NM_TRUNC_L_D = 0x18c,
18720 NM_TRUNC_W_S = 0x0ac,
18721 NM_TRUNC_W_D = 0x1ac,
18722 NM_ROUND_L_S = 0x0cc,
18723 NM_ROUND_L_D = 0x1cc,
18724 NM_ROUND_W_S = 0x0ec,
18725 NM_ROUND_W_D = 0x1ec,
18726
18727 NM_MOV_S = 0x01,
18728 NM_MOV_D = 0x81,
18729 NM_ABS_S = 0x0d,
18730 NM_ABS_D = 0x8d,
18731 NM_NEG_S = 0x2d,
18732 NM_NEG_D = 0xad,
18733 NM_CVT_D_S = 0x04d,
18734 NM_CVT_D_W = 0x0cd,
18735 NM_CVT_D_L = 0x14d,
18736 NM_CVT_S_D = 0x06d,
18737 NM_CVT_S_W = 0x0ed,
18738 NM_CVT_S_L = 0x16d,
18739};
18740
18741/* P.LL instruction pool */
18742enum {
18743 NM_LL = 0x00,
18744 NM_LLWP = 0x01,
18745};
18746
18747/* P.SC instruction pool */
18748enum {
18749 NM_SC = 0x00,
18750 NM_SCWP = 0x01,
18751};
18752
18753/* P.DVP instruction pool */
18754enum {
18755 NM_DVP = 0x00,
18756 NM_EVP = 0x01,
18757};
18758
c533c0f4
AM
18759
18760/*
18761 *
18762 * nanoMIPS decoding engine
18763 *
18764 */
18765
6bfa9f4c
AM
18766
18767/* extraction utilities */
18768
99e49abf
AM
18769#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18770#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18771#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
18772#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18773#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18774
ea4ca3c2
YK
18775/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18776static inline int decode_gpr_gpr3(int r)
18777{
18778 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18779
18780 return map[r & 0x7];
18781}
18782
8bdb7029
YK
18783/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18784static inline int decode_gpr_gpr3_src_store(int r)
18785{
18786 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18787
18788 return map[r & 0x7];
18789}
18790
ea4ca3c2
YK
18791/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18792static inline int decode_gpr_gpr4(int r)
18793{
18794 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18795 16, 17, 18, 19, 20, 21, 22, 23 };
18796
18797 return map[r & 0xf];
18798}
18799
8bdb7029
YK
18800/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18801static inline int decode_gpr_gpr4_zero(int r)
18802{
18803 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18804 16, 17, 18, 19, 20, 21, 22, 23 };
18805
18806 return map[r & 0xf];
18807}
18808
6bfa9f4c 18809
bf0718c5
SM
18810static void gen_adjust_sp(DisasContext *ctx, int u)
18811{
18812 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18813}
18814
18815static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18816 uint8_t gp, uint16_t u)
18817{
18818 int counter = 0;
18819 TCGv va = tcg_temp_new();
18820 TCGv t0 = tcg_temp_new();
18821
18822 while (counter != count) {
18823 bool use_gp = gp && (counter == count - 1);
18824 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18825 int this_offset = -((counter + 1) << 2);
18826 gen_base_offset_addr(ctx, va, 29, this_offset);
18827 gen_load_gpr(t0, this_rt);
18828 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18829 (MO_TEUL | ctx->default_tcg_memop_mask));
18830 counter++;
18831 }
18832
18833 /* adjust stack pointer */
18834 gen_adjust_sp(ctx, -u);
18835
18836 tcg_temp_free(t0);
18837 tcg_temp_free(va);
18838}
18839
18840static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18841 uint8_t gp, uint16_t u)
18842{
18843 int counter = 0;
18844 TCGv va = tcg_temp_new();
18845 TCGv t0 = tcg_temp_new();
18846
18847 while (counter != count) {
18848 bool use_gp = gp && (counter == count - 1);
18849 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18850 int this_offset = u - ((counter + 1) << 2);
18851 gen_base_offset_addr(ctx, va, 29, this_offset);
18852 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18853 ctx->default_tcg_memop_mask);
18854 tcg_gen_ext32s_tl(t0, t0);
18855 gen_store_gpr(t0, this_rt);
18856 counter++;
18857 }
18858
18859 /* adjust stack pointer */
18860 gen_adjust_sp(ctx, u);
18861
18862 tcg_temp_free(t0);
18863 tcg_temp_free(va);
18864}
18865
80845edf
YK
18866static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18867{
99e49abf
AM
18868 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18869 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
18870
18871 switch (extract32(ctx->opcode, 2, 2)) {
18872 case NM_NOT16:
18873 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18874 break;
18875 case NM_AND16:
18876 gen_logic(ctx, OPC_AND, rt, rt, rs);
18877 break;
18878 case NM_XOR16:
18879 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18880 break;
18881 case NM_OR16:
18882 gen_logic(ctx, OPC_OR, rt, rt, rs);
18883 break;
18884 }
18885}
18886
0a1a6ed7 18887static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18888{
18889 int rt = extract32(ctx->opcode, 21, 5);
18890 int rs = extract32(ctx->opcode, 16, 5);
18891 int rd = extract32(ctx->opcode, 11, 5);
18892
18893 switch (extract32(ctx->opcode, 3, 7)) {
18894 case NM_P_TRAP:
18895 switch (extract32(ctx->opcode, 10, 1)) {
18896 case NM_TEQ:
fb32f8c8 18897 check_nms(ctx);
e0cf0e65
YK
18898 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18899 break;
18900 case NM_TNE:
fb32f8c8 18901 check_nms(ctx);
e0cf0e65
YK
18902 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18903 break;
18904 }
18905 break;
18906 case NM_RDHWR:
fb32f8c8 18907 check_nms(ctx);
e0cf0e65
YK
18908 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18909 break;
18910 case NM_SEB:
fb32f8c8 18911 check_nms(ctx);
e0cf0e65
YK
18912 gen_bshfl(ctx, OPC_SEB, rs, rt);
18913 break;
18914 case NM_SEH:
18915 gen_bshfl(ctx, OPC_SEH, rs, rt);
18916 break;
18917 case NM_SLLV:
18918 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18919 break;
18920 case NM_SRLV:
18921 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18922 break;
18923 case NM_SRAV:
18924 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18925 break;
18926 case NM_ROTRV:
18927 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18928 break;
18929 case NM_ADD:
18930 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18931 break;
18932 case NM_ADDU:
18933 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18934 break;
18935 case NM_SUB:
fb32f8c8 18936 check_nms(ctx);
e0cf0e65
YK
18937 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18938 break;
18939 case NM_SUBU:
18940 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18941 break;
18942 case NM_P_CMOVE:
18943 switch (extract32(ctx->opcode, 10, 1)) {
18944 case NM_MOVZ:
18945 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18946 break;
18947 case NM_MOVN:
18948 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18949 break;
18950 }
18951 break;
18952 case NM_AND:
18953 gen_logic(ctx, OPC_AND, rd, rs, rt);
18954 break;
18955 case NM_OR:
18956 gen_logic(ctx, OPC_OR, rd, rs, rt);
18957 break;
18958 case NM_NOR:
18959 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18960 break;
18961 case NM_XOR:
18962 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18963 break;
18964 case NM_SLT:
18965 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18966 break;
18967 case NM_P_SLTU:
18968 if (rd == 0) {
18969 /* P_DVP */
18970#ifndef CONFIG_USER_ONLY
18971 TCGv t0 = tcg_temp_new();
18972 switch (extract32(ctx->opcode, 10, 1)) {
18973 case NM_DVP:
18974 if (ctx->vp) {
18975 check_cp0_enabled(ctx);
18976 gen_helper_dvp(t0, cpu_env);
18977 gen_store_gpr(t0, rt);
18978 }
18979 break;
18980 case NM_EVP:
18981 if (ctx->vp) {
18982 check_cp0_enabled(ctx);
18983 gen_helper_evp(t0, cpu_env);
18984 gen_store_gpr(t0, rt);
18985 }
18986 break;
18987 }
18988 tcg_temp_free(t0);
18989#endif
18990 } else {
18991 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18992 }
18993 break;
18994 case NM_SOV:
18995 {
18996 TCGv t0 = tcg_temp_new();
18997 TCGv t1 = tcg_temp_new();
18998 TCGv t2 = tcg_temp_new();
18999
19000 gen_load_gpr(t1, rs);
19001 gen_load_gpr(t2, rt);
19002 tcg_gen_add_tl(t0, t1, t2);
19003 tcg_gen_ext32s_tl(t0, t0);
19004 tcg_gen_xor_tl(t1, t1, t2);
19005 tcg_gen_xor_tl(t2, t0, t2);
19006 tcg_gen_andc_tl(t1, t2, t1);
19007
19008 /* operands of same sign, result different sign */
19009 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19010 gen_store_gpr(t0, rd);
19011
19012 tcg_temp_free(t0);
19013 tcg_temp_free(t1);
19014 tcg_temp_free(t2);
19015 }
19016 break;
19017 case NM_MUL:
19018 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19019 break;
19020 case NM_MUH:
19021 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19022 break;
19023 case NM_MULU:
19024 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19025 break;
19026 case NM_MUHU:
19027 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19028 break;
19029 case NM_DIV:
19030 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19031 break;
19032 case NM_MOD:
19033 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19034 break;
19035 case NM_DIVU:
19036 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19037 break;
19038 case NM_MODU:
19039 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19040 break;
19041#ifndef CONFIG_USER_ONLY
19042 case NM_MFC0:
19043 check_cp0_enabled(ctx);
19044 if (rt == 0) {
19045 /* Treat as NOP. */
19046 break;
19047 }
19048 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19049 break;
19050 case NM_MTC0:
19051 check_cp0_enabled(ctx);
19052 {
19053 TCGv t0 = tcg_temp_new();
19054
19055 gen_load_gpr(t0, rt);
19056 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19057 tcg_temp_free(t0);
19058 }
19059 break;
0a1a6ed7
SM
19060 case NM_D_E_MT_VPE:
19061 {
19062 uint8_t sc = extract32(ctx->opcode, 10, 1);
19063 TCGv t0 = tcg_temp_new();
19064
19065 switch (sc) {
19066 case 0:
19067 if (rs == 1) {
19068 /* DMT */
19069 check_cp0_mt(ctx);
19070 gen_helper_dmt(t0);
19071 gen_store_gpr(t0, rt);
19072 } else if (rs == 0) {
19073 /* DVPE */
19074 check_cp0_mt(ctx);
19075 gen_helper_dvpe(t0, cpu_env);
19076 gen_store_gpr(t0, rt);
19077 } else {
19078 generate_exception_end(ctx, EXCP_RI);
19079 }
19080 break;
19081 case 1:
19082 if (rs == 1) {
19083 /* EMT */
19084 check_cp0_mt(ctx);
19085 gen_helper_emt(t0);
19086 gen_store_gpr(t0, rt);
19087 } else if (rs == 0) {
19088 /* EVPE */
19089 check_cp0_mt(ctx);
19090 gen_helper_evpe(t0, cpu_env);
19091 gen_store_gpr(t0, rt);
19092 } else {
19093 generate_exception_end(ctx, EXCP_RI);
19094 }
19095 break;
19096 }
19097
19098 tcg_temp_free(t0);
19099 }
19100 break;
19101 case NM_FORK:
19102 check_mt(ctx);
19103 {
19104 TCGv t0 = tcg_temp_new();
19105 TCGv t1 = tcg_temp_new();
19106
19107 gen_load_gpr(t0, rt);
19108 gen_load_gpr(t1, rs);
19109 gen_helper_fork(t0, t1);
19110 tcg_temp_free(t0);
19111 tcg_temp_free(t1);
19112 }
19113 break;
19114 case NM_MFTR:
19115 case NM_MFHTR:
19116 check_cp0_enabled(ctx);
19117 if (rd == 0) {
19118 /* Treat as NOP. */
19119 return;
19120 }
19121 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19122 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19123 break;
19124 case NM_MTTR:
19125 case NM_MTHTR:
19126 check_cp0_enabled(ctx);
19127 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19128 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19129 break;
19130 case NM_YIELD:
19131 check_mt(ctx);
19132 {
19133 TCGv t0 = tcg_temp_new();
19134
19135 gen_load_gpr(t0, rs);
19136 gen_helper_yield(t0, cpu_env, t0);
19137 gen_store_gpr(t0, rt);
19138 tcg_temp_free(t0);
19139 }
19140 break;
e0cf0e65
YK
19141#endif
19142 default:
19143 generate_exception_end(ctx, EXCP_RI);
19144 break;
19145 }
19146}
19147
2ed42efa
SM
19148/* dsp */
19149static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19150 int ret, int v1, int v2)
19151{
19152 TCGv_i32 t0;
19153 TCGv v0_t;
19154 TCGv v1_t;
19155
19156 t0 = tcg_temp_new_i32();
19157
19158 v0_t = tcg_temp_new();
19159 v1_t = tcg_temp_new();
19160
19161 tcg_gen_movi_i32(t0, v2 >> 3);
19162
19163 gen_load_gpr(v0_t, ret);
19164 gen_load_gpr(v1_t, v1);
19165
19166 switch (opc) {
19167 case NM_MAQ_S_W_PHR:
19168 check_dsp(ctx);
19169 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19170 break;
19171 case NM_MAQ_S_W_PHL:
19172 check_dsp(ctx);
19173 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19174 break;
19175 case NM_MAQ_SA_W_PHR:
19176 check_dsp(ctx);
19177 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19178 break;
19179 case NM_MAQ_SA_W_PHL:
19180 check_dsp(ctx);
19181 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19182 break;
19183 default:
19184 generate_exception_end(ctx, EXCP_RI);
19185 break;
19186 }
19187
19188 tcg_temp_free_i32(t0);
19189
19190 tcg_temp_free(v0_t);
19191 tcg_temp_free(v1_t);
19192}
19193
19194
19195static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19196 int ret, int v1, int v2)
19197{
19198 int16_t imm;
19199 TCGv t0 = tcg_temp_new();
19200 TCGv t1 = tcg_temp_new();
19201 TCGv v0_t = tcg_temp_new();
19202
19203 gen_load_gpr(v0_t, v1);
19204
19205 switch (opc) {
19206 case NM_POOL32AXF_1_0:
19207 check_dsp(ctx);
19208 switch (extract32(ctx->opcode, 12, 2)) {
19209 case NM_MFHI:
19210 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19211 break;
19212 case NM_MFLO:
19213 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19214 break;
19215 case NM_MTHI:
19216 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19217 break;
19218 case NM_MTLO:
19219 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19220 break;
19221 }
19222 break;
19223 case NM_POOL32AXF_1_1:
19224 check_dsp(ctx);
19225 switch (extract32(ctx->opcode, 12, 2)) {
19226 case NM_MTHLIP:
19227 tcg_gen_movi_tl(t0, v2);
19228 gen_helper_mthlip(t0, v0_t, cpu_env);
19229 break;
19230 case NM_SHILOV:
19231 tcg_gen_movi_tl(t0, v2 >> 3);
19232 gen_helper_shilo(t0, v0_t, cpu_env);
19233 break;
19234 default:
19235 generate_exception_end(ctx, EXCP_RI);
19236 break;
19237 }
19238 break;
19239 case NM_POOL32AXF_1_3:
19240 check_dsp(ctx);
19241 imm = extract32(ctx->opcode, 14, 7);
19242 switch (extract32(ctx->opcode, 12, 2)) {
19243 case NM_RDDSP:
19244 tcg_gen_movi_tl(t0, imm);
19245 gen_helper_rddsp(t0, t0, cpu_env);
19246 gen_store_gpr(t0, ret);
19247 break;
19248 case NM_WRDSP:
19249 gen_load_gpr(t0, ret);
19250 tcg_gen_movi_tl(t1, imm);
19251 gen_helper_wrdsp(t0, t1, cpu_env);
19252 break;
19253 case NM_EXTP:
19254 tcg_gen_movi_tl(t0, v2 >> 3);
19255 tcg_gen_movi_tl(t1, v1);
19256 gen_helper_extp(t0, t0, t1, cpu_env);
19257 gen_store_gpr(t0, ret);
19258 break;
19259 case NM_EXTPDP:
19260 tcg_gen_movi_tl(t0, v2 >> 3);
19261 tcg_gen_movi_tl(t1, v1);
19262 gen_helper_extpdp(t0, t0, t1, cpu_env);
19263 gen_store_gpr(t0, ret);
19264 break;
19265 }
19266 break;
19267 case NM_POOL32AXF_1_4:
19268 check_dsp(ctx);
19269 tcg_gen_movi_tl(t0, v2 >> 2);
19270 switch (extract32(ctx->opcode, 12, 1)) {
19271 case NM_SHLL_QB:
19272 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19273 gen_store_gpr(t0, ret);
19274 break;
19275 case NM_SHRL_QB:
19276 gen_helper_shrl_qb(t0, t0, v0_t);
19277 gen_store_gpr(t0, ret);
19278 break;
19279 }
19280 break;
19281 case NM_POOL32AXF_1_5:
19282 opc = extract32(ctx->opcode, 12, 2);
19283 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19284 break;
19285 case NM_POOL32AXF_1_7:
19286 check_dsp(ctx);
19287 tcg_gen_movi_tl(t0, v2 >> 3);
19288 tcg_gen_movi_tl(t1, v1);
19289 switch (extract32(ctx->opcode, 12, 2)) {
19290 case NM_EXTR_W:
19291 gen_helper_extr_w(t0, t0, t1, cpu_env);
19292 gen_store_gpr(t0, ret);
19293 break;
19294 case NM_EXTR_R_W:
19295 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19296 gen_store_gpr(t0, ret);
19297 break;
19298 case NM_EXTR_RS_W:
19299 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19300 gen_store_gpr(t0, ret);
19301 break;
19302 case NM_EXTR_S_H:
19303 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19304 gen_store_gpr(t0, ret);
19305 break;
19306 }
19307 break;
19308 default:
19309 generate_exception_end(ctx, EXCP_RI);
19310 break;
19311 }
19312
19313 tcg_temp_free(t0);
19314 tcg_temp_free(t1);
19315 tcg_temp_free(v0_t);
19316}
19317
8b3698b2
SM
19318static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19319 TCGv v0, TCGv v1, int rd)
19320{
19321 TCGv_i32 t0;
19322
19323 t0 = tcg_temp_new_i32();
19324
19325 tcg_gen_movi_i32(t0, rd >> 3);
19326
19327 switch (opc) {
19328 case NM_POOL32AXF_2_0_7:
19329 switch (extract32(ctx->opcode, 9, 3)) {
19330 case NM_DPA_W_PH:
908f6be1 19331 check_dsp_r2(ctx);
8b3698b2
SM
19332 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19333 break;
19334 case NM_DPAQ_S_W_PH:
19335 check_dsp(ctx);
19336 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19337 break;
19338 case NM_DPS_W_PH:
908f6be1 19339 check_dsp_r2(ctx);
8b3698b2
SM
19340 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19341 break;
19342 case NM_DPSQ_S_W_PH:
19343 check_dsp(ctx);
19344 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19345 break;
19346 default:
19347 generate_exception_end(ctx, EXCP_RI);
19348 break;
19349 }
19350 break;
19351 case NM_POOL32AXF_2_8_15:
19352 switch (extract32(ctx->opcode, 9, 3)) {
19353 case NM_DPAX_W_PH:
908f6be1 19354 check_dsp_r2(ctx);
8b3698b2
SM
19355 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19356 break;
19357 case NM_DPAQ_SA_L_W:
19358 check_dsp(ctx);
19359 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19360 break;
19361 case NM_DPSX_W_PH:
908f6be1 19362 check_dsp_r2(ctx);
8b3698b2
SM
19363 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19364 break;
19365 case NM_DPSQ_SA_L_W:
19366 check_dsp(ctx);
19367 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19368 break;
19369 default:
19370 generate_exception_end(ctx, EXCP_RI);
19371 break;
19372 }
19373 break;
19374 case NM_POOL32AXF_2_16_23:
19375 switch (extract32(ctx->opcode, 9, 3)) {
19376 case NM_DPAU_H_QBL:
19377 check_dsp(ctx);
19378 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19379 break;
19380 case NM_DPAQX_S_W_PH:
908f6be1 19381 check_dsp_r2(ctx);
8b3698b2
SM
19382 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19383 break;
19384 case NM_DPSU_H_QBL:
19385 check_dsp(ctx);
19386 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19387 break;
19388 case NM_DPSQX_S_W_PH:
908f6be1 19389 check_dsp_r2(ctx);
8b3698b2
SM
19390 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19391 break;
19392 case NM_MULSA_W_PH:
908f6be1 19393 check_dsp_r2(ctx);
8b3698b2
SM
19394 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19395 break;
19396 default:
19397 generate_exception_end(ctx, EXCP_RI);
19398 break;
19399 }
19400 break;
19401 case NM_POOL32AXF_2_24_31:
19402 switch (extract32(ctx->opcode, 9, 3)) {
19403 case NM_DPAU_H_QBR:
19404 check_dsp(ctx);
19405 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19406 break;
19407 case NM_DPAQX_SA_W_PH:
908f6be1 19408 check_dsp_r2(ctx);
8b3698b2
SM
19409 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19410 break;
19411 case NM_DPSU_H_QBR:
19412 check_dsp(ctx);
19413 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19414 break;
19415 case NM_DPSQX_SA_W_PH:
908f6be1 19416 check_dsp_r2(ctx);
8b3698b2
SM
19417 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19418 break;
19419 case NM_MULSAQ_S_W_PH:
19420 check_dsp(ctx);
19421 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19422 break;
19423 default:
19424 generate_exception_end(ctx, EXCP_RI);
19425 break;
19426 }
19427 break;
19428 default:
19429 generate_exception_end(ctx, EXCP_RI);
19430 break;
19431 }
19432
19433 tcg_temp_free_i32(t0);
19434}
19435
19436static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19437 int rt, int rs, int rd)
19438{
19439 int ret = rt;
19440 TCGv t0 = tcg_temp_new();
19441 TCGv t1 = tcg_temp_new();
19442 TCGv v0_t = tcg_temp_new();
19443 TCGv v1_t = tcg_temp_new();
19444
19445 gen_load_gpr(v0_t, rt);
19446 gen_load_gpr(v1_t, rs);
19447
19448 switch (opc) {
19449 case NM_POOL32AXF_2_0_7:
19450 switch (extract32(ctx->opcode, 9, 3)) {
19451 case NM_DPA_W_PH:
19452 case NM_DPAQ_S_W_PH:
19453 case NM_DPS_W_PH:
19454 case NM_DPSQ_S_W_PH:
19455 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19456 break;
19457 case NM_BALIGN:
908f6be1 19458 check_dsp_r2(ctx);
8b3698b2
SM
19459 if (rt != 0) {
19460 gen_load_gpr(t0, rs);
19461 rd &= 3;
19462 if (rd != 0 && rd != 2) {
19463 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19464 tcg_gen_ext32u_tl(t0, t0);
19465 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19466 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19467 }
19468 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19469 }
19470 break;
19471 case NM_MADD:
19472 check_dsp(ctx);
19473 {
19474 int acc = extract32(ctx->opcode, 14, 2);
19475 TCGv_i64 t2 = tcg_temp_new_i64();
19476 TCGv_i64 t3 = tcg_temp_new_i64();
19477
19478 gen_load_gpr(t0, rt);
19479 gen_load_gpr(t1, rs);
19480 tcg_gen_ext_tl_i64(t2, t0);
19481 tcg_gen_ext_tl_i64(t3, t1);
19482 tcg_gen_mul_i64(t2, t2, t3);
19483 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19484 tcg_gen_add_i64(t2, t2, t3);
19485 tcg_temp_free_i64(t3);
19486 gen_move_low32(cpu_LO[acc], t2);
19487 gen_move_high32(cpu_HI[acc], t2);
19488 tcg_temp_free_i64(t2);
19489 }
19490 break;
19491 case NM_MULT:
19492 check_dsp(ctx);
19493 {
19494 int acc = extract32(ctx->opcode, 14, 2);
19495 TCGv_i32 t2 = tcg_temp_new_i32();
19496 TCGv_i32 t3 = tcg_temp_new_i32();
19497
19498 gen_load_gpr(t0, rs);
19499 gen_load_gpr(t1, rt);
19500 tcg_gen_trunc_tl_i32(t2, t0);
19501 tcg_gen_trunc_tl_i32(t3, t1);
19502 tcg_gen_muls2_i32(t2, t3, t2, t3);
19503 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19504 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19505 tcg_temp_free_i32(t2);
19506 tcg_temp_free_i32(t3);
19507 }
19508 break;
19509 case NM_EXTRV_W:
19510 check_dsp(ctx);
19511 gen_load_gpr(v1_t, rs);
19512 tcg_gen_movi_tl(t0, rd >> 3);
19513 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19514 gen_store_gpr(t0, ret);
19515 break;
19516 }
19517 break;
19518 case NM_POOL32AXF_2_8_15:
19519 switch (extract32(ctx->opcode, 9, 3)) {
19520 case NM_DPAX_W_PH:
19521 case NM_DPAQ_SA_L_W:
19522 case NM_DPSX_W_PH:
19523 case NM_DPSQ_SA_L_W:
19524 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19525 break;
19526 case NM_MADDU:
19527 check_dsp(ctx);
19528 {
19529 int acc = extract32(ctx->opcode, 14, 2);
19530 TCGv_i64 t2 = tcg_temp_new_i64();
19531 TCGv_i64 t3 = tcg_temp_new_i64();
19532
19533 gen_load_gpr(t0, rs);
19534 gen_load_gpr(t1, rt);
19535 tcg_gen_ext32u_tl(t0, t0);
19536 tcg_gen_ext32u_tl(t1, t1);
19537 tcg_gen_extu_tl_i64(t2, t0);
19538 tcg_gen_extu_tl_i64(t3, t1);
19539 tcg_gen_mul_i64(t2, t2, t3);
19540 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19541 tcg_gen_add_i64(t2, t2, t3);
19542 tcg_temp_free_i64(t3);
19543 gen_move_low32(cpu_LO[acc], t2);
19544 gen_move_high32(cpu_HI[acc], t2);
19545 tcg_temp_free_i64(t2);
19546 }
19547 break;
19548 case NM_MULTU:
19549 check_dsp(ctx);
19550 {
19551 int acc = extract32(ctx->opcode, 14, 2);
19552 TCGv_i32 t2 = tcg_temp_new_i32();
19553 TCGv_i32 t3 = tcg_temp_new_i32();
19554
19555 gen_load_gpr(t0, rs);
19556 gen_load_gpr(t1, rt);
19557 tcg_gen_trunc_tl_i32(t2, t0);
19558 tcg_gen_trunc_tl_i32(t3, t1);
19559 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19560 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19561 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19562 tcg_temp_free_i32(t2);
19563 tcg_temp_free_i32(t3);
19564 }
19565 break;
19566 case NM_EXTRV_R_W:
19567 check_dsp(ctx);
19568 tcg_gen_movi_tl(t0, rd >> 3);
19569 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19570 gen_store_gpr(t0, ret);
19571 break;
19572 default:
19573 generate_exception_end(ctx, EXCP_RI);
19574 break;
19575 }
19576 break;
19577 case NM_POOL32AXF_2_16_23:
19578 switch (extract32(ctx->opcode, 9, 3)) {
19579 case NM_DPAU_H_QBL:
19580 case NM_DPAQX_S_W_PH:
19581 case NM_DPSU_H_QBL:
19582 case NM_DPSQX_S_W_PH:
19583 case NM_MULSA_W_PH:
19584 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19585 break;
19586 case NM_EXTPV:
19587 check_dsp(ctx);
19588 tcg_gen_movi_tl(t0, rd >> 3);
19589 gen_helper_extp(t0, t0, v1_t, cpu_env);
19590 gen_store_gpr(t0, ret);
19591 break;
19592 case NM_MSUB:
19593 check_dsp(ctx);
19594 {
19595 int acc = extract32(ctx->opcode, 14, 2);
19596 TCGv_i64 t2 = tcg_temp_new_i64();
19597 TCGv_i64 t3 = tcg_temp_new_i64();
19598
19599 gen_load_gpr(t0, rs);
19600 gen_load_gpr(t1, rt);
19601 tcg_gen_ext_tl_i64(t2, t0);
19602 tcg_gen_ext_tl_i64(t3, t1);
19603 tcg_gen_mul_i64(t2, t2, t3);
19604 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19605 tcg_gen_sub_i64(t2, t3, t2);
19606 tcg_temp_free_i64(t3);
19607 gen_move_low32(cpu_LO[acc], t2);
19608 gen_move_high32(cpu_HI[acc], t2);
19609 tcg_temp_free_i64(t2);
19610 }
19611 break;
19612 case NM_EXTRV_RS_W:
19613 check_dsp(ctx);
19614 tcg_gen_movi_tl(t0, rd >> 3);
19615 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19616 gen_store_gpr(t0, ret);
19617 break;
19618 }
19619 break;
19620 case NM_POOL32AXF_2_24_31:
19621 switch (extract32(ctx->opcode, 9, 3)) {
19622 case NM_DPAU_H_QBR:
19623 case NM_DPAQX_SA_W_PH:
19624 case NM_DPSU_H_QBR:
19625 case NM_DPSQX_SA_W_PH:
19626 case NM_MULSAQ_S_W_PH:
19627 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19628 break;
19629 case NM_EXTPDPV:
19630 check_dsp(ctx);
19631 tcg_gen_movi_tl(t0, rd >> 3);
19632 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19633 gen_store_gpr(t0, ret);
19634 break;
19635 case NM_MSUBU:
19636 check_dsp(ctx);
19637 {
19638 int acc = extract32(ctx->opcode, 14, 2);
19639 TCGv_i64 t2 = tcg_temp_new_i64();
19640 TCGv_i64 t3 = tcg_temp_new_i64();
19641
19642 gen_load_gpr(t0, rs);
19643 gen_load_gpr(t1, rt);
19644 tcg_gen_ext32u_tl(t0, t0);
19645 tcg_gen_ext32u_tl(t1, t1);
19646 tcg_gen_extu_tl_i64(t2, t0);
19647 tcg_gen_extu_tl_i64(t3, t1);
19648 tcg_gen_mul_i64(t2, t2, t3);
19649 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19650 tcg_gen_sub_i64(t2, t3, t2);
19651 tcg_temp_free_i64(t3);
19652 gen_move_low32(cpu_LO[acc], t2);
19653 gen_move_high32(cpu_HI[acc], t2);
19654 tcg_temp_free_i64(t2);
19655 }
19656 break;
19657 case NM_EXTRV_S_H:
19658 check_dsp(ctx);
19659 tcg_gen_movi_tl(t0, rd >> 3);
19660 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19661 gen_store_gpr(t0, ret);
19662 break;
19663 }
19664 break;
19665 default:
19666 generate_exception_end(ctx, EXCP_RI);
19667 break;
19668 }
19669
19670 tcg_temp_free(t0);
19671 tcg_temp_free(t1);
19672
19673 tcg_temp_free(v0_t);
19674 tcg_temp_free(v1_t);
19675}
19676
4c75c985
SM
19677static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19678 int rt, int rs)
19679{
19680 int ret = rt;
19681 TCGv t0 = tcg_temp_new();
19682 TCGv v0_t = tcg_temp_new();
19683
19684 gen_load_gpr(v0_t, rs);
19685
19686 switch (opc) {
19687 case NM_ABSQ_S_QB:
908f6be1 19688 check_dsp_r2(ctx);
4c75c985
SM
19689 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19690 gen_store_gpr(v0_t, ret);
19691 break;
19692 case NM_ABSQ_S_PH:
19693 check_dsp(ctx);
19694 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19695 gen_store_gpr(v0_t, ret);
19696 break;
19697 case NM_ABSQ_S_W:
19698 check_dsp(ctx);
19699 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19700 gen_store_gpr(v0_t, ret);
19701 break;
19702 case NM_PRECEQ_W_PHL:
19703 check_dsp(ctx);
19704 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19705 tcg_gen_ext32s_tl(v0_t, v0_t);
19706 gen_store_gpr(v0_t, ret);
19707 break;
19708 case NM_PRECEQ_W_PHR:
19709 check_dsp(ctx);
19710 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19711 tcg_gen_shli_tl(v0_t, v0_t, 16);
19712 tcg_gen_ext32s_tl(v0_t, v0_t);
19713 gen_store_gpr(v0_t, ret);
19714 break;
19715 case NM_PRECEQU_PH_QBL:
19716 check_dsp(ctx);
19717 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19718 gen_store_gpr(v0_t, ret);
19719 break;
19720 case NM_PRECEQU_PH_QBR:
19721 check_dsp(ctx);
19722 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19723 gen_store_gpr(v0_t, ret);
19724 break;
19725 case NM_PRECEQU_PH_QBLA:
19726 check_dsp(ctx);
19727 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19728 gen_store_gpr(v0_t, ret);
19729 break;
19730 case NM_PRECEQU_PH_QBRA:
19731 check_dsp(ctx);
19732 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19733 gen_store_gpr(v0_t, ret);
19734 break;
19735 case NM_PRECEU_PH_QBL:
19736 check_dsp(ctx);
19737 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19738 gen_store_gpr(v0_t, ret);
19739 break;
19740 case NM_PRECEU_PH_QBR:
19741 check_dsp(ctx);
19742 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19743 gen_store_gpr(v0_t, ret);
19744 break;
19745 case NM_PRECEU_PH_QBLA:
19746 check_dsp(ctx);
19747 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19748 gen_store_gpr(v0_t, ret);
19749 break;
19750 case NM_PRECEU_PH_QBRA:
19751 check_dsp(ctx);
19752 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19753 gen_store_gpr(v0_t, ret);
19754 break;
19755 case NM_REPLV_PH:
19756 check_dsp(ctx);
19757 tcg_gen_ext16u_tl(v0_t, v0_t);
19758 tcg_gen_shli_tl(t0, v0_t, 16);
19759 tcg_gen_or_tl(v0_t, v0_t, t0);
19760 tcg_gen_ext32s_tl(v0_t, v0_t);
19761 gen_store_gpr(v0_t, ret);
19762 break;
19763 case NM_REPLV_QB:
19764 check_dsp(ctx);
19765 tcg_gen_ext8u_tl(v0_t, v0_t);
19766 tcg_gen_shli_tl(t0, v0_t, 8);
19767 tcg_gen_or_tl(v0_t, v0_t, t0);
19768 tcg_gen_shli_tl(t0, v0_t, 16);
19769 tcg_gen_or_tl(v0_t, v0_t, t0);
19770 tcg_gen_ext32s_tl(v0_t, v0_t);
19771 gen_store_gpr(v0_t, ret);
19772 break;
19773 case NM_BITREV:
19774 check_dsp(ctx);
19775 gen_helper_bitrev(v0_t, v0_t);
19776 gen_store_gpr(v0_t, ret);
19777 break;
19778 case NM_INSV:
19779 check_dsp(ctx);
19780 {
19781 TCGv tv0 = tcg_temp_new();
19782
19783 gen_load_gpr(tv0, rt);
19784 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19785 gen_store_gpr(v0_t, ret);
19786 tcg_temp_free(tv0);
19787 }
19788 break;
19789 case NM_RADDU_W_QB:
19790 check_dsp(ctx);
19791 gen_helper_raddu_w_qb(v0_t, v0_t);
19792 gen_store_gpr(v0_t, ret);
19793 break;
19794 case NM_BITSWAP:
19795 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19796 break;
19797 case NM_CLO:
fb32f8c8 19798 check_nms(ctx);
4c75c985
SM
19799 gen_cl(ctx, OPC_CLO, ret, rs);
19800 break;
19801 case NM_CLZ:
fb32f8c8 19802 check_nms(ctx);
4c75c985
SM
19803 gen_cl(ctx, OPC_CLZ, ret, rs);
19804 break;
19805 case NM_WSBH:
19806 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19807 break;
19808 default:
19809 generate_exception_end(ctx, EXCP_RI);
19810 break;
19811 }
19812
19813 tcg_temp_free(v0_t);
19814 tcg_temp_free(t0);
19815}
19816
0b591184
SM
19817static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19818 int rt, int rs, int rd)
19819{
19820 TCGv t0 = tcg_temp_new();
19821 TCGv rs_t = tcg_temp_new();
19822
19823 gen_load_gpr(rs_t, rs);
19824
19825 switch (opc) {
19826 case NM_SHRA_R_QB:
908f6be1 19827 check_dsp_r2(ctx);
0b591184
SM
19828 tcg_gen_movi_tl(t0, rd >> 2);
19829 switch (extract32(ctx->opcode, 12, 1)) {
19830 case 0:
19831 /* NM_SHRA_QB */
19832 gen_helper_shra_qb(t0, t0, rs_t);
19833 gen_store_gpr(t0, rt);
19834 break;
19835 case 1:
19836 /* NM_SHRA_R_QB */
19837 gen_helper_shra_r_qb(t0, t0, rs_t);
19838 gen_store_gpr(t0, rt);
19839 break;
19840 }
19841 break;
19842 case NM_SHRL_PH:
908f6be1 19843 check_dsp_r2(ctx);
0b591184
SM
19844 tcg_gen_movi_tl(t0, rd >> 1);
19845 gen_helper_shrl_ph(t0, t0, rs_t);
19846 gen_store_gpr(t0, rt);
19847 break;
19848 case NM_REPL_QB:
19849 check_dsp(ctx);
19850 {
19851 int16_t imm;
19852 target_long result;
19853 imm = extract32(ctx->opcode, 13, 8);
19854 result = (uint32_t)imm << 24 |
19855 (uint32_t)imm << 16 |
19856 (uint32_t)imm << 8 |
19857 (uint32_t)imm;
19858 result = (int32_t)result;
19859 tcg_gen_movi_tl(t0, result);
19860 gen_store_gpr(t0, rt);
19861 }
19862 break;
19863 default:
19864 generate_exception_end(ctx, EXCP_RI);
19865 break;
19866 }
19867 tcg_temp_free(t0);
19868 tcg_temp_free(rs_t);
19869}
19870
2ed42efa 19871
64224187
YK
19872static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19873{
64224187
YK
19874 int rt = extract32(ctx->opcode, 21, 5);
19875 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19876 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19877
19878 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19879 case NM_POOL32AXF_1:
19880 {
19881 int32_t op1 = extract32(ctx->opcode, 9, 3);
19882 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19883 }
19884 break;
19885 case NM_POOL32AXF_2:
8b3698b2
SM
19886 {
19887 int32_t op1 = extract32(ctx->opcode, 12, 2);
19888 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19889 }
2ed42efa 19890 break;
64224187 19891 case NM_POOL32AXF_4:
4c75c985
SM
19892 {
19893 int32_t op1 = extract32(ctx->opcode, 9, 7);
19894 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19895 }
2ed42efa 19896 break;
64224187
YK
19897 case NM_POOL32AXF_5:
19898 switch (extract32(ctx->opcode, 9, 7)) {
19899#ifndef CONFIG_USER_ONLY
19900 case NM_TLBP:
19901 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19902 break;
19903 case NM_TLBR:
19904 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19905 break;
19906 case NM_TLBWI:
19907 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19908 break;
19909 case NM_TLBWR:
19910 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19911 break;
19912 case NM_TLBINV:
19913 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19914 break;
19915 case NM_TLBINVF:
19916 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19917 break;
19918 case NM_DI:
19919 check_cp0_enabled(ctx);
19920 {
19921 TCGv t0 = tcg_temp_new();
19922
19923 save_cpu_state(ctx, 1);
19924 gen_helper_di(t0, cpu_env);
19925 gen_store_gpr(t0, rt);
19926 /* Stop translation as we may have switched the execution mode */
19927 ctx->base.is_jmp = DISAS_STOP;
19928 tcg_temp_free(t0);
19929 }
19930 break;
19931 case NM_EI:
19932 check_cp0_enabled(ctx);
19933 {
19934 TCGv t0 = tcg_temp_new();
19935
19936 save_cpu_state(ctx, 1);
19937 gen_helper_ei(t0, cpu_env);
19938 gen_store_gpr(t0, rt);
19939 /* Stop translation as we may have switched the execution mode */
19940 ctx->base.is_jmp = DISAS_STOP;
19941 tcg_temp_free(t0);
19942 }
19943 break;
19944 case NM_RDPGPR:
19945 gen_load_srsgpr(rs, rt);
19946 break;
19947 case NM_WRPGPR:
19948 gen_store_srsgpr(rs, rt);
19949 break;
19950 case NM_WAIT:
19951 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19952 break;
19953 case NM_DERET:
19954 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19955 break;
19956 case NM_ERETX:
19957 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19958 break;
19959#endif
19960 default:
19961 generate_exception_end(ctx, EXCP_RI);
19962 break;
19963 }
19964 break;
2ed42efa 19965 case NM_POOL32AXF_7:
0b591184
SM
19966 {
19967 int32_t op1 = extract32(ctx->opcode, 9, 3);
19968 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19969 }
2ed42efa 19970 break;
64224187
YK
19971 default:
19972 generate_exception_end(ctx, EXCP_RI);
19973 break;
19974 }
19975}
19976
11d0fc10
SM
19977/* Immediate Value Compact Branches */
19978static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19979 int rt, int32_t imm, int32_t offset)
19980{
19981 TCGCond cond;
19982 int bcond_compute = 0;
19983 TCGv t0 = tcg_temp_new();
19984 TCGv t1 = tcg_temp_new();
19985
19986 gen_load_gpr(t0, rt);
19987 tcg_gen_movi_tl(t1, imm);
19988 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19989
19990 /* Load needed operands and calculate btarget */
19991 switch (opc) {
19992 case NM_BEQIC:
19993 if (rt == 0 && imm == 0) {
19994 /* Unconditional branch */
19995 } else if (rt == 0 && imm != 0) {
19996 /* Treat as NOP */
19997 goto out;
19998 } else {
19999 bcond_compute = 1;
20000 cond = TCG_COND_EQ;
20001 }
20002 break;
20003 case NM_BBEQZC:
20004 case NM_BBNEZC:
fb32f8c8 20005 check_nms(ctx);
11d0fc10
SM
20006 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20007 generate_exception_end(ctx, EXCP_RI);
20008 goto out;
20009 } else if (rt == 0 && opc == NM_BBEQZC) {
20010 /* Unconditional branch */
20011 } else if (rt == 0 && opc == NM_BBNEZC) {
20012 /* Treat as NOP */
20013 goto out;
20014 } else {
20015 tcg_gen_shri_tl(t0, t0, imm);
20016 tcg_gen_andi_tl(t0, t0, 1);
20017 tcg_gen_movi_tl(t1, 0);
20018 bcond_compute = 1;
20019 if (opc == NM_BBEQZC) {
20020 cond = TCG_COND_EQ;
20021 } else {
20022 cond = TCG_COND_NE;
20023 }
20024 }
20025 break;
20026 case NM_BNEIC:
20027 if (rt == 0 && imm == 0) {
20028 /* Treat as NOP */
20029 goto out;
20030 } else if (rt == 0 && imm != 0) {
20031 /* Unconditional branch */
20032 } else {
20033 bcond_compute = 1;
20034 cond = TCG_COND_NE;
20035 }
20036 break;
20037 case NM_BGEIC:
20038 if (rt == 0 && imm == 0) {
20039 /* Unconditional branch */
20040 } else {
20041 bcond_compute = 1;
20042 cond = TCG_COND_GE;
20043 }
20044 break;
20045 case NM_BLTIC:
20046 bcond_compute = 1;
20047 cond = TCG_COND_LT;
20048 break;
20049 case NM_BGEIUC:
20050 if (rt == 0 && imm == 0) {
20051 /* Unconditional branch */
20052 } else {
20053 bcond_compute = 1;
20054 cond = TCG_COND_GEU;
20055 }
20056 break;
20057 case NM_BLTIUC:
20058 bcond_compute = 1;
20059 cond = TCG_COND_LTU;
20060 break;
20061 default:
20062 MIPS_INVAL("Immediate Value Compact branch");
20063 generate_exception_end(ctx, EXCP_RI);
20064 goto out;
20065 }
20066
697b7b6b
SM
20067 /* branch completion */
20068 clear_branch_hflags(ctx);
20069 ctx->base.is_jmp = DISAS_NORETURN;
20070
11d0fc10
SM
20071 if (bcond_compute == 0) {
20072 /* Uncoditional compact branch */
20073 gen_goto_tb(ctx, 0, ctx->btarget);
20074 } else {
20075 /* Conditional compact branch */
20076 TCGLabel *fs = gen_new_label();
20077
20078 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20079
20080 gen_goto_tb(ctx, 1, ctx->btarget);
20081 gen_set_label(fs);
20082
20083 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20084 }
20085
20086out:
20087 tcg_temp_free(t0);
20088 tcg_temp_free(t1);
20089}
20090
20091/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20092static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20093 int rt)
20094{
20095 TCGv t0 = tcg_temp_new();
20096 TCGv t1 = tcg_temp_new();
20097
20098 /* load rs */
20099 gen_load_gpr(t0, rs);
20100
20101 /* link */
20102 if (rt != 0) {
20103 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20104 }
20105
20106 /* calculate btarget */
20107 tcg_gen_shli_tl(t0, t0, 1);
20108 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20109 gen_op_addr_add(ctx, btarget, t1, t0);
20110
697b7b6b
SM
20111 /* branch completion */
20112 clear_branch_hflags(ctx);
20113 ctx->base.is_jmp = DISAS_NORETURN;
20114
11d0fc10
SM
20115 /* unconditional branch to register */
20116 tcg_gen_mov_tl(cpu_PC, btarget);
20117 tcg_gen_lookup_and_goto_ptr();
20118
20119 tcg_temp_free(t0);
20120 tcg_temp_free(t1);
20121}
20122
20123/* nanoMIPS Branches */
20124static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20125 int rs, int rt, int32_t offset)
20126{
20127 int bcond_compute = 0;
20128 TCGv t0 = tcg_temp_new();
20129 TCGv t1 = tcg_temp_new();
20130
20131 /* Load needed operands and calculate btarget */
20132 switch (opc) {
20133 /* compact branch */
20134 case OPC_BGEC:
20135 case OPC_BLTC:
20136 gen_load_gpr(t0, rs);
20137 gen_load_gpr(t1, rt);
20138 bcond_compute = 1;
20139 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20140 break;
20141 case OPC_BGEUC:
20142 case OPC_BLTUC:
20143 if (rs == 0 || rs == rt) {
20144 /* OPC_BLEZALC, OPC_BGEZALC */
20145 /* OPC_BGTZALC, OPC_BLTZALC */
20146 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20147 }
20148 gen_load_gpr(t0, rs);
20149 gen_load_gpr(t1, rt);
20150 bcond_compute = 1;
20151 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20152 break;
20153 case OPC_BC:
20154 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20155 break;
20156 case OPC_BEQZC:
20157 if (rs != 0) {
20158 /* OPC_BEQZC, OPC_BNEZC */
20159 gen_load_gpr(t0, rs);
20160 bcond_compute = 1;
20161 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20162 } else {
20163 /* OPC_JIC, OPC_JIALC */
20164 TCGv tbase = tcg_temp_new();
20165 TCGv toffset = tcg_temp_new();
20166
20167 gen_load_gpr(tbase, rt);
20168 tcg_gen_movi_tl(toffset, offset);
20169 gen_op_addr_add(ctx, btarget, tbase, toffset);
20170 tcg_temp_free(tbase);
20171 tcg_temp_free(toffset);
20172 }
20173 break;
20174 default:
20175 MIPS_INVAL("Compact branch/jump");
20176 generate_exception_end(ctx, EXCP_RI);
20177 goto out;
20178 }
20179
20180 if (bcond_compute == 0) {
20181 /* Uncoditional compact branch */
20182 switch (opc) {
20183 case OPC_BC:
20184 gen_goto_tb(ctx, 0, ctx->btarget);
20185 break;
20186 default:
20187 MIPS_INVAL("Compact branch/jump");
20188 generate_exception_end(ctx, EXCP_RI);
20189 goto out;
20190 }
20191 } else {
20192 /* Conditional compact branch */
20193 TCGLabel *fs = gen_new_label();
20194
20195 switch (opc) {
20196 case OPC_BGEUC:
20197 if (rs == 0 && rt != 0) {
20198 /* OPC_BLEZALC */
20199 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20200 } else if (rs != 0 && rt != 0 && rs == rt) {
20201 /* OPC_BGEZALC */
20202 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20203 } else {
20204 /* OPC_BGEUC */
20205 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20206 }
20207 break;
20208 case OPC_BLTUC:
20209 if (rs == 0 && rt != 0) {
20210 /* OPC_BGTZALC */
20211 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20212 } else if (rs != 0 && rt != 0 && rs == rt) {
20213 /* OPC_BLTZALC */
20214 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20215 } else {
20216 /* OPC_BLTUC */
20217 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20218 }
20219 break;
20220 case OPC_BGEC:
20221 if (rs == 0 && rt != 0) {
20222 /* OPC_BLEZC */
20223 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20224 } else if (rs != 0 && rt != 0 && rs == rt) {
20225 /* OPC_BGEZC */
20226 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20227 } else {
20228 /* OPC_BGEC */
20229 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20230 }
20231 break;
20232 case OPC_BLTC:
20233 if (rs == 0 && rt != 0) {
20234 /* OPC_BGTZC */
20235 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20236 } else if (rs != 0 && rt != 0 && rs == rt) {
20237 /* OPC_BLTZC */
20238 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20239 } else {
20240 /* OPC_BLTC */
20241 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20242 }
20243 break;
20244 case OPC_BEQZC:
20245 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20246 break;
20247 default:
20248 MIPS_INVAL("Compact conditional branch/jump");
20249 generate_exception_end(ctx, EXCP_RI);
20250 goto out;
20251 }
20252
697b7b6b
SM
20253 /* branch completion */
20254 clear_branch_hflags(ctx);
20255 ctx->base.is_jmp = DISAS_NORETURN;
20256
11d0fc10
SM
20257 /* Generating branch here as compact branches don't have delay slot */
20258 gen_goto_tb(ctx, 1, ctx->btarget);
20259 gen_set_label(fs);
20260
20261 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20262 }
20263
20264out:
20265 tcg_temp_free(t0);
20266 tcg_temp_free(t1);
20267}
20268
20269
20270/* nanoMIPS CP1 Branches */
20271static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20272 int32_t ft, int32_t offset)
20273{
20274 target_ulong btarget;
20275 TCGv_i64 t0 = tcg_temp_new_i64();
20276
20277 gen_load_fpr64(ctx, t0, ft);
20278 tcg_gen_andi_i64(t0, t0, 1);
20279
20280 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20281
20282 switch (op) {
20283 case NM_BC1EQZC:
20284 tcg_gen_xori_i64(t0, t0, 1);
20285 ctx->hflags |= MIPS_HFLAG_BC;
20286 break;
20287 case NM_BC1NEZC:
20288 /* t0 already set */
20289 ctx->hflags |= MIPS_HFLAG_BC;
20290 break;
20291 default:
20292 MIPS_INVAL("cp1 cond branch");
20293 generate_exception_end(ctx, EXCP_RI);
20294 goto out;
20295 }
20296
20297 tcg_gen_trunc_i64_tl(bcond, t0);
20298
20299 ctx->btarget = btarget;
20300
20301out:
20302 tcg_temp_free_i64(t0);
20303}
20304
eac52664
YK
20305
20306static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20307{
20308 TCGv t0, t1;
20309 t0 = tcg_temp_new();
20310 t1 = tcg_temp_new();
20311
20312 gen_load_gpr(t0, rs);
20313 gen_load_gpr(t1, rt);
20314
20315 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20316 /* PP.LSXS instructions require shifting */
20317 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20318 case NM_SHXS:
fb32f8c8 20319 check_nms(ctx);
45152d05 20320 /* fall through */
fb32f8c8 20321 case NM_LHXS:
eac52664
YK
20322 case NM_LHUXS:
20323 tcg_gen_shli_tl(t0, t0, 1);
20324 break;
eac52664 20325 case NM_SWXS:
fb32f8c8 20326 check_nms(ctx);
45152d05 20327 /* fall through */
fb32f8c8 20328 case NM_LWXS:
eac52664
YK
20329 case NM_LWC1XS:
20330 case NM_SWC1XS:
20331 tcg_gen_shli_tl(t0, t0, 2);
20332 break;
20333 case NM_LDC1XS:
20334 case NM_SDC1XS:
20335 tcg_gen_shli_tl(t0, t0, 3);
20336 break;
20337 }
20338 }
20339 gen_op_addr_add(ctx, t0, t0, t1);
20340
20341 switch (extract32(ctx->opcode, 7, 4)) {
20342 case NM_LBX:
20343 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20344 MO_SB);
20345 gen_store_gpr(t0, rd);
20346 break;
20347 case NM_LHX:
20348 /*case NM_LHXS:*/
20349 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20350 MO_TESW);
20351 gen_store_gpr(t0, rd);
20352 break;
20353 case NM_LWX:
20354 /*case NM_LWXS:*/
20355 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20356 MO_TESL);
20357 gen_store_gpr(t0, rd);
20358 break;
20359 case NM_LBUX:
20360 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20361 MO_UB);
20362 gen_store_gpr(t0, rd);
20363 break;
20364 case NM_LHUX:
20365 /*case NM_LHUXS:*/
20366 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20367 MO_TEUW);
20368 gen_store_gpr(t0, rd);
20369 break;
20370 case NM_SBX:
fb32f8c8 20371 check_nms(ctx);
eac52664
YK
20372 gen_load_gpr(t1, rd);
20373 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20374 MO_8);
20375 break;
20376 case NM_SHX:
20377 /*case NM_SHXS:*/
fb32f8c8 20378 check_nms(ctx);
eac52664
YK
20379 gen_load_gpr(t1, rd);
20380 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20381 MO_TEUW);
20382 break;
20383 case NM_SWX:
20384 /*case NM_SWXS:*/
fb32f8c8 20385 check_nms(ctx);
eac52664
YK
20386 gen_load_gpr(t1, rd);
20387 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20388 MO_TEUL);
20389 break;
20390 case NM_LWC1X:
20391 /*case NM_LWC1XS:*/
20392 case NM_LDC1X:
20393 /*case NM_LDC1XS:*/
20394 case NM_SWC1X:
20395 /*case NM_SWC1XS:*/
20396 case NM_SDC1X:
20397 /*case NM_SDC1XS:*/
20398 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20399 check_cp1_enabled(ctx);
20400 switch (extract32(ctx->opcode, 7, 4)) {
20401 case NM_LWC1X:
20402 /*case NM_LWC1XS:*/
20403 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20404 break;
20405 case NM_LDC1X:
20406 /*case NM_LDC1XS:*/
20407 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20408 break;
20409 case NM_SWC1X:
20410 /*case NM_SWC1XS:*/
20411 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20412 break;
20413 case NM_SDC1X:
20414 /*case NM_SDC1XS:*/
20415 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20416 break;
20417 }
20418 } else {
20419 generate_exception_err(ctx, EXCP_CpU, 1);
20420 }
20421 break;
20422 default:
20423 generate_exception_end(ctx, EXCP_RI);
20424 break;
20425 }
20426
20427 tcg_temp_free(t0);
20428 tcg_temp_free(t1);
20429}
20430
579b8ea9
YK
20431static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20432{
20433 int rt, rs, rd;
20434
20435 rt = extract32(ctx->opcode, 21, 5);
20436 rs = extract32(ctx->opcode, 16, 5);
20437 rd = extract32(ctx->opcode, 11, 5);
20438
20439 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20440 generate_exception_end(ctx, EXCP_RI);
20441 return;
20442 }
20443 check_cp1_enabled(ctx);
20444 switch (extract32(ctx->opcode, 0, 3)) {
20445 case NM_POOL32F_0:
20446 switch (extract32(ctx->opcode, 3, 7)) {
20447 case NM_RINT_S:
20448 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20449 break;
20450 case NM_RINT_D:
20451 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20452 break;
20453 case NM_CLASS_S:
20454 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20455 break;
20456 case NM_CLASS_D:
20457 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20458 break;
20459 case NM_ADD_S:
20460 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20461 break;
20462 case NM_ADD_D:
20463 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20464 break;
20465 case NM_SUB_S:
20466 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20467 break;
20468 case NM_SUB_D:
20469 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20470 break;
20471 case NM_MUL_S:
20472 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20473 break;
20474 case NM_MUL_D:
20475 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20476 break;
20477 case NM_DIV_S:
20478 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20479 break;
20480 case NM_DIV_D:
20481 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20482 break;
20483 case NM_SELEQZ_S:
20484 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20485 break;
20486 case NM_SELEQZ_D:
20487 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20488 break;
20489 case NM_SELNEZ_S:
20490 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20491 break;
20492 case NM_SELNEZ_D:
20493 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20494 break;
20495 case NM_SEL_S:
20496 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20497 break;
20498 case NM_SEL_D:
20499 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20500 break;
20501 case NM_MADDF_S:
20502 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20503 break;
20504 case NM_MADDF_D:
20505 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20506 break;
20507 case NM_MSUBF_S:
20508 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20509 break;
20510 case NM_MSUBF_D:
20511 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20512 break;
20513 default:
20514 generate_exception_end(ctx, EXCP_RI);
20515 break;
20516 }
20517 break;
20518 case NM_POOL32F_3:
20519 switch (extract32(ctx->opcode, 3, 3)) {
20520 case NM_MIN_FMT:
20521 switch (extract32(ctx->opcode, 9, 1)) {
20522 case FMT_SDPS_S:
20523 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20524 break;
20525 case FMT_SDPS_D:
20526 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20527 break;
20528 }
20529 break;
20530 case NM_MAX_FMT:
20531 switch (extract32(ctx->opcode, 9, 1)) {
20532 case FMT_SDPS_S:
20533 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20534 break;
20535 case FMT_SDPS_D:
20536 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20537 break;
20538 }
20539 break;
20540 case NM_MINA_FMT:
20541 switch (extract32(ctx->opcode, 9, 1)) {
20542 case FMT_SDPS_S:
20543 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20544 break;
20545 case FMT_SDPS_D:
20546 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20547 break;
20548 }
20549 break;
20550 case NM_MAXA_FMT:
20551 switch (extract32(ctx->opcode, 9, 1)) {
20552 case FMT_SDPS_S:
20553 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20554 break;
20555 case FMT_SDPS_D:
20556 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20557 break;
20558 }
20559 break;
20560 case NM_POOL32FXF:
20561 switch (extract32(ctx->opcode, 6, 8)) {
20562 case NM_CFC1:
20563 gen_cp1(ctx, OPC_CFC1, rt, rs);
20564 break;
20565 case NM_CTC1:
20566 gen_cp1(ctx, OPC_CTC1, rt, rs);
20567 break;
20568 case NM_MFC1:
20569 gen_cp1(ctx, OPC_MFC1, rt, rs);
20570 break;
20571 case NM_MTC1:
20572 gen_cp1(ctx, OPC_MTC1, rt, rs);
20573 break;
20574 case NM_MFHC1:
20575 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20576 break;
20577 case NM_MTHC1:
20578 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20579 break;
20580 case NM_CVT_S_PL:
20581 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20582 break;
20583 case NM_CVT_S_PU:
20584 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20585 break;
20586 default:
20587 switch (extract32(ctx->opcode, 6, 9)) {
20588 case NM_CVT_L_S:
20589 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20590 break;
20591 case NM_CVT_L_D:
20592 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20593 break;
20594 case NM_CVT_W_S:
20595 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20596 break;
20597 case NM_CVT_W_D:
20598 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20599 break;
20600 case NM_RSQRT_S:
20601 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20602 break;
20603 case NM_RSQRT_D:
20604 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20605 break;
20606 case NM_SQRT_S:
20607 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20608 break;
20609 case NM_SQRT_D:
20610 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20611 break;
20612 case NM_RECIP_S:
20613 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20614 break;
20615 case NM_RECIP_D:
20616 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20617 break;
20618 case NM_FLOOR_L_S:
20619 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20620 break;
20621 case NM_FLOOR_L_D:
20622 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20623 break;
20624 case NM_FLOOR_W_S:
20625 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20626 break;
20627 case NM_FLOOR_W_D:
20628 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20629 break;
20630 case NM_CEIL_L_S:
20631 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20632 break;
20633 case NM_CEIL_L_D:
20634 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20635 break;
20636 case NM_CEIL_W_S:
20637 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20638 break;
20639 case NM_CEIL_W_D:
20640 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20641 break;
20642 case NM_TRUNC_L_S:
20643 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20644 break;
20645 case NM_TRUNC_L_D:
20646 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20647 break;
20648 case NM_TRUNC_W_S:
20649 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20650 break;
20651 case NM_TRUNC_W_D:
20652 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20653 break;
20654 case NM_ROUND_L_S:
20655 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20656 break;
20657 case NM_ROUND_L_D:
20658 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20659 break;
20660 case NM_ROUND_W_S:
20661 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20662 break;
20663 case NM_ROUND_W_D:
20664 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20665 break;
20666 case NM_MOV_S:
20667 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20668 break;
20669 case NM_MOV_D:
20670 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20671 break;
20672 case NM_ABS_S:
20673 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20674 break;
20675 case NM_ABS_D:
20676 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20677 break;
20678 case NM_NEG_S:
20679 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20680 break;
20681 case NM_NEG_D:
20682 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20683 break;
20684 case NM_CVT_D_S:
20685 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20686 break;
20687 case NM_CVT_D_W:
20688 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20689 break;
20690 case NM_CVT_D_L:
20691 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20692 break;
20693 case NM_CVT_S_D:
20694 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20695 break;
20696 case NM_CVT_S_W:
20697 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20698 break;
20699 case NM_CVT_S_L:
20700 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20701 break;
20702 default:
20703 generate_exception_end(ctx, EXCP_RI);
20704 break;
20705 }
20706 break;
20707 }
20708 break;
20709 }
20710 break;
20711 case NM_POOL32F_5:
20712 switch (extract32(ctx->opcode, 3, 3)) {
20713 case NM_CMP_CONDN_S:
20714 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20715 break;
20716 case NM_CMP_CONDN_D:
20717 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20718 break;
20719 default:
20720 generate_exception_end(ctx, EXCP_RI);
20721 break;
20722 }
20723 break;
20724 default:
20725 generate_exception_end(ctx, EXCP_RI);
20726 break;
20727 }
20728}
20729
3285a3e4
SM
20730static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20731 int rd, int rs, int rt)
20732{
20733 int ret = rd;
20734 TCGv t0 = tcg_temp_new();
20735 TCGv v1_t = tcg_temp_new();
20736 TCGv v2_t = tcg_temp_new();
20737
20738 gen_load_gpr(v1_t, rs);
20739 gen_load_gpr(v2_t, rt);
20740
20741 switch (opc) {
20742 case NM_CMP_EQ_PH:
20743 check_dsp(ctx);
20744 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20745 break;
20746 case NM_CMP_LT_PH:
20747 check_dsp(ctx);
20748 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20749 break;
20750 case NM_CMP_LE_PH:
20751 check_dsp(ctx);
20752 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20753 break;
20754 case NM_CMPU_EQ_QB:
20755 check_dsp(ctx);
20756 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20757 break;
20758 case NM_CMPU_LT_QB:
20759 check_dsp(ctx);
20760 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20761 break;
20762 case NM_CMPU_LE_QB:
20763 check_dsp(ctx);
20764 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20765 break;
20766 case NM_CMPGU_EQ_QB:
20767 check_dsp(ctx);
20768 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20769 gen_store_gpr(v1_t, ret);
20770 break;
20771 case NM_CMPGU_LT_QB:
20772 check_dsp(ctx);
20773 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20774 gen_store_gpr(v1_t, ret);
20775 break;
20776 case NM_CMPGU_LE_QB:
20777 check_dsp(ctx);
20778 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20779 gen_store_gpr(v1_t, ret);
20780 break;
20781 case NM_CMPGDU_EQ_QB:
908f6be1 20782 check_dsp_r2(ctx);
3285a3e4
SM
20783 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20784 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20785 gen_store_gpr(v1_t, ret);
20786 break;
20787 case NM_CMPGDU_LT_QB:
908f6be1 20788 check_dsp_r2(ctx);
3285a3e4
SM
20789 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20790 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20791 gen_store_gpr(v1_t, ret);
20792 break;
20793 case NM_CMPGDU_LE_QB:
908f6be1 20794 check_dsp_r2(ctx);
3285a3e4
SM
20795 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20796 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20797 gen_store_gpr(v1_t, ret);
20798 break;
20799 case NM_PACKRL_PH:
20800 check_dsp(ctx);
20801 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20802 gen_store_gpr(v1_t, ret);
20803 break;
20804 case NM_PICK_QB:
20805 check_dsp(ctx);
20806 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20807 gen_store_gpr(v1_t, ret);
20808 break;
20809 case NM_PICK_PH:
20810 check_dsp(ctx);
20811 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20812 gen_store_gpr(v1_t, ret);
20813 break;
20814 case NM_ADDQ_S_W:
20815 check_dsp(ctx);
20816 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20817 gen_store_gpr(v1_t, ret);
20818 break;
20819 case NM_SUBQ_S_W:
20820 check_dsp(ctx);
20821 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20822 gen_store_gpr(v1_t, ret);
20823 break;
20824 case NM_ADDSC:
20825 check_dsp(ctx);
20826 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20827 gen_store_gpr(v1_t, ret);
20828 break;
20829 case NM_ADDWC:
20830 check_dsp(ctx);
20831 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20832 gen_store_gpr(v1_t, ret);
20833 break;
20834 case NM_ADDQ_S_PH:
20835 check_dsp(ctx);
20836 switch (extract32(ctx->opcode, 10, 1)) {
20837 case 0:
20838 /* ADDQ_PH */
20839 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20840 gen_store_gpr(v1_t, ret);
20841 break;
20842 case 1:
20843 /* ADDQ_S_PH */
20844 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20845 gen_store_gpr(v1_t, ret);
20846 break;
20847 }
20848 break;
20849 case NM_ADDQH_R_PH:
908f6be1 20850 check_dsp_r2(ctx);
3285a3e4
SM
20851 switch (extract32(ctx->opcode, 10, 1)) {
20852 case 0:
20853 /* ADDQH_PH */
20854 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20855 gen_store_gpr(v1_t, ret);
20856 break;
20857 case 1:
20858 /* ADDQH_R_PH */
20859 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20860 gen_store_gpr(v1_t, ret);
20861 break;
20862 }
20863 break;
20864 case NM_ADDQH_R_W:
908f6be1 20865 check_dsp_r2(ctx);
3285a3e4
SM
20866 switch (extract32(ctx->opcode, 10, 1)) {
20867 case 0:
20868 /* ADDQH_W */
20869 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20870 gen_store_gpr(v1_t, ret);
20871 break;
20872 case 1:
20873 /* ADDQH_R_W */
20874 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20875 gen_store_gpr(v1_t, ret);
20876 break;
20877 }
20878 break;
20879 case NM_ADDU_S_QB:
20880 check_dsp(ctx);
20881 switch (extract32(ctx->opcode, 10, 1)) {
20882 case 0:
20883 /* ADDU_QB */
20884 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20885 gen_store_gpr(v1_t, ret);
20886 break;
20887 case 1:
20888 /* ADDU_S_QB */
20889 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20890 gen_store_gpr(v1_t, ret);
20891 break;
20892 }
20893 break;
20894 case NM_ADDU_S_PH:
908f6be1 20895 check_dsp_r2(ctx);
3285a3e4
SM
20896 switch (extract32(ctx->opcode, 10, 1)) {
20897 case 0:
20898 /* ADDU_PH */
20899 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20900 gen_store_gpr(v1_t, ret);
20901 break;
20902 case 1:
20903 /* ADDU_S_PH */
20904 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20905 gen_store_gpr(v1_t, ret);
20906 break;
20907 }
20908 break;
20909 case NM_ADDUH_R_QB:
908f6be1 20910 check_dsp_r2(ctx);
3285a3e4
SM
20911 switch (extract32(ctx->opcode, 10, 1)) {
20912 case 0:
20913 /* ADDUH_QB */
20914 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20915 gen_store_gpr(v1_t, ret);
20916 break;
20917 case 1:
20918 /* ADDUH_R_QB */
20919 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20920 gen_store_gpr(v1_t, ret);
20921 break;
20922 }
20923 break;
20924 case NM_SHRAV_R_PH:
20925 check_dsp(ctx);
20926 switch (extract32(ctx->opcode, 10, 1)) {
20927 case 0:
20928 /* SHRAV_PH */
20929 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20930 gen_store_gpr(v1_t, ret);
20931 break;
20932 case 1:
20933 /* SHRAV_R_PH */
20934 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20935 gen_store_gpr(v1_t, ret);
20936 break;
20937 }
20938 break;
20939 case NM_SHRAV_R_QB:
908f6be1 20940 check_dsp_r2(ctx);
3285a3e4
SM
20941 switch (extract32(ctx->opcode, 10, 1)) {
20942 case 0:
20943 /* SHRAV_QB */
20944 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20945 gen_store_gpr(v1_t, ret);
20946 break;
20947 case 1:
20948 /* SHRAV_R_QB */
20949 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20950 gen_store_gpr(v1_t, ret);
20951 break;
20952 }
20953 break;
20954 case NM_SUBQ_S_PH:
20955 check_dsp(ctx);
20956 switch (extract32(ctx->opcode, 10, 1)) {
20957 case 0:
20958 /* SUBQ_PH */
20959 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20960 gen_store_gpr(v1_t, ret);
20961 break;
20962 case 1:
20963 /* SUBQ_S_PH */
20964 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20965 gen_store_gpr(v1_t, ret);
20966 break;
20967 }
20968 break;
20969 case NM_SUBQH_R_PH:
908f6be1 20970 check_dsp_r2(ctx);
3285a3e4
SM
20971 switch (extract32(ctx->opcode, 10, 1)) {
20972 case 0:
20973 /* SUBQH_PH */
20974 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20975 gen_store_gpr(v1_t, ret);
20976 break;
20977 case 1:
20978 /* SUBQH_R_PH */
20979 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20980 gen_store_gpr(v1_t, ret);
20981 break;
20982 }
20983 break;
20984 case NM_SUBQH_R_W:
908f6be1 20985 check_dsp_r2(ctx);
3285a3e4
SM
20986 switch (extract32(ctx->opcode, 10, 1)) {
20987 case 0:
20988 /* SUBQH_W */
20989 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20990 gen_store_gpr(v1_t, ret);
20991 break;
20992 case 1:
20993 /* SUBQH_R_W */
20994 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20995 gen_store_gpr(v1_t, ret);
20996 break;
20997 }
20998 break;
20999 case NM_SUBU_S_QB:
21000 check_dsp(ctx);
21001 switch (extract32(ctx->opcode, 10, 1)) {
21002 case 0:
21003 /* SUBU_QB */
21004 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21005 gen_store_gpr(v1_t, ret);
21006 break;
21007 case 1:
21008 /* SUBU_S_QB */
21009 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21010 gen_store_gpr(v1_t, ret);
21011 break;
21012 }
21013 break;
21014 case NM_SUBU_S_PH:
908f6be1 21015 check_dsp_r2(ctx);
3285a3e4
SM
21016 switch (extract32(ctx->opcode, 10, 1)) {
21017 case 0:
21018 /* SUBU_PH */
21019 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21020 gen_store_gpr(v1_t, ret);
21021 break;
21022 case 1:
21023 /* SUBU_S_PH */
21024 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21025 gen_store_gpr(v1_t, ret);
21026 break;
21027 }
21028 break;
21029 case NM_SUBUH_R_QB:
908f6be1 21030 check_dsp_r2(ctx);
3285a3e4
SM
21031 switch (extract32(ctx->opcode, 10, 1)) {
21032 case 0:
21033 /* SUBUH_QB */
21034 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21035 gen_store_gpr(v1_t, ret);
21036 break;
21037 case 1:
21038 /* SUBUH_R_QB */
21039 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21040 gen_store_gpr(v1_t, ret);
21041 break;
21042 }
21043 break;
21044 case NM_SHLLV_S_PH:
21045 check_dsp(ctx);
21046 switch (extract32(ctx->opcode, 10, 1)) {
21047 case 0:
21048 /* SHLLV_PH */
21049 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21050 gen_store_gpr(v1_t, ret);
21051 break;
21052 case 1:
21053 /* SHLLV_S_PH */
21054 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21055 gen_store_gpr(v1_t, ret);
21056 break;
21057 }
21058 break;
21059 case NM_PRECR_SRA_R_PH_W:
908f6be1 21060 check_dsp_r2(ctx);
3285a3e4
SM
21061 switch (extract32(ctx->opcode, 10, 1)) {
21062 case 0:
21063 /* PRECR_SRA_PH_W */
21064 {
21065 TCGv_i32 sa_t = tcg_const_i32(rd);
21066 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21067 cpu_gpr[rt]);
21068 gen_store_gpr(v1_t, rt);
21069 tcg_temp_free_i32(sa_t);
21070 }
21071 break;
21072 case 1:
21073 /* PRECR_SRA_R_PH_W */
21074 {
21075 TCGv_i32 sa_t = tcg_const_i32(rd);
21076 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21077 cpu_gpr[rt]);
21078 gen_store_gpr(v1_t, rt);
21079 tcg_temp_free_i32(sa_t);
21080 }
21081 break;
21082 }
21083 break;
21084 case NM_MULEU_S_PH_QBL:
21085 check_dsp(ctx);
21086 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21087 gen_store_gpr(v1_t, ret);
21088 break;
21089 case NM_MULEU_S_PH_QBR:
21090 check_dsp(ctx);
21091 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21092 gen_store_gpr(v1_t, ret);
21093 break;
21094 case NM_MULQ_RS_PH:
21095 check_dsp(ctx);
21096 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21097 gen_store_gpr(v1_t, ret);
21098 break;
21099 case NM_MULQ_S_PH:
908f6be1 21100 check_dsp_r2(ctx);
3285a3e4
SM
21101 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21102 gen_store_gpr(v1_t, ret);
21103 break;
21104 case NM_MULQ_RS_W:
908f6be1 21105 check_dsp_r2(ctx);
3285a3e4
SM
21106 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21107 gen_store_gpr(v1_t, ret);
21108 break;
21109 case NM_MULQ_S_W:
908f6be1 21110 check_dsp_r2(ctx);
3285a3e4
SM
21111 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21112 gen_store_gpr(v1_t, ret);
21113 break;
21114 case NM_APPEND:
908f6be1 21115 check_dsp_r2(ctx);
3285a3e4
SM
21116 gen_load_gpr(t0, rs);
21117 if (rd != 0) {
21118 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21119 }
21120 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21121 break;
21122 case NM_MODSUB:
21123 check_dsp(ctx);
21124 gen_helper_modsub(v1_t, v1_t, v2_t);
21125 gen_store_gpr(v1_t, ret);
21126 break;
21127 case NM_SHRAV_R_W:
21128 check_dsp(ctx);
21129 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21130 gen_store_gpr(v1_t, ret);
21131 break;
21132 case NM_SHRLV_PH:
908f6be1 21133 check_dsp_r2(ctx);
3285a3e4
SM
21134 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21135 gen_store_gpr(v1_t, ret);
21136 break;
21137 case NM_SHRLV_QB:
21138 check_dsp(ctx);
21139 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21140 gen_store_gpr(v1_t, ret);
21141 break;
21142 case NM_SHLLV_QB:
21143 check_dsp(ctx);
21144 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21145 gen_store_gpr(v1_t, ret);
21146 break;
21147 case NM_SHLLV_S_W:
21148 check_dsp(ctx);
21149 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21150 gen_store_gpr(v1_t, ret);
21151 break;
21152 case NM_SHILO:
21153 check_dsp(ctx);
21154 {
21155 TCGv tv0 = tcg_temp_new();
21156 TCGv tv1 = tcg_temp_new();
21157 int16_t imm = extract32(ctx->opcode, 16, 7);
21158
21159 tcg_gen_movi_tl(tv0, rd >> 3);
21160 tcg_gen_movi_tl(tv1, imm);
21161 gen_helper_shilo(tv0, tv1, cpu_env);
21162 }
21163 break;
21164 case NM_MULEQ_S_W_PHL:
21165 check_dsp(ctx);
21166 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21167 gen_store_gpr(v1_t, ret);
21168 break;
21169 case NM_MULEQ_S_W_PHR:
21170 check_dsp(ctx);
21171 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21172 gen_store_gpr(v1_t, ret);
21173 break;
21174 case NM_MUL_S_PH:
908f6be1 21175 check_dsp_r2(ctx);
3285a3e4
SM
21176 switch (extract32(ctx->opcode, 10, 1)) {
21177 case 0:
21178 /* MUL_PH */
21179 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21180 gen_store_gpr(v1_t, ret);
21181 break;
21182 case 1:
21183 /* MUL_S_PH */
21184 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21185 gen_store_gpr(v1_t, ret);
21186 break;
21187 }
21188 break;
21189 case NM_PRECR_QB_PH:
908f6be1 21190 check_dsp_r2(ctx);
3285a3e4
SM
21191 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21192 gen_store_gpr(v1_t, ret);
21193 break;
21194 case NM_PRECRQ_QB_PH:
21195 check_dsp(ctx);
21196 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21197 gen_store_gpr(v1_t, ret);
21198 break;
21199 case NM_PRECRQ_PH_W:
21200 check_dsp(ctx);
21201 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21202 gen_store_gpr(v1_t, ret);
21203 break;
21204 case NM_PRECRQ_RS_PH_W:
21205 check_dsp(ctx);
21206 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21207 gen_store_gpr(v1_t, ret);
21208 break;
21209 case NM_PRECRQU_S_QB_PH:
21210 check_dsp(ctx);
21211 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21212 gen_store_gpr(v1_t, ret);
21213 break;
21214 case NM_SHRA_R_W:
21215 check_dsp(ctx);
21216 tcg_gen_movi_tl(t0, rd);
21217 gen_helper_shra_r_w(v1_t, t0, v1_t);
21218 gen_store_gpr(v1_t, rt);
21219 break;
21220 case NM_SHRA_R_PH:
21221 check_dsp(ctx);
21222 tcg_gen_movi_tl(t0, rd >> 1);
21223 switch (extract32(ctx->opcode, 10, 1)) {
21224 case 0:
21225 /* SHRA_PH */
21226 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 21227 gen_store_gpr(v1_t, rt);
d5ebcbaf 21228 break;
3285a3e4
SM
21229 case 1:
21230 /* SHRA_R_PH */
21231 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21232 gen_store_gpr(v1_t, rt);
21233 break;
21234 }
21235 break;
21236 case NM_SHLL_S_PH:
21237 check_dsp(ctx);
21238 tcg_gen_movi_tl(t0, rd >> 1);
21239 switch (extract32(ctx->opcode, 10, 2)) {
21240 case 0:
21241 /* SHLL_PH */
21242 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21243 gen_store_gpr(v1_t, rt);
21244 break;
21245 case 2:
21246 /* SHLL_S_PH */
21247 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21248 gen_store_gpr(v1_t, rt);
21249 break;
21250 default:
21251 generate_exception_end(ctx, EXCP_RI);
21252 break;
21253 }
21254 break;
21255 case NM_SHLL_S_W:
21256 check_dsp(ctx);
21257 tcg_gen_movi_tl(t0, rd);
21258 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21259 gen_store_gpr(v1_t, rt);
21260 break;
21261 case NM_REPL_PH:
21262 check_dsp(ctx);
21263 {
21264 int16_t imm;
21265 imm = sextract32(ctx->opcode, 11, 11);
21266 imm = (int16_t)(imm << 6) >> 6;
21267 if (rt != 0) {
21268 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21269 }
21270 }
21271 break;
21272 default:
21273 generate_exception_end(ctx, EXCP_RI);
21274 break;
21275 }
21276}
21277
c0280983
YK
21278static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21279{
21280 uint16_t insn;
21281 uint32_t op;
eac52664 21282 int rt, rs, rd;
c0280983
YK
21283 int offset;
21284 int imm;
21285
21286 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21287 ctx->opcode = (ctx->opcode << 16) | insn;
21288
21289 rt = extract32(ctx->opcode, 21, 5);
21290 rs = extract32(ctx->opcode, 16, 5);
eac52664 21291 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
21292
21293 op = extract32(ctx->opcode, 26, 6);
21294 switch (op) {
21295 case NM_P_ADDIU:
21296 if (rt == 0) {
21297 /* P.RI */
21298 switch (extract32(ctx->opcode, 19, 2)) {
21299 case NM_SIGRIE:
21300 default:
21301 generate_exception_end(ctx, EXCP_RI);
21302 break;
21303 case NM_P_SYSCALL:
21304 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21305 generate_exception_end(ctx, EXCP_SYSCALL);
21306 } else {
21307 generate_exception_end(ctx, EXCP_RI);
21308 }
21309 break;
21310 case NM_BREAK:
21311 generate_exception_end(ctx, EXCP_BREAK);
21312 break;
21313 case NM_SDBBP:
21314 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21315 gen_helper_do_semihosting(cpu_env);
21316 } else {
21317 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21318 generate_exception_end(ctx, EXCP_RI);
21319 } else {
21320 generate_exception_end(ctx, EXCP_DBp);
21321 }
21322 }
21323 break;
21324 }
21325 } else {
21326 /* NM_ADDIU */
21327 imm = extract32(ctx->opcode, 0, 16);
21328 if (rs != 0) {
21329 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21330 } else {
21331 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21332 }
21333 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21334 }
21335 break;
21336 case NM_ADDIUPC:
21337 if (rt != 0) {
21338 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21339 extract32(ctx->opcode, 1, 20) << 1;
21340 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21341 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21342 }
21343 break;
21344 case NM_POOL32A:
e0cf0e65
YK
21345 switch (ctx->opcode & 0x07) {
21346 case NM_POOL32A0:
0a1a6ed7 21347 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21348 break;
3285a3e4
SM
21349 case NM_POOL32A5:
21350 {
21351 int32_t op1 = extract32(ctx->opcode, 3, 7);
21352 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21353 }
21354 break;
e0cf0e65 21355 case NM_POOL32A7:
64224187 21356 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21357 case NM_P_LSX:
21358 gen_p_lsx(ctx, rd, rs, rt);
21359 break;
21360 case NM_LSA:
7480515f
AM
21361 /*
21362 * In nanoMIPS, the shift field directly encodes the shift
eac52664 21363 * amount, meaning that the supported shift values are in
7480515f
AM
21364 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21365 */
eac52664
YK
21366 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21367 extract32(ctx->opcode, 9, 2) - 1);
21368 break;
821f2008
JH
21369 case NM_EXTW:
21370 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21371 break;
64224187
YK
21372 case NM_POOL32AXF:
21373 gen_pool32axf_nanomips_insn(env, ctx);
21374 break;
21375 default:
21376 generate_exception_end(ctx, EXCP_RI);
21377 break;
21378 }
e0cf0e65
YK
21379 break;
21380 default:
21381 generate_exception_end(ctx, EXCP_RI);
21382 break;
21383 }
c0280983
YK
21384 break;
21385 case NM_P_GP_W:
21386 switch (ctx->opcode & 0x03) {
21387 case NM_ADDIUGP_W:
21388 if (rt != 0) {
21389 offset = extract32(ctx->opcode, 0, 21);
21390 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21391 }
21392 break;
21393 case NM_LWGP:
21394 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21395 break;
21396 case NM_SWGP:
21397 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21398 break;
21399 default:
21400 generate_exception_end(ctx, EXCP_RI);
21401 break;
21402 }
21403 break;
21404 case NM_P48I:
7ef009b2
YK
21405 {
21406 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21407 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21408 switch (extract32(ctx->opcode, 16, 5)) {
21409 case NM_LI48:
fb32f8c8 21410 check_nms(ctx);
7ef009b2
YK
21411 if (rt != 0) {
21412 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21413 }
21414 break;
21415 case NM_ADDIU48:
fb32f8c8 21416 check_nms(ctx);
7ef009b2
YK
21417 if (rt != 0) {
21418 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21419 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21420 }
21421 break;
21422 case NM_ADDIUGP48:
fb32f8c8 21423 check_nms(ctx);
7ef009b2
YK
21424 if (rt != 0) {
21425 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21426 }
21427 break;
21428 case NM_ADDIUPC48:
fb32f8c8 21429 check_nms(ctx);
7ef009b2
YK
21430 if (rt != 0) {
21431 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21432 addr_off);
21433
21434 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21435 }
21436 break;
21437 case NM_LWPC48:
fb32f8c8 21438 check_nms(ctx);
7ef009b2
YK
21439 if (rt != 0) {
21440 TCGv t0;
21441 t0 = tcg_temp_new();
21442
21443 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21444 addr_off);
21445
21446 tcg_gen_movi_tl(t0, addr);
21447 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21448 tcg_temp_free(t0);
21449 }
21450 break;
21451 case NM_SWPC48:
fb32f8c8 21452 check_nms(ctx);
7ef009b2
YK
21453 {
21454 TCGv t0, t1;
21455 t0 = tcg_temp_new();
21456 t1 = tcg_temp_new();
21457
21458 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21459 addr_off);
21460
21461 tcg_gen_movi_tl(t0, addr);
21462 gen_load_gpr(t1, rt);
21463
21464 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21465
21466 tcg_temp_free(t0);
21467 tcg_temp_free(t1);
21468 }
21469 break;
21470 default:
21471 generate_exception_end(ctx, EXCP_RI);
21472 break;
21473 }
21474 return 6;
21475 }
c0280983
YK
21476 case NM_P_U12:
21477 switch (extract32(ctx->opcode, 12, 4)) {
21478 case NM_ORI:
21479 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21480 break;
21481 case NM_XORI:
21482 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21483 break;
21484 case NM_ANDI:
21485 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21486 break;
21487 case NM_P_SR:
21488 switch (extract32(ctx->opcode, 20, 1)) {
21489 case NM_PP_SR:
21490 switch (ctx->opcode & 3) {
21491 case NM_SAVE:
21492 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21493 extract32(ctx->opcode, 2, 1),
21494 extract32(ctx->opcode, 3, 9) << 3);
21495 break;
21496 case NM_RESTORE:
21497 case NM_RESTORE_JRC:
21498 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21499 extract32(ctx->opcode, 2, 1),
21500 extract32(ctx->opcode, 3, 9) << 3);
21501 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21502 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21503 }
21504 break;
21505 default:
21506 generate_exception_end(ctx, EXCP_RI);
21507 break;
21508 }
21509 break;
21510 case NM_P_SR_F:
21511 generate_exception_end(ctx, EXCP_RI);
21512 break;
21513 }
21514 break;
21515 case NM_SLTI:
21516 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21517 break;
21518 case NM_SLTIU:
21519 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21520 break;
21521 case NM_SEQI:
21522 {
21523 TCGv t0 = tcg_temp_new();
21524
21525 imm = extract32(ctx->opcode, 0, 12);
21526 gen_load_gpr(t0, rs);
21527 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21528 gen_store_gpr(t0, rt);
21529
21530 tcg_temp_free(t0);
21531 }
21532 break;
21533 case NM_ADDIUNEG:
21534 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21535 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21536 break;
21537 case NM_P_SHIFT:
21538 {
21539 int shift = extract32(ctx->opcode, 0, 5);
21540 switch (extract32(ctx->opcode, 5, 4)) {
21541 case NM_P_SLL:
21542 if (rt == 0 && shift == 0) {
21543 /* NOP */
21544 } else if (rt == 0 && shift == 3) {
21545 /* EHB - treat as NOP */
21546 } else if (rt == 0 && shift == 5) {
21547 /* PAUSE - treat as NOP */
21548 } else if (rt == 0 && shift == 6) {
21549 /* SYNC */
21550 gen_sync(extract32(ctx->opcode, 16, 5));
21551 } else {
21552 /* SLL */
21553 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21554 extract32(ctx->opcode, 0, 5));
21555 }
21556 break;
21557 case NM_SRL:
21558 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21559 extract32(ctx->opcode, 0, 5));
21560 break;
21561 case NM_SRA:
21562 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21563 extract32(ctx->opcode, 0, 5));
21564 break;
21565 case NM_ROTR:
21566 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21567 extract32(ctx->opcode, 0, 5));
21568 break;
21569 }
21570 }
21571 break;
21572 case NM_P_ROTX:
fb32f8c8 21573 check_nms(ctx);
e222f506
MF
21574 if (rt != 0) {
21575 TCGv t0 = tcg_temp_new();
21576 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21577 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21578 << 1);
21579 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21580
21581 gen_load_gpr(t0, rs);
21582 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21583 tcg_temp_free(t0);
21584
21585 tcg_temp_free_i32(shift);
21586 tcg_temp_free_i32(shiftx);
21587 tcg_temp_free_i32(stripe);
21588 }
c0280983
YK
21589 break;
21590 case NM_P_INS:
21591 switch (((ctx->opcode >> 10) & 2) |
21592 (extract32(ctx->opcode, 5, 1))) {
21593 case NM_INS:
fb32f8c8 21594 check_nms(ctx);
c0280983
YK
21595 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21596 extract32(ctx->opcode, 6, 5));
21597 break;
21598 default:
21599 generate_exception_end(ctx, EXCP_RI);
21600 break;
21601 }
21602 break;
21603 case NM_P_EXT:
21604 switch (((ctx->opcode >> 10) & 2) |
21605 (extract32(ctx->opcode, 5, 1))) {
21606 case NM_EXT:
fb32f8c8 21607 check_nms(ctx);
c0280983
YK
21608 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21609 extract32(ctx->opcode, 6, 5));
21610 break;
21611 default:
21612 generate_exception_end(ctx, EXCP_RI);
21613 break;
21614 }
21615 break;
21616 default:
21617 generate_exception_end(ctx, EXCP_RI);
21618 break;
21619 }
21620 break;
21621 case NM_POOL32F:
579b8ea9 21622 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
21623 break;
21624 case NM_POOL32S:
21625 break;
21626 case NM_P_LUI:
21627 switch (extract32(ctx->opcode, 1, 1)) {
21628 case NM_LUI:
21629 if (rt != 0) {
21630 tcg_gen_movi_tl(cpu_gpr[rt],
21631 sextract32(ctx->opcode, 0, 1) << 31 |
21632 extract32(ctx->opcode, 2, 10) << 21 |
21633 extract32(ctx->opcode, 12, 9) << 12);
21634 }
21635 break;
21636 case NM_ALUIPC:
21637 if (rt != 0) {
21638 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21639 extract32(ctx->opcode, 2, 10) << 21 |
21640 extract32(ctx->opcode, 12, 9) << 12;
21641 target_long addr;
21642 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21643 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21644 }
21645 break;
21646 }
21647 break;
21648 case NM_P_GP_BH:
8f1d9b6d
YK
21649 {
21650 uint32_t u = extract32(ctx->opcode, 0, 18);
21651
21652 switch (extract32(ctx->opcode, 18, 3)) {
21653 case NM_LBGP:
21654 gen_ld(ctx, OPC_LB, rt, 28, u);
21655 break;
21656 case NM_SBGP:
21657 gen_st(ctx, OPC_SB, rt, 28, u);
21658 break;
21659 case NM_LBUGP:
21660 gen_ld(ctx, OPC_LBU, rt, 28, u);
21661 break;
21662 case NM_ADDIUGP_B:
21663 if (rt != 0) {
21664 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21665 }
21666 break;
21667 case NM_P_GP_LH:
21668 u &= ~1;
21669 switch (ctx->opcode & 1) {
21670 case NM_LHGP:
21671 gen_ld(ctx, OPC_LH, rt, 28, u);
21672 break;
21673 case NM_LHUGP:
21674 gen_ld(ctx, OPC_LHU, rt, 28, u);
21675 break;
21676 }
21677 break;
21678 case NM_P_GP_SH:
21679 u &= ~1;
21680 switch (ctx->opcode & 1) {
21681 case NM_SHGP:
21682 gen_st(ctx, OPC_SH, rt, 28, u);
21683 break;
21684 default:
21685 generate_exception_end(ctx, EXCP_RI);
21686 break;
21687 }
21688 break;
21689 case NM_P_GP_CP1:
21690 u &= ~0x3;
21691 switch (ctx->opcode & 0x3) {
21692 case NM_LWC1GP:
21693 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21694 break;
21695 case NM_LDC1GP:
21696 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21697 break;
21698 case NM_SWC1GP:
21699 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21700 break;
21701 case NM_SDC1GP:
21702 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21703 break;
21704 }
21705 break;
21706 default:
21707 generate_exception_end(ctx, EXCP_RI);
21708 break;
21709 }
21710 }
c0280983
YK
21711 break;
21712 case NM_P_LS_U12:
8f1d9b6d
YK
21713 {
21714 uint32_t u = extract32(ctx->opcode, 0, 12);
21715
21716 switch (extract32(ctx->opcode, 12, 4)) {
21717 case NM_P_PREFU12:
21718 if (rt == 31) {
21719 /* SYNCI */
7480515f
AM
21720 /*
21721 * Break the TB to be able to sync copied instructions
21722 * immediately.
21723 */
8f1d9b6d
YK
21724 ctx->base.is_jmp = DISAS_STOP;
21725 } else {
21726 /* PREF */
21727 /* Treat as NOP. */
21728 }
21729 break;
21730 case NM_LB:
21731 gen_ld(ctx, OPC_LB, rt, rs, u);
21732 break;
21733 case NM_LH:
21734 gen_ld(ctx, OPC_LH, rt, rs, u);
21735 break;
21736 case NM_LW:
21737 gen_ld(ctx, OPC_LW, rt, rs, u);
21738 break;
21739 case NM_LBU:
21740 gen_ld(ctx, OPC_LBU, rt, rs, u);
21741 break;
21742 case NM_LHU:
21743 gen_ld(ctx, OPC_LHU, rt, rs, u);
21744 break;
21745 case NM_SB:
21746 gen_st(ctx, OPC_SB, rt, rs, u);
21747 break;
21748 case NM_SH:
21749 gen_st(ctx, OPC_SH, rt, rs, u);
21750 break;
21751 case NM_SW:
21752 gen_st(ctx, OPC_SW, rt, rs, u);
21753 break;
21754 case NM_LWC1:
21755 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21756 break;
21757 case NM_LDC1:
21758 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21759 break;
21760 case NM_SWC1:
21761 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21762 break;
21763 case NM_SDC1:
21764 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21765 break;
21766 default:
21767 generate_exception_end(ctx, EXCP_RI);
21768 break;
21769 }
21770 }
c0280983
YK
21771 break;
21772 case NM_P_LS_S9:
8f1d9b6d
YK
21773 {
21774 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21775 extract32(ctx->opcode, 0, 8);
21776
21777 switch (extract32(ctx->opcode, 8, 3)) {
21778 case NM_P_LS_S0:
21779 switch (extract32(ctx->opcode, 11, 4)) {
21780 case NM_LBS9:
21781 gen_ld(ctx, OPC_LB, rt, rs, s);
21782 break;
21783 case NM_LHS9:
21784 gen_ld(ctx, OPC_LH, rt, rs, s);
21785 break;
21786 case NM_LWS9:
21787 gen_ld(ctx, OPC_LW, rt, rs, s);
21788 break;
21789 case NM_LBUS9:
21790 gen_ld(ctx, OPC_LBU, rt, rs, s);
21791 break;
21792 case NM_LHUS9:
21793 gen_ld(ctx, OPC_LHU, rt, rs, s);
21794 break;
21795 case NM_SBS9:
21796 gen_st(ctx, OPC_SB, rt, rs, s);
21797 break;
21798 case NM_SHS9:
21799 gen_st(ctx, OPC_SH, rt, rs, s);
21800 break;
21801 case NM_SWS9:
21802 gen_st(ctx, OPC_SW, rt, rs, s);
21803 break;
21804 case NM_LWC1S9:
21805 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21806 break;
21807 case NM_LDC1S9:
21808 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21809 break;
21810 case NM_SWC1S9:
21811 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21812 break;
21813 case NM_SDC1S9:
21814 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21815 break;
21816 case NM_P_PREFS9:
21817 if (rt == 31) {
21818 /* SYNCI */
7480515f
AM
21819 /*
21820 * Break the TB to be able to sync copied instructions
21821 * immediately.
21822 */
8f1d9b6d
YK
21823 ctx->base.is_jmp = DISAS_STOP;
21824 } else {
21825 /* PREF */
21826 /* Treat as NOP. */
21827 }
21828 break;
21829 default:
21830 generate_exception_end(ctx, EXCP_RI);
21831 break;
21832 }
21833 break;
21834 case NM_P_LS_S1:
21835 switch (extract32(ctx->opcode, 11, 4)) {
21836 case NM_UALH:
21837 case NM_UASH:
fb32f8c8 21838 check_nms(ctx);
8f1d9b6d
YK
21839 {
21840 TCGv t0 = tcg_temp_new();
21841 TCGv t1 = tcg_temp_new();
21842
21843 gen_base_offset_addr(ctx, t0, rs, s);
21844
21845 switch (extract32(ctx->opcode, 11, 4)) {
21846 case NM_UALH:
21847 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21848 MO_UNALN);
21849 gen_store_gpr(t0, rt);
21850 break;
21851 case NM_UASH:
21852 gen_load_gpr(t1, rt);
21853 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21854 MO_UNALN);
21855 break;
21856 }
21857 tcg_temp_free(t0);
21858 tcg_temp_free(t1);
21859 }
21860 break;
21861 case NM_P_LL:
21862 switch (ctx->opcode & 0x03) {
21863 case NM_LL:
21864 gen_ld(ctx, OPC_LL, rt, rs, s);
21865 break;
21866 case NM_LLWP:
0b16dcd1
AR
21867 check_xnp(ctx);
21868 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21869 break;
21870 }
21871 break;
21872 case NM_P_SC:
21873 switch (ctx->opcode & 0x03) {
21874 case NM_SC:
33a07fa2 21875 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
21876 break;
21877 case NM_SCWP:
0b16dcd1 21878 check_xnp(ctx);
8d5388c1
AM
21879 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21880 false);
8f1d9b6d
YK
21881 break;
21882 }
21883 break;
21884 case NM_CACHE:
21885 check_cp0_enabled(ctx);
21886 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21887 gen_cache_operation(ctx, rt, rs, s);
21888 }
21889 break;
21890 }
21891 break;
d046a9ea
DN
21892 case NM_P_LS_E0:
21893 switch (extract32(ctx->opcode, 11, 4)) {
21894 case NM_LBE:
21895 check_eva(ctx);
21896 check_cp0_enabled(ctx);
21897 gen_ld(ctx, OPC_LBE, rt, rs, s);
21898 break;
21899 case NM_SBE:
21900 check_eva(ctx);
21901 check_cp0_enabled(ctx);
21902 gen_st(ctx, OPC_SBE, rt, rs, s);
21903 break;
21904 case NM_LBUE:
21905 check_eva(ctx);
21906 check_cp0_enabled(ctx);
21907 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21908 break;
21909 case NM_P_PREFE:
21910 if (rt == 31) {
21911 /* case NM_SYNCIE */
21912 check_eva(ctx);
21913 check_cp0_enabled(ctx);
7480515f
AM
21914 /*
21915 * Break the TB to be able to sync copied instructions
21916 * immediately.
21917 */
d046a9ea
DN
21918 ctx->base.is_jmp = DISAS_STOP;
21919 } else {
21920 /* case NM_PREFE */
21921 check_eva(ctx);
21922 check_cp0_enabled(ctx);
21923 /* Treat as NOP. */
21924 }
21925 break;
21926 case NM_LHE:
21927 check_eva(ctx);
21928 check_cp0_enabled(ctx);
21929 gen_ld(ctx, OPC_LHE, rt, rs, s);
21930 break;
21931 case NM_SHE:
21932 check_eva(ctx);
21933 check_cp0_enabled(ctx);
21934 gen_st(ctx, OPC_SHE, rt, rs, s);
21935 break;
21936 case NM_LHUE:
21937 check_eva(ctx);
21938 check_cp0_enabled(ctx);
21939 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21940 break;
21941 case NM_CACHEE:
21942 check_nms_dl_il_sl_tl_l2c(ctx);
21943 gen_cache_operation(ctx, rt, rs, s);
21944 break;
21945 case NM_LWE:
21946 check_eva(ctx);
21947 check_cp0_enabled(ctx);
21948 gen_ld(ctx, OPC_LWE, rt, rs, s);
21949 break;
21950 case NM_SWE:
21951 check_eva(ctx);
21952 check_cp0_enabled(ctx);
21953 gen_st(ctx, OPC_SWE, rt, rs, s);
21954 break;
21955 case NM_P_LLE:
21956 switch (extract32(ctx->opcode, 2, 2)) {
21957 case NM_LLE:
21958 check_xnp(ctx);
21959 check_eva(ctx);
21960 check_cp0_enabled(ctx);
21961 gen_ld(ctx, OPC_LLE, rt, rs, s);
21962 break;
21963 case NM_LLWPE:
21964 check_xnp(ctx);
21965 check_eva(ctx);
21966 check_cp0_enabled(ctx);
21967 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21968 break;
d046a9ea
DN
21969 default:
21970 generate_exception_end(ctx, EXCP_RI);
21971 break;
21972 }
21973 break;
21974 case NM_P_SCE:
21975 switch (extract32(ctx->opcode, 2, 2)) {
21976 case NM_SCE:
21977 check_xnp(ctx);
21978 check_eva(ctx);
21979 check_cp0_enabled(ctx);
33a07fa2 21980 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
21981 break;
21982 case NM_SCWPE:
21983 check_xnp(ctx);
21984 check_eva(ctx);
21985 check_cp0_enabled(ctx);
8d5388c1
AM
21986 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21987 true);
2431a422 21988 break;
d046a9ea
DN
21989 default:
21990 generate_exception_end(ctx, EXCP_RI);
21991 break;
21992 }
21993 break;
21994 }
21995 break;
8f1d9b6d
YK
21996 case NM_P_LS_WM:
21997 case NM_P_LS_UAWM:
fb32f8c8 21998 check_nms(ctx);
8f1d9b6d
YK
21999 {
22000 int count = extract32(ctx->opcode, 12, 3);
22001 int counter = 0;
22002
22003 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22004 extract32(ctx->opcode, 0, 8);
22005 TCGv va = tcg_temp_new();
22006 TCGv t1 = tcg_temp_new();
14776ab5 22007 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
22008 NM_P_LS_UAWM ? MO_UNALN : 0;
22009
22010 count = (count == 0) ? 8 : count;
22011 while (counter != count) {
22012 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22013 int this_offset = offset + (counter << 2);
22014
22015 gen_base_offset_addr(ctx, va, rs, this_offset);
22016
22017 switch (extract32(ctx->opcode, 11, 1)) {
22018 case NM_LWM:
22019 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22020 memop | MO_TESL);
22021 gen_store_gpr(t1, this_rt);
22022 if ((this_rt == rs) &&
22023 (counter != (count - 1))) {
22024 /* UNPREDICTABLE */
22025 }
22026 break;
22027 case NM_SWM:
22028 this_rt = (rt == 0) ? 0 : this_rt;
22029 gen_load_gpr(t1, this_rt);
22030 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22031 memop | MO_TEUL);
22032 break;
22033 }
22034 counter++;
22035 }
22036 tcg_temp_free(va);
22037 tcg_temp_free(t1);
22038 }
22039 break;
22040 default:
22041 generate_exception_end(ctx, EXCP_RI);
22042 break;
22043 }
22044 }
c0280983
YK
22045 break;
22046 case NM_MOVE_BALC:
fb32f8c8 22047 check_nms(ctx);
11d0fc10
SM
22048 {
22049 TCGv t0 = tcg_temp_new();
22050 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22051 extract32(ctx->opcode, 1, 20) << 1;
22052 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22053 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22054 extract32(ctx->opcode, 21, 3));
22055 gen_load_gpr(t0, rt);
22056 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22057 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22058 tcg_temp_free(t0);
22059 }
c0280983
YK
22060 break;
22061 case NM_P_BAL:
11d0fc10
SM
22062 {
22063 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22064 extract32(ctx->opcode, 1, 24) << 1;
22065
22066 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22067 /* BC */
22068 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22069 } else {
22070 /* BALC */
22071 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22072 }
22073 }
c0280983
YK
22074 break;
22075 case NM_P_J:
11d0fc10
SM
22076 switch (extract32(ctx->opcode, 12, 4)) {
22077 case NM_JALRC:
22078 case NM_JALRC_HB:
22079 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22080 break;
22081 case NM_P_BALRSC:
22082 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22083 break;
22084 default:
22085 generate_exception_end(ctx, EXCP_RI);
22086 break;
22087 }
c0280983
YK
22088 break;
22089 case NM_P_BR1:
11d0fc10
SM
22090 {
22091 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22092 extract32(ctx->opcode, 1, 13) << 1;
22093 switch (extract32(ctx->opcode, 14, 2)) {
22094 case NM_BEQC:
fb32f8c8 22095 check_nms(ctx);
11d0fc10
SM
22096 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22097 break;
22098 case NM_P_BR3A:
22099 s = sextract32(ctx->opcode, 0, 1) << 14 |
22100 extract32(ctx->opcode, 1, 13) << 1;
22101 check_cp1_enabled(ctx);
22102 switch (extract32(ctx->opcode, 16, 5)) {
22103 case NM_BC1EQZC:
22104 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22105 break;
22106 case NM_BC1NEZC:
22107 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22108 break;
6d033ca7 22109 case NM_BPOSGE32C:
908f6be1 22110 check_dsp_r3(ctx);
6d033ca7
SM
22111 {
22112 int32_t imm = extract32(ctx->opcode, 1, 13) |
22113 extract32(ctx->opcode, 0, 1) << 13;
22114
22115 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22116 imm);
22117 }
22118 break;
11d0fc10
SM
22119 default:
22120 generate_exception_end(ctx, EXCP_RI);
22121 break;
22122 }
22123 break;
22124 case NM_BGEC:
22125 if (rs == rt) {
22126 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22127 } else {
22128 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22129 }
22130 break;
22131 case NM_BGEUC:
22132 if (rs == rt || rt == 0) {
22133 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22134 } else if (rs == 0) {
22135 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22136 } else {
22137 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22138 }
22139 break;
22140 }
22141 }
c0280983
YK
22142 break;
22143 case NM_P_BR2:
11d0fc10
SM
22144 {
22145 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22146 extract32(ctx->opcode, 1, 13) << 1;
22147 switch (extract32(ctx->opcode, 14, 2)) {
22148 case NM_BNEC:
fb32f8c8 22149 check_nms(ctx);
11d0fc10
SM
22150 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22151 break;
22152 case NM_BLTC:
22153 if (rs != 0 && rt != 0 && rs == rt) {
22154 /* NOP */
22155 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22156 } else {
22157 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22158 }
22159 break;
22160 case NM_BLTUC:
22161 if (rs == 0 || rs == rt) {
22162 /* NOP */
22163 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22164 } else {
22165 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22166 }
22167 break;
22168 default:
22169 generate_exception_end(ctx, EXCP_RI);
22170 break;
22171 }
22172 }
c0280983
YK
22173 break;
22174 case NM_P_BRI:
11d0fc10
SM
22175 {
22176 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22177 extract32(ctx->opcode, 1, 10) << 1;
22178 uint32_t u = extract32(ctx->opcode, 11, 7);
22179
22180 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22181 rt, u, s);
22182 }
c0280983
YK
22183 break;
22184 default:
22185 generate_exception_end(ctx, EXCP_RI);
22186 break;
22187 }
22188 return 4;
22189}
22190
c533c0f4
AM
22191static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22192{
ea4ca3c2 22193 uint32_t op;
99e49abf
AM
22194 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22195 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22196 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 22197 int offset;
ea4ca3c2
YK
22198 int imm;
22199
22200 /* make sure instructions are on a halfword boundary */
22201 if (ctx->base.pc_next & 0x1) {
22202 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22203 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22204 tcg_temp_free(tmp);
22205 generate_exception_end(ctx, EXCP_AdEL);
22206 return 2;
22207 }
22208
22209 op = extract32(ctx->opcode, 10, 6);
22210 switch (op) {
22211 case NM_P16_MV:
8869ad02
YK
22212 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22213 if (rt != 0) {
22214 /* MOVE */
22215 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22216 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22217 } else {
22218 /* P16.RI */
22219 switch (extract32(ctx->opcode, 3, 2)) {
22220 case NM_P16_SYSCALL:
22221 if (extract32(ctx->opcode, 2, 1) == 0) {
22222 generate_exception_end(ctx, EXCP_SYSCALL);
22223 } else {
22224 generate_exception_end(ctx, EXCP_RI);
22225 }
22226 break;
22227 case NM_BREAK16:
22228 generate_exception_end(ctx, EXCP_BREAK);
22229 break;
22230 case NM_SDBBP16:
22231 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22232 gen_helper_do_semihosting(cpu_env);
22233 } else {
22234 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22235 generate_exception_end(ctx, EXCP_RI);
22236 } else {
22237 generate_exception_end(ctx, EXCP_DBp);
22238 }
22239 }
22240 break;
22241 default:
22242 generate_exception_end(ctx, EXCP_RI);
22243 break;
22244 }
22245 }
ea4ca3c2
YK
22246 break;
22247 case NM_P16_SHIFT:
c46562fb
YK
22248 {
22249 int shift = extract32(ctx->opcode, 0, 3);
22250 uint32_t opc = 0;
22251 shift = (shift == 0) ? 8 : shift;
22252
22253 switch (extract32(ctx->opcode, 3, 1)) {
22254 case NM_SLL16:
22255 opc = OPC_SLL;
22256 break;
22257 case NM_SRL16:
22258 opc = OPC_SRL;
22259 break;
22260 }
22261 gen_shift_imm(ctx, opc, rt, rs, shift);
22262 }
ea4ca3c2
YK
22263 break;
22264 case NM_P16C:
8bdb7029
YK
22265 switch (ctx->opcode & 1) {
22266 case NM_POOL16C_0:
80845edf 22267 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
22268 break;
22269 case NM_LWXS16:
22270 gen_ldxs(ctx, rt, rs, rd);
22271 break;
22272 }
ea4ca3c2
YK
22273 break;
22274 case NM_P16_A1:
22275 switch (extract32(ctx->opcode, 6, 1)) {
22276 case NM_ADDIUR1SP:
22277 imm = extract32(ctx->opcode, 0, 6) << 2;
22278 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22279 break;
22280 default:
22281 generate_exception_end(ctx, EXCP_RI);
22282 break;
22283 }
22284 break;
22285 case NM_P16_A2:
22286 switch (extract32(ctx->opcode, 3, 1)) {
22287 case NM_ADDIUR2:
22288 imm = extract32(ctx->opcode, 0, 3) << 2;
22289 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22290 break;
22291 case NM_P_ADDIURS5:
22292 rt = extract32(ctx->opcode, 5, 5);
22293 if (rt != 0) {
22294 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22295 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22296 (extract32(ctx->opcode, 0, 3));
22297 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22298 }
22299 break;
22300 }
22301 break;
22302 case NM_P16_ADDU:
22303 switch (ctx->opcode & 0x1) {
22304 case NM_ADDU16:
22305 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22306 break;
22307 case NM_SUBU16:
22308 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22309 break;
22310 }
22311 break;
22312 case NM_P16_4X4:
22313 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22314 extract32(ctx->opcode, 5, 3);
22315 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22316 extract32(ctx->opcode, 0, 3);
22317 rt = decode_gpr_gpr4(rt);
22318 rs = decode_gpr_gpr4(rs);
22319 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22320 (extract32(ctx->opcode, 3, 1))) {
22321 case NM_ADDU4X4:
fb32f8c8 22322 check_nms(ctx);
ea4ca3c2
YK
22323 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22324 break;
22325 case NM_MUL4X4:
fb32f8c8 22326 check_nms(ctx);
ea4ca3c2
YK
22327 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22328 break;
22329 default:
22330 generate_exception_end(ctx, EXCP_RI);
22331 break;
22332 }
22333 break;
22334 case NM_LI16:
8869ad02
YK
22335 {
22336 int imm = extract32(ctx->opcode, 0, 7);
22337 imm = (imm == 0x7f ? -1 : imm);
22338 if (rt != 0) {
22339 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22340 }
22341 }
ea4ca3c2
YK
22342 break;
22343 case NM_ANDI16:
80845edf
YK
22344 {
22345 uint32_t u = extract32(ctx->opcode, 0, 4);
22346 u = (u == 12) ? 0xff :
22347 (u == 13) ? 0xffff : u;
22348 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22349 }
ea4ca3c2
YK
22350 break;
22351 case NM_P16_LB:
8bdb7029
YK
22352 offset = extract32(ctx->opcode, 0, 2);
22353 switch (extract32(ctx->opcode, 2, 2)) {
22354 case NM_LB16:
22355 gen_ld(ctx, OPC_LB, rt, rs, offset);
22356 break;
22357 case NM_SB16:
22358 rt = decode_gpr_gpr3_src_store(
99e49abf 22359 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22360 gen_st(ctx, OPC_SB, rt, rs, offset);
22361 break;
22362 case NM_LBU16:
22363 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22364 break;
22365 default:
22366 generate_exception_end(ctx, EXCP_RI);
22367 break;
22368 }
ea4ca3c2
YK
22369 break;
22370 case NM_P16_LH:
8bdb7029
YK
22371 offset = extract32(ctx->opcode, 1, 2) << 1;
22372 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22373 case NM_LH16:
22374 gen_ld(ctx, OPC_LH, rt, rs, offset);
22375 break;
22376 case NM_SH16:
22377 rt = decode_gpr_gpr3_src_store(
99e49abf 22378 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22379 gen_st(ctx, OPC_SH, rt, rs, offset);
22380 break;
22381 case NM_LHU16:
22382 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22383 break;
22384 default:
22385 generate_exception_end(ctx, EXCP_RI);
22386 break;
22387 }
ea4ca3c2
YK
22388 break;
22389 case NM_LW16:
8bdb7029
YK
22390 offset = extract32(ctx->opcode, 0, 4) << 2;
22391 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22392 break;
22393 case NM_LWSP16:
8bdb7029
YK
22394 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22395 offset = extract32(ctx->opcode, 0, 5) << 2;
22396 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22397 break;
22398 case NM_LW4X4:
fb32f8c8 22399 check_nms(ctx);
8bdb7029
YK
22400 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22401 extract32(ctx->opcode, 5, 3);
22402 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22403 extract32(ctx->opcode, 0, 3);
22404 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22405 (extract32(ctx->opcode, 8, 1) << 2);
22406 rt = decode_gpr_gpr4(rt);
22407 rs = decode_gpr_gpr4(rs);
22408 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22409 break;
22410 case NM_SW4X4:
fb32f8c8 22411 check_nms(ctx);
8bdb7029
YK
22412 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22413 extract32(ctx->opcode, 5, 3);
22414 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22415 extract32(ctx->opcode, 0, 3);
22416 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22417 (extract32(ctx->opcode, 8, 1) << 2);
22418 rt = decode_gpr_gpr4_zero(rt);
22419 rs = decode_gpr_gpr4(rs);
22420 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22421 break;
22422 case NM_LWGP16:
8bdb7029
YK
22423 offset = extract32(ctx->opcode, 0, 7) << 2;
22424 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22425 break;
22426 case NM_SWSP16:
8bdb7029
YK
22427 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22428 offset = extract32(ctx->opcode, 0, 5) << 2;
22429 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22430 break;
22431 case NM_SW16:
8bdb7029 22432 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
22433 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22434 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
22435 offset = extract32(ctx->opcode, 0, 4) << 2;
22436 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22437 break;
22438 case NM_SWGP16:
8bdb7029 22439 rt = decode_gpr_gpr3_src_store(
99e49abf 22440 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22441 offset = extract32(ctx->opcode, 0, 7) << 2;
22442 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22443 break;
22444 case NM_BC16:
764371d2
SM
22445 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22446 (sextract32(ctx->opcode, 0, 1) << 10) |
22447 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22448 break;
22449 case NM_BALC16:
764371d2
SM
22450 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22451 (sextract32(ctx->opcode, 0, 1) << 10) |
22452 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22453 break;
22454 case NM_BEQZC16:
764371d2
SM
22455 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22456 (sextract32(ctx->opcode, 0, 1) << 7) |
22457 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22458 break;
22459 case NM_BNEZC16:
764371d2
SM
22460 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22461 (sextract32(ctx->opcode, 0, 1) << 7) |
22462 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22463 break;
22464 case NM_P16_BR:
764371d2
SM
22465 switch (ctx->opcode & 0xf) {
22466 case 0:
22467 /* P16.JRC */
22468 switch (extract32(ctx->opcode, 4, 1)) {
22469 case NM_JRC:
22470 gen_compute_branch_nm(ctx, OPC_JR, 2,
22471 extract32(ctx->opcode, 5, 5), 0, 0);
22472 break;
22473 case NM_JALRC16:
22474 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22475 extract32(ctx->opcode, 5, 5), 31, 0);
22476 break;
22477 }
22478 break;
22479 default:
22480 {
22481 /* P16.BRI */
22482 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22483 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22484 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22485 extract32(ctx->opcode, 0, 4) << 1);
22486 }
22487 break;
22488 }
ea4ca3c2
YK
22489 break;
22490 case NM_P16_SR:
bf0718c5
SM
22491 {
22492 int count = extract32(ctx->opcode, 0, 4);
22493 int u = extract32(ctx->opcode, 4, 4) << 4;
22494
22495 rt = 30 + extract32(ctx->opcode, 9, 1);
22496 switch (extract32(ctx->opcode, 8, 1)) {
22497 case NM_SAVE16:
22498 gen_save(ctx, rt, count, 0, u);
22499 break;
22500 case NM_RESTORE_JRC16:
22501 gen_restore(ctx, rt, count, 0, u);
22502 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22503 break;
22504 }
22505 }
ea4ca3c2
YK
22506 break;
22507 case NM_MOVEP:
ea4ca3c2 22508 case NM_MOVEPREV:
fb32f8c8 22509 check_nms(ctx);
4d18232c
YK
22510 {
22511 static const int gpr2reg1[] = {4, 5, 6, 7};
22512 static const int gpr2reg2[] = {5, 6, 7, 8};
22513 int re;
22514 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22515 extract32(ctx->opcode, 8, 1);
22516 int r1 = gpr2reg1[rd2];
22517 int r2 = gpr2reg2[rd2];
22518 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22519 extract32(ctx->opcode, 0, 3);
22520 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22521 extract32(ctx->opcode, 5, 3);
22522 TCGv t0 = tcg_temp_new();
22523 TCGv t1 = tcg_temp_new();
22524 if (op == NM_MOVEP) {
22525 rd = r1;
22526 re = r2;
22527 rs = decode_gpr_gpr4_zero(r3);
22528 rt = decode_gpr_gpr4_zero(r4);
22529 } else {
22530 rd = decode_gpr_gpr4(r3);
22531 re = decode_gpr_gpr4(r4);
22532 rs = r1;
22533 rt = r2;
22534 }
22535 gen_load_gpr(t0, rs);
22536 gen_load_gpr(t1, rt);
22537 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22538 tcg_gen_mov_tl(cpu_gpr[re], t1);
22539 tcg_temp_free(t0);
22540 tcg_temp_free(t1);
22541 }
ea4ca3c2
YK
22542 break;
22543 default:
c0280983 22544 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
22545 }
22546
c533c0f4
AM
22547 return 2;
22548}
22549
22550
3c824109
NF
22551/* SmartMIPS extension to MIPS32 */
22552
22553#if defined(TARGET_MIPS64)
22554
22555/* MDMX extension to MIPS64 */
22556
22557#endif
22558
9b1a1d68 22559/* MIPSDSP functions. */
d75c135e 22560static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
22561 int rd, int base, int offset)
22562{
9b1a1d68
JL
22563 TCGv t0;
22564
9b1a1d68
JL
22565 check_dsp(ctx);
22566 t0 = tcg_temp_new();
22567
22568 if (base == 0) {
22569 gen_load_gpr(t0, offset);
22570 } else if (offset == 0) {
22571 gen_load_gpr(t0, base);
22572 } else {
22573 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22574 }
22575
9b1a1d68
JL
22576 switch (opc) {
22577 case OPC_LBUX:
5f68f5ae 22578 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 22579 gen_store_gpr(t0, rd);
9b1a1d68
JL
22580 break;
22581 case OPC_LHX:
5f68f5ae 22582 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 22583 gen_store_gpr(t0, rd);
9b1a1d68
JL
22584 break;
22585 case OPC_LWX:
5f68f5ae 22586 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 22587 gen_store_gpr(t0, rd);
9b1a1d68
JL
22588 break;
22589#if defined(TARGET_MIPS64)
22590 case OPC_LDX:
5f68f5ae 22591 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 22592 gen_store_gpr(t0, rd);
9b1a1d68
JL
22593 break;
22594#endif
22595 }
9b1a1d68
JL
22596 tcg_temp_free(t0);
22597}
22598
461c08df
JL
22599static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22600 int ret, int v1, int v2)
22601{
461c08df
JL
22602 TCGv v1_t;
22603 TCGv v2_t;
22604
22605 if (ret == 0) {
22606 /* Treat as NOP. */
461c08df
JL
22607 return;
22608 }
22609
22610 v1_t = tcg_temp_new();
22611 v2_t = tcg_temp_new();
22612
22613 gen_load_gpr(v1_t, v1);
22614 gen_load_gpr(v2_t, v2);
22615
22616 switch (op1) {
22617 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22618 case OPC_MULT_G_2E:
908f6be1 22619 check_dsp_r2(ctx);
461c08df
JL
22620 switch (op2) {
22621 case OPC_ADDUH_QB:
22622 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22623 break;
22624 case OPC_ADDUH_R_QB:
22625 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22626 break;
22627 case OPC_ADDQH_PH:
22628 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22629 break;
22630 case OPC_ADDQH_R_PH:
22631 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22632 break;
22633 case OPC_ADDQH_W:
22634 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22635 break;
22636 case OPC_ADDQH_R_W:
22637 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22638 break;
22639 case OPC_SUBUH_QB:
22640 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22641 break;
22642 case OPC_SUBUH_R_QB:
22643 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22644 break;
22645 case OPC_SUBQH_PH:
22646 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22647 break;
22648 case OPC_SUBQH_R_PH:
22649 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22650 break;
22651 case OPC_SUBQH_W:
22652 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22653 break;
22654 case OPC_SUBQH_R_W:
22655 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22656 break;
22657 }
22658 break;
22659 case OPC_ABSQ_S_PH_DSP:
22660 switch (op2) {
22661 case OPC_ABSQ_S_QB:
908f6be1 22662 check_dsp_r2(ctx);
461c08df
JL
22663 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22664 break;
22665 case OPC_ABSQ_S_PH:
22666 check_dsp(ctx);
22667 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22668 break;
22669 case OPC_ABSQ_S_W:
22670 check_dsp(ctx);
22671 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22672 break;
22673 case OPC_PRECEQ_W_PHL:
22674 check_dsp(ctx);
22675 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22676 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22677 break;
22678 case OPC_PRECEQ_W_PHR:
22679 check_dsp(ctx);
22680 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22681 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22682 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22683 break;
22684 case OPC_PRECEQU_PH_QBL:
22685 check_dsp(ctx);
22686 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22687 break;
22688 case OPC_PRECEQU_PH_QBR:
22689 check_dsp(ctx);
22690 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22691 break;
22692 case OPC_PRECEQU_PH_QBLA:
22693 check_dsp(ctx);
22694 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22695 break;
22696 case OPC_PRECEQU_PH_QBRA:
22697 check_dsp(ctx);
22698 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22699 break;
22700 case OPC_PRECEU_PH_QBL:
22701 check_dsp(ctx);
22702 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22703 break;
22704 case OPC_PRECEU_PH_QBR:
22705 check_dsp(ctx);
22706 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22707 break;
22708 case OPC_PRECEU_PH_QBLA:
22709 check_dsp(ctx);
22710 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22711 break;
22712 case OPC_PRECEU_PH_QBRA:
22713 check_dsp(ctx);
22714 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22715 break;
22716 }
22717 break;
22718 case OPC_ADDU_QB_DSP:
22719 switch (op2) {
22720 case OPC_ADDQ_PH:
22721 check_dsp(ctx);
22722 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22723 break;
22724 case OPC_ADDQ_S_PH:
22725 check_dsp(ctx);
22726 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22727 break;
22728 case OPC_ADDQ_S_W:
22729 check_dsp(ctx);
22730 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22731 break;
22732 case OPC_ADDU_QB:
22733 check_dsp(ctx);
22734 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22735 break;
22736 case OPC_ADDU_S_QB:
22737 check_dsp(ctx);
22738 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22739 break;
22740 case OPC_ADDU_PH:
908f6be1 22741 check_dsp_r2(ctx);
461c08df
JL
22742 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22743 break;
22744 case OPC_ADDU_S_PH:
908f6be1 22745 check_dsp_r2(ctx);
461c08df
JL
22746 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22747 break;
22748 case OPC_SUBQ_PH:
22749 check_dsp(ctx);
22750 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22751 break;
22752 case OPC_SUBQ_S_PH:
22753 check_dsp(ctx);
22754 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22755 break;
22756 case OPC_SUBQ_S_W:
22757 check_dsp(ctx);
22758 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22759 break;
22760 case OPC_SUBU_QB:
22761 check_dsp(ctx);
22762 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22763 break;
22764 case OPC_SUBU_S_QB:
22765 check_dsp(ctx);
22766 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22767 break;
22768 case OPC_SUBU_PH:
908f6be1 22769 check_dsp_r2(ctx);
461c08df
JL
22770 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22771 break;
22772 case OPC_SUBU_S_PH:
908f6be1 22773 check_dsp_r2(ctx);
461c08df
JL
22774 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22775 break;
22776 case OPC_ADDSC:
22777 check_dsp(ctx);
22778 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22779 break;
22780 case OPC_ADDWC:
22781 check_dsp(ctx);
22782 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22783 break;
22784 case OPC_MODSUB:
22785 check_dsp(ctx);
22786 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22787 break;
22788 case OPC_RADDU_W_QB:
22789 check_dsp(ctx);
22790 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22791 break;
22792 }
22793 break;
22794 case OPC_CMPU_EQ_QB_DSP:
22795 switch (op2) {
22796 case OPC_PRECR_QB_PH:
908f6be1 22797 check_dsp_r2(ctx);
461c08df
JL
22798 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22799 break;
22800 case OPC_PRECRQ_QB_PH:
22801 check_dsp(ctx);
22802 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22803 break;
22804 case OPC_PRECR_SRA_PH_W:
908f6be1 22805 check_dsp_r2(ctx);
461c08df
JL
22806 {
22807 TCGv_i32 sa_t = tcg_const_i32(v2);
22808 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22809 cpu_gpr[ret]);
22810 tcg_temp_free_i32(sa_t);
22811 break;
22812 }
22813 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22814 check_dsp_r2(ctx);
461c08df
JL
22815 {
22816 TCGv_i32 sa_t = tcg_const_i32(v2);
22817 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22818 cpu_gpr[ret]);
22819 tcg_temp_free_i32(sa_t);
22820 break;
22821 }
22822 case OPC_PRECRQ_PH_W:
22823 check_dsp(ctx);
22824 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22825 break;
22826 case OPC_PRECRQ_RS_PH_W:
22827 check_dsp(ctx);
22828 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22829 break;
22830 case OPC_PRECRQU_S_QB_PH:
22831 check_dsp(ctx);
22832 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22833 break;
22834 }
22835 break;
22836#ifdef TARGET_MIPS64
22837 case OPC_ABSQ_S_QH_DSP:
22838 switch (op2) {
22839 case OPC_PRECEQ_L_PWL:
22840 check_dsp(ctx);
22841 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22842 break;
22843 case OPC_PRECEQ_L_PWR:
22844 check_dsp(ctx);
22845 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22846 break;
22847 case OPC_PRECEQ_PW_QHL:
22848 check_dsp(ctx);
22849 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22850 break;
22851 case OPC_PRECEQ_PW_QHR:
22852 check_dsp(ctx);
22853 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22854 break;
22855 case OPC_PRECEQ_PW_QHLA:
22856 check_dsp(ctx);
22857 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22858 break;
22859 case OPC_PRECEQ_PW_QHRA:
22860 check_dsp(ctx);
22861 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22862 break;
22863 case OPC_PRECEQU_QH_OBL:
22864 check_dsp(ctx);
22865 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22866 break;
22867 case OPC_PRECEQU_QH_OBR:
22868 check_dsp(ctx);
22869 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22870 break;
22871 case OPC_PRECEQU_QH_OBLA:
22872 check_dsp(ctx);
22873 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22874 break;
22875 case OPC_PRECEQU_QH_OBRA:
22876 check_dsp(ctx);
22877 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22878 break;
22879 case OPC_PRECEU_QH_OBL:
22880 check_dsp(ctx);
22881 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22882 break;
22883 case OPC_PRECEU_QH_OBR:
22884 check_dsp(ctx);
22885 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22886 break;
22887 case OPC_PRECEU_QH_OBLA:
22888 check_dsp(ctx);
22889 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22890 break;
22891 case OPC_PRECEU_QH_OBRA:
22892 check_dsp(ctx);
22893 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22894 break;
22895 case OPC_ABSQ_S_OB:
908f6be1 22896 check_dsp_r2(ctx);
461c08df
JL
22897 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22898 break;
22899 case OPC_ABSQ_S_PW:
22900 check_dsp(ctx);
22901 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22902 break;
22903 case OPC_ABSQ_S_QH:
22904 check_dsp(ctx);
22905 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22906 break;
22907 }
22908 break;
22909 case OPC_ADDU_OB_DSP:
22910 switch (op2) {
22911 case OPC_RADDU_L_OB:
22912 check_dsp(ctx);
22913 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22914 break;
22915 case OPC_SUBQ_PW:
22916 check_dsp(ctx);
22917 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22918 break;
22919 case OPC_SUBQ_S_PW:
22920 check_dsp(ctx);
22921 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22922 break;
22923 case OPC_SUBQ_QH:
22924 check_dsp(ctx);
22925 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22926 break;
22927 case OPC_SUBQ_S_QH:
22928 check_dsp(ctx);
22929 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22930 break;
22931 case OPC_SUBU_OB:
22932 check_dsp(ctx);
22933 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22934 break;
22935 case OPC_SUBU_S_OB:
22936 check_dsp(ctx);
22937 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22938 break;
22939 case OPC_SUBU_QH:
908f6be1 22940 check_dsp_r2(ctx);
461c08df
JL
22941 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22942 break;
22943 case OPC_SUBU_S_QH:
908f6be1 22944 check_dsp_r2(ctx);
461c08df
JL
22945 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22946 break;
22947 case OPC_SUBUH_OB:
908f6be1 22948 check_dsp_r2(ctx);
461c08df
JL
22949 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22950 break;
22951 case OPC_SUBUH_R_OB:
908f6be1 22952 check_dsp_r2(ctx);
461c08df
JL
22953 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22954 break;
22955 case OPC_ADDQ_PW:
22956 check_dsp(ctx);
22957 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22958 break;
22959 case OPC_ADDQ_S_PW:
22960 check_dsp(ctx);
22961 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22962 break;
22963 case OPC_ADDQ_QH:
22964 check_dsp(ctx);
22965 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22966 break;
22967 case OPC_ADDQ_S_QH:
22968 check_dsp(ctx);
22969 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22970 break;
22971 case OPC_ADDU_OB:
22972 check_dsp(ctx);
22973 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22974 break;
22975 case OPC_ADDU_S_OB:
22976 check_dsp(ctx);
22977 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22978 break;
22979 case OPC_ADDU_QH:
908f6be1 22980 check_dsp_r2(ctx);
461c08df
JL
22981 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22982 break;
22983 case OPC_ADDU_S_QH:
908f6be1 22984 check_dsp_r2(ctx);
461c08df
JL
22985 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22986 break;
22987 case OPC_ADDUH_OB:
908f6be1 22988 check_dsp_r2(ctx);
461c08df
JL
22989 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22990 break;
22991 case OPC_ADDUH_R_OB:
908f6be1 22992 check_dsp_r2(ctx);
461c08df
JL
22993 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22994 break;
22995 }
22996 break;
22997 case OPC_CMPU_EQ_OB_DSP:
22998 switch (op2) {
22999 case OPC_PRECR_OB_QH:
908f6be1 23000 check_dsp_r2(ctx);
461c08df
JL
23001 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23002 break;
23003 case OPC_PRECR_SRA_QH_PW:
908f6be1 23004 check_dsp_r2(ctx);
461c08df
JL
23005 {
23006 TCGv_i32 ret_t = tcg_const_i32(ret);
23007 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23008 tcg_temp_free_i32(ret_t);
23009 break;
23010 }
23011 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 23012 check_dsp_r2(ctx);
461c08df
JL
23013 {
23014 TCGv_i32 sa_v = tcg_const_i32(ret);
23015 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23016 tcg_temp_free_i32(sa_v);
23017 break;
23018 }
23019 case OPC_PRECRQ_OB_QH:
23020 check_dsp(ctx);
23021 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23022 break;
23023 case OPC_PRECRQ_PW_L:
23024 check_dsp(ctx);
23025 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23026 break;
23027 case OPC_PRECRQ_QH_PW:
23028 check_dsp(ctx);
23029 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23030 break;
23031 case OPC_PRECRQ_RS_QH_PW:
23032 check_dsp(ctx);
23033 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23034 break;
23035 case OPC_PRECRQU_S_OB_QH:
23036 check_dsp(ctx);
23037 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23038 break;
23039 }
23040 break;
23041#endif
23042 }
23043
23044 tcg_temp_free(v1_t);
23045 tcg_temp_free(v2_t);
461c08df 23046}
9b1a1d68 23047
77c5fa8b
JL
23048static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23049 int ret, int v1, int v2)
23050{
23051 uint32_t op2;
77c5fa8b
JL
23052 TCGv t0;
23053 TCGv v1_t;
23054 TCGv v2_t;
23055
23056 if (ret == 0) {
23057 /* Treat as NOP. */
77c5fa8b
JL
23058 return;
23059 }
23060
23061 t0 = tcg_temp_new();
23062 v1_t = tcg_temp_new();
23063 v2_t = tcg_temp_new();
23064
23065 tcg_gen_movi_tl(t0, v1);
23066 gen_load_gpr(v1_t, v1);
23067 gen_load_gpr(v2_t, v2);
23068
23069 switch (opc) {
23070 case OPC_SHLL_QB_DSP:
23071 {
23072 op2 = MASK_SHLL_QB(ctx->opcode);
23073 switch (op2) {
23074 case OPC_SHLL_QB:
23075 check_dsp(ctx);
23076 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23077 break;
23078 case OPC_SHLLV_QB:
23079 check_dsp(ctx);
23080 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23081 break;
23082 case OPC_SHLL_PH:
23083 check_dsp(ctx);
23084 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23085 break;
23086 case OPC_SHLLV_PH:
23087 check_dsp(ctx);
23088 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23089 break;
23090 case OPC_SHLL_S_PH:
23091 check_dsp(ctx);
23092 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23093 break;
23094 case OPC_SHLLV_S_PH:
23095 check_dsp(ctx);
23096 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23097 break;
23098 case OPC_SHLL_S_W:
23099 check_dsp(ctx);
23100 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23101 break;
23102 case OPC_SHLLV_S_W:
23103 check_dsp(ctx);
23104 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23105 break;
23106 case OPC_SHRL_QB:
23107 check_dsp(ctx);
23108 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23109 break;
23110 case OPC_SHRLV_QB:
23111 check_dsp(ctx);
23112 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23113 break;
23114 case OPC_SHRL_PH:
908f6be1 23115 check_dsp_r2(ctx);
77c5fa8b
JL
23116 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23117 break;
23118 case OPC_SHRLV_PH:
908f6be1 23119 check_dsp_r2(ctx);
77c5fa8b
JL
23120 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23121 break;
23122 case OPC_SHRA_QB:
908f6be1 23123 check_dsp_r2(ctx);
77c5fa8b
JL
23124 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23125 break;
23126 case OPC_SHRA_R_QB:
908f6be1 23127 check_dsp_r2(ctx);
77c5fa8b
JL
23128 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23129 break;
23130 case OPC_SHRAV_QB:
908f6be1 23131 check_dsp_r2(ctx);
77c5fa8b
JL
23132 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23133 break;
23134 case OPC_SHRAV_R_QB:
908f6be1 23135 check_dsp_r2(ctx);
77c5fa8b
JL
23136 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23137 break;
23138 case OPC_SHRA_PH:
23139 check_dsp(ctx);
23140 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23141 break;
23142 case OPC_SHRA_R_PH:
23143 check_dsp(ctx);
23144 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23145 break;
23146 case OPC_SHRAV_PH:
23147 check_dsp(ctx);
23148 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23149 break;
23150 case OPC_SHRAV_R_PH:
23151 check_dsp(ctx);
23152 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23153 break;
23154 case OPC_SHRA_R_W:
23155 check_dsp(ctx);
23156 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23157 break;
23158 case OPC_SHRAV_R_W:
23159 check_dsp(ctx);
23160 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23161 break;
23162 default: /* Invalid */
23163 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 23164 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23165 break;
23166 }
23167 break;
23168 }
23169#ifdef TARGET_MIPS64
23170 case OPC_SHLL_OB_DSP:
23171 op2 = MASK_SHLL_OB(ctx->opcode);
23172 switch (op2) {
23173 case OPC_SHLL_PW:
23174 check_dsp(ctx);
23175 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23176 break;
23177 case OPC_SHLLV_PW:
23178 check_dsp(ctx);
23179 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23180 break;
23181 case OPC_SHLL_S_PW:
23182 check_dsp(ctx);
23183 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23184 break;
23185 case OPC_SHLLV_S_PW:
23186 check_dsp(ctx);
23187 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23188 break;
23189 case OPC_SHLL_OB:
23190 check_dsp(ctx);
23191 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23192 break;
23193 case OPC_SHLLV_OB:
23194 check_dsp(ctx);
23195 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23196 break;
23197 case OPC_SHLL_QH:
23198 check_dsp(ctx);
23199 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23200 break;
23201 case OPC_SHLLV_QH:
23202 check_dsp(ctx);
23203 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23204 break;
23205 case OPC_SHLL_S_QH:
23206 check_dsp(ctx);
23207 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23208 break;
23209 case OPC_SHLLV_S_QH:
23210 check_dsp(ctx);
23211 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23212 break;
23213 case OPC_SHRA_OB:
908f6be1 23214 check_dsp_r2(ctx);
77c5fa8b
JL
23215 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23216 break;
23217 case OPC_SHRAV_OB:
908f6be1 23218 check_dsp_r2(ctx);
77c5fa8b
JL
23219 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23220 break;
23221 case OPC_SHRA_R_OB:
908f6be1 23222 check_dsp_r2(ctx);
77c5fa8b
JL
23223 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23224 break;
23225 case OPC_SHRAV_R_OB:
908f6be1 23226 check_dsp_r2(ctx);
77c5fa8b
JL
23227 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23228 break;
23229 case OPC_SHRA_PW:
23230 check_dsp(ctx);
23231 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23232 break;
23233 case OPC_SHRAV_PW:
23234 check_dsp(ctx);
23235 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23236 break;
23237 case OPC_SHRA_R_PW:
23238 check_dsp(ctx);
23239 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23240 break;
23241 case OPC_SHRAV_R_PW:
23242 check_dsp(ctx);
23243 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23244 break;
23245 case OPC_SHRA_QH:
23246 check_dsp(ctx);
23247 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23248 break;
23249 case OPC_SHRAV_QH:
23250 check_dsp(ctx);
23251 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23252 break;
23253 case OPC_SHRA_R_QH:
23254 check_dsp(ctx);
23255 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23256 break;
23257 case OPC_SHRAV_R_QH:
23258 check_dsp(ctx);
23259 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23260 break;
23261 case OPC_SHRL_OB:
23262 check_dsp(ctx);
23263 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23264 break;
23265 case OPC_SHRLV_OB:
23266 check_dsp(ctx);
23267 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23268 break;
23269 case OPC_SHRL_QH:
908f6be1 23270 check_dsp_r2(ctx);
77c5fa8b
JL
23271 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23272 break;
23273 case OPC_SHRLV_QH:
908f6be1 23274 check_dsp_r2(ctx);
77c5fa8b
JL
23275 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23276 break;
23277 default: /* Invalid */
23278 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 23279 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23280 break;
23281 }
23282 break;
23283#endif
23284 }
23285
23286 tcg_temp_free(t0);
23287 tcg_temp_free(v1_t);
23288 tcg_temp_free(v2_t);
77c5fa8b
JL
23289}
23290
a22260ae
JL
23291static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23292 int ret, int v1, int v2, int check_ret)
23293{
a22260ae
JL
23294 TCGv_i32 t0;
23295 TCGv v1_t;
23296 TCGv v2_t;
23297
23298 if ((ret == 0) && (check_ret == 1)) {
23299 /* Treat as NOP. */
a22260ae
JL
23300 return;
23301 }
23302
23303 t0 = tcg_temp_new_i32();
23304 v1_t = tcg_temp_new();
23305 v2_t = tcg_temp_new();
23306
23307 tcg_gen_movi_i32(t0, ret);
23308 gen_load_gpr(v1_t, v1);
23309 gen_load_gpr(v2_t, v2);
23310
23311 switch (op1) {
7480515f
AM
23312 /*
23313 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23314 * the same mask and op1.
23315 */
a22260ae 23316 case OPC_MULT_G_2E:
908f6be1 23317 check_dsp_r2(ctx);
a22260ae
JL
23318 switch (op2) {
23319 case OPC_MUL_PH:
23320 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23321 break;
23322 case OPC_MUL_S_PH:
23323 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23324 break;
23325 case OPC_MULQ_S_W:
23326 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23327 break;
23328 case OPC_MULQ_RS_W:
23329 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23330 break;
23331 }
23332 break;
23333 case OPC_DPA_W_PH_DSP:
23334 switch (op2) {
23335 case OPC_DPAU_H_QBL:
23336 check_dsp(ctx);
23337 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23338 break;
23339 case OPC_DPAU_H_QBR:
23340 check_dsp(ctx);
23341 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23342 break;
23343 case OPC_DPSU_H_QBL:
23344 check_dsp(ctx);
23345 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23346 break;
23347 case OPC_DPSU_H_QBR:
23348 check_dsp(ctx);
23349 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23350 break;
23351 case OPC_DPA_W_PH:
908f6be1 23352 check_dsp_r2(ctx);
a22260ae
JL
23353 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23354 break;
23355 case OPC_DPAX_W_PH:
908f6be1 23356 check_dsp_r2(ctx);
a22260ae
JL
23357 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23358 break;
23359 case OPC_DPAQ_S_W_PH:
23360 check_dsp(ctx);
23361 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23362 break;
23363 case OPC_DPAQX_S_W_PH:
908f6be1 23364 check_dsp_r2(ctx);
a22260ae
JL
23365 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23366 break;
23367 case OPC_DPAQX_SA_W_PH:
908f6be1 23368 check_dsp_r2(ctx);
a22260ae
JL
23369 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23370 break;
23371 case OPC_DPS_W_PH:
908f6be1 23372 check_dsp_r2(ctx);
a22260ae
JL
23373 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23374 break;
23375 case OPC_DPSX_W_PH:
908f6be1 23376 check_dsp_r2(ctx);
a22260ae
JL
23377 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23378 break;
23379 case OPC_DPSQ_S_W_PH:
23380 check_dsp(ctx);
23381 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23382 break;
23383 case OPC_DPSQX_S_W_PH:
908f6be1 23384 check_dsp_r2(ctx);
a22260ae
JL
23385 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23386 break;
23387 case OPC_DPSQX_SA_W_PH:
908f6be1 23388 check_dsp_r2(ctx);
a22260ae
JL
23389 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23390 break;
23391 case OPC_MULSAQ_S_W_PH:
23392 check_dsp(ctx);
23393 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23394 break;
23395 case OPC_DPAQ_SA_L_W:
23396 check_dsp(ctx);
23397 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23398 break;
23399 case OPC_DPSQ_SA_L_W:
23400 check_dsp(ctx);
23401 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23402 break;
23403 case OPC_MAQ_S_W_PHL:
23404 check_dsp(ctx);
23405 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23406 break;
23407 case OPC_MAQ_S_W_PHR:
23408 check_dsp(ctx);
23409 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23410 break;
23411 case OPC_MAQ_SA_W_PHL:
23412 check_dsp(ctx);
23413 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23414 break;
23415 case OPC_MAQ_SA_W_PHR:
23416 check_dsp(ctx);
23417 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23418 break;
23419 case OPC_MULSA_W_PH:
908f6be1 23420 check_dsp_r2(ctx);
a22260ae
JL
23421 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23422 break;
23423 }
23424 break;
23425#ifdef TARGET_MIPS64
23426 case OPC_DPAQ_W_QH_DSP:
23427 {
23428 int ac = ret & 0x03;
23429 tcg_gen_movi_i32(t0, ac);
23430
23431 switch (op2) {
23432 case OPC_DMADD:
23433 check_dsp(ctx);
23434 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23435 break;
23436 case OPC_DMADDU:
23437 check_dsp(ctx);
23438 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23439 break;
23440 case OPC_DMSUB:
23441 check_dsp(ctx);
23442 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23443 break;
23444 case OPC_DMSUBU:
23445 check_dsp(ctx);
23446 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23447 break;
23448 case OPC_DPA_W_QH:
908f6be1 23449 check_dsp_r2(ctx);
a22260ae
JL
23450 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23451 break;
23452 case OPC_DPAQ_S_W_QH:
23453 check_dsp(ctx);
23454 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23455 break;
23456 case OPC_DPAQ_SA_L_PW:
23457 check_dsp(ctx);
23458 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23459 break;
23460 case OPC_DPAU_H_OBL:
23461 check_dsp(ctx);
23462 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23463 break;
23464 case OPC_DPAU_H_OBR:
23465 check_dsp(ctx);
23466 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23467 break;
23468 case OPC_DPS_W_QH:
908f6be1 23469 check_dsp_r2(ctx);
a22260ae
JL
23470 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23471 break;
23472 case OPC_DPSQ_S_W_QH:
23473 check_dsp(ctx);
23474 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23475 break;
23476 case OPC_DPSQ_SA_L_PW:
23477 check_dsp(ctx);
23478 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23479 break;
23480 case OPC_DPSU_H_OBL:
23481 check_dsp(ctx);
23482 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23483 break;
23484 case OPC_DPSU_H_OBR:
23485 check_dsp(ctx);
23486 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23487 break;
23488 case OPC_MAQ_S_L_PWL:
23489 check_dsp(ctx);
23490 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23491 break;
23492 case OPC_MAQ_S_L_PWR:
23493 check_dsp(ctx);
23494 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23495 break;
23496 case OPC_MAQ_S_W_QHLL:
23497 check_dsp(ctx);
23498 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23499 break;
23500 case OPC_MAQ_SA_W_QHLL:
23501 check_dsp(ctx);
23502 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23503 break;
23504 case OPC_MAQ_S_W_QHLR:
23505 check_dsp(ctx);
23506 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23507 break;
23508 case OPC_MAQ_SA_W_QHLR:
23509 check_dsp(ctx);
23510 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23511 break;
23512 case OPC_MAQ_S_W_QHRL:
23513 check_dsp(ctx);
23514 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23515 break;
23516 case OPC_MAQ_SA_W_QHRL:
23517 check_dsp(ctx);
23518 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23519 break;
23520 case OPC_MAQ_S_W_QHRR:
23521 check_dsp(ctx);
23522 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23523 break;
23524 case OPC_MAQ_SA_W_QHRR:
23525 check_dsp(ctx);
23526 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23527 break;
23528 case OPC_MULSAQ_S_L_PW:
23529 check_dsp(ctx);
23530 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23531 break;
23532 case OPC_MULSAQ_S_W_QH:
23533 check_dsp(ctx);
23534 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23535 break;
23536 }
23537 }
23538 break;
23539#endif
23540 case OPC_ADDU_QB_DSP:
23541 switch (op2) {
23542 case OPC_MULEU_S_PH_QBL:
23543 check_dsp(ctx);
23544 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23545 break;
23546 case OPC_MULEU_S_PH_QBR:
23547 check_dsp(ctx);
23548 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23549 break;
23550 case OPC_MULQ_RS_PH:
23551 check_dsp(ctx);
23552 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23553 break;
23554 case OPC_MULEQ_S_W_PHL:
23555 check_dsp(ctx);
23556 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23557 break;
23558 case OPC_MULEQ_S_W_PHR:
23559 check_dsp(ctx);
23560 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23561 break;
23562 case OPC_MULQ_S_PH:
908f6be1 23563 check_dsp_r2(ctx);
a22260ae
JL
23564 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23565 break;
23566 }
23567 break;
23568#ifdef TARGET_MIPS64
23569 case OPC_ADDU_OB_DSP:
23570 switch (op2) {
23571 case OPC_MULEQ_S_PW_QHL:
23572 check_dsp(ctx);
23573 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23574 break;
23575 case OPC_MULEQ_S_PW_QHR:
23576 check_dsp(ctx);
23577 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23578 break;
23579 case OPC_MULEU_S_QH_OBL:
23580 check_dsp(ctx);
23581 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23582 break;
23583 case OPC_MULEU_S_QH_OBR:
23584 check_dsp(ctx);
23585 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23586 break;
23587 case OPC_MULQ_RS_QH:
23588 check_dsp(ctx);
23589 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23590 break;
23591 }
23592 break;
23593#endif
23594 }
23595
23596 tcg_temp_free_i32(t0);
23597 tcg_temp_free(v1_t);
23598 tcg_temp_free(v2_t);
a22260ae
JL
23599}
23600
d75c135e 23601static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
23602 int ret, int val)
23603{
1cb6686c
JL
23604 int16_t imm;
23605 TCGv t0;
23606 TCGv val_t;
23607
23608 if (ret == 0) {
23609 /* Treat as NOP. */
1cb6686c
JL
23610 return;
23611 }
23612
23613 t0 = tcg_temp_new();
23614 val_t = tcg_temp_new();
23615 gen_load_gpr(val_t, val);
23616
23617 switch (op1) {
23618 case OPC_ABSQ_S_PH_DSP:
23619 switch (op2) {
23620 case OPC_BITREV:
23621 check_dsp(ctx);
23622 gen_helper_bitrev(cpu_gpr[ret], val_t);
23623 break;
23624 case OPC_REPL_QB:
23625 check_dsp(ctx);
23626 {
23627 target_long result;
23628 imm = (ctx->opcode >> 16) & 0xFF;
23629 result = (uint32_t)imm << 24 |
23630 (uint32_t)imm << 16 |
23631 (uint32_t)imm << 8 |
23632 (uint32_t)imm;
23633 result = (int32_t)result;
23634 tcg_gen_movi_tl(cpu_gpr[ret], result);
23635 }
23636 break;
23637 case OPC_REPLV_QB:
23638 check_dsp(ctx);
23639 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23640 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23641 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23642 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23643 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23644 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23645 break;
23646 case OPC_REPL_PH:
23647 check_dsp(ctx);
23648 {
23649 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23650 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23651 tcg_gen_movi_tl(cpu_gpr[ret], \
23652 (target_long)((int32_t)imm << 16 | \
c4aaba92 23653 (uint16_t)imm));
1cb6686c
JL
23654 }
23655 break;
23656 case OPC_REPLV_PH:
23657 check_dsp(ctx);
23658 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23659 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23660 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23661 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23662 break;
23663 }
23664 break;
23665#ifdef TARGET_MIPS64
23666 case OPC_ABSQ_S_QH_DSP:
23667 switch (op2) {
23668 case OPC_REPL_OB:
23669 check_dsp(ctx);
23670 {
23671 target_long temp;
23672
23673 imm = (ctx->opcode >> 16) & 0xFF;
23674 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23675 temp = (temp << 16) | temp;
23676 temp = (temp << 32) | temp;
23677 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23678 break;
23679 }
23680 case OPC_REPL_PW:
23681 check_dsp(ctx);
23682 {
23683 target_long temp;
23684
23685 imm = (ctx->opcode >> 16) & 0x03FF;
23686 imm = (int16_t)(imm << 6) >> 6;
23687 temp = ((target_long)imm << 32) \
23688 | ((target_long)imm & 0xFFFFFFFF);
23689 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23690 break;
23691 }
23692 case OPC_REPL_QH:
23693 check_dsp(ctx);
23694 {
23695 target_long temp;
23696
23697 imm = (ctx->opcode >> 16) & 0x03FF;
23698 imm = (int16_t)(imm << 6) >> 6;
23699
23700 temp = ((uint64_t)(uint16_t)imm << 48) |
23701 ((uint64_t)(uint16_t)imm << 32) |
23702 ((uint64_t)(uint16_t)imm << 16) |
23703 (uint64_t)(uint16_t)imm;
23704 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23705 break;
23706 }
23707 case OPC_REPLV_OB:
23708 check_dsp(ctx);
23709 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23710 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23711 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23712 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23713 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23714 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23715 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23716 break;
23717 case OPC_REPLV_PW:
23718 check_dsp(ctx);
23719 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23720 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23721 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23722 break;
23723 case OPC_REPLV_QH:
23724 check_dsp(ctx);
23725 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23726 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23727 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23728 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23729 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23730 break;
23731 }
23732 break;
23733#endif
23734 }
23735 tcg_temp_free(t0);
23736 tcg_temp_free(val_t);
1cb6686c
JL
23737}
23738
26690560
JL
23739static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23740 uint32_t op1, uint32_t op2,
23741 int ret, int v1, int v2, int check_ret)
23742{
26690560
JL
23743 TCGv t1;
23744 TCGv v1_t;
23745 TCGv v2_t;
23746
23747 if ((ret == 0) && (check_ret == 1)) {
23748 /* Treat as NOP. */
26690560
JL
23749 return;
23750 }
23751
26690560
JL
23752 t1 = tcg_temp_new();
23753 v1_t = tcg_temp_new();
23754 v2_t = tcg_temp_new();
23755
23756 gen_load_gpr(v1_t, v1);
23757 gen_load_gpr(v2_t, v2);
23758
23759 switch (op1) {
26690560
JL
23760 case OPC_CMPU_EQ_QB_DSP:
23761 switch (op2) {
23762 case OPC_CMPU_EQ_QB:
23763 check_dsp(ctx);
23764 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23765 break;
23766 case OPC_CMPU_LT_QB:
23767 check_dsp(ctx);
23768 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23769 break;
23770 case OPC_CMPU_LE_QB:
23771 check_dsp(ctx);
23772 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23773 break;
23774 case OPC_CMPGU_EQ_QB:
23775 check_dsp(ctx);
23776 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23777 break;
23778 case OPC_CMPGU_LT_QB:
23779 check_dsp(ctx);
23780 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23781 break;
23782 case OPC_CMPGU_LE_QB:
23783 check_dsp(ctx);
23784 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23785 break;
23786 case OPC_CMPGDU_EQ_QB:
908f6be1 23787 check_dsp_r2(ctx);
26690560
JL
23788 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23789 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23790 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23791 tcg_gen_shli_tl(t1, t1, 24);
23792 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23793 break;
23794 case OPC_CMPGDU_LT_QB:
908f6be1 23795 check_dsp_r2(ctx);
26690560
JL
23796 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23797 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23798 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23799 tcg_gen_shli_tl(t1, t1, 24);
23800 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23801 break;
23802 case OPC_CMPGDU_LE_QB:
908f6be1 23803 check_dsp_r2(ctx);
26690560
JL
23804 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23805 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23806 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23807 tcg_gen_shli_tl(t1, t1, 24);
23808 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23809 break;
23810 case OPC_CMP_EQ_PH:
23811 check_dsp(ctx);
23812 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23813 break;
23814 case OPC_CMP_LT_PH:
23815 check_dsp(ctx);
23816 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23817 break;
23818 case OPC_CMP_LE_PH:
23819 check_dsp(ctx);
23820 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23821 break;
23822 case OPC_PICK_QB:
23823 check_dsp(ctx);
23824 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23825 break;
23826 case OPC_PICK_PH:
23827 check_dsp(ctx);
23828 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23829 break;
23830 case OPC_PACKRL_PH:
23831 check_dsp(ctx);
23832 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23833 break;
23834 }
23835 break;
23836#ifdef TARGET_MIPS64
23837 case OPC_CMPU_EQ_OB_DSP:
23838 switch (op2) {
23839 case OPC_CMP_EQ_PW:
23840 check_dsp(ctx);
23841 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23842 break;
23843 case OPC_CMP_LT_PW:
23844 check_dsp(ctx);
23845 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23846 break;
23847 case OPC_CMP_LE_PW:
23848 check_dsp(ctx);
23849 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23850 break;
23851 case OPC_CMP_EQ_QH:
23852 check_dsp(ctx);
23853 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23854 break;
23855 case OPC_CMP_LT_QH:
23856 check_dsp(ctx);
23857 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23858 break;
23859 case OPC_CMP_LE_QH:
23860 check_dsp(ctx);
23861 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23862 break;
23863 case OPC_CMPGDU_EQ_OB:
908f6be1 23864 check_dsp_r2(ctx);
26690560
JL
23865 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23866 break;
23867 case OPC_CMPGDU_LT_OB:
908f6be1 23868 check_dsp_r2(ctx);
26690560
JL
23869 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23870 break;
23871 case OPC_CMPGDU_LE_OB:
908f6be1 23872 check_dsp_r2(ctx);
26690560
JL
23873 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23874 break;
23875 case OPC_CMPGU_EQ_OB:
23876 check_dsp(ctx);
23877 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23878 break;
23879 case OPC_CMPGU_LT_OB:
23880 check_dsp(ctx);
23881 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23882 break;
23883 case OPC_CMPGU_LE_OB:
23884 check_dsp(ctx);
23885 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23886 break;
23887 case OPC_CMPU_EQ_OB:
23888 check_dsp(ctx);
23889 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23890 break;
23891 case OPC_CMPU_LT_OB:
23892 check_dsp(ctx);
23893 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23894 break;
23895 case OPC_CMPU_LE_OB:
23896 check_dsp(ctx);
23897 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23898 break;
23899 case OPC_PACKRL_PW:
23900 check_dsp(ctx);
23901 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23902 break;
23903 case OPC_PICK_OB:
23904 check_dsp(ctx);
23905 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23906 break;
23907 case OPC_PICK_PW:
23908 check_dsp(ctx);
23909 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23910 break;
23911 case OPC_PICK_QH:
23912 check_dsp(ctx);
23913 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23914 break;
23915 }
23916 break;
df6126a7
AJ
23917#endif
23918 }
23919
23920 tcg_temp_free(t1);
23921 tcg_temp_free(v1_t);
23922 tcg_temp_free(v2_t);
df6126a7
AJ
23923}
23924
23925static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23926 uint32_t op1, int rt, int rs, int sa)
23927{
df6126a7
AJ
23928 TCGv t0;
23929
908f6be1 23930 check_dsp_r2(ctx);
df6126a7
AJ
23931
23932 if (rt == 0) {
23933 /* Treat as NOP. */
df6126a7
AJ
23934 return;
23935 }
23936
23937 t0 = tcg_temp_new();
23938 gen_load_gpr(t0, rs);
23939
23940 switch (op1) {
23941 case OPC_APPEND_DSP:
23942 switch (MASK_APPEND(ctx->opcode)) {
23943 case OPC_APPEND:
23944 if (sa != 0) {
23945 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23946 }
23947 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23948 break;
23949 case OPC_PREPEND:
23950 if (sa != 0) {
23951 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23952 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23953 tcg_gen_shli_tl(t0, t0, 32 - sa);
23954 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23955 }
23956 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23957 break;
23958 case OPC_BALIGN:
23959 sa &= 3;
23960 if (sa != 0 && sa != 2) {
23961 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23962 tcg_gen_ext32u_tl(t0, t0);
23963 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23964 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23965 }
23966 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23967 break;
23968 default: /* Invalid */
23969 MIPS_INVAL("MASK APPEND");
9c708c7f 23970 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
23971 break;
23972 }
23973 break;
23974#ifdef TARGET_MIPS64
26690560 23975 case OPC_DAPPEND_DSP:
df6126a7 23976 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23977 case OPC_DAPPEND:
df6126a7
AJ
23978 if (sa != 0) {
23979 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23980 }
26690560
JL
23981 break;
23982 case OPC_PREPENDD:
df6126a7
AJ
23983 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23984 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23985 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23986 break;
23987 case OPC_PREPENDW:
df6126a7
AJ
23988 if (sa != 0) {
23989 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23990 tcg_gen_shli_tl(t0, t0, 64 - sa);
23991 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23992 }
26690560
JL
23993 break;
23994 case OPC_DBALIGN:
df6126a7
AJ
23995 sa &= 7;
23996 if (sa != 0 && sa != 2 && sa != 4) {
23997 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23998 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23999 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24000 }
26690560
JL
24001 break;
24002 default: /* Invalid */
24003 MIPS_INVAL("MASK DAPPEND");
9c708c7f 24004 generate_exception_end(ctx, EXCP_RI);
26690560
JL
24005 break;
24006 }
24007 break;
24008#endif
24009 }
df6126a7 24010 tcg_temp_free(t0);
26690560
JL
24011}
24012
b53371ed
JL
24013static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24014 int ret, int v1, int v2, int check_ret)
24015
24016{
b53371ed
JL
24017 TCGv t0;
24018 TCGv t1;
24019 TCGv v1_t;
24020 TCGv v2_t;
24021 int16_t imm;
24022
24023 if ((ret == 0) && (check_ret == 1)) {
24024 /* Treat as NOP. */
b53371ed
JL
24025 return;
24026 }
24027
24028 t0 = tcg_temp_new();
24029 t1 = tcg_temp_new();
24030 v1_t = tcg_temp_new();
24031 v2_t = tcg_temp_new();
24032
24033 gen_load_gpr(v1_t, v1);
24034 gen_load_gpr(v2_t, v2);
24035
24036 switch (op1) {
24037 case OPC_EXTR_W_DSP:
24038 check_dsp(ctx);
24039 switch (op2) {
24040 case OPC_EXTR_W:
24041 tcg_gen_movi_tl(t0, v2);
24042 tcg_gen_movi_tl(t1, v1);
24043 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24044 break;
24045 case OPC_EXTR_R_W:
24046 tcg_gen_movi_tl(t0, v2);
24047 tcg_gen_movi_tl(t1, v1);
24048 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24049 break;
24050 case OPC_EXTR_RS_W:
24051 tcg_gen_movi_tl(t0, v2);
24052 tcg_gen_movi_tl(t1, v1);
24053 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24054 break;
24055 case OPC_EXTR_S_H:
24056 tcg_gen_movi_tl(t0, v2);
24057 tcg_gen_movi_tl(t1, v1);
24058 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24059 break;
24060 case OPC_EXTRV_S_H:
24061 tcg_gen_movi_tl(t0, v2);
24062 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24063 break;
24064 case OPC_EXTRV_W:
24065 tcg_gen_movi_tl(t0, v2);
24066 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24067 break;
24068 case OPC_EXTRV_R_W:
24069 tcg_gen_movi_tl(t0, v2);
24070 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24071 break;
24072 case OPC_EXTRV_RS_W:
24073 tcg_gen_movi_tl(t0, v2);
24074 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24075 break;
24076 case OPC_EXTP:
24077 tcg_gen_movi_tl(t0, v2);
24078 tcg_gen_movi_tl(t1, v1);
24079 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24080 break;
24081 case OPC_EXTPV:
24082 tcg_gen_movi_tl(t0, v2);
24083 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24084 break;
24085 case OPC_EXTPDP:
24086 tcg_gen_movi_tl(t0, v2);
24087 tcg_gen_movi_tl(t1, v1);
24088 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24089 break;
24090 case OPC_EXTPDPV:
24091 tcg_gen_movi_tl(t0, v2);
24092 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24093 break;
24094 case OPC_SHILO:
24095 imm = (ctx->opcode >> 20) & 0x3F;
24096 tcg_gen_movi_tl(t0, ret);
24097 tcg_gen_movi_tl(t1, imm);
24098 gen_helper_shilo(t0, t1, cpu_env);
24099 break;
24100 case OPC_SHILOV:
24101 tcg_gen_movi_tl(t0, ret);
24102 gen_helper_shilo(t0, v1_t, cpu_env);
24103 break;
24104 case OPC_MTHLIP:
24105 tcg_gen_movi_tl(t0, ret);
24106 gen_helper_mthlip(t0, v1_t, cpu_env);
24107 break;
24108 case OPC_WRDSP:
24109 imm = (ctx->opcode >> 11) & 0x3FF;
24110 tcg_gen_movi_tl(t0, imm);
24111 gen_helper_wrdsp(v1_t, t0, cpu_env);
24112 break;
24113 case OPC_RDDSP:
24114 imm = (ctx->opcode >> 16) & 0x03FF;
24115 tcg_gen_movi_tl(t0, imm);
24116 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24117 break;
24118 }
24119 break;
24120#ifdef TARGET_MIPS64
24121 case OPC_DEXTR_W_DSP:
24122 check_dsp(ctx);
24123 switch (op2) {
24124 case OPC_DMTHLIP:
24125 tcg_gen_movi_tl(t0, ret);
24126 gen_helper_dmthlip(v1_t, t0, cpu_env);
24127 break;
24128 case OPC_DSHILO:
24129 {
24130 int shift = (ctx->opcode >> 19) & 0x7F;
24131 int ac = (ctx->opcode >> 11) & 0x03;
24132 tcg_gen_movi_tl(t0, shift);
24133 tcg_gen_movi_tl(t1, ac);
24134 gen_helper_dshilo(t0, t1, cpu_env);
24135 break;
24136 }
24137 case OPC_DSHILOV:
24138 {
24139 int ac = (ctx->opcode >> 11) & 0x03;
24140 tcg_gen_movi_tl(t0, ac);
24141 gen_helper_dshilo(v1_t, t0, cpu_env);
24142 break;
24143 }
24144 case OPC_DEXTP:
24145 tcg_gen_movi_tl(t0, v2);
24146 tcg_gen_movi_tl(t1, v1);
24147
24148 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24149 break;
24150 case OPC_DEXTPV:
24151 tcg_gen_movi_tl(t0, v2);
24152 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24153 break;
24154 case OPC_DEXTPDP:
24155 tcg_gen_movi_tl(t0, v2);
24156 tcg_gen_movi_tl(t1, v1);
24157 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24158 break;
24159 case OPC_DEXTPDPV:
24160 tcg_gen_movi_tl(t0, v2);
24161 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24162 break;
24163 case OPC_DEXTR_L:
24164 tcg_gen_movi_tl(t0, v2);
24165 tcg_gen_movi_tl(t1, v1);
24166 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24167 break;
24168 case OPC_DEXTR_R_L:
24169 tcg_gen_movi_tl(t0, v2);
24170 tcg_gen_movi_tl(t1, v1);
24171 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24172 break;
24173 case OPC_DEXTR_RS_L:
24174 tcg_gen_movi_tl(t0, v2);
24175 tcg_gen_movi_tl(t1, v1);
24176 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24177 break;
24178 case OPC_DEXTR_W:
24179 tcg_gen_movi_tl(t0, v2);
24180 tcg_gen_movi_tl(t1, v1);
24181 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24182 break;
24183 case OPC_DEXTR_R_W:
24184 tcg_gen_movi_tl(t0, v2);
24185 tcg_gen_movi_tl(t1, v1);
24186 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24187 break;
24188 case OPC_DEXTR_RS_W:
24189 tcg_gen_movi_tl(t0, v2);
24190 tcg_gen_movi_tl(t1, v1);
24191 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24192 break;
24193 case OPC_DEXTR_S_H:
24194 tcg_gen_movi_tl(t0, v2);
24195 tcg_gen_movi_tl(t1, v1);
24196 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24197 break;
24198 case OPC_DEXTRV_S_H:
24199 tcg_gen_movi_tl(t0, v2);
24200 tcg_gen_movi_tl(t1, v1);
24201 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24202 break;
24203 case OPC_DEXTRV_L:
24204 tcg_gen_movi_tl(t0, v2);
24205 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24206 break;
24207 case OPC_DEXTRV_R_L:
24208 tcg_gen_movi_tl(t0, v2);
24209 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24210 break;
24211 case OPC_DEXTRV_RS_L:
24212 tcg_gen_movi_tl(t0, v2);
24213 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24214 break;
24215 case OPC_DEXTRV_W:
24216 tcg_gen_movi_tl(t0, v2);
24217 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24218 break;
24219 case OPC_DEXTRV_R_W:
24220 tcg_gen_movi_tl(t0, v2);
24221 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24222 break;
24223 case OPC_DEXTRV_RS_W:
24224 tcg_gen_movi_tl(t0, v2);
24225 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24226 break;
24227 }
24228 break;
24229#endif
24230 }
24231
24232 tcg_temp_free(t0);
24233 tcg_temp_free(t1);
24234 tcg_temp_free(v1_t);
24235 tcg_temp_free(v2_t);
b53371ed
JL
24236}
24237
9b1a1d68
JL
24238/* End MIPSDSP functions. */
24239
10dc65db
LA
24240static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24241{
4267d3e6 24242 int rs, rt, rd, sa;
b42ee5e1 24243 uint32_t op1, op2;
10dc65db
LA
24244
24245 rs = (ctx->opcode >> 21) & 0x1f;
24246 rt = (ctx->opcode >> 16) & 0x1f;
24247 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 24248 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24249
24250 op1 = MASK_SPECIAL(ctx->opcode);
24251 switch (op1) {
d4ea6acd 24252 case OPC_LSA:
1f1b4c00 24253 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24254 break;
c2e19f3c
AM
24255 case OPC_MULT:
24256 case OPC_MULTU:
24257 case OPC_DIV:
24258 case OPC_DIVU:
b42ee5e1
LA
24259 op2 = MASK_R6_MULDIV(ctx->opcode);
24260 switch (op2) {
24261 case R6_OPC_MUL:
24262 case R6_OPC_MUH:
24263 case R6_OPC_MULU:
24264 case R6_OPC_MUHU:
24265 case R6_OPC_DIV:
24266 case R6_OPC_MOD:
24267 case R6_OPC_DIVU:
24268 case R6_OPC_MODU:
24269 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24270 break;
24271 default:
24272 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24273 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24274 break;
24275 }
24276 break;
10dc65db
LA
24277 case OPC_SELEQZ:
24278 case OPC_SELNEZ:
24279 gen_cond_move(ctx, op1, rd, rs, rt);
24280 break;
4267d3e6
LA
24281 case R6_OPC_CLO:
24282 case R6_OPC_CLZ:
24283 if (rt == 0 && sa == 1) {
7480515f
AM
24284 /*
24285 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24286 * We need additionally to check other fields.
24287 */
4267d3e6
LA
24288 gen_cl(ctx, op1, rd, rs);
24289 } else {
9c708c7f 24290 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24291 }
24292 break;
24293 case R6_OPC_SDBBP:
3b3c1694
LA
24294 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24295 gen_helper_do_semihosting(cpu_env);
faf1f68b 24296 } else {
3b3c1694 24297 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 24298 generate_exception_end(ctx, EXCP_RI);
3b3c1694 24299 } else {
9c708c7f 24300 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24301 }
faf1f68b 24302 }
4267d3e6 24303 break;
b42ee5e1 24304#if defined(TARGET_MIPS64)
d4ea6acd
LA
24305 case OPC_DLSA:
24306 check_mips_64(ctx);
1f1b4c00 24307 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24308 break;
4267d3e6
LA
24309 case R6_OPC_DCLO:
24310 case R6_OPC_DCLZ:
24311 if (rt == 0 && sa == 1) {
7480515f
AM
24312 /*
24313 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24314 * We need additionally to check other fields.
24315 */
4267d3e6
LA
24316 check_mips_64(ctx);
24317 gen_cl(ctx, op1, rd, rs);
24318 } else {
9c708c7f 24319 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24320 }
24321 break;
c2e19f3c
AM
24322 case OPC_DMULT:
24323 case OPC_DMULTU:
24324 case OPC_DDIV:
24325 case OPC_DDIVU:
24326
b42ee5e1
LA
24327 op2 = MASK_R6_MULDIV(ctx->opcode);
24328 switch (op2) {
24329 case R6_OPC_DMUL:
24330 case R6_OPC_DMUH:
24331 case R6_OPC_DMULU:
24332 case R6_OPC_DMUHU:
24333 case R6_OPC_DDIV:
24334 case R6_OPC_DMOD:
24335 case R6_OPC_DDIVU:
24336 case R6_OPC_DMODU:
24337 check_mips_64(ctx);
24338 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24339 break;
24340 default:
24341 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24342 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24343 break;
24344 }
24345 break;
24346#endif
10dc65db
LA
24347 default: /* Invalid */
24348 MIPS_INVAL("special_r6");
9c708c7f 24349 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24350 break;
24351 }
24352}
24353
9dc324ce
FN
24354static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24355{
24356 int rs = extract32(ctx->opcode, 21, 5);
24357 int rt = extract32(ctx->opcode, 16, 5);
24358 int rd = extract32(ctx->opcode, 11, 5);
24359 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24360
24361 switch (op1) {
24362 case OPC_MOVN: /* Conditional move */
24363 case OPC_MOVZ:
24364 gen_cond_move(ctx, op1, rd, rs, rt);
24365 break;
24366 case OPC_MFHI: /* Move from HI/LO */
24367 case OPC_MFLO:
24368 gen_HILO(ctx, op1, 0, rd);
24369 break;
24370 case OPC_MTHI:
24371 case OPC_MTLO: /* Move to HI/LO */
24372 gen_HILO(ctx, op1, 0, rs);
24373 break;
24374 case OPC_MULT:
24375 case OPC_MULTU:
24376 gen_mul_txx9(ctx, op1, rd, rs, rt);
24377 break;
24378 case OPC_DIV:
24379 case OPC_DIVU:
24380 gen_muldiv(ctx, op1, 0, rs, rt);
24381 break;
24382#if defined(TARGET_MIPS64)
24383 case OPC_DMULT:
24384 case OPC_DMULTU:
24385 case OPC_DDIV:
24386 case OPC_DDIVU:
24387 check_insn_opc_user_only(ctx, INSN_R5900);
24388 gen_muldiv(ctx, op1, 0, rs, rt);
24389 break;
24390#endif
24391 case OPC_JR:
24392 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24393 break;
24394 default: /* Invalid */
24395 MIPS_INVAL("special_tx79");
24396 generate_exception_end(ctx, EXCP_RI);
24397 break;
24398 }
24399}
24400
10dc65db
LA
24401static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24402{
b42ee5e1 24403 int rs, rt, rd, sa;
10dc65db
LA
24404 uint32_t op1;
24405
24406 rs = (ctx->opcode >> 21) & 0x1f;
24407 rt = (ctx->opcode >> 16) & 0x1f;
24408 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24409 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24410
24411 op1 = MASK_SPECIAL(ctx->opcode);
24412 switch (op1) {
24413 case OPC_MOVN: /* Conditional move */
24414 case OPC_MOVZ:
24415 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
9dc324ce 24416 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24417 gen_cond_move(ctx, op1, rd, rs, rt);
24418 break;
24419 case OPC_MFHI: /* Move from HI/LO */
24420 case OPC_MFLO:
24421 gen_HILO(ctx, op1, rs & 3, rd);
24422 break;
24423 case OPC_MTHI:
24424 case OPC_MTLO: /* Move to HI/LO */
24425 gen_HILO(ctx, op1, rd & 3, rs);
24426 break;
24427 case OPC_MOVCI:
24428 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24429 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24430 check_cp1_enabled(ctx);
24431 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24432 (ctx->opcode >> 16) & 1);
24433 } else {
24434 generate_exception_err(ctx, EXCP_CpU, 1);
24435 }
24436 break;
b42ee5e1
LA
24437 case OPC_MULT:
24438 case OPC_MULTU:
24439 if (sa) {
24440 check_insn(ctx, INSN_VR54XX);
24441 op1 = MASK_MUL_VR54XX(ctx->opcode);
24442 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24443 } else {
24444 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24445 }
24446 break;
24447 case OPC_DIV:
24448 case OPC_DIVU:
24449 gen_muldiv(ctx, op1, 0, rs, rt);
24450 break;
24451#if defined(TARGET_MIPS64)
c2e19f3c
AM
24452 case OPC_DMULT:
24453 case OPC_DMULTU:
24454 case OPC_DDIV:
24455 case OPC_DDIVU:
b42ee5e1
LA
24456 check_insn(ctx, ISA_MIPS3);
24457 check_mips_64(ctx);
24458 gen_muldiv(ctx, op1, 0, rs, rt);
24459 break;
24460#endif
0aefa333 24461 case OPC_JR:
b231c103 24462 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24463 break;
4267d3e6
LA
24464 case OPC_SPIM:
24465#ifdef MIPS_STRICT_STANDARD
24466 MIPS_INVAL("SPIM");
9c708c7f 24467 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24468#else
24469 /* Implemented as RI exception for now. */
24470 MIPS_INVAL("spim (unofficial)");
9c708c7f 24471 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24472#endif
24473 break;
10dc65db
LA
24474 default: /* Invalid */
24475 MIPS_INVAL("special_legacy");
9c708c7f 24476 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24477 break;
24478 }
24479}
24480
099e5b4d 24481static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24482{
3c824109 24483 int rs, rt, rd, sa;
099e5b4d 24484 uint32_t op1;
3c824109 24485
3c824109
NF
24486 rs = (ctx->opcode >> 21) & 0x1f;
24487 rt = (ctx->opcode >> 16) & 0x1f;
24488 rd = (ctx->opcode >> 11) & 0x1f;
24489 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24490
24491 op1 = MASK_SPECIAL(ctx->opcode);
24492 switch (op1) {
24493 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24494 if (sa == 5 && rd == 0 &&
24495 rs == 0 && rt == 0) { /* PAUSE */
24496 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24497 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24498 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24499 break;
24500 }
24501 }
24502 /* Fallthrough */
099e5b4d
LA
24503 case OPC_SRA:
24504 gen_shift_imm(ctx, op1, rd, rt, sa);
24505 break;
24506 case OPC_SRL:
24507 switch ((ctx->opcode >> 21) & 0x1f) {
24508 case 1:
24509 /* rotr is decoded as srl on non-R2 CPUs */
24510 if (ctx->insn_flags & ISA_MIPS32R2) {
24511 op1 = OPC_ROTR;
ea63e2c3 24512 }
099e5b4d
LA
24513 /* Fallthrough */
24514 case 0:
24515 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24516 break;
099e5b4d 24517 default:
9c708c7f 24518 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24519 break;
099e5b4d
LA
24520 }
24521 break;
c2e19f3c
AM
24522 case OPC_ADD:
24523 case OPC_ADDU:
24524 case OPC_SUB:
24525 case OPC_SUBU:
099e5b4d
LA
24526 gen_arith(ctx, op1, rd, rs, rt);
24527 break;
24528 case OPC_SLLV: /* Shifts */
24529 case OPC_SRAV:
24530 gen_shift(ctx, op1, rd, rs, rt);
24531 break;
24532 case OPC_SRLV:
24533 switch ((ctx->opcode >> 6) & 0x1f) {
24534 case 1:
24535 /* rotrv is decoded as srlv on non-R2 CPUs */
24536 if (ctx->insn_flags & ISA_MIPS32R2) {
24537 op1 = OPC_ROTRV;
26135ead 24538 }
099e5b4d
LA
24539 /* Fallthrough */
24540 case 0:
24541 gen_shift(ctx, op1, rd, rs, rt);
26135ead 24542 break;
099e5b4d 24543 default:
9c708c7f 24544 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 24545 break;
099e5b4d
LA
24546 }
24547 break;
24548 case OPC_SLT: /* Set on less than */
24549 case OPC_SLTU:
24550 gen_slt(ctx, op1, rd, rs, rt);
24551 break;
24552 case OPC_AND: /* Logic*/
24553 case OPC_OR:
24554 case OPC_NOR:
24555 case OPC_XOR:
24556 gen_logic(ctx, op1, rd, rs, rt);
24557 break;
0aefa333 24558 case OPC_JALR:
b231c103 24559 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 24560 break;
c2e19f3c
AM
24561 case OPC_TGE: /* Traps */
24562 case OPC_TGEU:
24563 case OPC_TLT:
24564 case OPC_TLTU:
24565 case OPC_TEQ:
099e5b4d 24566 case OPC_TNE:
d9224450 24567 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
24568 gen_trap(ctx, op1, rs, rt, -1);
24569 break;
d4ea6acd 24570 case OPC_LSA: /* OPC_PMON */
f7685877
YK
24571 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24572 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
24573 decode_opc_special_r6(env, ctx);
24574 } else {
24575 /* Pmon entry point, also R4010 selsl */
b48cfdff 24576#ifdef MIPS_STRICT_STANDARD
d4ea6acd 24577 MIPS_INVAL("PMON / selsl");
9c708c7f 24578 generate_exception_end(ctx, EXCP_RI);
b48cfdff 24579#else
d4ea6acd 24580 gen_helper_0e0i(pmon, sa);
b48cfdff 24581#endif
d4ea6acd 24582 }
099e5b4d
LA
24583 break;
24584 case OPC_SYSCALL:
9c708c7f 24585 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
24586 break;
24587 case OPC_BREAK:
9c708c7f 24588 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 24589 break;
099e5b4d 24590 case OPC_SYNC:
d9224450 24591 check_insn(ctx, ISA_MIPS2);
d208ac0c 24592 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 24593 break;
4ad40f36 24594
d26bc211 24595#if defined(TARGET_MIPS64)
099e5b4d
LA
24596 /* MIPS64 specific opcodes */
24597 case OPC_DSLL:
24598 case OPC_DSRA:
24599 case OPC_DSLL32:
24600 case OPC_DSRA32:
24601 check_insn(ctx, ISA_MIPS3);
24602 check_mips_64(ctx);
24603 gen_shift_imm(ctx, op1, rd, rt, sa);
24604 break;
24605 case OPC_DSRL:
24606 switch ((ctx->opcode >> 21) & 0x1f) {
24607 case 1:
24608 /* drotr is decoded as dsrl on non-R2 CPUs */
24609 if (ctx->insn_flags & ISA_MIPS32R2) {
24610 op1 = OPC_DROTR;
ea63e2c3 24611 }
099e5b4d
LA
24612 /* Fallthrough */
24613 case 0:
d75c135e 24614 check_insn(ctx, ISA_MIPS3);
e189e748 24615 check_mips_64(ctx);
099e5b4d 24616 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24617 break;
099e5b4d 24618 default:
9c708c7f 24619 generate_exception_end(ctx, EXCP_RI);
460f00c4 24620 break;
099e5b4d
LA
24621 }
24622 break;
24623 case OPC_DSRL32:
24624 switch ((ctx->opcode >> 21) & 0x1f) {
24625 case 1:
24626 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24627 if (ctx->insn_flags & ISA_MIPS32R2) {
24628 op1 = OPC_DROTR32;
ea63e2c3 24629 }
099e5b4d
LA
24630 /* Fallthrough */
24631 case 0:
d75c135e 24632 check_insn(ctx, ISA_MIPS3);
e189e748 24633 check_mips_64(ctx);
099e5b4d 24634 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24635 break;
099e5b4d 24636 default:
9c708c7f 24637 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24638 break;
24639 }
24640 break;
c2e19f3c
AM
24641 case OPC_DADD:
24642 case OPC_DADDU:
24643 case OPC_DSUB:
24644 case OPC_DSUBU:
099e5b4d
LA
24645 check_insn(ctx, ISA_MIPS3);
24646 check_mips_64(ctx);
24647 gen_arith(ctx, op1, rd, rs, rt);
24648 break;
24649 case OPC_DSLLV:
24650 case OPC_DSRAV:
24651 check_insn(ctx, ISA_MIPS3);
24652 check_mips_64(ctx);
24653 gen_shift(ctx, op1, rd, rs, rt);
24654 break;
24655 case OPC_DSRLV:
24656 switch ((ctx->opcode >> 6) & 0x1f) {
24657 case 1:
24658 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24659 if (ctx->insn_flags & ISA_MIPS32R2) {
24660 op1 = OPC_DROTRV;
6af0bf9c 24661 }
099e5b4d
LA
24662 /* Fallthrough */
24663 case 0:
24664 check_insn(ctx, ISA_MIPS3);
e189e748 24665 check_mips_64(ctx);
099e5b4d 24666 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 24667 break;
099e5b4d 24668 default:
9c708c7f 24669 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24670 break;
24671 }
24672 break;
f7685877
YK
24673 case OPC_DLSA:
24674 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24675 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24676 decode_opc_special_r6(env, ctx);
24677 }
24678 break;
099e5b4d 24679#endif
10dc65db
LA
24680 default:
24681 if (ctx->insn_flags & ISA_MIPS32R6) {
24682 decode_opc_special_r6(env, ctx);
9dc324ce
FN
24683 } else if (ctx->insn_flags & INSN_R5900) {
24684 decode_opc_special_tx79(env, ctx);
10dc65db
LA
24685 } else {
24686 decode_opc_special_legacy(env, ctx);
24687 }
24688 }
24689}
24690
d67da337 24691
37b9aae2
MM
24692#if defined(TARGET_MIPS64)
24693
24694/*
24695 *
24696 * MMI (MultiMedia Interface) ASE instructions
24697 * ===========================================
24698 */
24699
24700/*
24701 * MMI instructions category: data communication
24702 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24703 *
24704 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24705 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24706 * PCPYUD PEXEH PEXTLW PPACW
24707 * PEXEW PEXTUB
24708 * PEXTUH
24709 * PEXTUW
24710 */
24711
d3434d9f
MM
24712/*
24713 * PCPYH rd, rt
24714 *
24715 * Parallel Copy Halfword
24716 *
24717 * 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
24718 * +-----------+---------+---------+---------+---------+-----------+
24719 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24720 * +-----------+---------+---------+---------+---------+-----------+
24721 */
24722static void gen_mmi_pcpyh(DisasContext *ctx)
24723{
24724 uint32_t pd, rt, rd;
24725 uint32_t opcode;
24726
24727 opcode = ctx->opcode;
24728
24729 pd = extract32(opcode, 21, 5);
24730 rt = extract32(opcode, 16, 5);
24731 rd = extract32(opcode, 11, 5);
24732
24733 if (unlikely(pd != 0)) {
24734 generate_exception_end(ctx, EXCP_RI);
24735 } else if (rd == 0) {
24736 /* nop */
24737 } else if (rt == 0) {
24738 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24739 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24740 } else {
24741 TCGv_i64 t0 = tcg_temp_new();
24742 TCGv_i64 t1 = tcg_temp_new();
24743 uint64_t mask = (1ULL << 16) - 1;
24744
24745 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24746 tcg_gen_movi_i64(t1, 0);
24747 tcg_gen_or_i64(t1, t0, t1);
24748 tcg_gen_shli_i64(t0, t0, 16);
24749 tcg_gen_or_i64(t1, t0, t1);
24750 tcg_gen_shli_i64(t0, t0, 16);
24751 tcg_gen_or_i64(t1, t0, t1);
24752 tcg_gen_shli_i64(t0, t0, 16);
24753 tcg_gen_or_i64(t1, t0, t1);
24754
24755 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24756
24757 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24758 tcg_gen_movi_i64(t1, 0);
24759 tcg_gen_or_i64(t1, t0, t1);
24760 tcg_gen_shli_i64(t0, t0, 16);
24761 tcg_gen_or_i64(t1, t0, t1);
24762 tcg_gen_shli_i64(t0, t0, 16);
24763 tcg_gen_or_i64(t1, t0, t1);
24764 tcg_gen_shli_i64(t0, t0, 16);
24765 tcg_gen_or_i64(t1, t0, t1);
24766
24767 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24768
24769 tcg_temp_free(t0);
24770 tcg_temp_free(t1);
24771 }
24772}
24773
b87eef31
MM
24774/*
24775 * PCPYLD rd, rs, rt
24776 *
24777 * Parallel Copy Lower Doubleword
24778 *
24779 * 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
24780 * +-----------+---------+---------+---------+---------+-----------+
24781 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24782 * +-----------+---------+---------+---------+---------+-----------+
24783 */
24784static void gen_mmi_pcpyld(DisasContext *ctx)
24785{
24786 uint32_t rs, rt, rd;
24787 uint32_t opcode;
24788
24789 opcode = ctx->opcode;
24790
24791 rs = extract32(opcode, 21, 5);
24792 rt = extract32(opcode, 16, 5);
24793 rd = extract32(opcode, 11, 5);
24794
24795 if (rd == 0) {
24796 /* nop */
24797 } else {
24798 if (rs == 0) {
24799 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24800 } else {
24801 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24802 }
24803 if (rt == 0) {
24804 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24805 } else {
24806 if (rd != rt) {
24807 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24808 }
24809 }
24810 }
24811}
24812
fd487f83
MM
24813/*
24814 * PCPYUD rd, rs, rt
24815 *
24816 * Parallel Copy Upper Doubleword
24817 *
24818 * 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
24819 * +-----------+---------+---------+---------+---------+-----------+
24820 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24821 * +-----------+---------+---------+---------+---------+-----------+
24822 */
24823static void gen_mmi_pcpyud(DisasContext *ctx)
24824{
24825 uint32_t rs, rt, rd;
24826 uint32_t opcode;
24827
24828 opcode = ctx->opcode;
24829
24830 rs = extract32(opcode, 21, 5);
24831 rt = extract32(opcode, 16, 5);
24832 rd = extract32(opcode, 11, 5);
24833
24834 if (rd == 0) {
24835 /* nop */
24836 } else {
24837 if (rs == 0) {
24838 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24839 } else {
24840 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24841 }
24842 if (rt == 0) {
24843 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24844 } else {
24845 if (rd != rt) {
24846 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24847 }
24848 }
24849 }
24850}
24851
37b9aae2
MM
24852#endif
24853
24854
b621f018
AM
24855#if !defined(TARGET_MIPS64)
24856
d67da337
AM
24857/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24858#define MXU_APTN1_A 0
24859#define MXU_APTN1_S 1
24860
b70bb918
CJ
24861/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24862#define MXU_APTN2_AA 0
24863#define MXU_APTN2_AS 1
24864#define MXU_APTN2_SA 2
24865#define MXU_APTN2_SS 3
24866
5bb29992
AM
24867/* MXU execute add/subtract 2-bit pattern 'eptn2' */
24868#define MXU_EPTN2_AA 0
24869#define MXU_EPTN2_AS 1
24870#define MXU_EPTN2_SA 2
24871#define MXU_EPTN2_SS 3
24872
a35723f4 24873/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
24874#define MXU_OPTN2_PTN0 0
24875#define MXU_OPTN2_PTN1 1
24876#define MXU_OPTN2_PTN2 2
24877#define MXU_OPTN2_PTN3 3
24878/* alternative naming scheme for 'optn2' */
a35723f4
CJ
24879#define MXU_OPTN2_WW 0
24880#define MXU_OPTN2_LW 1
24881#define MXU_OPTN2_HW 2
24882#define MXU_OPTN2_XW 3
24883
53f1131f
CJ
24884/* MXU operand getting pattern 'optn3' */
24885#define MXU_OPTN3_PTN0 0
24886#define MXU_OPTN3_PTN1 1
24887#define MXU_OPTN3_PTN2 2
24888#define MXU_OPTN3_PTN3 3
24889#define MXU_OPTN3_PTN4 4
24890#define MXU_OPTN3_PTN5 5
24891#define MXU_OPTN3_PTN6 6
24892#define MXU_OPTN3_PTN7 7
24893
d67da337 24894
96992d1a
CJ
24895/*
24896 * S32I2M XRa, rb - Register move from GRF to XRF
24897 */
24898static void gen_mxu_s32i2m(DisasContext *ctx)
24899{
24900 TCGv t0;
24901 uint32_t XRa, Rb;
24902
24903 t0 = tcg_temp_new();
24904
24905 XRa = extract32(ctx->opcode, 6, 5);
24906 Rb = extract32(ctx->opcode, 16, 5);
24907
24908 gen_load_gpr(t0, Rb);
24909 if (XRa <= 15) {
24910 gen_store_mxu_gpr(t0, XRa);
24911 } else if (XRa == 16) {
24912 gen_store_mxu_cr(t0);
24913 }
24914
24915 tcg_temp_free(t0);
24916}
24917
24918/*
24919 * S32M2I XRa, rb - Register move from XRF to GRF
24920 */
24921static void gen_mxu_s32m2i(DisasContext *ctx)
24922{
24923 TCGv t0;
24924 uint32_t XRa, Rb;
24925
24926 t0 = tcg_temp_new();
24927
24928 XRa = extract32(ctx->opcode, 6, 5);
24929 Rb = extract32(ctx->opcode, 16, 5);
24930
24931 if (XRa <= 15) {
24932 gen_load_mxu_gpr(t0, XRa);
24933 } else if (XRa == 16) {
24934 gen_load_mxu_cr(t0);
24935 }
24936
24937 gen_store_gpr(t0, Rb);
24938
24939 tcg_temp_free(t0);
24940}
24941
be57bcdb
CJ
24942/*
24943 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24944 */
24945static void gen_mxu_s8ldd(DisasContext *ctx)
24946{
24947 TCGv t0, t1;
be57bcdb
CJ
24948 uint32_t XRa, Rb, s8, optn3;
24949
24950 t0 = tcg_temp_new();
24951 t1 = tcg_temp_new();
24952
be57bcdb
CJ
24953 XRa = extract32(ctx->opcode, 6, 4);
24954 s8 = extract32(ctx->opcode, 10, 8);
24955 optn3 = extract32(ctx->opcode, 18, 3);
24956 Rb = extract32(ctx->opcode, 21, 5);
24957
be57bcdb
CJ
24958 gen_load_gpr(t0, Rb);
24959 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24960
24961 switch (optn3) {
24962 /* XRa[7:0] = tmp8 */
24963 case MXU_OPTN3_PTN0:
24964 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24965 gen_load_mxu_gpr(t0, XRa);
24966 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24967 break;
24968 /* XRa[15:8] = tmp8 */
24969 case MXU_OPTN3_PTN1:
24970 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24971 gen_load_mxu_gpr(t0, XRa);
24972 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24973 break;
24974 /* XRa[23:16] = tmp8 */
24975 case MXU_OPTN3_PTN2:
24976 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24977 gen_load_mxu_gpr(t0, XRa);
24978 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24979 break;
24980 /* XRa[31:24] = tmp8 */
24981 case MXU_OPTN3_PTN3:
24982 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24983 gen_load_mxu_gpr(t0, XRa);
24984 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24985 break;
24986 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24987 case MXU_OPTN3_PTN4:
24988 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24989 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24990 break;
24991 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24992 case MXU_OPTN3_PTN5:
24993 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24994 tcg_gen_shli_tl(t1, t1, 8);
24995 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24996 break;
24997 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24998 case MXU_OPTN3_PTN6:
24999 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25000 tcg_gen_mov_tl(t0, t1);
25001 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25002 tcg_gen_shli_tl(t1, t1, 16);
25003 tcg_gen_or_tl(t0, t0, t1);
25004 break;
25005 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25006 case MXU_OPTN3_PTN7:
25007 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25008 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25009 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25010 break;
25011 }
25012
25013 gen_store_mxu_gpr(t0, XRa);
25014
be57bcdb
CJ
25015 tcg_temp_free(t0);
25016 tcg_temp_free(t1);
25017}
25018
72c9bcf8
CJ
25019/*
25020 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25021 */
25022static void gen_mxu_d16mul(DisasContext *ctx)
25023{
25024 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
25025 uint32_t XRa, XRb, XRc, XRd, optn2;
25026
25027 t0 = tcg_temp_new();
25028 t1 = tcg_temp_new();
25029 t2 = tcg_temp_new();
25030 t3 = tcg_temp_new();
25031
72c9bcf8
CJ
25032 XRa = extract32(ctx->opcode, 6, 4);
25033 XRb = extract32(ctx->opcode, 10, 4);
25034 XRc = extract32(ctx->opcode, 14, 4);
25035 XRd = extract32(ctx->opcode, 18, 4);
25036 optn2 = extract32(ctx->opcode, 22, 2);
25037
72c9bcf8
CJ
25038 gen_load_mxu_gpr(t1, XRb);
25039 tcg_gen_sextract_tl(t0, t1, 0, 16);
25040 tcg_gen_sextract_tl(t1, t1, 16, 16);
25041 gen_load_mxu_gpr(t3, XRc);
25042 tcg_gen_sextract_tl(t2, t3, 0, 16);
25043 tcg_gen_sextract_tl(t3, t3, 16, 16);
25044
25045 switch (optn2) {
25046 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25047 tcg_gen_mul_tl(t3, t1, t3);
25048 tcg_gen_mul_tl(t2, t0, t2);
25049 break;
25050 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25051 tcg_gen_mul_tl(t3, t0, t3);
25052 tcg_gen_mul_tl(t2, t0, t2);
25053 break;
25054 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25055 tcg_gen_mul_tl(t3, t1, t3);
25056 tcg_gen_mul_tl(t2, t1, t2);
25057 break;
25058 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25059 tcg_gen_mul_tl(t3, t0, t3);
25060 tcg_gen_mul_tl(t2, t1, t2);
25061 break;
25062 }
25063 gen_store_mxu_gpr(t3, XRa);
25064 gen_store_mxu_gpr(t2, XRd);
25065
72c9bcf8
CJ
25066 tcg_temp_free(t0);
25067 tcg_temp_free(t1);
25068 tcg_temp_free(t2);
25069 tcg_temp_free(t3);
25070}
25071
e67915b4
CJ
25072/*
25073 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25074 * and accumulate
25075 */
25076static void gen_mxu_d16mac(DisasContext *ctx)
25077{
25078 TCGv t0, t1, t2, t3;
e67915b4
CJ
25079 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25080
25081 t0 = tcg_temp_new();
25082 t1 = tcg_temp_new();
25083 t2 = tcg_temp_new();
25084 t3 = tcg_temp_new();
25085
e67915b4
CJ
25086 XRa = extract32(ctx->opcode, 6, 4);
25087 XRb = extract32(ctx->opcode, 10, 4);
25088 XRc = extract32(ctx->opcode, 14, 4);
25089 XRd = extract32(ctx->opcode, 18, 4);
25090 optn2 = extract32(ctx->opcode, 22, 2);
25091 aptn2 = extract32(ctx->opcode, 24, 2);
25092
e67915b4
CJ
25093 gen_load_mxu_gpr(t1, XRb);
25094 tcg_gen_sextract_tl(t0, t1, 0, 16);
25095 tcg_gen_sextract_tl(t1, t1, 16, 16);
25096
25097 gen_load_mxu_gpr(t3, XRc);
25098 tcg_gen_sextract_tl(t2, t3, 0, 16);
25099 tcg_gen_sextract_tl(t3, t3, 16, 16);
25100
25101 switch (optn2) {
25102 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25103 tcg_gen_mul_tl(t3, t1, t3);
25104 tcg_gen_mul_tl(t2, t0, t2);
25105 break;
25106 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25107 tcg_gen_mul_tl(t3, t0, t3);
25108 tcg_gen_mul_tl(t2, t0, t2);
25109 break;
25110 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25111 tcg_gen_mul_tl(t3, t1, t3);
25112 tcg_gen_mul_tl(t2, t1, t2);
25113 break;
25114 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25115 tcg_gen_mul_tl(t3, t0, t3);
25116 tcg_gen_mul_tl(t2, t1, t2);
25117 break;
25118 }
25119 gen_load_mxu_gpr(t0, XRa);
25120 gen_load_mxu_gpr(t1, XRd);
25121
25122 switch (aptn2) {
25123 case MXU_APTN2_AA:
25124 tcg_gen_add_tl(t3, t0, t3);
25125 tcg_gen_add_tl(t2, t1, t2);
25126 break;
25127 case MXU_APTN2_AS:
25128 tcg_gen_add_tl(t3, t0, t3);
25129 tcg_gen_sub_tl(t2, t1, t2);
25130 break;
25131 case MXU_APTN2_SA:
25132 tcg_gen_sub_tl(t3, t0, t3);
25133 tcg_gen_add_tl(t2, t1, t2);
25134 break;
25135 case MXU_APTN2_SS:
25136 tcg_gen_sub_tl(t3, t0, t3);
25137 tcg_gen_sub_tl(t2, t1, t2);
25138 break;
25139 }
25140 gen_store_mxu_gpr(t3, XRa);
25141 gen_store_mxu_gpr(t2, XRd);
25142
e67915b4
CJ
25143 tcg_temp_free(t0);
25144 tcg_temp_free(t1);
25145 tcg_temp_free(t2);
25146 tcg_temp_free(t3);
25147}
25148
a9a4181b
CJ
25149/*
25150 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25151 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25152 */
25153static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25154{
25155 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
25156 uint32_t XRa, XRb, XRc, XRd, sel;
25157
25158 t0 = tcg_temp_new();
25159 t1 = tcg_temp_new();
25160 t2 = tcg_temp_new();
25161 t3 = tcg_temp_new();
25162 t4 = tcg_temp_new();
25163 t5 = tcg_temp_new();
25164 t6 = tcg_temp_new();
25165 t7 = tcg_temp_new();
25166
a9a4181b
CJ
25167 XRa = extract32(ctx->opcode, 6, 4);
25168 XRb = extract32(ctx->opcode, 10, 4);
25169 XRc = extract32(ctx->opcode, 14, 4);
25170 XRd = extract32(ctx->opcode, 18, 4);
25171 sel = extract32(ctx->opcode, 22, 2);
25172
a9a4181b
CJ
25173 gen_load_mxu_gpr(t3, XRb);
25174 gen_load_mxu_gpr(t7, XRc);
25175
25176 if (sel == 0x2) {
25177 /* Q8MULSU */
25178 tcg_gen_ext8s_tl(t0, t3);
25179 tcg_gen_shri_tl(t3, t3, 8);
25180 tcg_gen_ext8s_tl(t1, t3);
25181 tcg_gen_shri_tl(t3, t3, 8);
25182 tcg_gen_ext8s_tl(t2, t3);
25183 tcg_gen_shri_tl(t3, t3, 8);
25184 tcg_gen_ext8s_tl(t3, t3);
25185 } else {
25186 /* Q8MUL */
25187 tcg_gen_ext8u_tl(t0, t3);
25188 tcg_gen_shri_tl(t3, t3, 8);
25189 tcg_gen_ext8u_tl(t1, t3);
25190 tcg_gen_shri_tl(t3, t3, 8);
25191 tcg_gen_ext8u_tl(t2, t3);
25192 tcg_gen_shri_tl(t3, t3, 8);
25193 tcg_gen_ext8u_tl(t3, t3);
25194 }
25195
25196 tcg_gen_ext8u_tl(t4, t7);
25197 tcg_gen_shri_tl(t7, t7, 8);
25198 tcg_gen_ext8u_tl(t5, t7);
25199 tcg_gen_shri_tl(t7, t7, 8);
25200 tcg_gen_ext8u_tl(t6, t7);
25201 tcg_gen_shri_tl(t7, t7, 8);
25202 tcg_gen_ext8u_tl(t7, t7);
25203
25204 tcg_gen_mul_tl(t0, t0, t4);
25205 tcg_gen_mul_tl(t1, t1, t5);
25206 tcg_gen_mul_tl(t2, t2, t6);
25207 tcg_gen_mul_tl(t3, t3, t7);
25208
25209 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25210 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25211 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25212 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25213
25214 tcg_gen_shli_tl(t1, t1, 16);
25215 tcg_gen_shli_tl(t3, t3, 16);
25216
25217 tcg_gen_or_tl(t0, t0, t1);
25218 tcg_gen_or_tl(t1, t2, t3);
25219
25220 gen_store_mxu_gpr(t0, XRd);
25221 gen_store_mxu_gpr(t1, XRa);
25222
a9a4181b
CJ
25223 tcg_temp_free(t0);
25224 tcg_temp_free(t1);
25225 tcg_temp_free(t2);
25226 tcg_temp_free(t3);
25227 tcg_temp_free(t4);
25228 tcg_temp_free(t5);
25229 tcg_temp_free(t6);
25230 tcg_temp_free(t7);
25231}
25232
4ca83721
CJ
25233/*
25234 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25235 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25236 */
25237static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25238{
25239 TCGv t0, t1;
4ca83721
CJ
25240 uint32_t XRa, Rb, s12, sel;
25241
25242 t0 = tcg_temp_new();
25243 t1 = tcg_temp_new();
25244
4ca83721
CJ
25245 XRa = extract32(ctx->opcode, 6, 4);
25246 s12 = extract32(ctx->opcode, 10, 10);
25247 sel = extract32(ctx->opcode, 20, 1);
25248 Rb = extract32(ctx->opcode, 21, 5);
25249
4ca83721
CJ
25250 gen_load_gpr(t0, Rb);
25251
25252 tcg_gen_movi_tl(t1, s12);
25253 tcg_gen_shli_tl(t1, t1, 2);
25254 if (s12 & 0x200) {
25255 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25256 }
25257 tcg_gen_add_tl(t1, t0, t1);
25258 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25259
25260 if (sel == 1) {
25261 /* S32LDDR */
25262 tcg_gen_bswap32_tl(t1, t1);
25263 }
25264 gen_store_mxu_gpr(t1, XRa);
25265
4ca83721
CJ
25266 tcg_temp_free(t0);
25267 tcg_temp_free(t1);
25268}
25269
96992d1a 25270
b621f018
AM
25271/*
25272 * MXU instruction category: logic
25273 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25274 *
25275 * S32NOR S32AND S32OR S32XOR
25276 */
25277
25278/*
25279 * S32NOR XRa, XRb, XRc
25280 * Update XRa with the result of logical bitwise 'nor' operation
25281 * applied to the content of XRb and XRc.
25282 *
25283 * 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
25284 * +-----------+---------+-----+-------+-------+-------+-----------+
25285 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25286 * +-----------+---------+-----+-------+-------+-------+-----------+
25287 */
25288static void gen_mxu_S32NOR(DisasContext *ctx)
25289{
25290 uint32_t pad, XRc, XRb, XRa;
25291
25292 pad = extract32(ctx->opcode, 21, 5);
25293 XRc = extract32(ctx->opcode, 14, 4);
25294 XRb = extract32(ctx->opcode, 10, 4);
25295 XRa = extract32(ctx->opcode, 6, 4);
25296
25297 if (unlikely(pad != 0)) {
25298 /* opcode padding incorrect -> do nothing */
25299 } else if (unlikely(XRa == 0)) {
25300 /* destination is zero register -> do nothing */
25301 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25302 /* both operands zero registers -> just set destination to all 1s */
25303 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25304 } else if (unlikely(XRb == 0)) {
25305 /* XRb zero register -> just set destination to the negation of XRc */
25306 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25307 } else if (unlikely(XRc == 0)) {
25308 /* XRa zero register -> just set destination to the negation of XRb */
25309 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25310 } else if (unlikely(XRb == XRc)) {
25311 /* both operands same -> just set destination to the negation of XRb */
25312 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25313 } else {
25314 /* the most general case */
25315 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25316 }
25317}
25318
25319/*
25320 * S32AND XRa, XRb, XRc
25321 * Update XRa with the result of logical bitwise 'and' operation
25322 * applied to the content of XRb and XRc.
25323 *
25324 * 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
25325 * +-----------+---------+-----+-------+-------+-------+-----------+
25326 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25327 * +-----------+---------+-----+-------+-------+-------+-----------+
25328 */
25329static void gen_mxu_S32AND(DisasContext *ctx)
25330{
25331 uint32_t pad, XRc, XRb, XRa;
25332
25333 pad = extract32(ctx->opcode, 21, 5);
25334 XRc = extract32(ctx->opcode, 14, 4);
25335 XRb = extract32(ctx->opcode, 10, 4);
25336 XRa = extract32(ctx->opcode, 6, 4);
25337
25338 if (unlikely(pad != 0)) {
25339 /* opcode padding incorrect -> do nothing */
25340 } else if (unlikely(XRa == 0)) {
25341 /* destination is zero register -> do nothing */
25342 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25343 /* one of operands zero register -> just set destination to all 0s */
25344 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25345 } else if (unlikely(XRb == XRc)) {
25346 /* both operands same -> just set destination to one of them */
25347 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25348 } else {
25349 /* the most general case */
25350 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25351 }
25352}
25353
25354/*
25355 * S32OR XRa, XRb, XRc
25356 * Update XRa with the result of logical bitwise 'or' operation
25357 * applied to the content of XRb and XRc.
25358 *
25359 * 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
25360 * +-----------+---------+-----+-------+-------+-------+-----------+
25361 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25362 * +-----------+---------+-----+-------+-------+-------+-----------+
25363 */
25364static void gen_mxu_S32OR(DisasContext *ctx)
25365{
25366 uint32_t pad, XRc, XRb, XRa;
25367
25368 pad = extract32(ctx->opcode, 21, 5);
25369 XRc = extract32(ctx->opcode, 14, 4);
25370 XRb = extract32(ctx->opcode, 10, 4);
25371 XRa = extract32(ctx->opcode, 6, 4);
25372
25373 if (unlikely(pad != 0)) {
25374 /* opcode padding incorrect -> do nothing */
25375 } else if (unlikely(XRa == 0)) {
25376 /* destination is zero register -> do nothing */
25377 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25378 /* both operands zero registers -> just set destination to all 0s */
25379 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25380 } else if (unlikely(XRb == 0)) {
25381 /* XRb zero register -> just set destination to the content of XRc */
25382 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25383 } else if (unlikely(XRc == 0)) {
25384 /* XRc zero register -> just set destination to the content of XRb */
25385 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25386 } else if (unlikely(XRb == XRc)) {
25387 /* both operands same -> just set destination to one of them */
25388 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25389 } else {
25390 /* the most general case */
25391 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25392 }
25393}
25394
25395/*
25396 * S32XOR XRa, XRb, XRc
25397 * Update XRa with the result of logical bitwise 'xor' operation
25398 * applied to the content of XRb and XRc.
25399 *
25400 * 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
25401 * +-----------+---------+-----+-------+-------+-------+-----------+
25402 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25403 * +-----------+---------+-----+-------+-------+-------+-----------+
25404 */
25405static void gen_mxu_S32XOR(DisasContext *ctx)
25406{
25407 uint32_t pad, XRc, XRb, XRa;
25408
25409 pad = extract32(ctx->opcode, 21, 5);
25410 XRc = extract32(ctx->opcode, 14, 4);
25411 XRb = extract32(ctx->opcode, 10, 4);
25412 XRa = extract32(ctx->opcode, 6, 4);
25413
25414 if (unlikely(pad != 0)) {
25415 /* opcode padding incorrect -> do nothing */
25416 } else if (unlikely(XRa == 0)) {
25417 /* destination is zero register -> do nothing */
25418 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25419 /* both operands zero registers -> just set destination to all 0s */
25420 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25421 } else if (unlikely(XRb == 0)) {
25422 /* XRb zero register -> just set destination to the content of XRc */
25423 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25424 } else if (unlikely(XRc == 0)) {
25425 /* XRc zero register -> just set destination to the content of XRb */
25426 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25427 } else if (unlikely(XRb == XRc)) {
25428 /* both operands same -> just set destination to all 0s */
25429 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25430 } else {
25431 /* the most general case */
25432 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25433 }
25434}
25435
25436
bb84cbf3
AM
25437/*
25438 * MXU instruction category max/min
25439 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25440 *
25441 * S32MAX D16MAX Q8MAX
25442 * S32MIN D16MIN Q8MIN
25443 */
25444
25445/*
25446 * S32MAX XRa, XRb, XRc
25447 * Update XRa with the maximum of signed 32-bit integers contained
25448 * in XRb and XRc.
25449 *
25450 * S32MIN XRa, XRb, XRc
25451 * Update XRa with the minimum of signed 32-bit integers contained
25452 * in XRb and XRc.
25453 *
25454 * 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
25455 * +-----------+---------+-----+-------+-------+-------+-----------+
25456 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25457 * +-----------+---------+-----+-------+-------+-------+-----------+
25458 */
25459static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25460{
25461 uint32_t pad, opc, XRc, XRb, XRa;
25462
25463 pad = extract32(ctx->opcode, 21, 5);
25464 opc = extract32(ctx->opcode, 18, 3);
25465 XRc = extract32(ctx->opcode, 14, 4);
25466 XRb = extract32(ctx->opcode, 10, 4);
25467 XRa = extract32(ctx->opcode, 6, 4);
25468
25469 if (unlikely(pad != 0)) {
25470 /* opcode padding incorrect -> do nothing */
25471 } else if (unlikely(XRa == 0)) {
25472 /* destination is zero register -> do nothing */
25473 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25474 /* both operands zero registers -> just set destination to zero */
25475 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25476 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25477 /* exactly one operand is zero register - find which one is not...*/
25478 uint32_t XRx = XRb ? XRb : XRc;
25479 /* ...and do max/min operation with one operand 0 */
25480 if (opc == OPC_MXU_S32MAX) {
25481 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25482 } else {
25483 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25484 }
25485 } else if (unlikely(XRb == XRc)) {
25486 /* both operands same -> just set destination to one of them */
25487 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25488 } else {
25489 /* the most general case */
25490 if (opc == OPC_MXU_S32MAX) {
25491 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25492 mxu_gpr[XRc - 1]);
25493 } else {
25494 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25495 mxu_gpr[XRc - 1]);
25496 }
25497 }
25498}
25499
25500/*
25501 * D16MAX
25502 * Update XRa with the 16-bit-wise maximums of signed integers
25503 * contained in XRb and XRc.
25504 *
25505 * D16MIN
25506 * Update XRa with the 16-bit-wise minimums of signed integers
25507 * contained in XRb and XRc.
25508 *
25509 * 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
25510 * +-----------+---------+-----+-------+-------+-------+-----------+
25511 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25512 * +-----------+---------+-----+-------+-------+-------+-----------+
25513 */
25514static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25515{
25516 uint32_t pad, opc, XRc, XRb, XRa;
25517
25518 pad = extract32(ctx->opcode, 21, 5);
25519 opc = extract32(ctx->opcode, 18, 3);
25520 XRc = extract32(ctx->opcode, 14, 4);
25521 XRb = extract32(ctx->opcode, 10, 4);
25522 XRa = extract32(ctx->opcode, 6, 4);
25523
25524 if (unlikely(pad != 0)) {
25525 /* opcode padding incorrect -> do nothing */
25526 } else if (unlikely(XRc == 0)) {
25527 /* destination is zero register -> do nothing */
25528 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25529 /* both operands zero registers -> just set destination to zero */
25530 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25531 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25532 /* exactly one operand is zero register - find which one is not...*/
25533 uint32_t XRx = XRb ? XRb : XRc;
25534 /* ...and do half-word-wise max/min with one operand 0 */
25535 TCGv_i32 t0 = tcg_temp_new();
25536 TCGv_i32 t1 = tcg_const_i32(0);
25537
25538 /* the left half-word first */
25539 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25540 if (opc == OPC_MXU_D16MAX) {
25541 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25542 } else {
25543 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25544 }
25545
25546 /* the right half-word */
25547 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25548 /* move half-words to the leftmost position */
25549 tcg_gen_shli_i32(t0, t0, 16);
25550 /* t0 will be max/min of t0 and t1 */
25551 if (opc == OPC_MXU_D16MAX) {
25552 tcg_gen_smax_i32(t0, t0, t1);
25553 } else {
25554 tcg_gen_smin_i32(t0, t0, t1);
25555 }
25556 /* return resulting half-words to its original position */
25557 tcg_gen_shri_i32(t0, t0, 16);
25558 /* finaly update the destination */
25559 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25560
25561 tcg_temp_free(t1);
25562 tcg_temp_free(t0);
25563 } else if (unlikely(XRb == XRc)) {
25564 /* both operands same -> just set destination to one of them */
25565 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25566 } else {
25567 /* the most general case */
25568 TCGv_i32 t0 = tcg_temp_new();
25569 TCGv_i32 t1 = tcg_temp_new();
25570
25571 /* the left half-word first */
25572 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25573 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25574 if (opc == OPC_MXU_D16MAX) {
25575 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25576 } else {
25577 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25578 }
25579
25580 /* the right half-word */
25581 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25582 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25583 /* move half-words to the leftmost position */
25584 tcg_gen_shli_i32(t0, t0, 16);
25585 tcg_gen_shli_i32(t1, t1, 16);
25586 /* t0 will be max/min of t0 and t1 */
25587 if (opc == OPC_MXU_D16MAX) {
25588 tcg_gen_smax_i32(t0, t0, t1);
25589 } else {
25590 tcg_gen_smin_i32(t0, t0, t1);
25591 }
25592 /* return resulting half-words to its original position */
25593 tcg_gen_shri_i32(t0, t0, 16);
25594 /* finaly update the destination */
25595 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25596
25597 tcg_temp_free(t1);
25598 tcg_temp_free(t0);
25599 }
25600}
25601
25602/*
25603 * Q8MAX
25604 * Update XRa with the 8-bit-wise maximums of signed integers
25605 * contained in XRb and XRc.
25606 *
25607 * Q8MIN
25608 * Update XRa with the 8-bit-wise minimums of signed integers
25609 * contained in XRb and XRc.
25610 *
25611 * 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
25612 * +-----------+---------+-----+-------+-------+-------+-----------+
25613 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25614 * +-----------+---------+-----+-------+-------+-------+-----------+
25615 */
25616static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25617{
25618 uint32_t pad, opc, XRc, XRb, XRa;
25619
25620 pad = extract32(ctx->opcode, 21, 5);
25621 opc = extract32(ctx->opcode, 18, 3);
25622 XRc = extract32(ctx->opcode, 14, 4);
25623 XRb = extract32(ctx->opcode, 10, 4);
25624 XRa = extract32(ctx->opcode, 6, 4);
25625
25626 if (unlikely(pad != 0)) {
25627 /* opcode padding incorrect -> do nothing */
25628 } else if (unlikely(XRa == 0)) {
25629 /* destination is zero register -> do nothing */
25630 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25631 /* both operands zero registers -> just set destination to zero */
25632 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25633 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25634 /* exactly one operand is zero register - make it be the first...*/
25635 uint32_t XRx = XRb ? XRb : XRc;
25636 /* ...and do byte-wise max/min with one operand 0 */
25637 TCGv_i32 t0 = tcg_temp_new();
25638 TCGv_i32 t1 = tcg_const_i32(0);
25639 int32_t i;
25640
25641 /* the leftmost byte (byte 3) first */
25642 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25643 if (opc == OPC_MXU_Q8MAX) {
25644 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25645 } else {
25646 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25647 }
25648
25649 /* bytes 2, 1, 0 */
25650 for (i = 2; i >= 0; i--) {
25651 /* extract the byte */
25652 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25653 /* move the byte to the leftmost position */
25654 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25655 /* t0 will be max/min of t0 and t1 */
25656 if (opc == OPC_MXU_Q8MAX) {
25657 tcg_gen_smax_i32(t0, t0, t1);
25658 } else {
25659 tcg_gen_smin_i32(t0, t0, t1);
25660 }
25661 /* return resulting byte to its original position */
25662 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25663 /* finaly update the destination */
25664 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25665 }
25666
25667 tcg_temp_free(t1);
25668 tcg_temp_free(t0);
25669 } else if (unlikely(XRb == XRc)) {
25670 /* both operands same -> just set destination to one of them */
25671 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25672 } else {
25673 /* the most general case */
25674 TCGv_i32 t0 = tcg_temp_new();
25675 TCGv_i32 t1 = tcg_temp_new();
25676 int32_t i;
25677
25678 /* the leftmost bytes (bytes 3) first */
25679 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25680 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25681 if (opc == OPC_MXU_Q8MAX) {
25682 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25683 } else {
25684 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25685 }
25686
25687 /* bytes 2, 1, 0 */
25688 for (i = 2; i >= 0; i--) {
25689 /* extract corresponding bytes */
25690 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25691 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25692 /* move the bytes to the leftmost position */
25693 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25694 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25695 /* t0 will be max/min of t0 and t1 */
25696 if (opc == OPC_MXU_Q8MAX) {
25697 tcg_gen_smax_i32(t0, t0, t1);
25698 } else {
25699 tcg_gen_smin_i32(t0, t0, t1);
25700 }
25701 /* return resulting byte to its original position */
25702 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25703 /* finaly update the destination */
25704 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25705 }
25706
25707 tcg_temp_free(t1);
25708 tcg_temp_free(t0);
25709 }
25710}
25711
25712
79f5fee7
AM
25713/*
25714 * MXU instruction category: align
25715 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25716 *
25717 * S32ALN S32ALNI
25718 */
25719
25720/*
25721 * S32ALNI XRc, XRb, XRa, optn3
25722 * Arrange bytes from XRb and XRc according to one of five sets of
25723 * rules determined by optn3, and place the result in XRa.
25724 *
25725 * 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
25726 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25727 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25728 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25729 *
25730 */
25731static void gen_mxu_S32ALNI(DisasContext *ctx)
25732{
25733 uint32_t optn3, pad, XRc, XRb, XRa;
25734
25735 optn3 = extract32(ctx->opcode, 23, 3);
25736 pad = extract32(ctx->opcode, 21, 2);
25737 XRc = extract32(ctx->opcode, 14, 4);
25738 XRb = extract32(ctx->opcode, 10, 4);
25739 XRa = extract32(ctx->opcode, 6, 4);
25740
25741 if (unlikely(pad != 0)) {
25742 /* opcode padding incorrect -> do nothing */
25743 } else if (unlikely(XRa == 0)) {
25744 /* destination is zero register -> do nothing */
25745 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25746 /* both operands zero registers -> just set destination to all 0s */
25747 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25748 } else if (unlikely(XRb == 0)) {
25749 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25750 switch (optn3) {
25751 case MXU_OPTN3_PTN0:
25752 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25753 break;
25754 case MXU_OPTN3_PTN1:
25755 case MXU_OPTN3_PTN2:
25756 case MXU_OPTN3_PTN3:
25757 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25758 8 * (4 - optn3));
25759 break;
25760 case MXU_OPTN3_PTN4:
25761 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25762 break;
25763 }
25764 } else if (unlikely(XRc == 0)) {
25765 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25766 switch (optn3) {
25767 case MXU_OPTN3_PTN0:
25768 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25769 break;
25770 case MXU_OPTN3_PTN1:
25771 case MXU_OPTN3_PTN2:
25772 case MXU_OPTN3_PTN3:
25773 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25774 break;
25775 case MXU_OPTN3_PTN4:
25776 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25777 break;
25778 }
25779 } else if (unlikely(XRb == XRc)) {
25780 /* both operands same -> just rotation or moving from any of them */
25781 switch (optn3) {
25782 case MXU_OPTN3_PTN0:
25783 case MXU_OPTN3_PTN4:
25784 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25785 break;
25786 case MXU_OPTN3_PTN1:
25787 case MXU_OPTN3_PTN2:
25788 case MXU_OPTN3_PTN3:
25789 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25790 break;
25791 }
25792 } else {
25793 /* the most general case */
25794 switch (optn3) {
25795 case MXU_OPTN3_PTN0:
25796 {
25797 /* */
25798 /* XRb XRc */
25799 /* +---------------+ */
25800 /* | A B C D | E F G H */
25801 /* +-------+-------+ */
25802 /* | */
25803 /* XRa */
25804 /* */
25805
25806 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25807 }
25808 break;
25809 case MXU_OPTN3_PTN1:
25810 {
25811 /* */
25812 /* XRb XRc */
25813 /* +-------------------+ */
25814 /* A | B C D E | F G H */
25815 /* +---------+---------+ */
25816 /* | */
25817 /* XRa */
25818 /* */
25819
25820 TCGv_i32 t0 = tcg_temp_new();
25821 TCGv_i32 t1 = tcg_temp_new();
25822
25823 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25824 tcg_gen_shli_i32(t0, t0, 8);
25825
25826 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25827 tcg_gen_shri_i32(t1, t1, 24);
25828
25829 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25830
25831 tcg_temp_free(t1);
25832 tcg_temp_free(t0);
25833 }
25834 break;
25835 case MXU_OPTN3_PTN2:
25836 {
25837 /* */
25838 /* XRb XRc */
25839 /* +-------------------+ */
25840 /* A B | C D E F | G H */
25841 /* +---------+---------+ */
25842 /* | */
25843 /* XRa */
25844 /* */
25845
25846 TCGv_i32 t0 = tcg_temp_new();
25847 TCGv_i32 t1 = tcg_temp_new();
25848
25849 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25850 tcg_gen_shli_i32(t0, t0, 16);
25851
25852 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25853 tcg_gen_shri_i32(t1, t1, 16);
25854
25855 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25856
25857 tcg_temp_free(t1);
25858 tcg_temp_free(t0);
25859 }
25860 break;
25861 case MXU_OPTN3_PTN3:
25862 {
25863 /* */
25864 /* XRb XRc */
25865 /* +-------------------+ */
25866 /* A B C | D E F G | H */
25867 /* +---------+---------+ */
25868 /* | */
25869 /* XRa */
25870 /* */
25871
25872 TCGv_i32 t0 = tcg_temp_new();
25873 TCGv_i32 t1 = tcg_temp_new();
25874
25875 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25876 tcg_gen_shli_i32(t0, t0, 24);
25877
25878 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25879 tcg_gen_shri_i32(t1, t1, 8);
25880
25881 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25882
25883 tcg_temp_free(t1);
25884 tcg_temp_free(t0);
25885 }
25886 break;
25887 case MXU_OPTN3_PTN4:
25888 {
25889 /* */
25890 /* XRb XRc */
25891 /* +---------------+ */
25892 /* A B C D | E F G H | */
25893 /* +-------+-------+ */
25894 /* | */
25895 /* XRa */
25896 /* */
25897
25898 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25899 }
25900 break;
25901 }
25902 }
25903}
25904
25905
96992d1a
CJ
25906/*
25907 * Decoding engine for MXU
25908 * =======================
25909 */
25910
03f40088
AM
25911/*
25912 *
25913 * Decode MXU pool00
25914 *
25915 * 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
25916 * +-----------+---------+-----+-------+-------+-------+-----------+
25917 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25918 * +-----------+---------+-----+-------+-------+-------+-----------+
25919 *
25920 */
25921static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25922{
25923 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25924
25925 switch (opcode) {
25926 case OPC_MXU_S32MAX:
03f40088 25927 case OPC_MXU_S32MIN:
bb84cbf3 25928 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
25929 break;
25930 case OPC_MXU_D16MAX:
03f40088 25931 case OPC_MXU_D16MIN:
bb84cbf3 25932 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
25933 break;
25934 case OPC_MXU_Q8MAX:
03f40088 25935 case OPC_MXU_Q8MIN:
bb84cbf3 25936 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
25937 break;
25938 case OPC_MXU_Q8SLT:
25939 /* TODO: Implement emulation of Q8SLT instruction. */
25940 MIPS_INVAL("OPC_MXU_Q8SLT");
25941 generate_exception_end(ctx, EXCP_RI);
25942 break;
25943 case OPC_MXU_Q8SLTU:
25944 /* TODO: Implement emulation of Q8SLTU instruction. */
25945 MIPS_INVAL("OPC_MXU_Q8SLTU");
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 pool01
25958 *
25959 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25960 * 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
25961 * +-----------+---------+-----+-------+-------+-------+-----------+
25962 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25963 * +-----------+---------+-----+-------+-------+-------+-----------+
25964 *
25965 * Q8ADD:
25966 * 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
25967 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25968 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25969 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25970 *
25971 */
25972static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25973{
25974 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25975
25976 switch (opcode) {
25977 case OPC_MXU_S32SLT:
25978 /* TODO: Implement emulation of S32SLT instruction. */
25979 MIPS_INVAL("OPC_MXU_S32SLT");
25980 generate_exception_end(ctx, EXCP_RI);
25981 break;
25982 case OPC_MXU_D16SLT:
25983 /* TODO: Implement emulation of D16SLT instruction. */
25984 MIPS_INVAL("OPC_MXU_D16SLT");
25985 generate_exception_end(ctx, EXCP_RI);
25986 break;
25987 case OPC_MXU_D16AVG:
25988 /* TODO: Implement emulation of D16AVG instruction. */
25989 MIPS_INVAL("OPC_MXU_D16AVG");
25990 generate_exception_end(ctx, EXCP_RI);
25991 break;
25992 case OPC_MXU_D16AVGR:
25993 /* TODO: Implement emulation of D16AVGR instruction. */
25994 MIPS_INVAL("OPC_MXU_D16AVGR");
25995 generate_exception_end(ctx, EXCP_RI);
25996 break;
25997 case OPC_MXU_Q8AVG:
25998 /* TODO: Implement emulation of Q8AVG instruction. */
25999 MIPS_INVAL("OPC_MXU_Q8AVG");
26000 generate_exception_end(ctx, EXCP_RI);
26001 break;
26002 case OPC_MXU_Q8AVGR:
26003 /* TODO: Implement emulation of Q8AVGR instruction. */
26004 MIPS_INVAL("OPC_MXU_Q8AVGR");
26005 generate_exception_end(ctx, EXCP_RI);
26006 break;
26007 case OPC_MXU_Q8ADD:
26008 /* TODO: Implement emulation of Q8ADD instruction. */
26009 MIPS_INVAL("OPC_MXU_Q8ADD");
26010 generate_exception_end(ctx, EXCP_RI);
26011 break;
26012 default:
26013 MIPS_INVAL("decode_opc_mxu");
26014 generate_exception_end(ctx, EXCP_RI);
26015 break;
26016 }
26017}
26018
26019/*
26020 *
26021 * Decode MXU pool02
26022 *
26023 * 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
26024 * +-----------+---------+-----+-------+-------+-------+-----------+
26025 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26026 * +-----------+---------+-----+-------+-------+-------+-----------+
26027 *
26028 */
26029static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26030{
26031 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26032
26033 switch (opcode) {
26034 case OPC_MXU_S32CPS:
26035 /* TODO: Implement emulation of S32CPS instruction. */
26036 MIPS_INVAL("OPC_MXU_S32CPS");
26037 generate_exception_end(ctx, EXCP_RI);
26038 break;
26039 case OPC_MXU_D16CPS:
26040 /* TODO: Implement emulation of D16CPS instruction. */
26041 MIPS_INVAL("OPC_MXU_D16CPS");
26042 generate_exception_end(ctx, EXCP_RI);
26043 break;
26044 case OPC_MXU_Q8ABD:
26045 /* TODO: Implement emulation of Q8ABD instruction. */
26046 MIPS_INVAL("OPC_MXU_Q8ABD");
26047 generate_exception_end(ctx, EXCP_RI);
26048 break;
26049 case OPC_MXU_Q16SAT:
26050 /* TODO: Implement emulation of Q16SAT instruction. */
26051 MIPS_INVAL("OPC_MXU_Q16SAT");
26052 generate_exception_end(ctx, EXCP_RI);
26053 break;
26054 default:
26055 MIPS_INVAL("decode_opc_mxu");
26056 generate_exception_end(ctx, EXCP_RI);
26057 break;
26058 }
26059}
26060
26061/*
26062 *
26063 * Decode MXU pool03
26064 *
26065 * D16MULF:
26066 * 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
26067 * +-----------+---+---+-------+-------+-------+-------+-----------+
26068 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26069 * +-----------+---+---+-------+-------+-------+-------+-----------+
26070 *
26071 * D16MULE:
26072 * 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
26073 * +-----------+---+---+-------+-------+-------+-------+-----------+
26074 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26075 * +-----------+---+---+-------+-------+-------+-------+-----------+
26076 *
26077 */
26078static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26079{
26080 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26081
26082 switch (opcode) {
26083 case OPC_MXU_D16MULF:
26084 /* TODO: Implement emulation of D16MULF instruction. */
26085 MIPS_INVAL("OPC_MXU_D16MULF");
26086 generate_exception_end(ctx, EXCP_RI);
26087 break;
26088 case OPC_MXU_D16MULE:
26089 /* TODO: Implement emulation of D16MULE instruction. */
26090 MIPS_INVAL("OPC_MXU_D16MULE");
26091 generate_exception_end(ctx, EXCP_RI);
26092 break;
26093 default:
26094 MIPS_INVAL("decode_opc_mxu");
26095 generate_exception_end(ctx, EXCP_RI);
26096 break;
26097 }
26098}
26099
26100/*
26101 *
26102 * Decode MXU pool04
26103 *
26104 * 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
26105 * +-----------+---------+-+-------------------+-------+-----------+
26106 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26107 * +-----------+---------+-+-------------------+-------+-----------+
26108 *
26109 */
26110static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26111{
26112 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26113
26114 switch (opcode) {
26115 case OPC_MXU_S32LDD:
03f40088 26116 case OPC_MXU_S32LDDR:
4ca83721 26117 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
26118 break;
26119 default:
26120 MIPS_INVAL("decode_opc_mxu");
26121 generate_exception_end(ctx, EXCP_RI);
26122 break;
26123 }
26124}
26125
26126/*
26127 *
26128 * Decode MXU pool05
26129 *
26130 * 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
26131 * +-----------+---------+-+-------------------+-------+-----------+
26132 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26133 * +-----------+---------+-+-------------------+-------+-----------+
26134 *
26135 */
26136static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26137{
26138 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26139
26140 switch (opcode) {
26141 case OPC_MXU_S32STD:
26142 /* TODO: Implement emulation of S32STD instruction. */
26143 MIPS_INVAL("OPC_MXU_S32STD");
26144 generate_exception_end(ctx, EXCP_RI);
26145 break;
26146 case OPC_MXU_S32STDR:
26147 /* TODO: Implement emulation of S32STDR instruction. */
26148 MIPS_INVAL("OPC_MXU_S32STDR");
26149 generate_exception_end(ctx, EXCP_RI);
26150 break;
26151 default:
26152 MIPS_INVAL("decode_opc_mxu");
26153 generate_exception_end(ctx, EXCP_RI);
26154 break;
26155 }
26156}
26157
26158/*
26159 *
26160 * Decode MXU pool06
26161 *
26162 * 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
26163 * +-----------+---------+---------+---+-------+-------+-----------+
26164 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26165 * +-----------+---------+---------+---+-------+-------+-----------+
26166 *
26167 */
26168static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26169{
26170 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26171
26172 switch (opcode) {
26173 case OPC_MXU_S32LDDV:
26174 /* TODO: Implement emulation of S32LDDV instruction. */
26175 MIPS_INVAL("OPC_MXU_S32LDDV");
26176 generate_exception_end(ctx, EXCP_RI);
26177 break;
26178 case OPC_MXU_S32LDDVR:
26179 /* TODO: Implement emulation of S32LDDVR instruction. */
26180 MIPS_INVAL("OPC_MXU_S32LDDVR");
26181 generate_exception_end(ctx, EXCP_RI);
26182 break;
26183 default:
26184 MIPS_INVAL("decode_opc_mxu");
26185 generate_exception_end(ctx, EXCP_RI);
26186 break;
26187 }
26188}
26189
26190/*
26191 *
26192 * Decode MXU pool07
26193 *
26194 * 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
26195 * +-----------+---------+---------+---+-------+-------+-----------+
26196 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26197 * +-----------+---------+---------+---+-------+-------+-----------+
26198 *
26199 */
26200static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26201{
26202 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26203
26204 switch (opcode) {
26205 case OPC_MXU_S32STDV:
26206 /* TODO: Implement emulation of S32TDV instruction. */
26207 MIPS_INVAL("OPC_MXU_S32TDV");
26208 generate_exception_end(ctx, EXCP_RI);
26209 break;
26210 case OPC_MXU_S32STDVR:
26211 /* TODO: Implement emulation of S32TDVR instruction. */
26212 MIPS_INVAL("OPC_MXU_S32TDVR");
26213 generate_exception_end(ctx, EXCP_RI);
26214 break;
26215 default:
26216 MIPS_INVAL("decode_opc_mxu");
26217 generate_exception_end(ctx, EXCP_RI);
26218 break;
26219 }
26220}
26221
26222/*
26223 *
26224 * Decode MXU pool08
26225 *
26226 * 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
26227 * +-----------+---------+-+-------------------+-------+-----------+
26228 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26229 * +-----------+---------+-+-------------------+-------+-----------+
26230 *
7480515f 26231 */
03f40088
AM
26232static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26233{
26234 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26235
26236 switch (opcode) {
26237 case OPC_MXU_S32LDI:
26238 /* TODO: Implement emulation of S32LDI instruction. */
26239 MIPS_INVAL("OPC_MXU_S32LDI");
26240 generate_exception_end(ctx, EXCP_RI);
26241 break;
26242 case OPC_MXU_S32LDIR:
26243 /* TODO: Implement emulation of S32LDIR instruction. */
26244 MIPS_INVAL("OPC_MXU_S32LDIR");
26245 generate_exception_end(ctx, EXCP_RI);
26246 break;
26247 default:
26248 MIPS_INVAL("decode_opc_mxu");
26249 generate_exception_end(ctx, EXCP_RI);
26250 break;
26251 }
26252}
26253
26254/*
26255 *
26256 * Decode MXU pool09
26257 *
26258 * 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
26259 * +-----------+---------+-+-------------------+-------+-----------+
26260 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26261 * +-----------+---------+-+-------------------+-------+-----------+
26262 *
26263 */
26264static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26265{
26266 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26267
26268 switch (opcode) {
26269 case OPC_MXU_S32SDI:
26270 /* TODO: Implement emulation of S32SDI instruction. */
26271 MIPS_INVAL("OPC_MXU_S32SDI");
26272 generate_exception_end(ctx, EXCP_RI);
26273 break;
26274 case OPC_MXU_S32SDIR:
26275 /* TODO: Implement emulation of S32SDIR instruction. */
26276 MIPS_INVAL("OPC_MXU_S32SDIR");
26277 generate_exception_end(ctx, EXCP_RI);
26278 break;
26279 default:
26280 MIPS_INVAL("decode_opc_mxu");
26281 generate_exception_end(ctx, EXCP_RI);
26282 break;
26283 }
26284}
26285
26286/*
26287 *
26288 * Decode MXU pool10
26289 *
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 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26293 * +-----------+---------+---------+---+-------+-------+-----------+
26294 *
26295 */
26296static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26297{
26298 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26299
26300 switch (opcode) {
26301 case OPC_MXU_S32LDIV:
26302 /* TODO: Implement emulation of S32LDIV instruction. */
26303 MIPS_INVAL("OPC_MXU_S32LDIV");
26304 generate_exception_end(ctx, EXCP_RI);
26305 break;
26306 case OPC_MXU_S32LDIVR:
26307 /* TODO: Implement emulation of S32LDIVR instruction. */
26308 MIPS_INVAL("OPC_MXU_S32LDIVR");
26309 generate_exception_end(ctx, EXCP_RI);
26310 break;
26311 default:
26312 MIPS_INVAL("decode_opc_mxu");
26313 generate_exception_end(ctx, EXCP_RI);
26314 break;
26315 }
26316}
26317
26318/*
26319 *
26320 * Decode MXU pool11
26321 *
26322 * 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
26323 * +-----------+---------+---------+---+-------+-------+-----------+
26324 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26325 * +-----------+---------+---------+---+-------+-------+-----------+
26326 *
26327 */
26328static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26329{
26330 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26331
26332 switch (opcode) {
26333 case OPC_MXU_S32SDIV:
26334 /* TODO: Implement emulation of S32SDIV instruction. */
26335 MIPS_INVAL("OPC_MXU_S32SDIV");
26336 generate_exception_end(ctx, EXCP_RI);
26337 break;
26338 case OPC_MXU_S32SDIVR:
26339 /* TODO: Implement emulation of S32SDIVR instruction. */
26340 MIPS_INVAL("OPC_MXU_S32SDIVR");
26341 generate_exception_end(ctx, EXCP_RI);
26342 break;
26343 default:
26344 MIPS_INVAL("decode_opc_mxu");
26345 generate_exception_end(ctx, EXCP_RI);
26346 break;
26347 }
26348}
26349
26350/*
26351 *
26352 * Decode MXU pool12
26353 *
26354 * 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
26355 * +-----------+---+---+-------+-------+-------+-------+-----------+
26356 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26357 * +-----------+---+---+-------+-------+-------+-------+-----------+
26358 *
26359 */
26360static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26361{
26362 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26363
26364 switch (opcode) {
26365 case OPC_MXU_D32ACC:
26366 /* TODO: Implement emulation of D32ACC instruction. */
26367 MIPS_INVAL("OPC_MXU_D32ACC");
26368 generate_exception_end(ctx, EXCP_RI);
26369 break;
26370 case OPC_MXU_D32ACCM:
26371 /* TODO: Implement emulation of D32ACCM instruction. */
26372 MIPS_INVAL("OPC_MXU_D32ACCM");
26373 generate_exception_end(ctx, EXCP_RI);
26374 break;
26375 case OPC_MXU_D32ASUM:
26376 /* TODO: Implement emulation of D32ASUM instruction. */
26377 MIPS_INVAL("OPC_MXU_D32ASUM");
26378 generate_exception_end(ctx, EXCP_RI);
26379 break;
26380 default:
26381 MIPS_INVAL("decode_opc_mxu");
26382 generate_exception_end(ctx, EXCP_RI);
26383 break;
26384 }
26385}
26386
26387/*
26388 *
26389 * Decode MXU pool13
26390 *
26391 * 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
26392 * +-----------+---+---+-------+-------+-------+-------+-----------+
26393 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26394 * +-----------+---+---+-------+-------+-------+-------+-----------+
26395 *
26396 */
26397static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26398{
26399 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26400
26401 switch (opcode) {
26402 case OPC_MXU_Q16ACC:
26403 /* TODO: Implement emulation of Q16ACC instruction. */
26404 MIPS_INVAL("OPC_MXU_Q16ACC");
26405 generate_exception_end(ctx, EXCP_RI);
26406 break;
26407 case OPC_MXU_Q16ACCM:
26408 /* TODO: Implement emulation of Q16ACCM instruction. */
26409 MIPS_INVAL("OPC_MXU_Q16ACCM");
26410 generate_exception_end(ctx, EXCP_RI);
26411 break;
26412 case OPC_MXU_Q16ASUM:
26413 /* TODO: Implement emulation of Q16ASUM instruction. */
26414 MIPS_INVAL("OPC_MXU_Q16ASUM");
26415 generate_exception_end(ctx, EXCP_RI);
26416 break;
26417 default:
26418 MIPS_INVAL("decode_opc_mxu");
26419 generate_exception_end(ctx, EXCP_RI);
26420 break;
26421 }
26422}
26423
26424/*
26425 *
26426 * Decode MXU pool14
26427 *
26428 * Q8ADDE, Q8ACCE:
26429 * 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
26430 * +-----------+---+---+-------+-------+-------+-------+-----------+
26431 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26432 * +-----------+---+---+-------+-------+-------+-------+-----------+
26433 *
26434 * D8SUM, D8SUMC:
26435 * 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
26436 * +-----------+---+---+-------+-------+-------+-------+-----------+
26437 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26438 * +-----------+---+---+-------+-------+-------+-------+-----------+
26439 *
26440 */
26441static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26442{
26443 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26444
26445 switch (opcode) {
26446 case OPC_MXU_Q8ADDE:
26447 /* TODO: Implement emulation of Q8ADDE instruction. */
26448 MIPS_INVAL("OPC_MXU_Q8ADDE");
26449 generate_exception_end(ctx, EXCP_RI);
26450 break;
26451 case OPC_MXU_D8SUM:
26452 /* TODO: Implement emulation of D8SUM instruction. */
26453 MIPS_INVAL("OPC_MXU_D8SUM");
26454 generate_exception_end(ctx, EXCP_RI);
26455 break;
26456 case OPC_MXU_D8SUMC:
26457 /* TODO: Implement emulation of D8SUMC instruction. */
26458 MIPS_INVAL("OPC_MXU_D8SUMC");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26461 default:
26462 MIPS_INVAL("decode_opc_mxu");
26463 generate_exception_end(ctx, EXCP_RI);
26464 break;
26465 }
26466}
26467
26468/*
26469 *
26470 * Decode MXU pool15
26471 *
26472 * S32MUL, S32MULU, S32EXTRV:
26473 * 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
26474 * +-----------+---------+---------+---+-------+-------+-----------+
26475 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26476 * +-----------+---------+---------+---+-------+-------+-----------+
26477 *
26478 * S32EXTR:
26479 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26480 * +-----------+---------+---------+---+-------+-------+-----------+
26481 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26482 * +-----------+---------+---------+---+-------+-------+-----------+
26483 *
26484 */
26485static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26486{
26487 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26488
26489 switch (opcode) {
26490 case OPC_MXU_S32MUL:
26491 /* TODO: Implement emulation of S32MUL instruction. */
26492 MIPS_INVAL("OPC_MXU_S32MUL");
26493 generate_exception_end(ctx, EXCP_RI);
26494 break;
26495 case OPC_MXU_S32MULU:
26496 /* TODO: Implement emulation of S32MULU instruction. */
26497 MIPS_INVAL("OPC_MXU_S32MULU");
26498 generate_exception_end(ctx, EXCP_RI);
26499 break;
26500 case OPC_MXU_S32EXTR:
26501 /* TODO: Implement emulation of S32EXTR instruction. */
26502 MIPS_INVAL("OPC_MXU_S32EXTR");
26503 generate_exception_end(ctx, EXCP_RI);
26504 break;
26505 case OPC_MXU_S32EXTRV:
26506 /* TODO: Implement emulation of S32EXTRV instruction. */
26507 MIPS_INVAL("OPC_MXU_S32EXTRV");
26508 generate_exception_end(ctx, EXCP_RI);
26509 break;
26510 default:
26511 MIPS_INVAL("decode_opc_mxu");
26512 generate_exception_end(ctx, EXCP_RI);
26513 break;
26514 }
26515}
26516
26517/*
26518 *
26519 * Decode MXU pool16
26520 *
26521 * D32SARW:
26522 * 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
26523 * +-----------+---------+-----+-------+-------+-------+-----------+
26524 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26525 * +-----------+---------+-----+-------+-------+-------+-----------+
26526 *
26527 * S32ALN:
26528 * 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
26529 * +-----------+---------+-----+-------+-------+-------+-----------+
26530 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26531 * +-----------+---------+-----+-------+-------+-------+-----------+
26532 *
26533 * S32ALNI:
26534 * 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
26535 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26536 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26537 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26538 *
03f40088
AM
26539 * S32LUI:
26540 * 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
26541 * +-----------+-----+---+-----+-------+---------------+-----------+
26542 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26543 * +-----------+-----+---+-----+-------+---------------+-----------+
26544 *
b621f018
AM
26545 * S32NOR, S32AND, S32OR, S32XOR:
26546 * 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
26547 * +-----------+---------+-----+-------+-------+-------+-----------+
26548 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26549 * +-----------+---------+-----+-------+-------+-------+-----------+
26550 *
03f40088
AM
26551 */
26552static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26553{
26554 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26555
26556 switch (opcode) {
26557 case OPC_MXU_D32SARW:
26558 /* TODO: Implement emulation of D32SARW instruction. */
26559 MIPS_INVAL("OPC_MXU_D32SARW");
26560 generate_exception_end(ctx, EXCP_RI);
26561 break;
26562 case OPC_MXU_S32ALN:
26563 /* TODO: Implement emulation of S32ALN instruction. */
26564 MIPS_INVAL("OPC_MXU_S32ALN");
26565 generate_exception_end(ctx, EXCP_RI);
26566 break;
26567 case OPC_MXU_S32ALNI:
79f5fee7 26568 gen_mxu_S32ALNI(ctx);
03f40088 26569 break;
b621f018
AM
26570 case OPC_MXU_S32LUI:
26571 /* TODO: Implement emulation of S32LUI instruction. */
26572 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
26573 generate_exception_end(ctx, EXCP_RI);
26574 break;
b621f018
AM
26575 case OPC_MXU_S32NOR:
26576 gen_mxu_S32NOR(ctx);
26577 break;
03f40088 26578 case OPC_MXU_S32AND:
b621f018 26579 gen_mxu_S32AND(ctx);
03f40088
AM
26580 break;
26581 case OPC_MXU_S32OR:
b621f018 26582 gen_mxu_S32OR(ctx);
03f40088
AM
26583 break;
26584 case OPC_MXU_S32XOR:
b621f018 26585 gen_mxu_S32XOR(ctx);
03f40088
AM
26586 break;
26587 default:
26588 MIPS_INVAL("decode_opc_mxu");
26589 generate_exception_end(ctx, EXCP_RI);
26590 break;
26591 }
26592}
26593
26594/*
26595 *
26596 * Decode MXU pool17
26597 *
26598 * 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
26599 * +-----------+---------+---------+---+---------+-----+-----------+
26600 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26601 * +-----------+---------+---------+---+---------+-----+-----------+
26602 *
26603 */
26604static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26605{
26606 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26607
26608 switch (opcode) {
26609 case OPC_MXU_LXW:
26610 /* TODO: Implement emulation of LXW instruction. */
26611 MIPS_INVAL("OPC_MXU_LXW");
26612 generate_exception_end(ctx, EXCP_RI);
26613 break;
26614 case OPC_MXU_LXH:
26615 /* TODO: Implement emulation of LXH instruction. */
26616 MIPS_INVAL("OPC_MXU_LXH");
26617 generate_exception_end(ctx, EXCP_RI);
26618 break;
26619 case OPC_MXU_LXHU:
26620 /* TODO: Implement emulation of LXHU instruction. */
26621 MIPS_INVAL("OPC_MXU_LXHU");
26622 generate_exception_end(ctx, EXCP_RI);
26623 break;
26624 case OPC_MXU_LXB:
26625 /* TODO: Implement emulation of LXB instruction. */
26626 MIPS_INVAL("OPC_MXU_LXB");
26627 generate_exception_end(ctx, EXCP_RI);
26628 break;
26629 case OPC_MXU_LXBU:
26630 /* TODO: Implement emulation of LXBU instruction. */
26631 MIPS_INVAL("OPC_MXU_LXBU");
26632 generate_exception_end(ctx, EXCP_RI);
26633 break;
26634 default:
26635 MIPS_INVAL("decode_opc_mxu");
26636 generate_exception_end(ctx, EXCP_RI);
26637 break;
26638 }
26639}
26640/*
26641 *
26642 * Decode MXU pool18
26643 *
26644 * 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 26645 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26646 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
26647 * +-----------+---------+-----+-------+-------+-------+-----------+
26648 *
26649 */
c233bf07 26650static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26651{
26652 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26653
26654 switch (opcode) {
26655 case OPC_MXU_D32SLLV:
26656 /* TODO: Implement emulation of D32SLLV instruction. */
26657 MIPS_INVAL("OPC_MXU_D32SLLV");
26658 generate_exception_end(ctx, EXCP_RI);
26659 break;
26660 case OPC_MXU_D32SLRV:
26661 /* TODO: Implement emulation of D32SLRV instruction. */
26662 MIPS_INVAL("OPC_MXU_D32SLRV");
26663 generate_exception_end(ctx, EXCP_RI);
26664 break;
26665 case OPC_MXU_D32SARV:
26666 /* TODO: Implement emulation of D32SARV instruction. */
26667 MIPS_INVAL("OPC_MXU_D32SARV");
26668 generate_exception_end(ctx, EXCP_RI);
26669 break;
26670 case OPC_MXU_Q16SLLV:
26671 /* TODO: Implement emulation of Q16SLLV instruction. */
26672 MIPS_INVAL("OPC_MXU_Q16SLLV");
26673 generate_exception_end(ctx, EXCP_RI);
26674 break;
26675 case OPC_MXU_Q16SLRV:
26676 /* TODO: Implement emulation of Q16SLRV instruction. */
26677 MIPS_INVAL("OPC_MXU_Q16SLRV");
26678 generate_exception_end(ctx, EXCP_RI);
26679 break;
26680 case OPC_MXU_Q16SARV:
26681 /* TODO: Implement emulation of Q16SARV instruction. */
26682 MIPS_INVAL("OPC_MXU_Q16SARV");
26683 generate_exception_end(ctx, EXCP_RI);
26684 break;
26685 default:
26686 MIPS_INVAL("decode_opc_mxu");
26687 generate_exception_end(ctx, EXCP_RI);
26688 break;
26689 }
26690}
26691
26692/*
26693 *
c233bf07 26694 * Decode MXU pool19
03f40088
AM
26695 *
26696 * 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
26697 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26698 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
26699 * +-----------+---+---+-------+-------+-------+-------+-----------+
26700 *
26701 */
c233bf07 26702static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26703{
26704 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26705
26706 switch (opcode) {
26707 case OPC_MXU_Q8MUL:
03f40088 26708 case OPC_MXU_Q8MULSU:
a9a4181b 26709 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
26710 break;
26711 default:
26712 MIPS_INVAL("decode_opc_mxu");
26713 generate_exception_end(ctx, EXCP_RI);
26714 break;
26715 }
26716}
26717
26718/*
26719 *
c233bf07 26720 * Decode MXU pool20
03f40088
AM
26721 *
26722 * 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
26723 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26724 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
26725 * +-----------+---------+-----+-------+-------+-------+-----------+
26726 *
26727 */
c233bf07 26728static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26729{
26730 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26731
26732 switch (opcode) {
26733 case OPC_MXU_Q8MOVZ:
26734 /* TODO: Implement emulation of Q8MOVZ instruction. */
26735 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26736 generate_exception_end(ctx, EXCP_RI);
26737 break;
26738 case OPC_MXU_Q8MOVN:
26739 /* TODO: Implement emulation of Q8MOVN instruction. */
26740 MIPS_INVAL("OPC_MXU_Q8MOVN");
26741 generate_exception_end(ctx, EXCP_RI);
26742 break;
26743 case OPC_MXU_D16MOVZ:
26744 /* TODO: Implement emulation of D16MOVZ instruction. */
26745 MIPS_INVAL("OPC_MXU_D16MOVZ");
26746 generate_exception_end(ctx, EXCP_RI);
26747 break;
26748 case OPC_MXU_D16MOVN:
26749 /* TODO: Implement emulation of D16MOVN instruction. */
26750 MIPS_INVAL("OPC_MXU_D16MOVN");
26751 generate_exception_end(ctx, EXCP_RI);
26752 break;
26753 case OPC_MXU_S32MOVZ:
26754 /* TODO: Implement emulation of S32MOVZ instruction. */
26755 MIPS_INVAL("OPC_MXU_S32MOVZ");
26756 generate_exception_end(ctx, EXCP_RI);
26757 break;
26758 case OPC_MXU_S32MOVN:
26759 /* TODO: Implement emulation of S32MOVN instruction. */
26760 MIPS_INVAL("OPC_MXU_S32MOVN");
26761 generate_exception_end(ctx, EXCP_RI);
26762 break;
26763 default:
26764 MIPS_INVAL("decode_opc_mxu");
26765 generate_exception_end(ctx, EXCP_RI);
26766 break;
26767 }
26768}
26769
26770/*
26771 *
c233bf07 26772 * Decode MXU pool21
03f40088
AM
26773 *
26774 * 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
26775 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26776 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
26777 * +-----------+---+---+-------+-------+-------+-------+-----------+
26778 *
26779 */
c233bf07 26780static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26781{
26782 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26783
26784 switch (opcode) {
26785 case OPC_MXU_Q8MAC:
26786 /* TODO: Implement emulation of Q8MAC instruction. */
26787 MIPS_INVAL("OPC_MXU_Q8MAC");
26788 generate_exception_end(ctx, EXCP_RI);
26789 break;
26790 case OPC_MXU_Q8MACSU:
26791 /* TODO: Implement emulation of Q8MACSU instruction. */
26792 MIPS_INVAL("OPC_MXU_Q8MACSU");
26793 generate_exception_end(ctx, EXCP_RI);
26794 break;
26795 default:
26796 MIPS_INVAL("decode_opc_mxu");
26797 generate_exception_end(ctx, EXCP_RI);
26798 break;
26799 }
26800}
26801
26802
26803/*
26804 * Main MXU decoding function
26805 *
26806 * 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
26807 * +-----------+---------------------------------------+-----------+
26808 * | SPECIAL2 | |x x x x x x|
26809 * +-----------+---------------------------------------+-----------+
26810 *
26811 */
0a348b9a
AM
26812static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26813{
11d56f61
CJ
26814 /*
26815 * TODO: Investigate necessity of including handling of
26816 * CLZ, CLO, SDBB in this function, as they belong to
26817 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26818 */
03f40088
AM
26819 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26820
87860df5
AM
26821 if (opcode == OPC__MXU_MUL) {
26822 uint32_t rs, rt, rd, op1;
26823
26824 rs = extract32(ctx->opcode, 21, 5);
26825 rt = extract32(ctx->opcode, 16, 5);
26826 rd = extract32(ctx->opcode, 11, 5);
26827 op1 = MASK_SPECIAL2(ctx->opcode);
26828
26829 gen_arith(ctx, op1, rd, rs, rt);
26830
26831 return;
26832 }
26833
26834 if (opcode == OPC_MXU_S32M2I) {
26835 gen_mxu_s32m2i(ctx);
26836 return;
26837 }
26838
26839 if (opcode == OPC_MXU_S32I2M) {
26840 gen_mxu_s32i2m(ctx);
26841 return;
26842 }
26843
e5bf8a08
AM
26844 {
26845 TCGv t_mxu_cr = tcg_temp_new();
26846 TCGLabel *l_exit = gen_new_label();
26847
26848 gen_load_mxu_cr(t_mxu_cr);
26849 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26850 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26851
26852 switch (opcode) {
26853 case OPC_MXU_S32MADD:
26854 /* TODO: Implement emulation of S32MADD instruction. */
26855 MIPS_INVAL("OPC_MXU_S32MADD");
26856 generate_exception_end(ctx, EXCP_RI);
26857 break;
26858 case OPC_MXU_S32MADDU:
26859 /* TODO: Implement emulation of S32MADDU instruction. */
26860 MIPS_INVAL("OPC_MXU_S32MADDU");
26861 generate_exception_end(ctx, EXCP_RI);
26862 break;
26863 case OPC_MXU__POOL00:
26864 decode_opc_mxu__pool00(env, ctx);
26865 break;
26866 case OPC_MXU_S32MSUB:
26867 /* TODO: Implement emulation of S32MSUB instruction. */
26868 MIPS_INVAL("OPC_MXU_S32MSUB");
26869 generate_exception_end(ctx, EXCP_RI);
26870 break;
26871 case OPC_MXU_S32MSUBU:
26872 /* TODO: Implement emulation of S32MSUBU instruction. */
26873 MIPS_INVAL("OPC_MXU_S32MSUBU");
26874 generate_exception_end(ctx, EXCP_RI);
26875 break;
26876 case OPC_MXU__POOL01:
26877 decode_opc_mxu__pool01(env, ctx);
26878 break;
26879 case OPC_MXU__POOL02:
26880 decode_opc_mxu__pool02(env, ctx);
26881 break;
26882 case OPC_MXU_D16MUL:
26883 gen_mxu_d16mul(ctx);
26884 break;
26885 case OPC_MXU__POOL03:
26886 decode_opc_mxu__pool03(env, ctx);
26887 break;
26888 case OPC_MXU_D16MAC:
26889 gen_mxu_d16mac(ctx);
26890 break;
26891 case OPC_MXU_D16MACF:
26892 /* TODO: Implement emulation of D16MACF instruction. */
26893 MIPS_INVAL("OPC_MXU_D16MACF");
26894 generate_exception_end(ctx, EXCP_RI);
26895 break;
26896 case OPC_MXU_D16MADL:
26897 /* TODO: Implement emulation of D16MADL instruction. */
26898 MIPS_INVAL("OPC_MXU_D16MADL");
26899 generate_exception_end(ctx, EXCP_RI);
26900 break;
26901 case OPC_MXU_S16MAD:
26902 /* TODO: Implement emulation of S16MAD instruction. */
26903 MIPS_INVAL("OPC_MXU_S16MAD");
26904 generate_exception_end(ctx, EXCP_RI);
26905 break;
26906 case OPC_MXU_Q16ADD:
26907 /* TODO: Implement emulation of Q16ADD instruction. */
26908 MIPS_INVAL("OPC_MXU_Q16ADD");
26909 generate_exception_end(ctx, EXCP_RI);
26910 break;
26911 case OPC_MXU_D16MACE:
26912 /* TODO: Implement emulation of D16MACE instruction. */
26913 MIPS_INVAL("OPC_MXU_D16MACE");
26914 generate_exception_end(ctx, EXCP_RI);
26915 break;
26916 case OPC_MXU__POOL04:
26917 decode_opc_mxu__pool04(env, ctx);
26918 break;
26919 case OPC_MXU__POOL05:
26920 decode_opc_mxu__pool05(env, ctx);
26921 break;
26922 case OPC_MXU__POOL06:
26923 decode_opc_mxu__pool06(env, ctx);
26924 break;
26925 case OPC_MXU__POOL07:
26926 decode_opc_mxu__pool07(env, ctx);
26927 break;
26928 case OPC_MXU__POOL08:
26929 decode_opc_mxu__pool08(env, ctx);
26930 break;
26931 case OPC_MXU__POOL09:
26932 decode_opc_mxu__pool09(env, ctx);
26933 break;
26934 case OPC_MXU__POOL10:
26935 decode_opc_mxu__pool10(env, ctx);
26936 break;
26937 case OPC_MXU__POOL11:
26938 decode_opc_mxu__pool11(env, ctx);
26939 break;
26940 case OPC_MXU_D32ADD:
26941 /* TODO: Implement emulation of D32ADD instruction. */
26942 MIPS_INVAL("OPC_MXU_D32ADD");
26943 generate_exception_end(ctx, EXCP_RI);
26944 break;
26945 case OPC_MXU__POOL12:
26946 decode_opc_mxu__pool12(env, ctx);
26947 break;
26948 case OPC_MXU__POOL13:
26949 decode_opc_mxu__pool13(env, ctx);
26950 break;
26951 case OPC_MXU__POOL14:
26952 decode_opc_mxu__pool14(env, ctx);
26953 break;
26954 case OPC_MXU_Q8ACCE:
26955 /* TODO: Implement emulation of Q8ACCE instruction. */
26956 MIPS_INVAL("OPC_MXU_Q8ACCE");
26957 generate_exception_end(ctx, EXCP_RI);
26958 break;
26959 case OPC_MXU_S8LDD:
26960 gen_mxu_s8ldd(ctx);
26961 break;
26962 case OPC_MXU_S8STD:
26963 /* TODO: Implement emulation of S8STD instruction. */
26964 MIPS_INVAL("OPC_MXU_S8STD");
26965 generate_exception_end(ctx, EXCP_RI);
26966 break;
26967 case OPC_MXU_S8LDI:
26968 /* TODO: Implement emulation of S8LDI instruction. */
26969 MIPS_INVAL("OPC_MXU_S8LDI");
26970 generate_exception_end(ctx, EXCP_RI);
26971 break;
26972 case OPC_MXU_S8SDI:
26973 /* TODO: Implement emulation of S8SDI instruction. */
26974 MIPS_INVAL("OPC_MXU_S8SDI");
26975 generate_exception_end(ctx, EXCP_RI);
26976 break;
26977 case OPC_MXU__POOL15:
26978 decode_opc_mxu__pool15(env, ctx);
26979 break;
26980 case OPC_MXU__POOL16:
26981 decode_opc_mxu__pool16(env, ctx);
26982 break;
c233bf07
AM
26983 case OPC_MXU__POOL17:
26984 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
26985 break;
26986 case OPC_MXU_S16LDD:
26987 /* TODO: Implement emulation of S16LDD instruction. */
26988 MIPS_INVAL("OPC_MXU_S16LDD");
26989 generate_exception_end(ctx, EXCP_RI);
26990 break;
26991 case OPC_MXU_S16STD:
26992 /* TODO: Implement emulation of S16STD instruction. */
26993 MIPS_INVAL("OPC_MXU_S16STD");
26994 generate_exception_end(ctx, EXCP_RI);
26995 break;
26996 case OPC_MXU_S16LDI:
26997 /* TODO: Implement emulation of S16LDI instruction. */
26998 MIPS_INVAL("OPC_MXU_S16LDI");
26999 generate_exception_end(ctx, EXCP_RI);
27000 break;
27001 case OPC_MXU_S16SDI:
27002 /* TODO: Implement emulation of S16SDI instruction. */
27003 MIPS_INVAL("OPC_MXU_S16SDI");
27004 generate_exception_end(ctx, EXCP_RI);
27005 break;
27006 case OPC_MXU_D32SLL:
27007 /* TODO: Implement emulation of D32SLL instruction. */
27008 MIPS_INVAL("OPC_MXU_D32SLL");
27009 generate_exception_end(ctx, EXCP_RI);
27010 break;
27011 case OPC_MXU_D32SLR:
27012 /* TODO: Implement emulation of D32SLR instruction. */
27013 MIPS_INVAL("OPC_MXU_D32SLR");
27014 generate_exception_end(ctx, EXCP_RI);
27015 break;
27016 case OPC_MXU_D32SARL:
27017 /* TODO: Implement emulation of D32SARL instruction. */
27018 MIPS_INVAL("OPC_MXU_D32SARL");
27019 generate_exception_end(ctx, EXCP_RI);
27020 break;
27021 case OPC_MXU_D32SAR:
27022 /* TODO: Implement emulation of D32SAR instruction. */
27023 MIPS_INVAL("OPC_MXU_D32SAR");
27024 generate_exception_end(ctx, EXCP_RI);
27025 break;
27026 case OPC_MXU_Q16SLL:
27027 /* TODO: Implement emulation of Q16SLL instruction. */
27028 MIPS_INVAL("OPC_MXU_Q16SLL");
27029 generate_exception_end(ctx, EXCP_RI);
27030 break;
27031 case OPC_MXU_Q16SLR:
27032 /* TODO: Implement emulation of Q16SLR instruction. */
27033 MIPS_INVAL("OPC_MXU_Q16SLR");
27034 generate_exception_end(ctx, EXCP_RI);
27035 break;
c233bf07
AM
27036 case OPC_MXU__POOL18:
27037 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
27038 break;
27039 case OPC_MXU_Q16SAR:
27040 /* TODO: Implement emulation of Q16SAR instruction. */
27041 MIPS_INVAL("OPC_MXU_Q16SAR");
27042 generate_exception_end(ctx, EXCP_RI);
27043 break;
e5bf8a08
AM
27044 case OPC_MXU__POOL19:
27045 decode_opc_mxu__pool19(env, ctx);
27046 break;
27047 case OPC_MXU__POOL20:
27048 decode_opc_mxu__pool20(env, ctx);
27049 break;
c233bf07
AM
27050 case OPC_MXU__POOL21:
27051 decode_opc_mxu__pool21(env, ctx);
27052 break;
e5bf8a08
AM
27053 case OPC_MXU_Q16SCOP:
27054 /* TODO: Implement emulation of Q16SCOP instruction. */
27055 MIPS_INVAL("OPC_MXU_Q16SCOP");
27056 generate_exception_end(ctx, EXCP_RI);
27057 break;
27058 case OPC_MXU_Q8MADL:
27059 /* TODO: Implement emulation of Q8MADL instruction. */
27060 MIPS_INVAL("OPC_MXU_Q8MADL");
27061 generate_exception_end(ctx, EXCP_RI);
27062 break;
27063 case OPC_MXU_S32SFL:
27064 /* TODO: Implement emulation of S32SFL instruction. */
27065 MIPS_INVAL("OPC_MXU_S32SFL");
27066 generate_exception_end(ctx, EXCP_RI);
27067 break;
27068 case OPC_MXU_Q8SAD:
27069 /* TODO: Implement emulation of Q8SAD instruction. */
27070 MIPS_INVAL("OPC_MXU_Q8SAD");
27071 generate_exception_end(ctx, EXCP_RI);
27072 break;
27073 default:
27074 MIPS_INVAL("decode_opc_mxu");
27075 generate_exception_end(ctx, EXCP_RI);
27076 }
27077
27078 gen_set_label(l_exit);
27079 tcg_temp_free(t_mxu_cr);
03f40088 27080 }
0a348b9a
AM
27081}
27082
b621f018
AM
27083#endif /* !defined(TARGET_MIPS64) */
27084
03f40088 27085
10dc65db 27086static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
27087{
27088 int rs, rt, rd;
27089 uint32_t op1;
6c5c1e20 27090
4267d3e6
LA
27091 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27092
099e5b4d
LA
27093 rs = (ctx->opcode >> 21) & 0x1f;
27094 rt = (ctx->opcode >> 16) & 0x1f;
27095 rd = (ctx->opcode >> 11) & 0x1f;
27096
27097 op1 = MASK_SPECIAL2(ctx->opcode);
27098 switch (op1) {
c2e19f3c
AM
27099 case OPC_MADD: /* Multiply and add/sub */
27100 case OPC_MADDU:
27101 case OPC_MSUB:
27102 case OPC_MSUBU:
099e5b4d
LA
27103 check_insn(ctx, ISA_MIPS32);
27104 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27105 break;
27106 case OPC_MUL:
099e5b4d
LA
27107 gen_arith(ctx, op1, rd, rs, rt);
27108 break;
fac5a073
LA
27109 case OPC_DIV_G_2F:
27110 case OPC_DIVU_G_2F:
27111 case OPC_MULT_G_2F:
27112 case OPC_MULTU_G_2F:
27113 case OPC_MOD_G_2F:
27114 case OPC_MODU_G_2F:
27115 check_insn(ctx, INSN_LOONGSON2F);
27116 gen_loongson_integer(ctx, op1, rd, rs, rt);
27117 break;
099e5b4d
LA
27118 case OPC_CLO:
27119 case OPC_CLZ:
27120 check_insn(ctx, ISA_MIPS32);
27121 gen_cl(ctx, op1, rd, rs);
27122 break;
27123 case OPC_SDBBP:
3b3c1694
LA
27124 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27125 gen_helper_do_semihosting(cpu_env);
27126 } else {
7480515f
AM
27127 /*
27128 * XXX: not clear which exception should be raised
3b3c1694
LA
27129 * when in debug mode...
27130 */
27131 check_insn(ctx, ISA_MIPS32);
9c708c7f 27132 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 27133 }
099e5b4d 27134 break;
9b1a1d68 27135#if defined(TARGET_MIPS64)
099e5b4d
LA
27136 case OPC_DCLO:
27137 case OPC_DCLZ:
27138 check_insn(ctx, ISA_MIPS64);
27139 check_mips_64(ctx);
27140 gen_cl(ctx, op1, rd, rs);
27141 break;
4267d3e6
LA
27142 case OPC_DMULT_G_2F:
27143 case OPC_DMULTU_G_2F:
27144 case OPC_DDIV_G_2F:
27145 case OPC_DDIVU_G_2F:
27146 case OPC_DMOD_G_2F:
27147 case OPC_DMODU_G_2F:
27148 check_insn(ctx, INSN_LOONGSON2F);
27149 gen_loongson_integer(ctx, op1, rd, rs, rt);
27150 break;
10dc65db 27151#endif
4267d3e6
LA
27152 default: /* Invalid */
27153 MIPS_INVAL("special2_legacy");
9c708c7f 27154 generate_exception_end(ctx, EXCP_RI);
4267d3e6 27155 break;
10dc65db
LA
27156 }
27157}
27158
27159static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27160{
15eacb9b
YK
27161 int rs, rt, rd, sa;
27162 uint32_t op1, op2;
10dc65db
LA
27163 int16_t imm;
27164
27165 rs = (ctx->opcode >> 21) & 0x1f;
27166 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
27167 rd = (ctx->opcode >> 11) & 0x1f;
27168 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
27169 imm = (int16_t)ctx->opcode >> 7;
27170
27171 op1 = MASK_SPECIAL3(ctx->opcode);
27172 switch (op1) {
bf7910c6
LA
27173 case R6_OPC_PREF:
27174 if (rt >= 24) {
27175 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 27176 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
27177 }
27178 /* Treat as NOP. */
27179 break;
27180 case R6_OPC_CACHE:
40d48212 27181 check_cp0_enabled(ctx);
0d74a222
LA
27182 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27183 gen_cache_operation(ctx, rt, rs, imm);
27184 }
bf7910c6 27185 break;
10dc65db 27186 case R6_OPC_SC:
33a07fa2 27187 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
27188 break;
27189 case R6_OPC_LL:
27190 gen_ld(ctx, op1, rt, rs, imm);
27191 break;
15eacb9b
YK
27192 case OPC_BSHFL:
27193 {
27194 if (rd == 0) {
27195 /* Treat as NOP. */
27196 break;
27197 }
15eacb9b
YK
27198 op2 = MASK_BSHFL(ctx->opcode);
27199 switch (op2) {
c2e19f3c 27200 case OPC_ALIGN:
373ecd38
AM
27201 case OPC_ALIGN_1:
27202 case OPC_ALIGN_2:
27203 case OPC_ALIGN_3:
821f2008 27204 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
27205 break;
27206 case OPC_BITSWAP:
1f1b4c00 27207 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27208 break;
27209 }
15eacb9b
YK
27210 }
27211 break;
bf7910c6
LA
27212#if defined(TARGET_MIPS64)
27213 case R6_OPC_SCD:
33a07fa2 27214 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
27215 break;
27216 case R6_OPC_LLD:
27217 gen_ld(ctx, op1, rt, rs, imm);
27218 break;
15eacb9b
YK
27219 case OPC_DBSHFL:
27220 check_mips_64(ctx);
27221 {
27222 if (rd == 0) {
27223 /* Treat as NOP. */
27224 break;
27225 }
15eacb9b
YK
27226 op2 = MASK_DBSHFL(ctx->opcode);
27227 switch (op2) {
c2e19f3c 27228 case OPC_DALIGN:
373ecd38
AM
27229 case OPC_DALIGN_1:
27230 case OPC_DALIGN_2:
27231 case OPC_DALIGN_3:
27232 case OPC_DALIGN_4:
27233 case OPC_DALIGN_5:
27234 case OPC_DALIGN_6:
27235 case OPC_DALIGN_7:
821f2008 27236 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
27237 break;
27238 case OPC_DBITSWAP:
1f1b4c00 27239 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27240 break;
27241 }
1f1b4c00 27242
15eacb9b
YK
27243 }
27244 break;
bf7910c6 27245#endif
10dc65db
LA
27246 default: /* Invalid */
27247 MIPS_INVAL("special3_r6");
9c708c7f 27248 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
27249 break;
27250 }
27251}
27252
27253static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27254{
fac5a073 27255 int rs, rt, rd;
099e5b4d 27256 uint32_t op1, op2;
099e5b4d
LA
27257
27258 rs = (ctx->opcode >> 21) & 0x1f;
27259 rt = (ctx->opcode >> 16) & 0x1f;
27260 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
27261
27262 op1 = MASK_SPECIAL3(ctx->opcode);
27263 switch (op1) {
c2e19f3c
AM
27264 case OPC_DIV_G_2E:
27265 case OPC_DIVU_G_2E:
27266 case OPC_MOD_G_2E:
27267 case OPC_MODU_G_2E:
27268 case OPC_MULT_G_2E:
27269 case OPC_MULTU_G_2E:
7480515f
AM
27270 /*
27271 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27272 * the same mask and op1.
27273 */
908f6be1 27274 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 27275 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 27276 switch (op2) {
099e5b4d
LA
27277 case OPC_ADDUH_QB:
27278 case OPC_ADDUH_R_QB:
27279 case OPC_ADDQH_PH:
27280 case OPC_ADDQH_R_PH:
27281 case OPC_ADDQH_W:
27282 case OPC_ADDQH_R_W:
27283 case OPC_SUBUH_QB:
27284 case OPC_SUBUH_R_QB:
27285 case OPC_SUBQH_PH:
27286 case OPC_SUBQH_R_PH:
27287 case OPC_SUBQH_W:
27288 case OPC_SUBQH_R_W:
461c08df
JL
27289 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27290 break;
099e5b4d
LA
27291 case OPC_MUL_PH:
27292 case OPC_MUL_S_PH:
27293 case OPC_MULQ_S_W:
27294 case OPC_MULQ_RS_W:
27295 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27296 break;
461c08df 27297 default:
099e5b4d 27298 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 27299 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
27300 break;
27301 }
099e5b4d
LA
27302 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27303 gen_loongson_integer(ctx, op1, rd, rs, rt);
27304 } else {
9c708c7f 27305 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27306 }
27307 break;
27308 case OPC_LX_DSP:
27309 op2 = MASK_LX(ctx->opcode);
27310 switch (op2) {
27311#if defined(TARGET_MIPS64)
27312 case OPC_LDX:
27313#endif
27314 case OPC_LBUX:
27315 case OPC_LHX:
27316 case OPC_LWX:
27317 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27318 break;
27319 default: /* Invalid */
27320 MIPS_INVAL("MASK LX");
9c708c7f 27321 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27322 break;
27323 }
27324 break;
27325 case OPC_ABSQ_S_PH_DSP:
27326 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27327 switch (op2) {
27328 case OPC_ABSQ_S_QB:
27329 case OPC_ABSQ_S_PH:
27330 case OPC_ABSQ_S_W:
27331 case OPC_PRECEQ_W_PHL:
27332 case OPC_PRECEQ_W_PHR:
27333 case OPC_PRECEQU_PH_QBL:
27334 case OPC_PRECEQU_PH_QBR:
27335 case OPC_PRECEQU_PH_QBLA:
27336 case OPC_PRECEQU_PH_QBRA:
27337 case OPC_PRECEU_PH_QBL:
27338 case OPC_PRECEU_PH_QBR:
27339 case OPC_PRECEU_PH_QBLA:
27340 case OPC_PRECEU_PH_QBRA:
27341 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27342 break;
27343 case OPC_BITREV:
27344 case OPC_REPL_QB:
27345 case OPC_REPLV_QB:
27346 case OPC_REPL_PH:
27347 case OPC_REPLV_PH:
27348 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27349 break;
27350 default:
27351 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 27352 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27353 break;
27354 }
27355 break;
27356 case OPC_ADDU_QB_DSP:
27357 op2 = MASK_ADDU_QB(ctx->opcode);
27358 switch (op2) {
27359 case OPC_ADDQ_PH:
27360 case OPC_ADDQ_S_PH:
27361 case OPC_ADDQ_S_W:
27362 case OPC_ADDU_QB:
27363 case OPC_ADDU_S_QB:
27364 case OPC_ADDU_PH:
27365 case OPC_ADDU_S_PH:
27366 case OPC_SUBQ_PH:
27367 case OPC_SUBQ_S_PH:
27368 case OPC_SUBQ_S_W:
27369 case OPC_SUBU_QB:
27370 case OPC_SUBU_S_QB:
27371 case OPC_SUBU_PH:
27372 case OPC_SUBU_S_PH:
27373 case OPC_ADDSC:
27374 case OPC_ADDWC:
27375 case OPC_MODSUB:
27376 case OPC_RADDU_W_QB:
27377 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27378 break;
27379 case OPC_MULEU_S_PH_QBL:
27380 case OPC_MULEU_S_PH_QBR:
27381 case OPC_MULQ_RS_PH:
27382 case OPC_MULEQ_S_W_PHL:
27383 case OPC_MULEQ_S_W_PHR:
27384 case OPC_MULQ_S_PH:
27385 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27386 break;
27387 default: /* Invalid */
27388 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 27389 generate_exception_end(ctx, EXCP_RI);
461c08df 27390 break;
461c08df 27391
099e5b4d
LA
27392 }
27393 break;
27394 case OPC_CMPU_EQ_QB_DSP:
27395 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27396 switch (op2) {
27397 case OPC_PRECR_SRA_PH_W:
27398 case OPC_PRECR_SRA_R_PH_W:
27399 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 27400 break;
099e5b4d
LA
27401 case OPC_PRECR_QB_PH:
27402 case OPC_PRECRQ_QB_PH:
27403 case OPC_PRECRQ_PH_W:
27404 case OPC_PRECRQ_RS_PH_W:
27405 case OPC_PRECRQU_S_QB_PH:
27406 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 27407 break;
099e5b4d
LA
27408 case OPC_CMPU_EQ_QB:
27409 case OPC_CMPU_LT_QB:
27410 case OPC_CMPU_LE_QB:
27411 case OPC_CMP_EQ_PH:
27412 case OPC_CMP_LT_PH:
27413 case OPC_CMP_LE_PH:
27414 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 27415 break;
099e5b4d
LA
27416 case OPC_CMPGU_EQ_QB:
27417 case OPC_CMPGU_LT_QB:
27418 case OPC_CMPGU_LE_QB:
27419 case OPC_CMPGDU_EQ_QB:
27420 case OPC_CMPGDU_LT_QB:
27421 case OPC_CMPGDU_LE_QB:
27422 case OPC_PICK_QB:
27423 case OPC_PICK_PH:
27424 case OPC_PACKRL_PH:
27425 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27426 break;
27427 default: /* Invalid */
27428 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 27429 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27430 break;
27431 }
27432 break;
27433 case OPC_SHLL_QB_DSP:
27434 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27435 break;
27436 case OPC_DPA_W_PH_DSP:
27437 op2 = MASK_DPA_W_PH(ctx->opcode);
27438 switch (op2) {
27439 case OPC_DPAU_H_QBL:
27440 case OPC_DPAU_H_QBR:
27441 case OPC_DPSU_H_QBL:
27442 case OPC_DPSU_H_QBR:
27443 case OPC_DPA_W_PH:
27444 case OPC_DPAX_W_PH:
27445 case OPC_DPAQ_S_W_PH:
27446 case OPC_DPAQX_S_W_PH:
27447 case OPC_DPAQX_SA_W_PH:
27448 case OPC_DPS_W_PH:
27449 case OPC_DPSX_W_PH:
27450 case OPC_DPSQ_S_W_PH:
27451 case OPC_DPSQX_S_W_PH:
27452 case OPC_DPSQX_SA_W_PH:
27453 case OPC_MULSAQ_S_W_PH:
27454 case OPC_DPAQ_SA_L_W:
27455 case OPC_DPSQ_SA_L_W:
27456 case OPC_MAQ_S_W_PHL:
27457 case OPC_MAQ_S_W_PHR:
27458 case OPC_MAQ_SA_W_PHL:
27459 case OPC_MAQ_SA_W_PHR:
27460 case OPC_MULSA_W_PH:
27461 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27462 break;
27463 default: /* Invalid */
27464 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 27465 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27466 break;
27467 }
27468 break;
27469 case OPC_INSV_DSP:
27470 op2 = MASK_INSV(ctx->opcode);
27471 switch (op2) {
27472 case OPC_INSV:
27473 check_dsp(ctx);
27474 {
27475 TCGv t0, t1;
27476
27477 if (rt == 0) {
099e5b4d
LA
27478 break;
27479 }
27480
27481 t0 = tcg_temp_new();
27482 t1 = tcg_temp_new();
27483
27484 gen_load_gpr(t0, rt);
27485 gen_load_gpr(t1, rs);
27486
27487 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27488
27489 tcg_temp_free(t0);
27490 tcg_temp_free(t1);
a22260ae
JL
27491 break;
27492 }
099e5b4d
LA
27493 default: /* Invalid */
27494 MIPS_INVAL("MASK INSV");
9c708c7f 27495 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27496 break;
27497 }
27498 break;
27499 case OPC_APPEND_DSP:
27500 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27501 break;
27502 case OPC_EXTR_W_DSP:
27503 op2 = MASK_EXTR_W(ctx->opcode);
27504 switch (op2) {
27505 case OPC_EXTR_W:
27506 case OPC_EXTR_R_W:
27507 case OPC_EXTR_RS_W:
27508 case OPC_EXTR_S_H:
27509 case OPC_EXTRV_S_H:
27510 case OPC_EXTRV_W:
27511 case OPC_EXTRV_R_W:
27512 case OPC_EXTRV_RS_W:
27513 case OPC_EXTP:
27514 case OPC_EXTPV:
27515 case OPC_EXTPDP:
27516 case OPC_EXTPDPV:
27517 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27518 break;
27519 case OPC_RDDSP:
27520 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27521 break;
27522 case OPC_SHILO:
27523 case OPC_SHILOV:
27524 case OPC_MTHLIP:
27525 case OPC_WRDSP:
27526 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27527 break;
27528 default: /* Invalid */
27529 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27530 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27531 break;
27532 }
27533 break;
099e5b4d 27534#if defined(TARGET_MIPS64)
c2e19f3c
AM
27535 case OPC_DDIV_G_2E:
27536 case OPC_DDIVU_G_2E:
27537 case OPC_DMULT_G_2E:
27538 case OPC_DMULTU_G_2E:
27539 case OPC_DMOD_G_2E:
27540 case OPC_DMODU_G_2E:
fac5a073
LA
27541 check_insn(ctx, INSN_LOONGSON2E);
27542 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 27543 break;
099e5b4d
LA
27544 case OPC_ABSQ_S_QH_DSP:
27545 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27546 switch (op2) {
27547 case OPC_PRECEQ_L_PWL:
27548 case OPC_PRECEQ_L_PWR:
27549 case OPC_PRECEQ_PW_QHL:
27550 case OPC_PRECEQ_PW_QHR:
27551 case OPC_PRECEQ_PW_QHLA:
27552 case OPC_PRECEQ_PW_QHRA:
27553 case OPC_PRECEQU_QH_OBL:
27554 case OPC_PRECEQU_QH_OBR:
27555 case OPC_PRECEQU_QH_OBLA:
27556 case OPC_PRECEQU_QH_OBRA:
27557 case OPC_PRECEU_QH_OBL:
27558 case OPC_PRECEU_QH_OBR:
27559 case OPC_PRECEU_QH_OBLA:
27560 case OPC_PRECEU_QH_OBRA:
27561 case OPC_ABSQ_S_OB:
27562 case OPC_ABSQ_S_PW:
27563 case OPC_ABSQ_S_QH:
27564 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27565 break;
27566 case OPC_REPL_OB:
27567 case OPC_REPL_PW:
27568 case OPC_REPL_QH:
27569 case OPC_REPLV_OB:
27570 case OPC_REPLV_PW:
27571 case OPC_REPLV_QH:
27572 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27573 break;
27574 default: /* Invalid */
27575 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 27576 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27577 break;
27578 }
27579 break;
27580 case OPC_ADDU_OB_DSP:
27581 op2 = MASK_ADDU_OB(ctx->opcode);
27582 switch (op2) {
27583 case OPC_RADDU_L_OB:
27584 case OPC_SUBQ_PW:
27585 case OPC_SUBQ_S_PW:
27586 case OPC_SUBQ_QH:
27587 case OPC_SUBQ_S_QH:
27588 case OPC_SUBU_OB:
27589 case OPC_SUBU_S_OB:
27590 case OPC_SUBU_QH:
27591 case OPC_SUBU_S_QH:
27592 case OPC_SUBUH_OB:
27593 case OPC_SUBUH_R_OB:
27594 case OPC_ADDQ_PW:
27595 case OPC_ADDQ_S_PW:
27596 case OPC_ADDQ_QH:
27597 case OPC_ADDQ_S_QH:
27598 case OPC_ADDU_OB:
27599 case OPC_ADDU_S_OB:
27600 case OPC_ADDU_QH:
27601 case OPC_ADDU_S_QH:
27602 case OPC_ADDUH_OB:
27603 case OPC_ADDUH_R_OB:
27604 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 27605 break;
099e5b4d
LA
27606 case OPC_MULEQ_S_PW_QHL:
27607 case OPC_MULEQ_S_PW_QHR:
27608 case OPC_MULEU_S_QH_OBL:
27609 case OPC_MULEU_S_QH_OBR:
27610 case OPC_MULQ_RS_QH:
27611 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27612 break;
099e5b4d
LA
27613 default: /* Invalid */
27614 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 27615 generate_exception_end(ctx, EXCP_RI);
26690560 27616 break;
099e5b4d
LA
27617 }
27618 break;
27619 case OPC_CMPU_EQ_OB_DSP:
27620 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27621 switch (op2) {
27622 case OPC_PRECR_SRA_QH_PW:
27623 case OPC_PRECR_SRA_R_QH_PW:
27624 /* Return value is rt. */
27625 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 27626 break;
099e5b4d
LA
27627 case OPC_PRECR_OB_QH:
27628 case OPC_PRECRQ_OB_QH:
27629 case OPC_PRECRQ_PW_L:
27630 case OPC_PRECRQ_QH_PW:
27631 case OPC_PRECRQ_RS_QH_PW:
27632 case OPC_PRECRQU_S_OB_QH:
27633 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 27634 break;
099e5b4d
LA
27635 case OPC_CMPU_EQ_OB:
27636 case OPC_CMPU_LT_OB:
27637 case OPC_CMPU_LE_OB:
27638 case OPC_CMP_EQ_QH:
27639 case OPC_CMP_LT_QH:
27640 case OPC_CMP_LE_QH:
27641 case OPC_CMP_EQ_PW:
27642 case OPC_CMP_LT_PW:
27643 case OPC_CMP_LE_PW:
27644 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 27645 break;
099e5b4d
LA
27646 case OPC_CMPGDU_EQ_OB:
27647 case OPC_CMPGDU_LT_OB:
27648 case OPC_CMPGDU_LE_OB:
27649 case OPC_CMPGU_EQ_OB:
27650 case OPC_CMPGU_LT_OB:
27651 case OPC_CMPGU_LE_OB:
27652 case OPC_PACKRL_PW:
27653 case OPC_PICK_OB:
27654 case OPC_PICK_PW:
27655 case OPC_PICK_QH:
27656 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 27657 break;
099e5b4d
LA
27658 default: /* Invalid */
27659 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 27660 generate_exception_end(ctx, EXCP_RI);
161f85e6 27661 break;
099e5b4d
LA
27662 }
27663 break;
27664 case OPC_DAPPEND_DSP:
27665 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27666 break;
27667 case OPC_DEXTR_W_DSP:
27668 op2 = MASK_DEXTR_W(ctx->opcode);
27669 switch (op2) {
27670 case OPC_DEXTP:
27671 case OPC_DEXTPDP:
27672 case OPC_DEXTPDPV:
27673 case OPC_DEXTPV:
27674 case OPC_DEXTR_L:
27675 case OPC_DEXTR_R_L:
27676 case OPC_DEXTR_RS_L:
27677 case OPC_DEXTR_W:
27678 case OPC_DEXTR_R_W:
27679 case OPC_DEXTR_RS_W:
27680 case OPC_DEXTR_S_H:
27681 case OPC_DEXTRV_L:
27682 case OPC_DEXTRV_R_L:
27683 case OPC_DEXTRV_RS_L:
27684 case OPC_DEXTRV_S_H:
27685 case OPC_DEXTRV_W:
27686 case OPC_DEXTRV_R_W:
27687 case OPC_DEXTRV_RS_W:
27688 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 27689 break;
099e5b4d
LA
27690 case OPC_DMTHLIP:
27691 case OPC_DSHILO:
27692 case OPC_DSHILOV:
27693 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 27694 break;
099e5b4d
LA
27695 default: /* Invalid */
27696 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27697 generate_exception_end(ctx, EXCP_RI);
461c08df 27698 break;
099e5b4d
LA
27699 }
27700 break;
27701 case OPC_DPAQ_W_QH_DSP:
27702 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27703 switch (op2) {
27704 case OPC_DPAU_H_OBL:
27705 case OPC_DPAU_H_OBR:
27706 case OPC_DPSU_H_OBL:
27707 case OPC_DPSU_H_OBR:
27708 case OPC_DPA_W_QH:
27709 case OPC_DPAQ_S_W_QH:
27710 case OPC_DPS_W_QH:
27711 case OPC_DPSQ_S_W_QH:
27712 case OPC_MULSAQ_S_W_QH:
27713 case OPC_DPAQ_SA_L_PW:
27714 case OPC_DPSQ_SA_L_PW:
27715 case OPC_MULSAQ_S_L_PW:
27716 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27717 break;
27718 case OPC_MAQ_S_W_QHLL:
27719 case OPC_MAQ_S_W_QHLR:
27720 case OPC_MAQ_S_W_QHRL:
27721 case OPC_MAQ_S_W_QHRR:
27722 case OPC_MAQ_SA_W_QHLL:
27723 case OPC_MAQ_SA_W_QHLR:
27724 case OPC_MAQ_SA_W_QHRL:
27725 case OPC_MAQ_SA_W_QHRR:
27726 case OPC_MAQ_S_L_PWL:
27727 case OPC_MAQ_S_L_PWR:
27728 case OPC_DMADD:
27729 case OPC_DMADDU:
27730 case OPC_DMSUB:
27731 case OPC_DMSUBU:
27732 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 27733 break;
099e5b4d
LA
27734 default: /* Invalid */
27735 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 27736 generate_exception_end(ctx, EXCP_RI);
b53371ed 27737 break;
099e5b4d
LA
27738 }
27739 break;
27740 case OPC_DINSV_DSP:
27741 op2 = MASK_INSV(ctx->opcode);
27742 switch (op2) {
27743 case OPC_DINSV:
27744 {
27745 TCGv t0, t1;
27746
27747 if (rt == 0) {
a22260ae
JL
27748 break;
27749 }
099e5b4d 27750 check_dsp(ctx);
1cb6686c 27751
099e5b4d
LA
27752 t0 = tcg_temp_new();
27753 t1 = tcg_temp_new();
1cb6686c 27754
099e5b4d
LA
27755 gen_load_gpr(t0, rt);
27756 gen_load_gpr(t1, rs);
1cb6686c 27757
099e5b4d 27758 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 27759
099e5b4d
LA
27760 tcg_temp_free(t0);
27761 tcg_temp_free(t1);
77c5fa8b 27762 break;
099e5b4d 27763 }
7a387fff 27764 default: /* Invalid */
099e5b4d 27765 MIPS_INVAL("MASK DINSV");
9c708c7f 27766 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
27767 break;
27768 }
27769 break;
099e5b4d
LA
27770 case OPC_SHLL_OB_DSP:
27771 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27772 break;
27773#endif
fac5a073
LA
27774 default: /* Invalid */
27775 MIPS_INVAL("special3_legacy");
9c708c7f 27776 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
27777 break;
27778 }
27779}
27780
37b9aae2
MM
27781
27782#if defined(TARGET_MIPS64)
27783
874b2879 27784static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 27785{
c8341e00 27786 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
27787
27788 switch (opc) {
baa609db
AM
27789 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27790 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27791 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27792 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27793 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27794 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27795 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27796 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27797 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27798 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27799 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27800 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27801 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27802 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27803 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27804 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27805 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27806 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27807 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27808 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27809 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27810 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27811 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27812 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27813 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27814 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
27815 break;
27816 default:
27817 MIPS_INVAL("TX79 MMI class MMI0");
27818 generate_exception_end(ctx, EXCP_RI);
27819 break;
27820 }
27821}
27822
874b2879 27823static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 27824{
c8341e00 27825 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
27826
27827 switch (opc) {
baa609db
AM
27828 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27829 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27830 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27831 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27832 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27833 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27834 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27835 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27836 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27837 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27838 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27839 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27840 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27841 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27842 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27843 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27844 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27845 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27846 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
27847 break;
27848 default:
27849 MIPS_INVAL("TX79 MMI class MMI1");
27850 generate_exception_end(ctx, EXCP_RI);
27851 break;
27852 }
27853}
27854
874b2879 27855static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 27856{
c8341e00 27857 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
27858
27859 switch (opc) {
baa609db
AM
27860 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27861 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27862 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27863 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27864 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27865 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27866 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27867 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27868 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
baa609db
AM
27869 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27870 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27871 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27872 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27873 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27874 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27875 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27876 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27877 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27878 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27879 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27880 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27881 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3 27882 break;
b87eef31
MM
27883 case MMI_OPC_2_PCPYLD:
27884 gen_mmi_pcpyld(ctx);
27885 break;
6c1e48d3
FN
27886 default:
27887 MIPS_INVAL("TX79 MMI class MMI2");
27888 generate_exception_end(ctx, EXCP_RI);
27889 break;
27890 }
27891}
27892
874b2879 27893static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 27894{
c8341e00 27895 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
27896
27897 switch (opc) {
baa609db
AM
27898 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27899 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27900 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27901 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27902 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27903 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27904 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
baa609db
AM
27905 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27906 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27907 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
baa609db
AM
27908 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27909 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc 27910 break;
d3434d9f
MM
27911 case MMI_OPC_3_PCPYH:
27912 gen_mmi_pcpyh(ctx);
27913 break;
fd487f83
MM
27914 case MMI_OPC_3_PCPYUD:
27915 gen_mmi_pcpyud(ctx);
27916 break;
ec1944fc
FN
27917 default:
27918 MIPS_INVAL("TX79 MMI class MMI3");
27919 generate_exception_end(ctx, EXCP_RI);
27920 break;
27921 }
27922}
27923
874b2879 27924static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 27925{
c8341e00 27926 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
27927 int rs = extract32(ctx->opcode, 21, 5);
27928 int rt = extract32(ctx->opcode, 16, 5);
27929 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
27930
27931 switch (opc) {
baa609db 27932 case MMI_OPC_CLASS_MMI0:
874b2879 27933 decode_mmi0(env, ctx);
88eafe0b 27934 break;
baa609db 27935 case MMI_OPC_CLASS_MMI1:
874b2879 27936 decode_mmi1(env, ctx);
7a803ca2 27937 break;
baa609db 27938 case MMI_OPC_CLASS_MMI2:
874b2879 27939 decode_mmi2(env, ctx);
6c1e48d3 27940 break;
baa609db 27941 case MMI_OPC_CLASS_MMI3:
874b2879 27942 decode_mmi3(env, ctx);
ec1944fc 27943 break;
baa609db
AM
27944 case MMI_OPC_MULT1:
27945 case MMI_OPC_MULTU1:
3b948f05
PMD
27946 case MMI_OPC_MADD:
27947 case MMI_OPC_MADDU:
a95c4c26
FN
27948 case MMI_OPC_MADD1:
27949 case MMI_OPC_MADDU1:
06de726b
FN
27950 gen_mul_txx9(ctx, opc, rd, rs, rt);
27951 break;
baa609db
AM
27952 case MMI_OPC_DIV1:
27953 case MMI_OPC_DIVU1:
c42171c3 27954 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 27955 break;
baa609db
AM
27956 case MMI_OPC_MTLO1:
27957 case MMI_OPC_MTHI1:
86efbfb6 27958 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 27959 break;
baa609db
AM
27960 case MMI_OPC_MFLO1:
27961 case MMI_OPC_MFHI1:
86efbfb6 27962 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 27963 break;
baa609db 27964 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
27965 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27966 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27967 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27968 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27969 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27970 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27971 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27972 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27973 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
27974 break;
27975 default:
27976 MIPS_INVAL("TX79 MMI class");
27977 generate_exception_end(ctx, EXCP_RI);
27978 break;
27979 }
27980}
27981
874b2879 27982static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 27983{
baa609db 27984 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
27985}
27986
874b2879 27987static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 27988{
baa609db 27989 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
27990}
27991
27992/*
27993 * The TX79-specific instruction Store Quadword
27994 *
27995 * +--------+-------+-------+------------------------+
27996 * | 011111 | base | rt | offset | SQ
27997 * +--------+-------+-------+------------------------+
27998 * 6 5 5 16
27999 *
28000 * has the same opcode as the Read Hardware Register instruction
28001 *
28002 * +--------+-------+-------+-------+-------+--------+
28003 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28004 * +--------+-------+-------+-------+-------+--------+
28005 * 6 5 5 5 5 6
28006 *
28007 * that is required, trapped and emulated by the Linux kernel. However, all
28008 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28009 * offset is odd. Therefore all valid SQ instructions can execute normally.
28010 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28011 * between SQ and RDHWR, as the Linux kernel does.
28012 */
874b2879 28013static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
28014{
28015 int base = extract32(ctx->opcode, 21, 5);
28016 int rt = extract32(ctx->opcode, 16, 5);
28017 int offset = extract32(ctx->opcode, 0, 16);
28018
28019#ifdef CONFIG_USER_ONLY
28020 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28021 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28022
28023 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28024 int rd = extract32(ctx->opcode, 11, 5);
28025
28026 gen_rdhwr(ctx, rt, rd, 0);
28027 return;
28028 }
28029#endif
28030
874b2879 28031 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
28032}
28033
37b9aae2
MM
28034#endif
28035
fac5a073
LA
28036static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28037{
28038 int rs, rt, rd, sa;
28039 uint32_t op1, op2;
76964147 28040 int16_t imm;
fac5a073
LA
28041
28042 rs = (ctx->opcode >> 21) & 0x1f;
28043 rt = (ctx->opcode >> 16) & 0x1f;
28044 rd = (ctx->opcode >> 11) & 0x1f;
28045 sa = (ctx->opcode >> 6) & 0x1f;
76964147 28046 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
28047
28048 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
28049
28050 /*
28051 * EVA loads and stores overlap Loongson 2E instructions decoded by
28052 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28053 * EVA is absent.
28054 */
28055 if (ctx->eva) {
28056 switch (op1) {
c2e19f3c
AM
28057 case OPC_LWLE:
28058 case OPC_LWRE:
76964147
JH
28059 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28060 /* fall through */
c2e19f3c
AM
28061 case OPC_LBUE:
28062 case OPC_LHUE:
28063 case OPC_LBE:
28064 case OPC_LHE:
28065 case OPC_LLE:
28066 case OPC_LWE:
76964147
JH
28067 check_cp0_enabled(ctx);
28068 gen_ld(ctx, op1, rt, rs, imm);
28069 return;
c2e19f3c
AM
28070 case OPC_SWLE:
28071 case OPC_SWRE:
76964147
JH
28072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28073 /* fall through */
c2e19f3c
AM
28074 case OPC_SBE:
28075 case OPC_SHE:
76964147
JH
28076 case OPC_SWE:
28077 check_cp0_enabled(ctx);
28078 gen_st(ctx, op1, rt, rs, imm);
28079 return;
28080 case OPC_SCE:
28081 check_cp0_enabled(ctx);
33a07fa2 28082 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
28083 return;
28084 case OPC_CACHEE:
28085 check_cp0_enabled(ctx);
28086 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28087 gen_cache_operation(ctx, rt, rs, imm);
28088 }
28089 /* Treat as NOP. */
28090 return;
28091 case OPC_PREFE:
28092 check_cp0_enabled(ctx);
28093 /* Treat as NOP. */
28094 return;
28095 }
28096 }
28097
fac5a073
LA
28098 switch (op1) {
28099 case OPC_EXT:
28100 case OPC_INS:
28101 check_insn(ctx, ISA_MIPS32R2);
28102 gen_bitops(ctx, op1, rt, rs, sa, rd);
28103 break;
28104 case OPC_BSHFL:
fac5a073 28105 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 28106 switch (op2) {
c2e19f3c 28107 case OPC_ALIGN:
373ecd38
AM
28108 case OPC_ALIGN_1:
28109 case OPC_ALIGN_2:
28110 case OPC_ALIGN_3:
15eacb9b
YK
28111 case OPC_BITSWAP:
28112 check_insn(ctx, ISA_MIPS32R6);
28113 decode_opc_special3_r6(env, ctx);
28114 break;
28115 default:
28116 check_insn(ctx, ISA_MIPS32R2);
28117 gen_bshfl(ctx, op2, rt, rd);
28118 break;
28119 }
fac5a073
LA
28120 break;
28121#if defined(TARGET_MIPS64)
c2e19f3c
AM
28122 case OPC_DEXTM:
28123 case OPC_DEXTU:
28124 case OPC_DEXT:
28125 case OPC_DINSM:
28126 case OPC_DINSU:
28127 case OPC_DINS:
fac5a073
LA
28128 check_insn(ctx, ISA_MIPS64R2);
28129 check_mips_64(ctx);
28130 gen_bitops(ctx, op1, rt, rs, sa, rd);
28131 break;
28132 case OPC_DBSHFL:
fac5a073 28133 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 28134 switch (op2) {
c2e19f3c 28135 case OPC_DALIGN:
373ecd38
AM
28136 case OPC_DALIGN_1:
28137 case OPC_DALIGN_2:
28138 case OPC_DALIGN_3:
28139 case OPC_DALIGN_4:
28140 case OPC_DALIGN_5:
28141 case OPC_DALIGN_6:
28142 case OPC_DALIGN_7:
15eacb9b
YK
28143 case OPC_DBITSWAP:
28144 check_insn(ctx, ISA_MIPS32R6);
28145 decode_opc_special3_r6(env, ctx);
28146 break;
28147 default:
28148 check_insn(ctx, ISA_MIPS64R2);
28149 check_mips_64(ctx);
28150 op2 = MASK_DBSHFL(ctx->opcode);
28151 gen_bshfl(ctx, op2, rt, rd);
28152 break;
28153 }
fac5a073
LA
28154 break;
28155#endif
28156 case OPC_RDHWR:
b00c7218 28157 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
28158 break;
28159 case OPC_FORK:
9affc1c5 28160 check_mt(ctx);
fac5a073
LA
28161 {
28162 TCGv t0 = tcg_temp_new();
28163 TCGv t1 = tcg_temp_new();
28164
28165 gen_load_gpr(t0, rt);
28166 gen_load_gpr(t1, rs);
28167 gen_helper_fork(t0, t1);
28168 tcg_temp_free(t0);
28169 tcg_temp_free(t1);
28170 }
28171 break;
28172 case OPC_YIELD:
9affc1c5 28173 check_mt(ctx);
fac5a073
LA
28174 {
28175 TCGv t0 = tcg_temp_new();
28176
fac5a073
LA
28177 gen_load_gpr(t0, rs);
28178 gen_helper_yield(t0, cpu_env, t0);
28179 gen_store_gpr(t0, rd);
28180 tcg_temp_free(t0);
28181 }
28182 break;
10dc65db
LA
28183 default:
28184 if (ctx->insn_flags & ISA_MIPS32R6) {
28185 decode_opc_special3_r6(env, ctx);
28186 } else {
28187 decode_opc_special3_legacy(env, ctx);
28188 }
099e5b4d
LA
28189 }
28190}
28191
863f264d
YK
28192/* MIPS SIMD Architecture (MSA) */
28193static inline int check_msa_access(DisasContext *ctx)
28194{
28195 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28196 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 28197 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28198 return 0;
28199 }
28200
28201 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28202 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 28203 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
28204 return 0;
28205 } else {
9c708c7f 28206 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28207 return 0;
28208 }
28209 }
28210 return 1;
28211}
28212
5692c6e1
YK
28213static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28214{
28215 /* generates tcg ops to check if any element is 0 */
28216 /* Note this function only works with MSA_WRLEN = 128 */
28217 uint64_t eval_zero_or_big = 0;
28218 uint64_t eval_big = 0;
28219 TCGv_i64 t0 = tcg_temp_new_i64();
28220 TCGv_i64 t1 = tcg_temp_new_i64();
28221 switch (df) {
28222 case DF_BYTE:
28223 eval_zero_or_big = 0x0101010101010101ULL;
28224 eval_big = 0x8080808080808080ULL;
28225 break;
28226 case DF_HALF:
28227 eval_zero_or_big = 0x0001000100010001ULL;
28228 eval_big = 0x8000800080008000ULL;
28229 break;
28230 case DF_WORD:
28231 eval_zero_or_big = 0x0000000100000001ULL;
28232 eval_big = 0x8000000080000000ULL;
28233 break;
28234 case DF_DOUBLE:
28235 eval_zero_or_big = 0x0000000000000001ULL;
28236 eval_big = 0x8000000000000000ULL;
28237 break;
28238 }
235785e8
AM
28239 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28240 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
5692c6e1 28241 tcg_gen_andi_i64(t0, t0, eval_big);
235785e8
AM
28242 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28243 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28244 tcg_gen_andi_i64(t1, t1, eval_big);
28245 tcg_gen_or_i64(t0, t0, t1);
28246 /* if all bits are zero then all elements are not zero */
28247 /* if some bit is non-zero then some element is zero */
28248 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28249 tcg_gen_trunc_i64_tl(tresult, t0);
28250 tcg_temp_free_i64(t0);
28251 tcg_temp_free_i64(t1);
28252}
28253
28254static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28255{
28256 uint8_t df = (ctx->opcode >> 21) & 0x3;
28257 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28258 int64_t s16 = (int16_t)ctx->opcode;
28259
28260 check_msa_access(ctx);
28261
075a1fe7 28262 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 28263 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
28264 return;
28265 }
28266 switch (op1) {
28267 case OPC_BZ_V:
28268 case OPC_BNZ_V:
28269 {
28270 TCGv_i64 t0 = tcg_temp_new_i64();
235785e8 28271 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28272 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28273 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28274 tcg_gen_trunc_i64_tl(bcond, t0);
28275 tcg_temp_free_i64(t0);
28276 }
28277 break;
28278 case OPC_BZ_B:
28279 case OPC_BZ_H:
28280 case OPC_BZ_W:
28281 case OPC_BZ_D:
28282 gen_check_zero_element(bcond, df, wt);
28283 break;
28284 case OPC_BNZ_B:
28285 case OPC_BNZ_H:
28286 case OPC_BNZ_W:
28287 case OPC_BNZ_D:
28288 gen_check_zero_element(bcond, df, wt);
28289 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28290 break;
28291 }
28292
eeb3bba8 28293 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
28294
28295 ctx->hflags |= MIPS_HFLAG_BC;
28296 ctx->hflags |= MIPS_HFLAG_BDS32;
28297}
28298
4c789546
YK
28299static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28300{
28301#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28302 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28303 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28304 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28305
28306 TCGv_i32 twd = tcg_const_i32(wd);
28307 TCGv_i32 tws = tcg_const_i32(ws);
28308 TCGv_i32 ti8 = tcg_const_i32(i8);
28309
28310 switch (MASK_MSA_I8(ctx->opcode)) {
28311 case OPC_ANDI_B:
28312 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28313 break;
28314 case OPC_ORI_B:
28315 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28316 break;
28317 case OPC_NORI_B:
28318 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28319 break;
28320 case OPC_XORI_B:
28321 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28322 break;
28323 case OPC_BMNZI_B:
28324 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28325 break;
28326 case OPC_BMZI_B:
28327 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28328 break;
28329 case OPC_BSELI_B:
28330 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28331 break;
28332 case OPC_SHF_B:
28333 case OPC_SHF_H:
28334 case OPC_SHF_W:
28335 {
28336 uint8_t df = (ctx->opcode >> 24) & 0x3;
28337 if (df == DF_DOUBLE) {
9c708c7f 28338 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28339 } else {
28340 TCGv_i32 tdf = tcg_const_i32(df);
28341 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28342 tcg_temp_free_i32(tdf);
28343 }
28344 }
28345 break;
28346 default:
28347 MIPS_INVAL("MSA instruction");
9c708c7f 28348 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28349 break;
28350 }
28351
28352 tcg_temp_free_i32(twd);
28353 tcg_temp_free_i32(tws);
28354 tcg_temp_free_i32(ti8);
28355}
28356
80e71591
YK
28357static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28358{
28359#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28360 uint8_t df = (ctx->opcode >> 21) & 0x3;
28361 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28362 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28363 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28364 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28365
28366 TCGv_i32 tdf = tcg_const_i32(df);
28367 TCGv_i32 twd = tcg_const_i32(wd);
28368 TCGv_i32 tws = tcg_const_i32(ws);
28369 TCGv_i32 timm = tcg_temp_new_i32();
28370 tcg_gen_movi_i32(timm, u5);
28371
28372 switch (MASK_MSA_I5(ctx->opcode)) {
28373 case OPC_ADDVI_df:
28374 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28375 break;
28376 case OPC_SUBVI_df:
28377 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28378 break;
28379 case OPC_MAXI_S_df:
28380 tcg_gen_movi_i32(timm, s5);
28381 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28382 break;
28383 case OPC_MAXI_U_df:
28384 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28385 break;
28386 case OPC_MINI_S_df:
28387 tcg_gen_movi_i32(timm, s5);
28388 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28389 break;
28390 case OPC_MINI_U_df:
28391 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28392 break;
28393 case OPC_CEQI_df:
28394 tcg_gen_movi_i32(timm, s5);
28395 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28396 break;
28397 case OPC_CLTI_S_df:
28398 tcg_gen_movi_i32(timm, s5);
28399 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28400 break;
28401 case OPC_CLTI_U_df:
28402 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28403 break;
28404 case OPC_CLEI_S_df:
28405 tcg_gen_movi_i32(timm, s5);
28406 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28407 break;
28408 case OPC_CLEI_U_df:
28409 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28410 break;
28411 case OPC_LDI_df:
28412 {
28413 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28414 tcg_gen_movi_i32(timm, s10);
28415 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28416 }
28417 break;
28418 default:
28419 MIPS_INVAL("MSA instruction");
9c708c7f 28420 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
28421 break;
28422 }
28423
28424 tcg_temp_free_i32(tdf);
28425 tcg_temp_free_i32(twd);
28426 tcg_temp_free_i32(tws);
28427 tcg_temp_free_i32(timm);
28428}
28429
d4cf28de
YK
28430static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28431{
28432#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28433 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28434 uint32_t df = 0, m = 0;
28435 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28436 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28437
28438 TCGv_i32 tdf;
28439 TCGv_i32 tm;
28440 TCGv_i32 twd;
28441 TCGv_i32 tws;
28442
28443 if ((dfm & 0x40) == 0x00) {
28444 m = dfm & 0x3f;
28445 df = DF_DOUBLE;
28446 } else if ((dfm & 0x60) == 0x40) {
28447 m = dfm & 0x1f;
28448 df = DF_WORD;
28449 } else if ((dfm & 0x70) == 0x60) {
28450 m = dfm & 0x0f;
28451 df = DF_HALF;
28452 } else if ((dfm & 0x78) == 0x70) {
28453 m = dfm & 0x7;
28454 df = DF_BYTE;
28455 } else {
9c708c7f 28456 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28457 return;
28458 }
28459
28460 tdf = tcg_const_i32(df);
28461 tm = tcg_const_i32(m);
28462 twd = tcg_const_i32(wd);
28463 tws = tcg_const_i32(ws);
28464
28465 switch (MASK_MSA_BIT(ctx->opcode)) {
28466 case OPC_SLLI_df:
28467 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28468 break;
28469 case OPC_SRAI_df:
28470 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28471 break;
28472 case OPC_SRLI_df:
28473 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28474 break;
28475 case OPC_BCLRI_df:
28476 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28477 break;
28478 case OPC_BSETI_df:
28479 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28480 break;
28481 case OPC_BNEGI_df:
28482 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28483 break;
28484 case OPC_BINSLI_df:
28485 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28486 break;
28487 case OPC_BINSRI_df:
28488 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28489 break;
28490 case OPC_SAT_S_df:
28491 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28492 break;
28493 case OPC_SAT_U_df:
28494 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28495 break;
28496 case OPC_SRARI_df:
28497 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28498 break;
28499 case OPC_SRLRI_df:
28500 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28501 break;
28502 default:
28503 MIPS_INVAL("MSA instruction");
9c708c7f 28504 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28505 break;
28506 }
28507
28508 tcg_temp_free_i32(tdf);
28509 tcg_temp_free_i32(tm);
28510 tcg_temp_free_i32(twd);
28511 tcg_temp_free_i32(tws);
28512}
28513
28f99f08
YK
28514static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28515{
28516#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28517 uint8_t df = (ctx->opcode >> 21) & 0x3;
28518 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28519 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28520 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28521
28522 TCGv_i32 tdf = tcg_const_i32(df);
28523 TCGv_i32 twd = tcg_const_i32(wd);
28524 TCGv_i32 tws = tcg_const_i32(ws);
28525 TCGv_i32 twt = tcg_const_i32(wt);
28526
28527 switch (MASK_MSA_3R(ctx->opcode)) {
2e3eddb0
AM
28528 case OPC_BINSL_df:
28529 switch (df) {
28530 case DF_BYTE:
28531 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28532 break;
28533 case DF_HALF:
28534 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28535 break;
28536 case DF_WORD:
28537 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28538 break;
28539 case DF_DOUBLE:
28540 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28541 break;
28542 }
28543 break;
28544 case OPC_BINSR_df:
28545 switch (df) {
28546 case DF_BYTE:
28547 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28548 break;
28549 case DF_HALF:
28550 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28551 break;
28552 case DF_WORD:
28553 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28554 break;
28555 case DF_DOUBLE:
28556 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28557 break;
28558 }
28559 break;
a44d6d14
AM
28560 case OPC_BCLR_df:
28561 switch (df) {
28562 case DF_BYTE:
28563 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28564 break;
28565 case DF_HALF:
28566 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28567 break;
28568 case DF_WORD:
28569 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28570 break;
28571 case DF_DOUBLE:
28572 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28573 break;
28574 }
28575 break;
28576 case OPC_BNEG_df:
28577 switch (df) {
28578 case DF_BYTE:
28579 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28580 break;
28581 case DF_HALF:
28582 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28583 break;
28584 case DF_WORD:
28585 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28586 break;
28587 case DF_DOUBLE:
28588 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28589 break;
28590 }
28591 break;
28592 case OPC_BSET_df:
28593 switch (df) {
28594 case DF_BYTE:
28595 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28596 break;
28597 case DF_HALF:
28598 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28599 break;
28600 case DF_WORD:
28601 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28602 break;
28603 case DF_DOUBLE:
28604 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28605 break;
28606 }
28607 break;
c65ca134
AM
28608 case OPC_ADD_A_df:
28609 switch (df) {
28610 case DF_BYTE:
28611 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28612 break;
28613 case DF_HALF:
28614 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28615 break;
28616 case DF_WORD:
28617 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28618 break;
28619 case DF_DOUBLE:
28620 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28621 break;
28622 }
28623 break;
28624 case OPC_ADDS_A_df:
28625 switch (df) {
28626 case DF_BYTE:
28627 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28628 break;
28629 case DF_HALF:
28630 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28631 break;
28632 case DF_WORD:
28633 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28634 break;
28635 case DF_DOUBLE:
28636 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28637 break;
28638 }
28639 break;
28640 case OPC_ADDS_S_df:
28641 switch (df) {
28642 case DF_BYTE:
28643 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28644 break;
28645 case DF_HALF:
28646 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28647 break;
28648 case DF_WORD:
28649 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28650 break;
28651 case DF_DOUBLE:
28652 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28653 break;
28654 }
28655 break;
28656 case OPC_ADDS_U_df:
28657 switch (df) {
28658 case DF_BYTE:
28659 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28660 break;
28661 case DF_HALF:
28662 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28663 break;
28664 case DF_WORD:
28665 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28666 break;
28667 case DF_DOUBLE:
28668 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28669 break;
28670 }
28671 break;
28672 case OPC_ADDV_df:
28673 switch (df) {
28674 case DF_BYTE:
28675 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28676 break;
28677 case DF_HALF:
28678 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28679 break;
28680 case DF_WORD:
28681 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28682 break;
28683 case DF_DOUBLE:
28684 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28685 break;
28686 }
28687 break;
7672edc4
AM
28688 case OPC_AVE_S_df:
28689 switch (df) {
28690 case DF_BYTE:
28691 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28692 break;
28693 case DF_HALF:
28694 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28695 break;
28696 case DF_WORD:
28697 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28698 break;
28699 case DF_DOUBLE:
28700 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28701 break;
28702 }
28703 break;
28704 case OPC_AVE_U_df:
28705 switch (df) {
28706 case DF_BYTE:
28707 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28708 break;
28709 case DF_HALF:
28710 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28711 break;
28712 case DF_WORD:
28713 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28714 break;
28715 case DF_DOUBLE:
28716 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28717 break;
28718 }
28719 break;
755107e2
AM
28720 case OPC_AVER_S_df:
28721 switch (df) {
28722 case DF_BYTE:
28723 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28724 break;
28725 case DF_HALF:
28726 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28727 break;
28728 case DF_WORD:
28729 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28730 break;
28731 case DF_DOUBLE:
28732 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28733 break;
28734 }
28735 break;
28736 case OPC_AVER_U_df:
28737 switch (df) {
28738 case DF_BYTE:
28739 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28740 break;
28741 case DF_HALF:
28742 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28743 break;
28744 case DF_WORD:
28745 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28746 break;
28747 case DF_DOUBLE:
28748 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28749 break;
28750 }
28751 break;
ade7e788
AM
28752 case OPC_CEQ_df:
28753 switch (df) {
28754 case DF_BYTE:
28755 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28756 break;
28757 case DF_HALF:
28758 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28759 break;
28760 case DF_WORD:
28761 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28762 break;
28763 case DF_DOUBLE:
28764 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28765 break;
28766 }
28767 break;
0501bb1a
AM
28768 case OPC_CLE_S_df:
28769 switch (df) {
28770 case DF_BYTE:
28771 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28772 break;
28773 case DF_HALF:
28774 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28775 break;
28776 case DF_WORD:
28777 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28778 break;
28779 case DF_DOUBLE:
28780 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28781 break;
28782 }
28783 break;
28784 case OPC_CLE_U_df:
28785 switch (df) {
28786 case DF_BYTE:
28787 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28788 break;
28789 case DF_HALF:
28790 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28791 break;
28792 case DF_WORD:
28793 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28794 break;
28795 case DF_DOUBLE:
28796 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28797 break;
28798 }
28799 break;
11656699
AM
28800 case OPC_CLT_S_df:
28801 switch (df) {
28802 case DF_BYTE:
28803 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28804 break;
28805 case DF_HALF:
28806 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28807 break;
28808 case DF_WORD:
28809 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28810 break;
28811 case DF_DOUBLE:
28812 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28813 break;
28814 }
28815 break;
28816 case OPC_CLT_U_df:
28817 switch (df) {
28818 case DF_BYTE:
28819 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28820 break;
28821 case DF_HALF:
28822 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28823 break;
28824 case DF_WORD:
28825 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28826 break;
28827 case DF_DOUBLE:
28828 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28829 break;
28830 }
28831 break;
64a0257f
AM
28832 case OPC_DIV_S_df:
28833 switch (df) {
28834 case DF_BYTE:
28835 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28836 break;
28837 case DF_HALF:
28838 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28839 break;
28840 case DF_WORD:
28841 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28842 break;
28843 case DF_DOUBLE:
28844 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28845 break;
28846 }
28847 break;
28848 case OPC_DIV_U_df:
28849 switch (df) {
28850 case DF_BYTE:
28851 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28852 break;
28853 case DF_HALF:
28854 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28855 break;
28856 case DF_WORD:
28857 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28858 break;
28859 case DF_DOUBLE:
28860 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28861 break;
28862 }
28863 break;
e8e01ef0
AM
28864 case OPC_MAX_A_df:
28865 switch (df) {
28866 case DF_BYTE:
28867 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28868 break;
28869 case DF_HALF:
28870 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28871 break;
28872 case DF_WORD:
28873 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28874 break;
28875 case DF_DOUBLE:
28876 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28877 break;
28878 }
28879 break;
2db26305
AM
28880 case OPC_MAX_S_df:
28881 switch (df) {
28882 case DF_BYTE:
28883 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28884 break;
28885 case DF_HALF:
28886 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28887 break;
28888 case DF_WORD:
28889 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28890 break;
28891 case DF_DOUBLE:
28892 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28893 break;
28894 }
28895 break;
28896 case OPC_MAX_U_df:
28897 switch (df) {
28898 case DF_BYTE:
28899 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28900 break;
28901 case DF_HALF:
28902 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28903 break;
28904 case DF_WORD:
28905 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28906 break;
28907 case DF_DOUBLE:
28908 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28909 break;
28910 }
28911 break;
e8e01ef0
AM
28912 case OPC_MIN_A_df:
28913 switch (df) {
28914 case DF_BYTE:
28915 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28916 break;
28917 case DF_HALF:
28918 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28919 break;
28920 case DF_WORD:
28921 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28922 break;
28923 case DF_DOUBLE:
28924 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28925 break;
28926 }
28927 break;
2db26305
AM
28928 case OPC_MIN_S_df:
28929 switch (df) {
28930 case DF_BYTE:
28931 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
28932 break;
28933 case DF_HALF:
28934 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
28935 break;
28936 case DF_WORD:
28937 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
28938 break;
28939 case DF_DOUBLE:
28940 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
28941 break;
28942 }
28943 break;
28944 case OPC_MIN_U_df:
28945 switch (df) {
28946 case DF_BYTE:
28947 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
28948 break;
28949 case DF_HALF:
28950 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
28951 break;
28952 case DF_WORD:
28953 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
28954 break;
28955 case DF_DOUBLE:
28956 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
28957 break;
28958 }
28959 break;
a6387ea5
AM
28960 case OPC_MOD_S_df:
28961 switch (df) {
28962 case DF_BYTE:
28963 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
28964 break;
28965 case DF_HALF:
28966 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
28967 break;
28968 case DF_WORD:
28969 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
28970 break;
28971 case DF_DOUBLE:
28972 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
28973 break;
28974 }
28975 break;
28976 case OPC_MOD_U_df:
28977 switch (df) {
28978 case DF_BYTE:
28979 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
28980 break;
28981 case DF_HALF:
28982 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
28983 break;
28984 case DF_WORD:
28985 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
28986 break;
28987 case DF_DOUBLE:
28988 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
28989 break;
28990 }
28991 break;
f392d134
AM
28992 case OPC_ASUB_S_df:
28993 switch (df) {
28994 case DF_BYTE:
28995 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
28996 break;
28997 case DF_HALF:
28998 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
28999 break;
29000 case DF_WORD:
29001 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29002 break;
29003 case DF_DOUBLE:
29004 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29005 break;
29006 }
29007 break;
29008 case OPC_ASUB_U_df:
29009 switch (df) {
29010 case DF_BYTE:
29011 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29012 break;
29013 case DF_HALF:
29014 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29015 break;
29016 case DF_WORD:
29017 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29018 break;
29019 case DF_DOUBLE:
29020 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29021 break;
29022 }
29023 break;
fb5f59b4
AM
29024 case OPC_ILVEV_df:
29025 switch (df) {
29026 case DF_BYTE:
29027 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_HALF:
29030 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29031 break;
29032 case DF_WORD:
29033 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29034 break;
29035 case DF_DOUBLE:
29036 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29037 break;
29038 }
29039 break;
29040 case OPC_ILVOD_df:
29041 switch (df) {
29042 case DF_BYTE:
29043 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_HALF:
29046 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29047 break;
29048 case DF_WORD:
29049 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29050 break;
29051 case DF_DOUBLE:
29052 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29053 break;
29054 }
29055 break;
29056 case OPC_ILVL_df:
29057 switch (df) {
29058 case DF_BYTE:
29059 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_HALF:
29062 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29063 break;
29064 case DF_WORD:
29065 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29066 break;
29067 case DF_DOUBLE:
29068 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29069 break;
29070 }
29071 break;
29072 case OPC_ILVR_df:
29073 switch (df) {
29074 case DF_BYTE:
29075 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_HALF:
29078 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29079 break;
29080 case DF_WORD:
29081 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29082 break;
29083 case DF_DOUBLE:
29084 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29085 break;
29086 }
29087 break;
8a0ee380
AM
29088 case OPC_PCKEV_df:
29089 switch (df) {
29090 case DF_BYTE:
29091 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_HALF:
29094 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29095 break;
29096 case DF_WORD:
29097 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29098 break;
29099 case DF_DOUBLE:
29100 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29101 break;
29102 }
29103 break;
29104 case OPC_PCKOD_df:
29105 switch (df) {
29106 case DF_BYTE:
29107 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_HALF:
29110 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29111 break;
29112 case DF_WORD:
29113 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29114 break;
29115 case DF_DOUBLE:
29116 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29117 break;
29118 }
29119 break;
28f99f08 29120 case OPC_SLL_df:
4d52cc2b
AM
29121 switch (df) {
29122 case DF_BYTE:
29123 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_HALF:
29126 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29127 break;
29128 case DF_WORD:
29129 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29130 break;
29131 case DF_DOUBLE:
29132 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29133 break;
29134 }
29135 break;
29136 case OPC_SRA_df:
29137 switch (df) {
29138 case DF_BYTE:
29139 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_HALF:
29142 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29143 break;
29144 case DF_WORD:
29145 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29146 break;
29147 case DF_DOUBLE:
29148 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29149 break;
29150 }
29151 break;
29152 case OPC_SRAR_df:
29153 switch (df) {
29154 case DF_BYTE:
29155 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_HALF:
29158 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29159 break;
29160 case DF_WORD:
29161 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29162 break;
29163 case DF_DOUBLE:
29164 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29165 break;
29166 }
29167 break;
29168 case OPC_SRL_df:
29169 switch (df) {
29170 case DF_BYTE:
29171 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_HALF:
29174 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29175 break;
29176 case DF_WORD:
29177 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29178 break;
29179 case DF_DOUBLE:
29180 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29181 break;
29182 }
29183 break;
29184 case OPC_SRLR_df:
29185 switch (df) {
29186 case DF_BYTE:
29187 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_HALF:
29190 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29191 break;
29192 case DF_WORD:
29193 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29194 break;
29195 case DF_DOUBLE:
29196 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29197 break;
29198 }
28f99f08 29199 break;
28f99f08
YK
29200 case OPC_SUBS_S_df:
29201 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
29202 break;
29203 case OPC_MULV_df:
29204 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
29205 break;
29206 case OPC_SLD_df:
29207 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29208 break;
29209 case OPC_VSHF_df:
29210 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29211 break;
28f99f08
YK
29212 case OPC_SUBV_df:
29213 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
29214 break;
28f99f08
YK
29215 case OPC_SUBS_U_df:
29216 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
29217 break;
29218 case OPC_MADDV_df:
29219 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
29220 break;
29221 case OPC_SPLAT_df:
29222 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29223 break;
28f99f08
YK
29224 case OPC_SUBSUS_U_df:
29225 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
29226 break;
29227 case OPC_MSUBV_df:
29228 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
29229 break;
28f99f08
YK
29230 case OPC_SUBSUU_S_df:
29231 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
29232 break;
28f99f08
YK
29233
29234 case OPC_DOTP_S_df:
29235 case OPC_DOTP_U_df:
29236 case OPC_DPADD_S_df:
29237 case OPC_DPADD_U_df:
29238 case OPC_DPSUB_S_df:
29239 case OPC_HADD_S_df:
29240 case OPC_DPSUB_U_df:
29241 case OPC_HADD_U_df:
29242 case OPC_HSUB_S_df:
29243 case OPC_HSUB_U_df:
29244 if (df == DF_BYTE) {
9c708c7f
PD
29245 generate_exception_end(ctx, EXCP_RI);
29246 break;
28f99f08
YK
29247 }
29248 switch (MASK_MSA_3R(ctx->opcode)) {
dc0af931
AM
29249 case OPC_HADD_S_df:
29250 switch (df) {
29251 case DF_HALF:
29252 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29253 break;
29254 case DF_WORD:
29255 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29256 break;
29257 case DF_DOUBLE:
29258 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29259 break;
29260 }
29261 break;
29262 case OPC_HADD_U_df:
29263 switch (df) {
29264 case DF_HALF:
29265 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29266 break;
29267 case DF_WORD:
29268 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29269 break;
29270 case DF_DOUBLE:
29271 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29272 break;
29273 }
29274 break;
b24b9aec
AM
29275 case OPC_HSUB_S_df:
29276 switch (df) {
29277 case DF_HALF:
29278 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29279 break;
29280 case DF_WORD:
29281 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29282 break;
29283 case DF_DOUBLE:
29284 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29285 break;
29286 }
29287 break;
29288 case OPC_HSUB_U_df:
29289 switch (df) {
29290 case DF_HALF:
29291 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29292 break;
29293 case DF_WORD:
29294 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29295 break;
29296 case DF_DOUBLE:
29297 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29298 break;
29299 }
29300 break;
28f99f08
YK
29301 case OPC_DOTP_S_df:
29302 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
29303 break;
29304 case OPC_DOTP_U_df:
29305 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
29306 break;
29307 case OPC_DPADD_S_df:
29308 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
29309 break;
29310 case OPC_DPADD_U_df:
29311 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
29312 break;
29313 case OPC_DPSUB_S_df:
29314 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
29315 break;
28f99f08
YK
29316 case OPC_DPSUB_U_df:
29317 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
29318 break;
28f99f08
YK
29319 }
29320 break;
29321 default:
29322 MIPS_INVAL("MSA instruction");
9c708c7f 29323 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
29324 break;
29325 }
29326 tcg_temp_free_i32(twd);
29327 tcg_temp_free_i32(tws);
29328 tcg_temp_free_i32(twt);
29329 tcg_temp_free_i32(tdf);
29330}
29331
1e608ec1
YK
29332static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29333{
29334#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29335 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29336 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29337 TCGv telm = tcg_temp_new();
29338 TCGv_i32 tsr = tcg_const_i32(source);
29339 TCGv_i32 tdt = tcg_const_i32(dest);
29340
29341 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29342 case OPC_CTCMSA:
29343 gen_load_gpr(telm, source);
29344 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29345 break;
29346 case OPC_CFCMSA:
29347 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29348 gen_store_gpr(telm, dest);
29349 break;
29350 case OPC_MOVE_V:
29351 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29352 break;
29353 default:
29354 MIPS_INVAL("MSA instruction");
9c708c7f 29355 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29356 break;
29357 }
29358
29359 tcg_temp_free(telm);
29360 tcg_temp_free_i32(tdt);
29361 tcg_temp_free_i32(tsr);
29362}
29363
29364static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29365 uint32_t n)
29366{
29367#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29368 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29369 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29370
29371 TCGv_i32 tws = tcg_const_i32(ws);
29372 TCGv_i32 twd = tcg_const_i32(wd);
29373 TCGv_i32 tn = tcg_const_i32(n);
29374 TCGv_i32 tdf = tcg_const_i32(df);
29375
29376 switch (MASK_MSA_ELM(ctx->opcode)) {
29377 case OPC_SLDI_df:
29378 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29379 break;
29380 case OPC_SPLATI_df:
29381 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29382 break;
29383 case OPC_INSVE_df:
29384 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29385 break;
29386 case OPC_COPY_S_df:
29387 case OPC_COPY_U_df:
29388 case OPC_INSERT_df:
29389#if !defined(TARGET_MIPS64)
29390 /* Double format valid only for MIPS64 */
29391 if (df == DF_DOUBLE) {
9c708c7f 29392 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29393 break;
29394 }
41d28858
MM
29395 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29396 (df == DF_WORD)) {
29397 generate_exception_end(ctx, EXCP_RI);
29398 break;
29399 }
1e608ec1
YK
29400#endif
29401 switch (MASK_MSA_ELM(ctx->opcode)) {
29402 case OPC_COPY_S_df:
cab48881 29403 if (likely(wd != 0)) {
631c4674
MM
29404 switch (df) {
29405 case DF_BYTE:
29406 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29407 break;
29408 case DF_HALF:
29409 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29410 break;
29411 case DF_WORD:
29412 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29413 break;
29414#if defined(TARGET_MIPS64)
29415 case DF_DOUBLE:
29416 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29417 break;
29418#endif
29419 default:
29420 assert(0);
29421 }
cab48881 29422 }
1e608ec1
YK
29423 break;
29424 case OPC_COPY_U_df:
cab48881 29425 if (likely(wd != 0)) {
41d28858
MM
29426 switch (df) {
29427 case DF_BYTE:
29428 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29429 break;
29430 case DF_HALF:
29431 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29432 break;
29433#if defined(TARGET_MIPS64)
29434 case DF_WORD:
29435 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29436 break;
29437#endif
29438 default:
29439 assert(0);
29440 }
cab48881 29441 }
1e608ec1
YK
29442 break;
29443 case OPC_INSERT_df:
c1c9a10f
MM
29444 switch (df) {
29445 case DF_BYTE:
29446 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29447 break;
29448 case DF_HALF:
29449 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29450 break;
29451 case DF_WORD:
29452 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29453 break;
29454#if defined(TARGET_MIPS64)
29455 case DF_DOUBLE:
29456 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29457 break;
29458#endif
29459 default:
29460 assert(0);
29461 }
1e608ec1
YK
29462 break;
29463 }
29464 break;
29465 default:
29466 MIPS_INVAL("MSA instruction");
9c708c7f 29467 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29468 }
29469 tcg_temp_free_i32(twd);
29470 tcg_temp_free_i32(tws);
29471 tcg_temp_free_i32(tn);
29472 tcg_temp_free_i32(tdf);
29473}
29474
29475static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29476{
29477 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29478 uint32_t df = 0, n = 0;
29479
29480 if ((dfn & 0x30) == 0x00) {
29481 n = dfn & 0x0f;
29482 df = DF_BYTE;
29483 } else if ((dfn & 0x38) == 0x20) {
29484 n = dfn & 0x07;
29485 df = DF_HALF;
29486 } else if ((dfn & 0x3c) == 0x30) {
29487 n = dfn & 0x03;
29488 df = DF_WORD;
29489 } else if ((dfn & 0x3e) == 0x38) {
29490 n = dfn & 0x01;
29491 df = DF_DOUBLE;
29492 } else if (dfn == 0x3E) {
29493 /* CTCMSA, CFCMSA, MOVE.V */
29494 gen_msa_elm_3e(env, ctx);
29495 return;
29496 } else {
9c708c7f 29497 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
29498 return;
29499 }
29500
29501 gen_msa_elm_df(env, ctx, df, n);
29502}
29503
7d05b9c8
YK
29504static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29505{
29506#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29507 uint8_t df = (ctx->opcode >> 21) & 0x1;
29508 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29509 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29510 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29511
29512 TCGv_i32 twd = tcg_const_i32(wd);
29513 TCGv_i32 tws = tcg_const_i32(ws);
29514 TCGv_i32 twt = tcg_const_i32(wt);
29515 TCGv_i32 tdf = tcg_temp_new_i32();
29516
29517 /* adjust df value for floating-point instruction */
29518 tcg_gen_movi_i32(tdf, df + 2);
29519
29520 switch (MASK_MSA_3RF(ctx->opcode)) {
29521 case OPC_FCAF_df:
29522 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29523 break;
29524 case OPC_FADD_df:
29525 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29526 break;
29527 case OPC_FCUN_df:
29528 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29529 break;
29530 case OPC_FSUB_df:
29531 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29532 break;
29533 case OPC_FCOR_df:
29534 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29535 break;
29536 case OPC_FCEQ_df:
29537 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29538 break;
29539 case OPC_FMUL_df:
29540 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29541 break;
29542 case OPC_FCUNE_df:
29543 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29544 break;
29545 case OPC_FCUEQ_df:
29546 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29547 break;
29548 case OPC_FDIV_df:
29549 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29550 break;
29551 case OPC_FCNE_df:
29552 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29553 break;
29554 case OPC_FCLT_df:
29555 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29556 break;
29557 case OPC_FMADD_df:
29558 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29559 break;
29560 case OPC_MUL_Q_df:
29561 tcg_gen_movi_i32(tdf, df + 1);
29562 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29563 break;
29564 case OPC_FCULT_df:
29565 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29566 break;
29567 case OPC_FMSUB_df:
29568 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29569 break;
29570 case OPC_MADD_Q_df:
29571 tcg_gen_movi_i32(tdf, df + 1);
29572 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29573 break;
29574 case OPC_FCLE_df:
29575 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29576 break;
29577 case OPC_MSUB_Q_df:
29578 tcg_gen_movi_i32(tdf, df + 1);
29579 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29580 break;
29581 case OPC_FCULE_df:
29582 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29583 break;
29584 case OPC_FEXP2_df:
29585 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29586 break;
29587 case OPC_FSAF_df:
29588 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29589 break;
29590 case OPC_FEXDO_df:
29591 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29592 break;
29593 case OPC_FSUN_df:
29594 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29595 break;
29596 case OPC_FSOR_df:
29597 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29598 break;
29599 case OPC_FSEQ_df:
29600 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29601 break;
29602 case OPC_FTQ_df:
29603 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29604 break;
29605 case OPC_FSUNE_df:
29606 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29607 break;
29608 case OPC_FSUEQ_df:
29609 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29610 break;
29611 case OPC_FSNE_df:
29612 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29613 break;
29614 case OPC_FSLT_df:
29615 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29616 break;
29617 case OPC_FMIN_df:
29618 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29619 break;
29620 case OPC_MULR_Q_df:
29621 tcg_gen_movi_i32(tdf, df + 1);
29622 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29623 break;
29624 case OPC_FSULT_df:
29625 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29626 break;
29627 case OPC_FMIN_A_df:
29628 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29629 break;
29630 case OPC_MADDR_Q_df:
29631 tcg_gen_movi_i32(tdf, df + 1);
29632 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29633 break;
29634 case OPC_FSLE_df:
29635 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29636 break;
29637 case OPC_FMAX_df:
29638 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29639 break;
29640 case OPC_MSUBR_Q_df:
29641 tcg_gen_movi_i32(tdf, df + 1);
29642 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29643 break;
29644 case OPC_FSULE_df:
29645 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29646 break;
29647 case OPC_FMAX_A_df:
29648 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29649 break;
29650 default:
29651 MIPS_INVAL("MSA instruction");
9c708c7f 29652 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
29653 break;
29654 }
29655
29656 tcg_temp_free_i32(twd);
29657 tcg_temp_free_i32(tws);
29658 tcg_temp_free_i32(twt);
29659 tcg_temp_free_i32(tdf);
29660}
29661
cbe50b9a
YK
29662static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29663{
29664#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29665 (op & (0x7 << 18)))
29666 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29667 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29668 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29669 uint8_t df = (ctx->opcode >> 16) & 0x3;
29670 TCGv_i32 twd = tcg_const_i32(wd);
29671 TCGv_i32 tws = tcg_const_i32(ws);
29672 TCGv_i32 twt = tcg_const_i32(wt);
29673 TCGv_i32 tdf = tcg_const_i32(df);
29674
29675 switch (MASK_MSA_2R(ctx->opcode)) {
29676 case OPC_FILL_df:
29677#if !defined(TARGET_MIPS64)
29678 /* Double format valid only for MIPS64 */
29679 if (df == DF_DOUBLE) {
9c708c7f 29680 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29681 break;
29682 }
29683#endif
29684 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29685 break;
cbe50b9a 29686 case OPC_NLOC_df:
81c4b059
AM
29687 switch (df) {
29688 case DF_BYTE:
29689 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29690 break;
29691 case DF_HALF:
29692 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29693 break;
29694 case DF_WORD:
29695 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29696 break;
29697 case DF_DOUBLE:
29698 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29699 break;
29700 }
cbe50b9a
YK
29701 break;
29702 case OPC_NLZC_df:
81c4b059
AM
29703 switch (df) {
29704 case DF_BYTE:
29705 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29706 break;
29707 case DF_HALF:
29708 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29709 break;
29710 case DF_WORD:
29711 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29712 break;
29713 case DF_DOUBLE:
29714 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29715 break;
29716 }
cbe50b9a 29717 break;
4c5daf38
AM
29718 case OPC_PCNT_df:
29719 switch (df) {
29720 case DF_BYTE:
29721 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29722 break;
29723 case DF_HALF:
29724 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29725 break;
29726 case DF_WORD:
29727 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29728 break;
29729 case DF_DOUBLE:
29730 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29731 break;
29732 }
29733 break;
cbe50b9a
YK
29734 default:
29735 MIPS_INVAL("MSA instruction");
9c708c7f 29736 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29737 break;
29738 }
29739
29740 tcg_temp_free_i32(twd);
29741 tcg_temp_free_i32(tws);
29742 tcg_temp_free_i32(twt);
29743 tcg_temp_free_i32(tdf);
29744}
29745
3bdeb688
YK
29746static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29747{
29748#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29749 (op & (0xf << 17)))
29750 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29751 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29752 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29753 uint8_t df = (ctx->opcode >> 16) & 0x1;
29754 TCGv_i32 twd = tcg_const_i32(wd);
29755 TCGv_i32 tws = tcg_const_i32(ws);
29756 TCGv_i32 twt = tcg_const_i32(wt);
29757 /* adjust df value for floating-point instruction */
29758 TCGv_i32 tdf = tcg_const_i32(df + 2);
29759
29760 switch (MASK_MSA_2RF(ctx->opcode)) {
29761 case OPC_FCLASS_df:
29762 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29763 break;
29764 case OPC_FTRUNC_S_df:
29765 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29766 break;
29767 case OPC_FTRUNC_U_df:
29768 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29769 break;
29770 case OPC_FSQRT_df:
29771 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29772 break;
29773 case OPC_FRSQRT_df:
29774 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29775 break;
29776 case OPC_FRCP_df:
29777 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29778 break;
29779 case OPC_FRINT_df:
29780 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29781 break;
29782 case OPC_FLOG2_df:
29783 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29784 break;
29785 case OPC_FEXUPL_df:
29786 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29787 break;
29788 case OPC_FEXUPR_df:
29789 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29790 break;
29791 case OPC_FFQL_df:
29792 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29793 break;
29794 case OPC_FFQR_df:
29795 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29796 break;
29797 case OPC_FTINT_S_df:
29798 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29799 break;
29800 case OPC_FTINT_U_df:
29801 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29802 break;
29803 case OPC_FFINT_S_df:
29804 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29805 break;
29806 case OPC_FFINT_U_df:
29807 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29808 break;
29809 }
29810
29811 tcg_temp_free_i32(twd);
29812 tcg_temp_free_i32(tws);
29813 tcg_temp_free_i32(twt);
29814 tcg_temp_free_i32(tdf);
29815}
29816
cbe50b9a
YK
29817static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29818{
29819#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29820 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29821 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29822 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29823 TCGv_i32 twd = tcg_const_i32(wd);
29824 TCGv_i32 tws = tcg_const_i32(ws);
29825 TCGv_i32 twt = tcg_const_i32(wt);
29826
29827 switch (MASK_MSA_VEC(ctx->opcode)) {
29828 case OPC_AND_V:
29829 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29830 break;
29831 case OPC_OR_V:
29832 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29833 break;
29834 case OPC_NOR_V:
29835 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29836 break;
29837 case OPC_XOR_V:
29838 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29839 break;
29840 case OPC_BMNZ_V:
29841 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29842 break;
29843 case OPC_BMZ_V:
29844 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29845 break;
29846 case OPC_BSEL_V:
29847 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29848 break;
29849 default:
29850 MIPS_INVAL("MSA instruction");
9c708c7f 29851 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29852 break;
29853 }
29854
29855 tcg_temp_free_i32(twd);
29856 tcg_temp_free_i32(tws);
29857 tcg_temp_free_i32(twt);
29858}
29859
29860static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29861{
29862 switch (MASK_MSA_VEC(ctx->opcode)) {
29863 case OPC_AND_V:
29864 case OPC_OR_V:
29865 case OPC_NOR_V:
29866 case OPC_XOR_V:
29867 case OPC_BMNZ_V:
29868 case OPC_BMZ_V:
29869 case OPC_BSEL_V:
29870 gen_msa_vec_v(env, ctx);
29871 break;
29872 case OPC_MSA_2R:
29873 gen_msa_2r(env, ctx);
29874 break;
3bdeb688
YK
29875 case OPC_MSA_2RF:
29876 gen_msa_2rf(env, ctx);
29877 break;
cbe50b9a
YK
29878 default:
29879 MIPS_INVAL("MSA instruction");
9c708c7f 29880 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29881 break;
29882 }
29883}
29884
4c789546
YK
29885static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29886{
29887 uint32_t opcode = ctx->opcode;
29888 check_insn(ctx, ASE_MSA);
29889 check_msa_access(ctx);
29890
29891 switch (MASK_MSA_MINOR(opcode)) {
29892 case OPC_MSA_I8_00:
29893 case OPC_MSA_I8_01:
29894 case OPC_MSA_I8_02:
29895 gen_msa_i8(env, ctx);
29896 break;
80e71591
YK
29897 case OPC_MSA_I5_06:
29898 case OPC_MSA_I5_07:
29899 gen_msa_i5(env, ctx);
29900 break;
d4cf28de
YK
29901 case OPC_MSA_BIT_09:
29902 case OPC_MSA_BIT_0A:
29903 gen_msa_bit(env, ctx);
29904 break;
28f99f08
YK
29905 case OPC_MSA_3R_0D:
29906 case OPC_MSA_3R_0E:
29907 case OPC_MSA_3R_0F:
29908 case OPC_MSA_3R_10:
29909 case OPC_MSA_3R_11:
29910 case OPC_MSA_3R_12:
29911 case OPC_MSA_3R_13:
29912 case OPC_MSA_3R_14:
29913 case OPC_MSA_3R_15:
29914 gen_msa_3r(env, ctx);
29915 break;
1e608ec1
YK
29916 case OPC_MSA_ELM:
29917 gen_msa_elm(env, ctx);
29918 break;
7d05b9c8
YK
29919 case OPC_MSA_3RF_1A:
29920 case OPC_MSA_3RF_1B:
29921 case OPC_MSA_3RF_1C:
29922 gen_msa_3rf(env, ctx);
29923 break;
cbe50b9a
YK
29924 case OPC_MSA_VEC:
29925 gen_msa_vec(env, ctx);
29926 break;
f7685877
YK
29927 case OPC_LD_B:
29928 case OPC_LD_H:
29929 case OPC_LD_W:
29930 case OPC_LD_D:
29931 case OPC_ST_B:
29932 case OPC_ST_H:
29933 case OPC_ST_W:
29934 case OPC_ST_D:
29935 {
29936 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29937 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29938 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29939 uint8_t df = (ctx->opcode >> 0) & 0x3;
29940
f7685877 29941 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
29942 TCGv taddr = tcg_temp_new();
29943 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
29944
29945 switch (MASK_MSA_MINOR(opcode)) {
29946 case OPC_LD_B:
adc370a4
YK
29947 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29948 break;
f7685877 29949 case OPC_LD_H:
adc370a4
YK
29950 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29951 break;
f7685877 29952 case OPC_LD_W:
adc370a4
YK
29953 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29954 break;
f7685877 29955 case OPC_LD_D:
adc370a4 29956 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
29957 break;
29958 case OPC_ST_B:
adc370a4
YK
29959 gen_helper_msa_st_b(cpu_env, twd, taddr);
29960 break;
f7685877 29961 case OPC_ST_H:
adc370a4
YK
29962 gen_helper_msa_st_h(cpu_env, twd, taddr);
29963 break;
f7685877 29964 case OPC_ST_W:
adc370a4
YK
29965 gen_helper_msa_st_w(cpu_env, twd, taddr);
29966 break;
f7685877 29967 case OPC_ST_D:
adc370a4 29968 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
29969 break;
29970 }
29971
29972 tcg_temp_free_i32(twd);
adc370a4 29973 tcg_temp_free(taddr);
f7685877
YK
29974 }
29975 break;
4c789546
YK
29976 default:
29977 MIPS_INVAL("MSA instruction");
9c708c7f 29978 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
29979 break;
29980 }
29981
29982}
29983
d2bfa6e6 29984static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
29985{
29986 int32_t offset;
29987 int rs, rt, rd, sa;
29988 uint32_t op, op1;
29989 int16_t imm;
29990
29991 /* make sure instructions are on a word boundary */
eeb3bba8
EC
29992 if (ctx->base.pc_next & 0x3) {
29993 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 29994 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
29995 return;
29996 }
29997
29998 /* Handle blikely not taken case */
29999 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 30000 TCGLabel *l1 = gen_new_label();
099e5b4d 30001
099e5b4d
LA
30002 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30003 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 30004 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
30005 gen_set_label(l1);
30006 }
30007
099e5b4d
LA
30008 op = MASK_OP_MAJOR(ctx->opcode);
30009 rs = (ctx->opcode >> 21) & 0x1f;
30010 rt = (ctx->opcode >> 16) & 0x1f;
30011 rd = (ctx->opcode >> 11) & 0x1f;
30012 sa = (ctx->opcode >> 6) & 0x1f;
30013 imm = (int16_t)ctx->opcode;
30014 switch (op) {
30015 case OPC_SPECIAL:
30016 decode_opc_special(env, ctx);
30017 break;
30018 case OPC_SPECIAL2:
37b9aae2 30019#if defined(TARGET_MIPS64)
71b8a6b3 30020 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 30021 decode_mmi(env, ctx);
37b9aae2
MM
30022#else
30023 if (ctx->insn_flags & ASE_MXU) {
0a348b9a 30024 decode_opc_mxu(env, ctx);
b621f018 30025#endif
71b8a6b3
FN
30026 } else {
30027 decode_opc_special2_legacy(env, ctx);
30028 }
099e5b4d
LA
30029 break;
30030 case OPC_SPECIAL3:
37b9aae2 30031#if defined(TARGET_MIPS64)
bb41e74b 30032 if (ctx->insn_flags & INSN_R5900) {
874b2879 30033 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
30034 } else {
30035 decode_opc_special3(env, ctx);
30036 }
37b9aae2
MM
30037#else
30038 decode_opc_special3(env, ctx);
30039#endif
099e5b4d 30040 break;
7a387fff
TS
30041 case OPC_REGIMM:
30042 op1 = MASK_REGIMM(ctx->opcode);
30043 switch (op1) {
fecd2646
LA
30044 case OPC_BLTZL: /* REGIMM branches */
30045 case OPC_BGEZL:
30046 case OPC_BLTZALL:
30047 case OPC_BGEZALL:
d9224450 30048 check_insn(ctx, ISA_MIPS2);
fecd2646 30049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30050 /* Fallthrough */
fecd2646
LA
30051 case OPC_BLTZ:
30052 case OPC_BGEZ:
b231c103 30053 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30054 break;
fecd2646
LA
30055 case OPC_BLTZAL:
30056 case OPC_BGEZAL:
0aefa333
YK
30057 if (ctx->insn_flags & ISA_MIPS32R6) {
30058 if (rs == 0) {
30059 /* OPC_NAL, OPC_BAL */
b231c103 30060 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 30061 } else {
9c708c7f 30062 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
30063 }
30064 } else {
b231c103 30065 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30066 }
c9602061 30067 break;
c2e19f3c
AM
30068 case OPC_TGEI: /* REGIMM traps */
30069 case OPC_TGEIU:
30070 case OPC_TLTI:
30071 case OPC_TLTIU:
30072 case OPC_TEQI:
30073
7a387fff 30074 case OPC_TNEI:
d9224450 30075 check_insn(ctx, ISA_MIPS2);
fecd2646 30076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
30077 gen_trap(ctx, op1, rs, -1, imm);
30078 break;
bb238210
YK
30079 case OPC_SIGRIE:
30080 check_insn(ctx, ISA_MIPS32R6);
30081 generate_exception_end(ctx, EXCP_RI);
30082 break;
7a387fff 30083 case OPC_SYNCI:
d75c135e 30084 check_insn(ctx, ISA_MIPS32R2);
7480515f
AM
30085 /*
30086 * Break the TB to be able to sync copied instructions
30087 * immediately.
30088 */
eeb3bba8 30089 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 30090 break;
e45a93e2
JL
30091 case OPC_BPOSGE32: /* MIPS DSP branch */
30092#if defined(TARGET_MIPS64)
30093 case OPC_BPOSGE64:
30094#endif
30095 check_dsp(ctx);
b231c103 30096 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 30097 break;
d4ea6acd
LA
30098#if defined(TARGET_MIPS64)
30099 case OPC_DAHI:
30100 check_insn(ctx, ISA_MIPS32R6);
30101 check_mips_64(ctx);
30102 if (rs != 0) {
30103 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30104 }
d4ea6acd
LA
30105 break;
30106 case OPC_DATI:
30107 check_insn(ctx, ISA_MIPS32R6);
30108 check_mips_64(ctx);
30109 if (rs != 0) {
30110 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30111 }
d4ea6acd
LA
30112 break;
30113#endif
6af0bf9c 30114 default: /* Invalid */
923617a3 30115 MIPS_INVAL("regimm");
9c708c7f 30116 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30117 break;
30118 }
30119 break;
7a387fff 30120 case OPC_CP0:
387a8fe5 30121 check_cp0_enabled(ctx);
7a387fff 30122 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 30123 switch (op1) {
7a387fff
TS
30124 case OPC_MFC0:
30125 case OPC_MTC0:
ead9360e
TS
30126 case OPC_MFTR:
30127 case OPC_MTTR:
5204ea79
LA
30128 case OPC_MFHC0:
30129 case OPC_MTHC0:
d26bc211 30130#if defined(TARGET_MIPS64)
7a387fff
TS
30131 case OPC_DMFC0:
30132 case OPC_DMTC0:
30133#endif
f1aa6320 30134#ifndef CONFIG_USER_ONLY
932e71cd 30135 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 30136#endif /* !CONFIG_USER_ONLY */
7a387fff 30137 break;
c38a1d52
AR
30138 case OPC_C0:
30139 case OPC_C0_1:
30140 case OPC_C0_2:
30141 case OPC_C0_3:
30142 case OPC_C0_4:
30143 case OPC_C0_5:
30144 case OPC_C0_6:
30145 case OPC_C0_7:
30146 case OPC_C0_8:
30147 case OPC_C0_9:
30148 case OPC_C0_A:
30149 case OPC_C0_B:
30150 case OPC_C0_C:
30151 case OPC_C0_D:
30152 case OPC_C0_E:
30153 case OPC_C0_F:
f1aa6320 30154#ifndef CONFIG_USER_ONLY
932e71cd 30155 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 30156#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
30157 break;
30158 case OPC_MFMC0:
8706c382 30159#ifndef CONFIG_USER_ONLY
932e71cd 30160 {
099e5b4d 30161 uint32_t op2;
35fbce2c 30162 TCGv t0 = tcg_temp_new();
6c5c1e20 30163
0eaef5aa 30164 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
30165 switch (op2) {
30166 case OPC_DMT:
9affc1c5 30167 check_cp0_mt(ctx);
9ed5726c 30168 gen_helper_dmt(t0);
35fbce2c 30169 gen_store_gpr(t0, rt);
6c5c1e20
TS
30170 break;
30171 case OPC_EMT:
9affc1c5 30172 check_cp0_mt(ctx);
9ed5726c 30173 gen_helper_emt(t0);
35fbce2c 30174 gen_store_gpr(t0, rt);
da80682b 30175 break;
6c5c1e20 30176 case OPC_DVPE:
9affc1c5 30177 check_cp0_mt(ctx);
895c2d04 30178 gen_helper_dvpe(t0, cpu_env);
35fbce2c 30179 gen_store_gpr(t0, rt);
6c5c1e20
TS
30180 break;
30181 case OPC_EVPE:
9affc1c5 30182 check_cp0_mt(ctx);
895c2d04 30183 gen_helper_evpe(t0, cpu_env);
35fbce2c 30184 gen_store_gpr(t0, rt);
6c5c1e20 30185 break;
01bc435b
YK
30186 case OPC_DVP:
30187 check_insn(ctx, ISA_MIPS32R6);
30188 if (ctx->vp) {
30189 gen_helper_dvp(t0, cpu_env);
30190 gen_store_gpr(t0, rt);
30191 }
30192 break;
30193 case OPC_EVP:
30194 check_insn(ctx, ISA_MIPS32R6);
30195 if (ctx->vp) {
30196 gen_helper_evp(t0, cpu_env);
30197 gen_store_gpr(t0, rt);
30198 }
30199 break;
6c5c1e20 30200 case OPC_DI:
d75c135e 30201 check_insn(ctx, ISA_MIPS32R2);
867abc7e 30202 save_cpu_state(ctx, 1);
895c2d04 30203 gen_helper_di(t0, cpu_env);
35fbce2c 30204 gen_store_gpr(t0, rt);
7480515f
AM
30205 /*
30206 * Stop translation as we may have switched
30207 * the execution mode.
30208 */
eeb3bba8 30209 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
30210 break;
30211 case OPC_EI:
d75c135e 30212 check_insn(ctx, ISA_MIPS32R2);
867abc7e 30213 save_cpu_state(ctx, 1);
895c2d04 30214 gen_helper_ei(t0, cpu_env);
35fbce2c 30215 gen_store_gpr(t0, rt);
7480515f
AM
30216 /*
30217 * DISAS_STOP isn't sufficient, we need to ensure we break
30218 * out of translated code to check for pending interrupts.
30219 */
eeb3bba8
EC
30220 gen_save_pc(ctx->base.pc_next + 4);
30221 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
30222 break;
30223 default: /* Invalid */
30224 MIPS_INVAL("mfmc0");
9c708c7f 30225 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
30226 break;
30227 }
6c5c1e20 30228 tcg_temp_free(t0);
7a387fff 30229 }
0eaef5aa 30230#endif /* !CONFIG_USER_ONLY */
6af0bf9c 30231 break;
7a387fff 30232 case OPC_RDPGPR:
d75c135e 30233 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 30234 gen_load_srsgpr(rt, rd);
ead9360e 30235 break;
7a387fff 30236 case OPC_WRPGPR:
d75c135e 30237 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 30238 gen_store_srsgpr(rt, rd);
38121543 30239 break;
6af0bf9c 30240 default:
923617a3 30241 MIPS_INVAL("cp0");
9c708c7f 30242 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30243 break;
30244 }
30245 break;
31837be3
YK
30246 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30247 if (ctx->insn_flags & ISA_MIPS32R6) {
30248 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30249 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30250 } else {
30251 /* OPC_ADDI */
30252 /* Arithmetic with immediate opcode */
30253 gen_arith_imm(ctx, op, rt, rs, imm);
30254 }
30255 break;
324d9e32 30256 case OPC_ADDIU:
d75c135e 30257 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 30258 break;
324d9e32
AJ
30259 case OPC_SLTI: /* Set on less than with immediate opcode */
30260 case OPC_SLTIU:
d75c135e 30261 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
30262 break;
30263 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 30264 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
30265 case OPC_ORI:
30266 case OPC_XORI:
d75c135e 30267 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 30268 break;
c2e19f3c
AM
30269 case OPC_J: /* Jump */
30270 case OPC_JAL:
7a387fff 30271 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30272 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 30273 break;
31837be3
YK
30274 /* Branch */
30275 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30276 if (ctx->insn_flags & ISA_MIPS32R6) {
30277 if (rt == 0) {
9c708c7f 30278 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30279 break;
30280 }
30281 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30282 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30283 } else {
30284 /* OPC_BLEZL */
b231c103 30285 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30286 }
30287 break;
30288 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30289 if (ctx->insn_flags & ISA_MIPS32R6) {
30290 if (rt == 0) {
9c708c7f 30291 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30292 break;
30293 }
30294 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30295 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30296 } else {
30297 /* OPC_BGTZL */
b231c103 30298 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30299 }
30300 break;
30301 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30302 if (rt == 0) {
30303 /* OPC_BLEZ */
b231c103 30304 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30305 } else {
30306 check_insn(ctx, ISA_MIPS32R6);
30307 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30308 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30309 }
30310 break;
30311 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30312 if (rt == 0) {
30313 /* OPC_BGTZ */
b231c103 30314 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30315 } else {
30316 check_insn(ctx, ISA_MIPS32R6);
30317 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30318 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30319 }
30320 break;
30321 case OPC_BEQL:
30322 case OPC_BNEL:
d9224450 30323 check_insn(ctx, ISA_MIPS2);
fecd2646 30324 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30325 /* Fallthrough */
31837be3
YK
30326 case OPC_BEQ:
30327 case OPC_BNE:
b231c103 30328 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 30329 break;
d9224450
MR
30330 case OPC_LL: /* Load and stores */
30331 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
30332 if (ctx->insn_flags & INSN_R5900) {
30333 check_insn_opc_user_only(ctx, INSN_R5900);
30334 }
d9224450
MR
30335 /* Fallthrough */
30336 case OPC_LWL:
fecd2646
LA
30337 case OPC_LWR:
30338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 30339 /* Fallthrough */
c2e19f3c
AM
30340 case OPC_LB:
30341 case OPC_LH:
30342 case OPC_LW:
30343 case OPC_LWPC:
30344 case OPC_LBU:
30345 case OPC_LHU:
d75c135e 30346 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 30347 break;
fecd2646 30348 case OPC_SWL:
7a387fff 30349 case OPC_SWR:
fecd2646 30350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30351 /* fall through */
c2e19f3c
AM
30352 case OPC_SB:
30353 case OPC_SH:
fecd2646 30354 case OPC_SW:
5c13fdfd 30355 gen_st(ctx, op, rt, rs, imm);
7a387fff 30356 break;
d66c7132 30357 case OPC_SC:
d9224450 30358 check_insn(ctx, ISA_MIPS2);
4368b29a 30359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
55fc7a69
FN
30360 if (ctx->insn_flags & INSN_R5900) {
30361 check_insn_opc_user_only(ctx, INSN_R5900);
30362 }
33a07fa2
LA
30363 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30364 break;
7a387fff 30365 case OPC_CACHE:
bf7910c6 30366 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 30367 check_cp0_enabled(ctx);
d75c135e 30368 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
30369 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30370 gen_cache_operation(ctx, rt, rs, imm);
30371 }
ead9360e 30372 /* Treat as NOP. */
34ae7b51 30373 break;
7a387fff 30374 case OPC_PREF:
bf7910c6 30375 check_insn_opc_removed(ctx, ISA_MIPS32R6);
992e8176
FN
30376 if (ctx->insn_flags & INSN_R5900) {
30377 /* Treat as NOP. */
30378 } else {
30379 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30380 /* Treat as NOP. */
30381 }
6af0bf9c 30382 break;
4ad40f36 30383
923617a3 30384 /* Floating point (COP1). */
7a387fff
TS
30385 case OPC_LWC1:
30386 case OPC_LDC1:
30387 case OPC_SWC1:
30388 case OPC_SDC1:
5ab5c041 30389 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
30390 break;
30391
7a387fff 30392 case OPC_CP1:
5692c6e1
YK
30393 op1 = MASK_CP1(ctx->opcode);
30394
30395 switch (op1) {
30396 case OPC_MFHC1:
30397 case OPC_MTHC1:
5e755519 30398 check_cp1_enabled(ctx);
5692c6e1 30399 check_insn(ctx, ISA_MIPS32R2);
146dd620 30400 /* fall through */
5692c6e1
YK
30401 case OPC_MFC1:
30402 case OPC_CFC1:
30403 case OPC_MTC1:
30404 case OPC_CTC1:
30405 check_cp1_enabled(ctx);
30406 gen_cp1(ctx, op1, rt, rd);
30407 break;
d26bc211 30408#if defined(TARGET_MIPS64)
5692c6e1
YK
30409 case OPC_DMFC1:
30410 case OPC_DMTC1:
30411 check_cp1_enabled(ctx);
30412 check_insn(ctx, ISA_MIPS3);
d9224450 30413 check_mips_64(ctx);
5692c6e1
YK
30414 gen_cp1(ctx, op1, rt, rd);
30415 break;
e189e748 30416#endif
5692c6e1
YK
30417 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30418 check_cp1_enabled(ctx);
30419 if (ctx->insn_flags & ISA_MIPS32R6) {
30420 /* OPC_BC1EQZ */
31837be3 30421 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 30422 rt, imm << 2, 4);
5692c6e1
YK
30423 } else {
30424 /* OPC_BC1ANY2 */
b8aa4598 30425 check_cop1x(ctx);
d75c135e 30426 check_insn(ctx, ASE_MIPS3D);
d75c135e 30427 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 30428 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
30429 }
30430 break;
30431 case OPC_BC1NEZ:
30432 check_cp1_enabled(ctx);
30433 check_insn(ctx, ISA_MIPS32R6);
30434 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 30435 rt, imm << 2, 4);
5692c6e1
YK
30436 break;
30437 case OPC_BC1ANY4:
30438 check_cp1_enabled(ctx);
30439 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30440 check_cop1x(ctx);
30441 check_insn(ctx, ASE_MIPS3D);
30442 /* fall through */
30443 case OPC_BC1:
30444 check_cp1_enabled(ctx);
30445 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30446 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30447 (rt >> 2) & 0x7, imm << 2);
30448 break;
30449 case OPC_PS_FMT:
e29c9628 30450 check_ps(ctx);
b6f3b233 30451 /* fall through */
5692c6e1
YK
30452 case OPC_S_FMT:
30453 case OPC_D_FMT:
30454 check_cp1_enabled(ctx);
30455 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30456 (imm >> 8) & 0x7);
30457 break;
30458 case OPC_W_FMT:
30459 case OPC_L_FMT:
30460 {
30461 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30462 check_cp1_enabled(ctx);
30463 if (ctx->insn_flags & ISA_MIPS32R6) {
30464 switch (r6_op) {
30465 case R6_OPC_CMP_AF_S:
30466 case R6_OPC_CMP_UN_S:
30467 case R6_OPC_CMP_EQ_S:
30468 case R6_OPC_CMP_UEQ_S:
30469 case R6_OPC_CMP_LT_S:
30470 case R6_OPC_CMP_ULT_S:
30471 case R6_OPC_CMP_LE_S:
30472 case R6_OPC_CMP_ULE_S:
30473 case R6_OPC_CMP_SAF_S:
30474 case R6_OPC_CMP_SUN_S:
30475 case R6_OPC_CMP_SEQ_S:
30476 case R6_OPC_CMP_SEUQ_S:
30477 case R6_OPC_CMP_SLT_S:
30478 case R6_OPC_CMP_SULT_S:
30479 case R6_OPC_CMP_SLE_S:
30480 case R6_OPC_CMP_SULE_S:
30481 case R6_OPC_CMP_OR_S:
30482 case R6_OPC_CMP_UNE_S:
30483 case R6_OPC_CMP_NE_S:
30484 case R6_OPC_CMP_SOR_S:
30485 case R6_OPC_CMP_SUNE_S:
30486 case R6_OPC_CMP_SNE_S:
30487 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30488 break;
30489 case R6_OPC_CMP_AF_D:
30490 case R6_OPC_CMP_UN_D:
30491 case R6_OPC_CMP_EQ_D:
30492 case R6_OPC_CMP_UEQ_D:
30493 case R6_OPC_CMP_LT_D:
30494 case R6_OPC_CMP_ULT_D:
30495 case R6_OPC_CMP_LE_D:
30496 case R6_OPC_CMP_ULE_D:
30497 case R6_OPC_CMP_SAF_D:
30498 case R6_OPC_CMP_SUN_D:
30499 case R6_OPC_CMP_SEQ_D:
30500 case R6_OPC_CMP_SEUQ_D:
30501 case R6_OPC_CMP_SLT_D:
30502 case R6_OPC_CMP_SULT_D:
30503 case R6_OPC_CMP_SLE_D:
30504 case R6_OPC_CMP_SULE_D:
30505 case R6_OPC_CMP_OR_D:
30506 case R6_OPC_CMP_UNE_D:
30507 case R6_OPC_CMP_NE_D:
30508 case R6_OPC_CMP_SOR_D:
30509 case R6_OPC_CMP_SUNE_D:
30510 case R6_OPC_CMP_SNE_D:
30511 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30512 break;
30513 default:
d2bfa6e6
MR
30514 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30515 rt, rd, sa, (imm >> 8) & 0x7);
30516
5692c6e1 30517 break;
3f493883 30518 }
5692c6e1
YK
30519 } else {
30520 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30521 (imm >> 8) & 0x7);
36d23958 30522 }
5692c6e1
YK
30523 break;
30524 }
30525 case OPC_BZ_V:
30526 case OPC_BNZ_V:
30527 case OPC_BZ_B:
30528 case OPC_BZ_H:
30529 case OPC_BZ_W:
30530 case OPC_BZ_D:
30531 case OPC_BNZ_B:
30532 case OPC_BNZ_H:
30533 case OPC_BNZ_W:
30534 case OPC_BNZ_D:
30535 check_insn(ctx, ASE_MSA);
30536 gen_msa_branch(env, ctx, op1);
30537 break;
30538 default:
30539 MIPS_INVAL("cp1");
9c708c7f 30540 generate_exception_end(ctx, EXCP_RI);
5692c6e1 30541 break;
6ea83fed 30542 }
4ad40f36
FB
30543 break;
30544
31837be3
YK
30545 /* Compact branches [R6] and COP2 [non-R6] */
30546 case OPC_BC: /* OPC_LWC2 */
30547 case OPC_BALC: /* OPC_SWC2 */
30548 if (ctx->insn_flags & ISA_MIPS32R6) {
30549 /* OPC_BC, OPC_BALC */
30550 gen_compute_compact_branch(ctx, op, 0, 0,
30551 sextract32(ctx->opcode << 2, 0, 28));
30552 } else {
30553 /* OPC_LWC2, OPC_SWC2 */
30554 /* COP2: Not implemented. */
30555 generate_exception_err(ctx, EXCP_CpU, 2);
30556 }
30557 break;
30558 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30559 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30560 if (ctx->insn_flags & ISA_MIPS32R6) {
30561 if (rs != 0) {
30562 /* OPC_BEQZC, OPC_BNEZC */
30563 gen_compute_compact_branch(ctx, op, rs, 0,
30564 sextract32(ctx->opcode << 2, 0, 23));
30565 } else {
30566 /* OPC_JIC, OPC_JIALC */
30567 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30568 }
30569 } else {
30570 /* OPC_LWC2, OPC_SWC2 */
30571 /* COP2: Not implemented. */
30572 generate_exception_err(ctx, EXCP_CpU, 2);
30573 }
4ad40f36 30574 break;
bd277fa1 30575 case OPC_CP2:
d75c135e 30576 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
30577 /* Note that these instructions use different fields. */
30578 gen_loongson_multimedia(ctx, sa, rd, rt);
30579 break;
4ad40f36 30580
7a387fff 30581 case OPC_CP3:
fecd2646 30582 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 30583 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 30584 check_cp1_enabled(ctx);
36d23958
TS
30585 op1 = MASK_CP3(ctx->opcode);
30586 switch (op1) {
d9224450
MR
30587 case OPC_LUXC1:
30588 case OPC_SUXC1:
30589 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30590 /* Fallthrough */
5a5012ec
TS
30591 case OPC_LWXC1:
30592 case OPC_LDXC1:
5a5012ec
TS
30593 case OPC_SWXC1:
30594 case OPC_SDXC1:
d9224450 30595 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 30596 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 30597 break;
e0c84da7 30598 case OPC_PREFX:
d9224450 30599 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 30600 /* Treat as NOP. */
e0c84da7 30601 break;
5a5012ec 30602 case OPC_ALNV_PS:
d9224450
MR
30603 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30604 /* Fallthrough */
5a5012ec
TS
30605 case OPC_MADD_S:
30606 case OPC_MADD_D:
30607 case OPC_MADD_PS:
30608 case OPC_MSUB_S:
30609 case OPC_MSUB_D:
30610 case OPC_MSUB_PS:
30611 case OPC_NMADD_S:
30612 case OPC_NMADD_D:
30613 case OPC_NMADD_PS:
30614 case OPC_NMSUB_S:
30615 case OPC_NMSUB_D:
30616 case OPC_NMSUB_PS:
d9224450 30617 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
30618 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30619 break;
36d23958 30620 default:
923617a3 30621 MIPS_INVAL("cp3");
9c708c7f 30622 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
30623 break;
30624 }
30625 } else {
e397ee33 30626 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 30627 }
4ad40f36
FB
30628 break;
30629
d26bc211 30630#if defined(TARGET_MIPS64)
7a387fff 30631 /* MIPS64 opcodes */
96631327 30632 case OPC_LLD:
55fc7a69
FN
30633 if (ctx->insn_flags & INSN_R5900) {
30634 check_insn_opc_user_only(ctx, INSN_R5900);
30635 }
96631327 30636 /* fall through */
c2e19f3c
AM
30637 case OPC_LDL:
30638 case OPC_LDR:
fecd2646 30639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30640 /* fall through */
fecd2646 30641 case OPC_LWU:
7a387fff 30642 case OPC_LD:
d75c135e 30643 check_insn(ctx, ISA_MIPS3);
5c13fdfd 30644 check_mips_64(ctx);
d75c135e 30645 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 30646 break;
c2e19f3c
AM
30647 case OPC_SDL:
30648 case OPC_SDR:
fecd2646 30649 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 30650 /* fall through */
7a387fff 30651 case OPC_SD:
d75c135e 30652 check_insn(ctx, ISA_MIPS3);
e189e748 30653 check_mips_64(ctx);
5c13fdfd 30654 gen_st(ctx, op, rt, rs, imm);
7a387fff 30655 break;
d66c7132 30656 case OPC_SCD:
bf7910c6 30657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 30658 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
30659 if (ctx->insn_flags & INSN_R5900) {
30660 check_insn_opc_user_only(ctx, INSN_R5900);
30661 }
d66c7132 30662 check_mips_64(ctx);
33a07fa2 30663 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 30664 break;
31837be3
YK
30665 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30666 if (ctx->insn_flags & ISA_MIPS32R6) {
30667 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30668 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30669 } else {
30670 /* OPC_DADDI */
30671 check_insn(ctx, ISA_MIPS3);
30672 check_mips_64(ctx);
30673 gen_arith_imm(ctx, op, rt, rs, imm);
30674 }
30675 break;
324d9e32 30676 case OPC_DADDIU:
d75c135e 30677 check_insn(ctx, ISA_MIPS3);
e189e748 30678 check_mips_64(ctx);
d75c135e 30679 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 30680 break;
31837be3
YK
30681#else
30682 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30683 if (ctx->insn_flags & ISA_MIPS32R6) {
30684 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30685 } else {
30686 MIPS_INVAL("major opcode");
9c708c7f 30687 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30688 }
30689 break;
6af0bf9c 30690#endif
d4ea6acd
LA
30691 case OPC_DAUI: /* OPC_JALX */
30692 if (ctx->insn_flags & ISA_MIPS32R6) {
30693#if defined(TARGET_MIPS64)
30694 /* OPC_DAUI */
30695 check_mips_64(ctx);
db77d852
LA
30696 if (rs == 0) {
30697 generate_exception(ctx, EXCP_RI);
30698 } else if (rt != 0) {
d4ea6acd
LA
30699 TCGv t0 = tcg_temp_new();
30700 gen_load_gpr(t0, rs);
30701 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30702 tcg_temp_free(t0);
30703 }
d4ea6acd 30704#else
9c708c7f 30705 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
30706 MIPS_INVAL("major opcode");
30707#endif
30708 } else {
30709 /* OPC_JALX */
30710 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30711 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30712 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 30713 }
364d4831 30714 break;
4c789546 30715 case OPC_MSA: /* OPC_MDMX */
f08099ad 30716 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 30717#if defined(TARGET_MIPS64)
874b2879 30718 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
37b9aae2 30719#endif
f08099ad
FN
30720 } else {
30721 /* MDMX: Not implemented. */
30722 gen_msa(env, ctx);
30723 }
d4ea6acd
LA
30724 break;
30725 case OPC_PCREL:
30726 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 30727 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 30728 break;
6af0bf9c 30729 default: /* Invalid */
923617a3 30730 MIPS_INVAL("major opcode");
9c708c7f 30731 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30732 break;
30733 }
6af0bf9c
FB
30734}
30735
18f440ed 30736static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 30737{
18f440ed 30738 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 30739 CPUMIPSState *env = cs->env_ptr;
12be9258 30740
18f440ed 30741 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
30742 ctx->saved_pc = -1;
30743 ctx->insn_flags = env->insn_flags;
30744 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 30745 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
30746 ctx->CP0_Config3 = env->CP0_Config3;
30747 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
30748 ctx->btarget = 0;
30749 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30750 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30751 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30752 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30753 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30754 ctx->PAMask = env->PAMask;
30755 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30756 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30757 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30758 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30759 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 30760 /* Restore delay slot state from the tb context. */
12be9258
EC
30761 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30762 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30763 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 30764 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
30765 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30766 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30767 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30768 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 30769 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
12be9258 30770 restore_cpu_state(env, ctx);
932e71cd 30771#ifdef CONFIG_USER_ONLY
12be9258 30772 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 30773#else
12be9258 30774 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 30775#endif
12be9258
EC
30776 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30777 MO_UNALN : MO_ALIGN;
190ce7fb 30778
18f440ed
EC
30779 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30780 ctx->hflags);
30781}
12be9258 30782
18f440ed
EC
30783static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30784{
30785}
b933066a 30786
18f440ed
EC
30787static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30788{
30789 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30790
18f440ed
EC
30791 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30792 ctx->btarget);
30793}
31837be3 30794
18f440ed
EC
30795static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30796 const CPUBreakpoint *bp)
30797{
30798 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30799
18f440ed
EC
30800 save_cpu_state(ctx, 1);
30801 ctx->base.is_jmp = DISAS_NORETURN;
30802 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
30803 /*
30804 * The address covered by the breakpoint must be included in
30805 * [tb->pc, tb->pc + tb->size) in order to for it to be
30806 * properly cleared -- thus we increment the PC here so that
30807 * the logic setting tb->size below does the right thing.
30808 */
18f440ed
EC
30809 ctx->base.pc_next += 4;
30810 return true;
30811}
4ad40f36 30812
18f440ed
EC
30813static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30814{
30815 CPUMIPSState *env = cs->env_ptr;
30816 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30817 int insn_bytes;
30818 int is_slot;
4ad40f36 30819
18f440ed 30820 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
30821 if (ctx->insn_flags & ISA_NANOMIPS32) {
30822 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30823 insn_bytes = decode_nanomips_opc(env, ctx);
30824 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
30825 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30826 insn_bytes = 4;
30827 decode_opc(env, ctx);
30828 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30829 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30830 insn_bytes = decode_micromips_opc(env, ctx);
30831 } else if (ctx->insn_flags & ASE_MIPS16) {
30832 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30833 insn_bytes = decode_mips16_opc(env, ctx);
30834 } else {
30835 generate_exception_end(ctx, EXCP_RI);
30836 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30837 return;
30838 }
faf7aaa9 30839
18f440ed
EC
30840 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30841 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30842 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
30843 /*
30844 * Force to generate branch as there is neither delay nor
30845 * forbidden slot.
30846 */
18f440ed
EC
30847 is_slot = 1;
30848 }
30849 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30850 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
30851 /*
30852 * Force to generate branch as microMIPS R6 doesn't restrict
30853 * branches in the forbidden slot.
30854 */
18f440ed 30855 is_slot = 1;
eeb3bba8 30856 }
18f440ed
EC
30857 }
30858 if (is_slot) {
30859 gen_branch(ctx, insn_bytes);
30860 }
30861 ctx->base.pc_next += insn_bytes;
1b530a6d 30862
18f440ed
EC
30863 if (ctx->base.is_jmp != DISAS_NEXT) {
30864 return;
6af0bf9c 30865 }
7480515f
AM
30866 /*
30867 * Execute a branch and its delay slot as a single instruction.
30868 * This is what GDB expects and is consistent with what the
30869 * hardware does (e.g. if a delay slot instruction faults, the
30870 * reported PC is the PC of the branch).
30871 */
18f440ed
EC
30872 if (ctx->base.singlestep_enabled &&
30873 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30874 ctx->base.is_jmp = DISAS_TOO_MANY;
30875 }
30876 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30877 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 30878 }
18f440ed
EC
30879}
30880
30881static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30882{
30883 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30884
12be9258
EC
30885 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30886 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 30887 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 30888 } else {
12be9258 30889 switch (ctx->base.is_jmp) {
b28425ba 30890 case DISAS_STOP:
12be9258 30891 gen_save_pc(ctx->base.pc_next);
cd314a7d 30892 tcg_gen_lookup_and_goto_ptr();
df1561e2 30893 break;
b28425ba 30894 case DISAS_NEXT:
18f440ed 30895 case DISAS_TOO_MANY:
12be9258
EC
30896 save_cpu_state(ctx, 0);
30897 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 30898 break;
b28425ba 30899 case DISAS_EXIT:
07ea28b4 30900 tcg_gen_exit_tb(NULL, 0);
16c00cb2 30901 break;
b28425ba 30902 case DISAS_NORETURN:
5a5012ec 30903 break;
18f440ed
EC
30904 default:
30905 g_assert_not_reached();
6958549d 30906 }
6af0bf9c 30907 }
18f440ed
EC
30908}
30909
30910static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30911{
30912 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30913 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30914}
30915
30916static const TranslatorOps mips_tr_ops = {
30917 .init_disas_context = mips_tr_init_disas_context,
30918 .tb_start = mips_tr_tb_start,
30919 .insn_start = mips_tr_insn_start,
30920 .breakpoint_check = mips_tr_breakpoint_check,
30921 .translate_insn = mips_tr_translate_insn,
30922 .tb_stop = mips_tr_tb_stop,
30923 .disas_log = mips_tr_disas_log,
30924};
30925
8b86d6d2 30926void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
30927{
30928 DisasContext ctx;
30929
8b86d6d2 30930 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
30931}
30932
71375b59 30933static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
30934{
30935 int i;
5e755519 30936 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 30937
2a5612e6
SW
30938#define printfpr(fp) \
30939 do { \
30940 if (is_fpu64) \
90c84c56
MA
30941 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30942 " fd:%13g fs:%13g psu: %13g\n", \
30943 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30944 (double)(fp)->fd, \
30945 (double)(fp)->fs[FP_ENDIAN_IDX], \
30946 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
30947 else { \
30948 fpr_t tmp; \
30949 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30950 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
30951 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30952 " fd:%13g fs:%13g psu:%13g\n", \
30953 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30954 (double)tmp.fd, \
30955 (double)tmp.fs[FP_ENDIAN_IDX], \
30956 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 30957 } \
71375b59 30958 } while (0)
6ea83fed 30959
5a5012ec 30960
90c84c56
MA
30961 qemu_fprintf(f,
30962 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30963 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30964 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 30965 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 30966 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 30967 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
30968 }
30969
30970#undef printfpr
30971}
30972
90c84c56 30973void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 30974{
878096ee
AF
30975 MIPSCPU *cpu = MIPS_CPU(cs);
30976 CPUMIPSState *env = &cpu->env;
6af0bf9c 30977 int i;
3b46e624 30978
90c84c56
MA
30979 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30980 " LO=0x" TARGET_FMT_lx " ds %04x "
30981 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30982 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30983 env->hflags, env->btarget, env->bcond);
6af0bf9c 30984 for (i = 0; i < 32; i++) {
1f8929d2 30985 if ((i & 3) == 0) {
90c84c56 30986 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 30987 }
90c84c56
MA
30988 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30989 regnames[i], env->active_tc.gpr[i]);
1f8929d2 30990 if ((i & 3) == 3) {
90c84c56 30991 qemu_fprintf(f, "\n");
1f8929d2 30992 }
90c84c56
MA
30993 }
30994
71375b59
AM
30995 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30996 TARGET_FMT_lx "\n",
90c84c56
MA
30997 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30998 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30999 PRIx64 "\n",
31000 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31001 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31002 env->CP0_Config2, env->CP0_Config3);
31003 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31004 env->CP0_Config4, env->CP0_Config5);
1cc5af69 31005 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 31006 fpu_dump_state(env, f, flags);
1cc5af69 31007 }
6af0bf9c
FB
31008}
31009
78ce64f4 31010void mips_tcg_init(void)
39454628 31011{
f01be154 31012 int i;
39454628 31013
f764718d 31014 cpu_gpr[0] = NULL;
bb928dbe 31015 for (i = 1; i < 32; i++)
e1ccc054 31016 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
71375b59
AM
31017 offsetof(CPUMIPSState,
31018 active_tc.gpr[i]),
4b2eb8d2 31019 regnames[i]);
d73ee8a2 31020
863f264d
YK
31021 for (i = 0; i < 32; i++) {
31022 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31023 msa_wr_d[i * 2] =
e1ccc054 31024 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
7480515f
AM
31025 /*
31026 * The scalar floating-point unit (FPU) registers are mapped on
31027 * the MSA vector registers.
31028 */
cb269f27 31029 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
31030 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31031 msa_wr_d[i * 2 + 1] =
e1ccc054 31032 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
31033 }
31034
e1ccc054 31035 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 31036 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 31037 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 31038 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 31039 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 31040 regnames_HI[i]);
e1ccc054 31041 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 31042 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 31043 regnames_LO[i]);
4b2eb8d2 31044 }
e1ccc054 31045 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
31046 offsetof(CPUMIPSState,
31047 active_tc.DSPControl),
4b2eb8d2 31048 "DSPControl");
e1ccc054 31049 bcond = tcg_global_mem_new(cpu_env,
7db13fae 31050 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 31051 btarget = tcg_global_mem_new(cpu_env,
7db13fae 31052 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 31053 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 31054 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 31055
e1ccc054 31056 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31057 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 31058 "fcr0");
e1ccc054 31059 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31060 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 31061 "fcr31");
33a07fa2
LA
31062 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31063 "lladdr");
31064 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31065 "llval");
a168a796
FN
31066
31067#if defined(TARGET_MIPS64)
31068 cpu_mmr[0] = NULL;
31069 for (i = 1; i < 32; i++) {
31070 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31071 offsetof(CPUMIPSState,
31072 active_tc.mmr[i]),
31073 regnames[i]);
31074 }
31075#endif
31076
b621f018 31077#if !defined(TARGET_MIPS64)
eb5559f6
CJ
31078 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31079 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31080 offsetof(CPUMIPSState,
31081 active_tc.mxu_gpr[i]),
31082 mxuregnames[i]);
31083 }
31084
31085 mxu_CR = tcg_global_mem_new(cpu_env,
31086 offsetof(CPUMIPSState, active_tc.mxu_cr),
31087 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 31088#endif
39454628
TS
31089}
31090
5b27a92d 31091#include "translate_init.inc.c"
aaed909a 31092
27e38392
PMD
31093void cpu_mips_realize_env(CPUMIPSState *env)
31094{
31095 env->exception_base = (int32_t)0xBFC00000;
31096
31097#ifndef CONFIG_USER_ONLY
31098 mmu_init(env, env->cpu_model);
31099#endif
31100 fpu_init(env, env->cpu_model);
31101 mvp_init(env, env->cpu_model);
31102}
31103
a7519f2b 31104bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 31105{
a7519f2b
IM
31106 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31107 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
31108}
31109
5b1e0981 31110bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
bed9e5ce 31111{
a7519f2b
IM
31112 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31113 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
31114}
31115
89777fd1
LA
31116void cpu_set_exception_base(int vp_index, target_ulong address)
31117{
31118 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31119 vp->env.exception_base = address;
31120}
31121
1bba0dc9 31122void cpu_state_reset(CPUMIPSState *env)
6ae81775 31123{
5a7330b3 31124 CPUState *cs = env_cpu(env);
6ae81775 31125
51cc2e78
BS
31126 /* Reset registers to their default values */
31127 env->CP0_PRid = env->cpu_model->CP0_PRid;
31128 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31129#ifdef TARGET_WORDS_BIGENDIAN
31130 env->CP0_Config0 |= (1 << CP0C0_BE);
31131#endif
31132 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31133 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31134 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
31135 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31136 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
31137 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31138 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
31139 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31140 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
31141 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31142 << env->cpu_model->CP0_LLAddr_shift;
31143 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
31144 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31145 env->CCRes = env->cpu_model->CCRes;
31146 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31147 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31148 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31149 env->current_tc = 0;
31150 env->SEGBITS = env->cpu_model->SEGBITS;
31151 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31152#if defined(TARGET_MIPS64)
31153 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31154 env->SEGMask |= 3ULL << 62;
31155 }
31156#endif
31157 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
31158 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31159 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31160 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31161 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31162 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31163 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31164 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31165 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31166 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31167 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
31168 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31169 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 31170 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 31171 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 31172 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 31173 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 31174 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
31175 env->insn_flags = env->cpu_model->insn_flags;
31176
0eaef5aa 31177#if defined(CONFIG_USER_ONLY)
03e6e501 31178 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
31179# ifdef TARGET_MIPS64
31180 /* Enable 64-bit register mode. */
31181 env->CP0_Status |= (1 << CP0St_PX);
31182# endif
31183# ifdef TARGET_ABI_MIPSN64
31184 /* Enable 64-bit address mode. */
31185 env->CP0_Status |= (1 << CP0St_UX);
31186# endif
7480515f
AM
31187 /*
31188 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31189 * hardware registers.
31190 */
94159135 31191 env->CP0_HWREna |= 0x0000000F;
91a75935 31192 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 31193 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 31194 }
6f0af304
PJ
31195 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31196 env->CP0_Status |= (1 << CP0St_MX);
853c3240 31197 }
4d66261f
PJ
31198# if defined(TARGET_MIPS64)
31199 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31200 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31201 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
31202 env->CP0_Status |= (1 << CP0St_FR);
31203 }
4d66261f 31204# endif
932e71cd
AJ
31205#else
31206 if (env->hflags & MIPS_HFLAG_BMASK) {
7480515f
AM
31207 /*
31208 * If the exception was raised from a delay slot,
31209 * come back to the jump.
31210 */
c3577479
MR
31211 env->CP0_ErrorEPC = (env->active_tc.PC
31212 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 31213 } else {
932e71cd
AJ
31214 env->CP0_ErrorEPC = env->active_tc.PC;
31215 }
89777fd1 31216 env->active_tc.PC = env->exception_base;
51cc2e78
BS
31217 env->CP0_Random = env->tlb->nb_tlb - 1;
31218 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 31219 env->CP0_Wired = 0;
01bc435b 31220 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 31221 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 31222 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
31223 env->CP0_EBase |= 0x40000000;
31224 } else {
74dbf824 31225 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 31226 }
c870e3f5
YK
31227 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31228 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31229 }
a0c80608
PB
31230 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
31231 0x3ff : 0xff;
932e71cd 31232 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
7480515f
AM
31233 /*
31234 * Vectored interrupts not implemented, timer on int 7,
31235 * no performance counters.
31236 */
932e71cd
AJ
31237 env->CP0_IntCtl = 0xe0000000;
31238 {
31239 int i;
31240
31241 for (i = 0; i < 7; i++) {
31242 env->CP0_WatchLo[i] = 0;
31243 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 31244 }
932e71cd
AJ
31245 env->CP0_WatchLo[7] = 0;
31246 env->CP0_WatchHi[7] = 0;
fd88b6ab 31247 }
932e71cd
AJ
31248 /* Count register increments in debug mode, EJTAG version 1 */
31249 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 31250
4b69c7e2
JH
31251 cpu_mips_store_count(env, 1);
31252
9e56e756
EI
31253 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31254 int i;
31255
31256 /* Only TC0 on VPE 0 starts as active. */
31257 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 31258 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
31259 env->tcs[i].CP0_TCHalt = 1;
31260 }
31261 env->active_tc.CP0_TCHalt = 1;
259186a7 31262 cs->halted = 1;
9e56e756 31263
55e5c285 31264 if (cs->cpu_index == 0) {
9e56e756
EI
31265 /* VPE0 starts up enabled. */
31266 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31267 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31268
31269 /* TC0 starts up unhalted. */
259186a7 31270 cs->halted = 0;
9e56e756
EI
31271 env->active_tc.CP0_TCHalt = 0;
31272 env->tcs[0].CP0_TCHalt = 0;
31273 /* With thread 0 active. */
31274 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31275 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31276 }
31277 }
cec56a73
JH
31278
31279 /*
31280 * Configure default legacy segmentation control. We use this regardless of
31281 * whether segmentation control is presented to the guest.
31282 */
31283 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31284 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31285 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31286 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31287 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31288 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31289 (2 << CP0SC_C);
31290 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31291 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31292 (3 << CP0SC_C)) << 16;
31293 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31294 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31295 (1 << CP0SC_EU) | (2 << CP0SC_C);
31296 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31297 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31298 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31299 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31300 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 31301#endif
ddc584bd
LA
31302 if ((env->insn_flags & ISA_MIPS32R6) &&
31303 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31304 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31305 env->CP0_Status |= (1 << CP0St_FR);
31306 }
31307
63010795
YK
31308 if (env->insn_flags & ISA_MIPS32R6) {
31309 /* PTW = 1 */
31310 env->CP0_PWSize = 0x40;
31311 /* GDI = 12 */
31312 /* UDI = 12 */
31313 /* MDI = 12 */
31314 /* PRI = 12 */
31315 /* PTEI = 2 */
31316 env->CP0_PWField = 0x0C30C302;
31317 } else {
31318 /* GDI = 0 */
31319 /* UDI = 0 */
31320 /* MDI = 0 */
31321 /* PRI = 0 */
31322 /* PTEI = 2 */
31323 env->CP0_PWField = 0x02;
31324 }
31325
0bbc0396
SM
31326 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31327 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
31328 env->hflags |= MIPS_HFLAG_M16;
31329 }
31330
863f264d
YK
31331 /* MSA */
31332 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31333 msa_reset(env);
31334 }
31335
03e6e501 31336 compute_hflags(env);
599bc5e8 31337 restore_fp_status(env);
e117f526 31338 restore_pamask(env);
27103424 31339 cs->exception_index = EXCP_NONE;
3b3c1694
LA
31340
31341 if (semihosting_get_argc()) {
31342 /* UHI interface can be used to obtain argc and argv */
31343 env->active_tc.gpr[4] = -1;
31344 }
6af0bf9c 31345}
d2856f1a 31346
bad729e2
RH
31347void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31348 target_ulong *data)
d2856f1a 31349{
bad729e2 31350 env->active_tc.PC = data[0];
d2856f1a 31351 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 31352 env->hflags |= data[1];
4636401d
AJ
31353 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31354 case MIPS_HFLAG_BR:
31355 break;
31356 case MIPS_HFLAG_BC:
31357 case MIPS_HFLAG_BL:
31358 case MIPS_HFLAG_B:
bad729e2 31359 env->btarget = data[2];
4636401d
AJ
31360 break;
31361 }
d2856f1a 31362}