]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
target/mips: msa: Unroll loops and demacro <BMNZ|BMZ|BSEL>.V
[mirror_qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c 1/*
ab99e0e4 2 * MIPS emulation for QEMU - main translation routines
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
6af0bf9c
FB
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
8167ee88 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
22 */
23
c684822a 24#include "qemu/osdep.h"
6af0bf9c 25#include "cpu.h"
26aa3d9a 26#include "internal.h"
76cad711 27#include "disas/disas.h"
63c91552 28#include "exec/exec-all.h"
57fec1fe 29#include "tcg-op.h"
f08b6170 30#include "exec/cpu_ldst.h"
d3d93c6c 31#include "hw/mips/cpudevs.h"
6af0bf9c 32
2ef6175a
RH
33#include "exec/helper-proto.h"
34#include "exec/helper-gen.h"
f1672e6f 35#include "hw/semihosting/semihost.h"
a7812ae4 36
b44a7fb1 37#include "target/mips/trace.h"
a7e30d84 38#include "trace-tcg.h"
b28425ba 39#include "exec/translator.h"
508127e2 40#include "exec/log.h"
0442428a 41#include "qemu/qemu-print.h"
a7e30d84 42
fb7729e2 43#define MIPS_DEBUG_DISAS 0
6af0bf9c 44
7a387fff 45/* MIPS major opcodes */
71375b59 46#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
47
48enum {
49 /* indirect opcode tables */
7a387fff
TS
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 58 /* arithmetic with immediate */
7a387fff
TS
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
324d9e32 63 /* logic with immediate */
7a387fff
TS
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
324d9e32 68 /* arithmetic with immediate */
7a387fff
TS
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
e37e863f 71 /* Jump and branches */
7a387fff
TS
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
b231c103 82 OPC_JALX = (0x1D << 26),
d4ea6acd 83 OPC_DAUI = (0x1D << 26),
e37e863f 84 /* Load and stores */
7a387fff
TS
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
364d4831 91 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
364d4831 106 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
e37e863f 110 /* Floating point load/store */
7a387fff
TS
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
31837be3
YK
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
7a387fff
TS
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
239dfebe
YK
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
e37e863f 148 /* Cache and prefetch */
7a387fff
TS
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
153};
154
155/* PC-relative address computation / loads */
71375b59
AM
156#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
158enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
163
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
170};
171
172/* MIPS special opcodes */
71375b59 173#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 174
e37e863f
FB
175enum {
176 /* Shifts */
7a387fff 177 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 182 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 186 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 194 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 200 /* Multiplication / division */
7a387fff
TS
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 209
e37e863f 210 /* 2 registers arithmetic / logic */
7a387fff
TS
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 225 /* Jumps */
7a387fff
TS
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 228 /* Traps */
7a387fff
TS
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 235 /* HI / LO registers load & stores */
7a387fff
TS
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 240 /* Conditional moves */
7a387fff
TS
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 243
b691d9d2
LA
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246
7a387fff 247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
248
249 /* Special */
a0d700e4 250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
255
7a387fff
TS
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
260};
261
7480515f
AM
262/*
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
265 */
71375b59 266#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
267
268enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
277
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
286
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
292
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
295};
296
e9c71dd1 297/* Multiplication variants of the vr54xx. */
71375b59 298#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
299
300enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
315};
316
7a387fff 317/* REGIMM (rt field) opcodes */
71375b59 318#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
319
320enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
337
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
340};
341
7a387fff 342/* Special2 opcodes */
71375b59 343#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 344
e37e863f 345enum {
7a387fff
TS
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 365 /* Misc */
7a387fff
TS
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 370 /* Special */
7a387fff
TS
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
372};
373
374/* Special3 opcodes */
71375b59 375#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
376
377enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
391
392 /* Loongson 2E */
393 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
394 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
395 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
396 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
397 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
398 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
399 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
400 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
401 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
402 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
403 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
404 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
405
406 /* MIPS DSP Load */
407 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
408 /* MIPS DSP Arithmetic */
409 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 410 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 411 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 412 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
413 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
414 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 416 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
417 /* MIPS DSP GPR-Based Shift Sub-class */
418 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 419 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
420 /* MIPS DSP Multiply Sub-class insns */
421 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
422 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
423 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 424 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
425 /* DSP Bit/Manipulation Sub-class */
426 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 427 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 428 /* MIPS DSP Append Sub-class */
26690560 429 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 430 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
431 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
432 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 433 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 434
76964147
JH
435 /* EVA */
436 OPC_LWLE = 0x19 | OPC_SPECIAL3,
437 OPC_LWRE = 0x1A | OPC_SPECIAL3,
438 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
439 OPC_SBE = 0x1C | OPC_SPECIAL3,
440 OPC_SHE = 0x1D | OPC_SPECIAL3,
441 OPC_SCE = 0x1E | OPC_SPECIAL3,
442 OPC_SWE = 0x1F | OPC_SPECIAL3,
443 OPC_SWLE = 0x21 | OPC_SPECIAL3,
444 OPC_SWRE = 0x22 | OPC_SPECIAL3,
445 OPC_PREFE = 0x23 | OPC_SPECIAL3,
446 OPC_LBUE = 0x28 | OPC_SPECIAL3,
447 OPC_LHUE = 0x29 | OPC_SPECIAL3,
448 OPC_LBE = 0x2C | OPC_SPECIAL3,
449 OPC_LHE = 0x2D | OPC_SPECIAL3,
450 OPC_LLE = 0x2E | OPC_SPECIAL3,
451 OPC_LWE = 0x2F | OPC_SPECIAL3,
452
4368b29a 453 /* R6 */
bf7910c6
LA
454 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
455 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
456 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
457 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
458 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
459 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
460};
461
7a387fff 462/* BSHFL opcodes */
71375b59 463#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 464
e37e863f 465enum {
15eacb9b
YK
466 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
467 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
468 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
469 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
470 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
471 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
472 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 473 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
474};
475
7a387fff 476/* DBSHFL opcodes */
71375b59 477#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 478
e37e863f 479enum {
15eacb9b
YK
480 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
481 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
482 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
483 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
484 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
485 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
486 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
487 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
488 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
489 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 490 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
491};
492
e45a93e2
JL
493/* MIPS DSP REGIMM opcodes */
494enum {
495 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 496 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
497};
498
71375b59 499#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
500/* MIPS DSP Load */
501enum {
502 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
503 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
504 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 505 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
506};
507
71375b59 508#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
509enum {
510 /* MIPS DSP Arithmetic Sub-class */
511 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
525 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
527 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
528 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
529 /* MIPS DSP Multiply Sub-class insns */
530 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
536};
537
538#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 539#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
540enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
554 /* MIPS DSP Multiply Sub-class insns */
555 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
559};
560
71375b59 561#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
562enum {
563 /* MIPS DSP Arithmetic Sub-class */
564 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
577 /* DSP Bit/Manipulation Sub-class */
578 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
583};
584
71375b59 585#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
586enum {
587 /* MIPS DSP Arithmetic Sub-class */
588 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
595 /* DSP Compare-Pick Sub-class */
596 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 611};
a22260ae 612
71375b59 613#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
614enum {
615 /* MIPS DSP GPR-Based Shift Sub-class */
616 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
638};
461c08df 639
71375b59 640#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
641enum {
642 /* MIPS DSP Multiply Sub-class insns */
643 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
665};
666
71375b59 667#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
668enum {
669 /* DSP Bit/Manipulation Sub-class */
670 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
671};
672
71375b59 673#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 674enum {
df6126a7 675 /* MIPS DSP Append Sub-class */
26690560
JL
676 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
677 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
678 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
679};
680
71375b59 681#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
682enum {
683 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
684 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
696 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
698 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
699 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
700 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
701};
702
71375b59 703#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
704enum {
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
723 /* DSP Bit/Manipulation Sub-class */
724 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 730};
461c08df 731
71375b59 732#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 733enum {
a22260ae
JL
734 /* MIPS DSP Multiply Sub-class insns */
735 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
762};
461c08df 763
71375b59 764#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 765enum {
26690560
JL
766 /* DSP Compare-Pick Sub-class */
767 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
786 /* MIPS DSP Arithmetic Sub-class */
787 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
795};
461c08df 796
71375b59 797#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 798enum {
df6126a7 799 /* DSP Append Sub-class */
26690560
JL
800 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
801 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
803 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
804};
26690560 805
71375b59 806#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
807enum {
808 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
809 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
810 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
830};
831
71375b59 832#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
833enum {
834 /* DSP Bit/Manipulation Sub-class */
835 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
836};
1cb6686c 837
71375b59 838#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
839enum {
840 /* MIPS DSP Multiply Sub-class insns */
841 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
867};
a22260ae 868
71375b59 869#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
870enum {
871 /* MIPS DSP GPR-Based Shift Sub-class */
872 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
898};
77c5fa8b 899
7a387fff 900/* Coprocessor 0 (rs field) */
71375b59 901#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 902
6ea83fed 903enum {
7a387fff
TS
904 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
905 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 906 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
907 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
908 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 909 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 910 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
911 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
912 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 913 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
914 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
915 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
916 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
917 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
918 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
919 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
920 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
921 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
922 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
923 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
924 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
925 OPC_C0_A = (0x1A << 21) | OPC_CP0,
926 OPC_C0_B = (0x1B << 21) | OPC_CP0,
927 OPC_C0_C = (0x1C << 21) | OPC_CP0,
928 OPC_C0_D = (0x1D << 21) | OPC_CP0,
929 OPC_C0_E = (0x1E << 21) | OPC_CP0,
930 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 931};
7a387fff
TS
932
933/* MFMC0 opcodes */
71375b59 934#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
935
936enum {
ead9360e
TS
937 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
938 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
940 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
941 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
942 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
943 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
944 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
945};
946
947/* Coprocessor 0 (with rs == C0) */
71375b59 948#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
949
950enum {
951 OPC_TLBR = 0x01 | OPC_C0,
952 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
953 OPC_TLBINV = 0x03 | OPC_C0,
954 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
955 OPC_TLBWR = 0x06 | OPC_C0,
956 OPC_TLBP = 0x08 | OPC_C0,
957 OPC_RFE = 0x10 | OPC_C0,
958 OPC_ERET = 0x18 | OPC_C0,
959 OPC_DERET = 0x1F | OPC_C0,
960 OPC_WAIT = 0x20 | OPC_C0,
961};
962
963/* Coprocessor 1 (rs field) */
71375b59 964#define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 965
bf4120ad
NF
966/* Values for the fmt field in FP instructions */
967enum {
968 /* 0 - 15 are reserved */
e459440a
AJ
969 FMT_S = 16, /* single fp */
970 FMT_D = 17, /* double fp */
971 FMT_E = 18, /* extended fp */
972 FMT_Q = 19, /* quad fp */
973 FMT_W = 20, /* 32-bit fixed */
974 FMT_L = 21, /* 64-bit fixed */
975 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
976 /* 23 - 31 are reserved */
977};
978
7a387fff
TS
979enum {
980 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
981 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
982 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 983 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
984 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
985 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
986 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 987 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 988 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
989 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
990 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
991 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
992 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
993 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
994 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
995 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
996 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
997 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
998 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
999 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
1000 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1001 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
1002 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1003 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1004 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1005 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1006 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1007 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1008 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1009 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
1010};
1011
71375b59
AM
1012#define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1013#define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
5a5012ec 1014
7a387fff
TS
1015enum {
1016 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1017 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1018 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1019 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1020};
1021
5a5012ec
TS
1022enum {
1023 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1024 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1025};
1026
1027enum {
1028 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1029 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1030};
7a387fff 1031
71375b59 1032#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
1033
1034enum {
1035 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1036 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1037 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1038 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1039 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1040 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1041 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1042 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1043 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1044 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1045 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1046};
1047
71375b59 1048#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1049
1050enum {
71375b59
AM
1051 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1059
1060 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1068
1069 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1073 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1074 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1075 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1076 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1077
1078 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1086
1087 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1088 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1093
1094 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1100
1101 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1107
1108 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1114
1115 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1116 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1117 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1118 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1121
1122 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1123 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1125 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1128
1129 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1130 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1131 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1135
1136 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1138 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1139 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1140 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1141 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1142};
1143
1144
71375b59 1145#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1146
1147enum {
71375b59
AM
1148 OPC_LWXC1 = 0x00 | OPC_CP3,
1149 OPC_LDXC1 = 0x01 | OPC_CP3,
1150 OPC_LUXC1 = 0x05 | OPC_CP3,
1151 OPC_SWXC1 = 0x08 | OPC_CP3,
1152 OPC_SDXC1 = 0x09 | OPC_CP3,
1153 OPC_SUXC1 = 0x0D | OPC_CP3,
1154 OPC_PREFX = 0x0F | OPC_CP3,
1155 OPC_ALNV_PS = 0x1E | OPC_CP3,
1156 OPC_MADD_S = 0x20 | OPC_CP3,
1157 OPC_MADD_D = 0x21 | OPC_CP3,
1158 OPC_MADD_PS = 0x26 | OPC_CP3,
1159 OPC_MSUB_S = 0x28 | OPC_CP3,
1160 OPC_MSUB_D = 0x29 | OPC_CP3,
1161 OPC_MSUB_PS = 0x2E | OPC_CP3,
1162 OPC_NMADD_S = 0x30 | OPC_CP3,
1163 OPC_NMADD_D = 0x31 | OPC_CP3,
1164 OPC_NMADD_PS = 0x36 | OPC_CP3,
1165 OPC_NMSUB_S = 0x38 | OPC_CP3,
1166 OPC_NMSUB_D = 0x39 | OPC_CP3,
1167 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1168};
1169
239dfebe 1170/* MSA Opcodes */
71375b59 1171#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
239dfebe
YK
1172enum {
1173 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1174 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1175 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1176 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1177 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1178 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1179 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1180 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1181 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1182 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1183 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1184 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1185 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1186 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1187 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1188 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1189 OPC_MSA_ELM = 0x19 | OPC_MSA,
1190 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1191 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1192 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1193 OPC_MSA_VEC = 0x1E | OPC_MSA,
1194
1195 /* MI10 instruction */
71375b59
AM
1196 OPC_LD_B = (0x20) | OPC_MSA,
1197 OPC_LD_H = (0x21) | OPC_MSA,
1198 OPC_LD_W = (0x22) | OPC_MSA,
1199 OPC_LD_D = (0x23) | OPC_MSA,
1200 OPC_ST_B = (0x24) | OPC_MSA,
1201 OPC_ST_H = (0x25) | OPC_MSA,
1202 OPC_ST_W = (0x26) | OPC_MSA,
1203 OPC_ST_D = (0x27) | OPC_MSA,
239dfebe
YK
1204};
1205
1206enum {
1207 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1208 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1209 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1210 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1211 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1213 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1214 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1217 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1218 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1219 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1220
1221 /* I8 instruction */
71375b59
AM
1222 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1223 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1225 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1226 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1228 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1229 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1230 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1231 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
239dfebe
YK
1232
1233 /* VEC/2R/2RF instruction */
71375b59
AM
1234 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1235 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1236 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1237 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1238 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1239 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1240 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
239dfebe
YK
1241
1242 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1244
1245 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
71375b59
AM
1246 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1247 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1248 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1249 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
239dfebe
YK
1250
1251 /* 2RF instruction df(bit 16) = _w, _d */
1252 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1253 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1255 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1256 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1257 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1258 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1259 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1260 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1262 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1263 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1264 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1266 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1268
1269 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1270 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1271 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1272 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1273 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1274 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1275 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1276 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1277 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1278 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1279 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1280 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1281 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1282 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1283 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1284 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1285 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1286 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1287 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1289 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1290 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1291 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1292 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1293 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1294 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1295 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1296 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1297 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1298 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1299 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1300 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1301 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1302 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1303 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1304 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1305 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1306 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1307 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1308 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1309 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1310 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1311 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1312 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1313 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1314 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1315 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1316 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1317 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1318 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1319 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1320 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1321 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1322 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1323 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1324 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1325 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1326 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1327 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1328 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1329 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1330 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1331 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1332 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1333
1334 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1335 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1341 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344
1345 /* 3RF instruction _df(bit 21) = _w, _d */
1346 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1361 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1362 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1364 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1365 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1369 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1370 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1372 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1373 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1375 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1378 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1381 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1384 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1385 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1386 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1387
1388 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1389 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1392 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1393 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1396 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1397 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1398 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1399 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1401};
1402
b158d449
AM
1403
1404/*
b158d449 1405 *
84e2c895
AM
1406 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1407 * ============================================
1408 *
1409 *
1410 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
b158d449
AM
1411 * instructions set. It is designed to fit the needs of signal, graphical and
1412 * video processing applications. MXU instruction set is used in Xburst family
1413 * of microprocessors by Ingenic.
1414 *
1415 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1416 * the control register.
1417 *
093ade12 1418 *
84e2c895
AM
1419 * The notation used in MXU assembler mnemonics
1420 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1421 *
1422 * Register operands:
1d0e663c
AM
1423 *
1424 * XRa, XRb, XRc, XRd - MXU registers
1425 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
093ade12 1426 *
84e2c895 1427 * Non-register operands:
093ade12 1428 *
84e2c895
AM
1429 * aptn1 - 1-bit accumulate add/subtract pattern
1430 * aptn2 - 2-bit accumulate add/subtract pattern
1431 * eptn2 - 2-bit execute add/subtract pattern
1432 * optn2 - 2-bit operand pattern
1433 * optn3 - 3-bit operand pattern
1434 * sft4 - 4-bit shift amount
1435 * strd2 - 2-bit stride amount
093ade12
AM
1436 *
1437 * Prefixes:
1438 *
84e2c895
AM
1439 * Level of parallelism: Operand size:
1440 * S - single operation at a time 32 - word
1441 * D - two operations in parallel 16 - half word
1442 * Q - four operations in parallel 8 - byte
093ade12
AM
1443 *
1444 * Operations:
1445 *
1446 * ADD - Add or subtract
1447 * ADDC - Add with carry-in
1448 * ACC - Accumulate
1449 * ASUM - Sum together then accumulate (add or subtract)
1450 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1451 * AVG - Average between 2 operands
1452 * ABD - Absolute difference
1453 * ALN - Align data
1454 * AND - Logical bitwise 'and' operation
1455 * CPS - Copy sign
1456 * EXTR - Extract bits
1457 * I2M - Move from GPR register to MXU register
1458 * LDD - Load data from memory to XRF
1459 * LDI - Load data from memory to XRF (and increase the address base)
1460 * LUI - Load unsigned immediate
1461 * MUL - Multiply
1462 * MULU - Unsigned multiply
1463 * MADD - 64-bit operand add 32x32 product
1464 * MSUB - 64-bit operand subtract 32x32 product
1465 * MAC - Multiply and accumulate (add or subtract)
1466 * MAD - Multiply and add or subtract
1467 * MAX - Maximum between 2 operands
1468 * MIN - Minimum between 2 operands
1469 * M2I - Move from MXU register to GPR register
1470 * MOVZ - Move if zero
1471 * MOVN - Move if non-zero
1472 * NOR - Logical bitwise 'nor' operation
1473 * OR - Logical bitwise 'or' operation
1474 * STD - Store data from XRF to memory
1475 * SDI - Store data from XRF to memory (and increase the address base)
1476 * SLT - Set of less than comparison
1477 * SAD - Sum of absolute differences
1478 * SLL - Logical shift left
1479 * SLR - Logical shift right
1480 * SAR - Arithmetic shift right
1481 * SAT - Saturation
1482 * SFL - Shuffle
1483 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1484 * XOR - Logical bitwise 'exclusive or' operation
1d0e663c 1485 *
84e2c895
AM
1486 * Suffixes:
1487 *
1488 * E - Expand results
1489 * F - Fixed point multiplication
1490 * L - Low part result
1491 * R - Doing rounding
1492 * V - Variable instead of immediate
1493 * W - Combine above L and V
1494 *
1495 *
1496 * The list of MXU instructions grouped by functionality
1497 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1498 *
1d0e663c
AM
1499 * Load/Store instructions Multiplication instructions
1500 * ----------------------- ---------------------------
1501 *
1502 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1503 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
093ade12
AM
1504 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1505 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1d0e663c
AM
1506 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1507 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1508 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1509 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1510 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1511 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1516 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1517 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1518 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1519 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1520 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1521 * S16SDI XRa, Rb, s10, eptn2
1522 * S8LDD XRa, Rb, s8, eptn3
1523 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1524 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1525 * S8SDI XRa, Rb, s8, eptn3
1526 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1527 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1528 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1529 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1530 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1531 * S32CPS XRa, XRb, XRc
1532 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1533 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1534 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1535 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1536 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1537 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1538 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1539 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1540 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1541 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1542 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1543 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1544 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1545 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1546 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1547 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1548 * Q8SLT XRa, XRb, XRc
1549 * Q8SLTU XRa, XRb, XRc
1550 * Q8MOVZ XRa, XRb, XRc Shift instructions
1551 * Q8MOVN XRa, XRb, XRc ------------------
1552 *
1553 * D32SLL XRa, XRb, XRc, XRd, sft4
1554 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1555 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1556 * D32SARL XRa, XRb, XRc, sft4
1557 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1558 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1559 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1560 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1561 * Q16SLL XRa, XRb, XRc, XRd, sft4
1562 * Q16SLR XRa, XRb, XRc, XRd, sft4
eab0bdb0 1563 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1d0e663c
AM
1564 * ------------------------- Q16SLLV XRa, XRb, Rb
1565 * Q16SLRV XRa, XRb, Rb
1566 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1567 * S32ALN XRa, XRb, XRc, Rb
1568 * S32ALNI XRa, XRb, XRc, s3
1569 * S32LUI XRa, s8, optn3 Move instructions
1570 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1571 * S32EXTRV XRa, XRb, Rs, Rt
1572 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1573 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1574 *
9ef5bff9 1575 *
84e2c895
AM
1576 * The opcode organization of MXU instructions
1577 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1578 *
1579 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1580 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1581 * other bits up to the instruction level is as follows:
1582 *
9ef5bff9
AM
1583 * bits
1584 * 05..00
1585 *
1586 * ┌─ 000000 ─ OPC_MXU_S32MADD
1587 * ├─ 000001 ─ OPC_MXU_S32MADDU
eab0bdb0
AM
1588 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1589 * │
9ef5bff9
AM
1590 * │ 20..18
1591 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1592 * │ ├─ 001 ─ OPC_MXU_S32MIN
1593 * │ ├─ 010 ─ OPC_MXU_D16MAX
1594 * │ ├─ 011 ─ OPC_MXU_D16MIN
1595 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1596 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1597 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1598 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1599 * ├─ 000100 ─ OPC_MXU_S32MSUB
1600 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1601 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1602 * │ ├─ 001 ─ OPC_MXU_D16SLT
1603 * │ ├─ 010 ─ OPC_MXU_D16AVG
1604 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1605 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1606 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1607 * │ └─ 111 ─ OPC_MXU_Q8ADD
1608 * │
1609 * │ 20..18
1610 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1611 * │ ├─ 010 ─ OPC_MXU_D16CPS
1612 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1613 * │ └─ 110 ─ OPC_MXU_Q16SAT
1614 * ├─ 001000 ─ OPC_MXU_D16MUL
1615 * │ 25..24
1616 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1617 * │ └─ 01 ─ OPC_MXU_D16MULE
1618 * ├─ 001010 ─ OPC_MXU_D16MAC
1619 * ├─ 001011 ─ OPC_MXU_D16MACF
1620 * ├─ 001100 ─ OPC_MXU_D16MADL
eab0bdb0 1621 * ├─ 001101 ─ OPC_MXU_S16MAD
9ef5bff9 1622 * ├─ 001110 ─ OPC_MXU_Q16ADD
eab0bdb0
AM
1623 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1624 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1625 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
9ef5bff9
AM
1626 * │
1627 * │ 23
eab0bdb0 1628 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
9ef5bff9
AM
1629 * │ └─ 1 ─ OPC_MXU_S32STDR
1630 * │
1631 * │ 13..10
eab0bdb0 1632 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
9ef5bff9
AM
1633 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1634 * │
1635 * │ 13..10
eab0bdb0 1636 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
9ef5bff9
AM
1637 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1638 * │
1639 * │ 23
eab0bdb0 1640 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
9ef5bff9
AM
1641 * │ └─ 1 ─ OPC_MXU_S32LDIR
1642 * │
1643 * │ 23
eab0bdb0 1644 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
9ef5bff9
AM
1645 * │ └─ 1 ─ OPC_MXU_S32SDIR
1646 * │
1647 * │ 13..10
eab0bdb0 1648 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
9ef5bff9
AM
1649 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1650 * │
1651 * │ 13..10
eab0bdb0 1652 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
9ef5bff9
AM
1653 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1654 * ├─ 011000 ─ OPC_MXU_D32ADD
1655 * │ 23..22
eab0bdb0 1656 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
9ef5bff9
AM
1657 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1658 * │ └─ 10 ─ OPC_MXU_D32ASUM
1659 * ├─ 011010 ─ <not assigned>
1660 * │ 23..22
eab0bdb0 1661 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
9ef5bff9
AM
1662 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1663 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1664 * │
1665 * │ 23..22
eab0bdb0 1666 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
9ef5bff9
AM
1667 * │ ├─ 01 ─ OPC_MXU_D8SUM
1668 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1669 * ├─ 011110 ─ <not assigned>
1670 * ├─ 011111 ─ <not assigned>
eab0bdb0
AM
1671 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1672 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
9ef5bff9 1673 * ├─ 100010 ─ OPC_MXU_S8LDD
eab0bdb0
AM
1674 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1675 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1676 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
9ef5bff9 1677 * │ ├─ 00 ─ OPC_MXU_S32EXTR
eab0bdb0 1678 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
9ef5bff9
AM
1679 * │
1680 * │ 20..18
eab0bdb0 1681 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
9ef5bff9 1682 * │ ├─ 001 ─ OPC_MXU_S32ALN
c233bf07 1683 * │ ├─ 010 ─ OPC_MXU_S32ALNI
b621f018
AM
1684 * │ ├─ 011 ─ OPC_MXU_S32LUI
1685 * │ ├─ 100 ─ OPC_MXU_S32NOR
1686 * │ ├─ 101 ─ OPC_MXU_S32AND
1687 * │ ├─ 110 ─ OPC_MXU_S32OR
1688 * │ └─ 111 ─ OPC_MXU_S32XOR
c233bf07
AM
1689 * │
1690 * │ 7..5
1691 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1692 * │ ├─ 001 ─ OPC_MXU_LXH
1693 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1694 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1695 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1696 * ├─ 101100 ─ OPC_MXU_S16LDI
1697 * ├─ 101101 ─ OPC_MXU_S16SDI
9ef5bff9
AM
1698 * ├─ 101110 ─ OPC_MXU_S32M2I
1699 * ├─ 101111 ─ OPC_MXU_S32I2M
1700 * ├─ 110000 ─ OPC_MXU_D32SLL
eab0bdb0
AM
1701 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1702 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1703 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1704 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1705 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
9ef5bff9 1706 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
c233bf07 1707 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
eab0bdb0 1708 * │
9ef5bff9
AM
1709 * ├─ 110111 ─ OPC_MXU_Q16SAR
1710 * │ 23..22
c233bf07 1711 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
9ef5bff9
AM
1712 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1713 * │
1714 * │ 20..18
c233bf07 1715 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
9ef5bff9
AM
1716 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1717 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1718 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1719 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
84e2c895 1720 * │ └─ 101 ─ OPC_MXU_S32MOVN
9ef5bff9
AM
1721 * │
1722 * │ 23..22
c233bf07 1723 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
9ef5bff9
AM
1724 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1725 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1726 * ├─ 111100 ─ OPC_MXU_Q8MADL
1727 * ├─ 111101 ─ OPC_MXU_S32SFL
1728 * ├─ 111110 ─ OPC_MXU_Q8SAD
eab0bdb0 1729 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
9ef5bff9
AM
1730 *
1731 *
84e2c895 1732 * Compiled after:
b158d449
AM
1733 *
1734 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
84e2c895 1735 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
b158d449
AM
1736 */
1737
8bacd1ff
AM
1738enum {
1739 OPC_MXU_S32MADD = 0x00,
1740 OPC_MXU_S32MADDU = 0x01,
11d56f61 1741 OPC__MXU_MUL = 0x02,
8bacd1ff
AM
1742 OPC_MXU__POOL00 = 0x03,
1743 OPC_MXU_S32MSUB = 0x04,
1744 OPC_MXU_S32MSUBU = 0x05,
1745 OPC_MXU__POOL01 = 0x06,
1746 OPC_MXU__POOL02 = 0x07,
1747 OPC_MXU_D16MUL = 0x08,
1748 OPC_MXU__POOL03 = 0x09,
1749 OPC_MXU_D16MAC = 0x0A,
1750 OPC_MXU_D16MACF = 0x0B,
1751 OPC_MXU_D16MADL = 0x0C,
eab0bdb0 1752 OPC_MXU_S16MAD = 0x0D,
8bacd1ff
AM
1753 OPC_MXU_Q16ADD = 0x0E,
1754 OPC_MXU_D16MACE = 0x0F,
eab0bdb0
AM
1755 OPC_MXU__POOL04 = 0x10,
1756 OPC_MXU__POOL05 = 0x11,
1757 OPC_MXU__POOL06 = 0x12,
1758 OPC_MXU__POOL07 = 0x13,
1759 OPC_MXU__POOL08 = 0x14,
1760 OPC_MXU__POOL09 = 0x15,
1761 OPC_MXU__POOL10 = 0x16,
1762 OPC_MXU__POOL11 = 0x17,
8bacd1ff 1763 OPC_MXU_D32ADD = 0x18,
eab0bdb0 1764 OPC_MXU__POOL12 = 0x19,
8bacd1ff 1765 /* not assigned 0x1A */
eab0bdb0
AM
1766 OPC_MXU__POOL13 = 0x1B,
1767 OPC_MXU__POOL14 = 0x1C,
8bacd1ff
AM
1768 OPC_MXU_Q8ACCE = 0x1D,
1769 /* not assigned 0x1E */
1770 /* not assigned 0x1F */
1771 /* not assigned 0x20 */
1772 /* not assigned 0x21 */
1773 OPC_MXU_S8LDD = 0x22,
1774 OPC_MXU_S8STD = 0x23,
1775 OPC_MXU_S8LDI = 0x24,
1776 OPC_MXU_S8SDI = 0x25,
eab0bdb0
AM
1777 OPC_MXU__POOL15 = 0x26,
1778 OPC_MXU__POOL16 = 0x27,
c233bf07 1779 OPC_MXU__POOL17 = 0x28,
8bacd1ff
AM
1780 /* not assigned 0x29 */
1781 OPC_MXU_S16LDD = 0x2A,
1782 OPC_MXU_S16STD = 0x2B,
1783 OPC_MXU_S16LDI = 0x2C,
1784 OPC_MXU_S16SDI = 0x2D,
1785 OPC_MXU_S32M2I = 0x2E,
1786 OPC_MXU_S32I2M = 0x2F,
1787 OPC_MXU_D32SLL = 0x30,
1788 OPC_MXU_D32SLR = 0x31,
1789 OPC_MXU_D32SARL = 0x32,
1790 OPC_MXU_D32SAR = 0x33,
1791 OPC_MXU_Q16SLL = 0x34,
1792 OPC_MXU_Q16SLR = 0x35,
c233bf07 1793 OPC_MXU__POOL18 = 0x36,
8bacd1ff 1794 OPC_MXU_Q16SAR = 0x37,
c233bf07
AM
1795 OPC_MXU__POOL19 = 0x38,
1796 OPC_MXU__POOL20 = 0x39,
1797 OPC_MXU__POOL21 = 0x3A,
8bacd1ff
AM
1798 OPC_MXU_Q16SCOP = 0x3B,
1799 OPC_MXU_Q8MADL = 0x3C,
1800 OPC_MXU_S32SFL = 0x3D,
1801 OPC_MXU_Q8SAD = 0x3E,
1802 /* not assigned 0x3F */
1803};
1804
1805
1806/*
1807 * MXU pool 00
1808 */
1809enum {
1810 OPC_MXU_S32MAX = 0x00,
1811 OPC_MXU_S32MIN = 0x01,
1812 OPC_MXU_D16MAX = 0x02,
1813 OPC_MXU_D16MIN = 0x03,
1814 OPC_MXU_Q8MAX = 0x04,
1815 OPC_MXU_Q8MIN = 0x05,
1816 OPC_MXU_Q8SLT = 0x06,
1817 OPC_MXU_Q8SLTU = 0x07,
1818};
1819
1820/*
1821 * MXU pool 01
1822 */
1823enum {
1824 OPC_MXU_S32SLT = 0x00,
1825 OPC_MXU_D16SLT = 0x01,
1826 OPC_MXU_D16AVG = 0x02,
1827 OPC_MXU_D16AVGR = 0x03,
1828 OPC_MXU_Q8AVG = 0x04,
1829 OPC_MXU_Q8AVGR = 0x05,
1830 OPC_MXU_Q8ADD = 0x07,
1831};
1832
1833/*
1834 * MXU pool 02
1835 */
1836enum {
1837 OPC_MXU_S32CPS = 0x00,
1838 OPC_MXU_D16CPS = 0x02,
1839 OPC_MXU_Q8ABD = 0x04,
1840 OPC_MXU_Q16SAT = 0x06,
1841};
1842
1843/*
1844 * MXU pool 03
1845 */
1846enum {
1847 OPC_MXU_D16MULF = 0x00,
1848 OPC_MXU_D16MULE = 0x01,
1849};
1850
1851/*
1852 * MXU pool 04
1853 */
8bacd1ff
AM
1854enum {
1855 OPC_MXU_S32LDD = 0x00,
1856 OPC_MXU_S32LDDR = 0x01,
1857};
1858
1859/*
eab0bdb0 1860 * MXU pool 05
8bacd1ff
AM
1861 */
1862enum {
1863 OPC_MXU_S32STD = 0x00,
1864 OPC_MXU_S32STDR = 0x01,
1865};
1866
1867/*
eab0bdb0 1868 * MXU pool 06
8bacd1ff
AM
1869 */
1870enum {
1871 OPC_MXU_S32LDDV = 0x00,
1872 OPC_MXU_S32LDDVR = 0x01,
1873};
1874
1875/*
eab0bdb0 1876 * MXU pool 07
8bacd1ff
AM
1877 */
1878enum {
1879 OPC_MXU_S32STDV = 0x00,
1880 OPC_MXU_S32STDVR = 0x01,
1881};
1882
1883/*
eab0bdb0 1884 * MXU pool 08
8bacd1ff
AM
1885 */
1886enum {
1887 OPC_MXU_S32LDI = 0x00,
1888 OPC_MXU_S32LDIR = 0x01,
1889};
1890
1891/*
eab0bdb0 1892 * MXU pool 09
8bacd1ff
AM
1893 */
1894enum {
1895 OPC_MXU_S32SDI = 0x00,
1896 OPC_MXU_S32SDIR = 0x01,
1897};
1898
1899/*
eab0bdb0 1900 * MXU pool 10
8bacd1ff
AM
1901 */
1902enum {
1903 OPC_MXU_S32LDIV = 0x00,
1904 OPC_MXU_S32LDIVR = 0x01,
1905};
1906
1907/*
eab0bdb0 1908 * MXU pool 11
8bacd1ff
AM
1909 */
1910enum {
1911 OPC_MXU_S32SDIV = 0x00,
1912 OPC_MXU_S32SDIVR = 0x01,
1913};
1914
1915/*
eab0bdb0 1916 * MXU pool 12
8bacd1ff
AM
1917 */
1918enum {
1919 OPC_MXU_D32ACC = 0x00,
1920 OPC_MXU_D32ACCM = 0x01,
1921 OPC_MXU_D32ASUM = 0x02,
1922};
1923
1924/*
eab0bdb0 1925 * MXU pool 13
8bacd1ff
AM
1926 */
1927enum {
1928 OPC_MXU_Q16ACC = 0x00,
1929 OPC_MXU_Q16ACCM = 0x01,
1930 OPC_MXU_Q16ASUM = 0x02,
1931};
1932
1933/*
eab0bdb0 1934 * MXU pool 14
8bacd1ff
AM
1935 */
1936enum {
1937 OPC_MXU_Q8ADDE = 0x00,
1938 OPC_MXU_D8SUM = 0x01,
1939 OPC_MXU_D8SUMC = 0x02,
1940};
1941
1942/*
eab0bdb0 1943 * MXU pool 15
8bacd1ff
AM
1944 */
1945enum {
1946 OPC_MXU_S32MUL = 0x00,
1947 OPC_MXU_S32MULU = 0x01,
1948 OPC_MXU_S32EXTR = 0x02,
1949 OPC_MXU_S32EXTRV = 0x03,
1950};
1951
1952/*
eab0bdb0 1953 * MXU pool 16
8bacd1ff
AM
1954 */
1955enum {
1956 OPC_MXU_D32SARW = 0x00,
1957 OPC_MXU_S32ALN = 0x01,
1958 OPC_MXU_S32ALNI = 0x02,
b621f018
AM
1959 OPC_MXU_S32LUI = 0x03,
1960 OPC_MXU_S32NOR = 0x04,
1961 OPC_MXU_S32AND = 0x05,
1962 OPC_MXU_S32OR = 0x06,
1963 OPC_MXU_S32XOR = 0x07,
8bacd1ff
AM
1964};
1965
1966/*
eab0bdb0 1967 * MXU pool 17
8bacd1ff 1968 */
c233bf07
AM
1969enum {
1970 OPC_MXU_LXB = 0x00,
1971 OPC_MXU_LXH = 0x01,
1972 OPC_MXU_LXW = 0x03,
1973 OPC_MXU_LXBU = 0x04,
1974 OPC_MXU_LXHU = 0x05,
1975};
1976
1977/*
1978 * MXU pool 18
1979 */
8bacd1ff
AM
1980enum {
1981 OPC_MXU_D32SLLV = 0x00,
1982 OPC_MXU_D32SLRV = 0x01,
1983 OPC_MXU_D32SARV = 0x03,
1984 OPC_MXU_Q16SLLV = 0x04,
1985 OPC_MXU_Q16SLRV = 0x05,
1986 OPC_MXU_Q16SARV = 0x07,
1987};
1988
1989/*
c233bf07 1990 * MXU pool 19
8bacd1ff
AM
1991 */
1992enum {
1993 OPC_MXU_Q8MUL = 0x00,
1994 OPC_MXU_Q8MULSU = 0x01,
1995};
1996
1997/*
c233bf07 1998 * MXU pool 20
8bacd1ff
AM
1999 */
2000enum {
2001 OPC_MXU_Q8MOVZ = 0x00,
2002 OPC_MXU_Q8MOVN = 0x01,
2003 OPC_MXU_D16MOVZ = 0x02,
2004 OPC_MXU_D16MOVN = 0x03,
2005 OPC_MXU_S32MOVZ = 0x04,
2006 OPC_MXU_S32MOVN = 0x05,
2007};
2008
2009/*
c233bf07 2010 * MXU pool 21
8bacd1ff
AM
2011 */
2012enum {
2013 OPC_MXU_Q8MAC = 0x00,
2014 OPC_MXU_Q8MACSU = 0x01,
2015};
2016
497f072b
FN
2017/*
2018 * Overview of the TX79-specific instruction set
2019 * =============================================
2020 *
2021 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2022 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2023 * instructions and certain multimedia instructions (MMIs). These MMIs
2024 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2025 * or sixteen 8-bit paths.
2026 *
2027 * Reference:
2028 *
2029 * The Toshiba TX System RISC TX79 Core Architecture manual,
2030 * https://wiki.qemu.org/File:C790.pdf
2031 *
2032 * Three-Operand Multiply and Multiply-Add (4 instructions)
2033 * --------------------------------------------------------
2034 * MADD [rd,] rs, rt Multiply/Add
2035 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2036 * MULT [rd,] rs, rt Multiply (3-operand)
2037 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2038 *
2039 * Multiply Instructions for Pipeline 1 (10 instructions)
2040 * ------------------------------------------------------
2041 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2042 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2043 * DIV1 rs, rt Divide Pipeline 1
2044 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2045 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2046 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2047 * MFHI1 rd Move From HI1 Register
2048 * MFLO1 rd Move From LO1 Register
2049 * MTHI1 rs Move To HI1 Register
2050 * MTLO1 rs Move To LO1 Register
2051 *
2052 * Arithmetic (19 instructions)
2053 * ----------------------------
2054 * PADDB rd, rs, rt Parallel Add Byte
2055 * PSUBB rd, rs, rt Parallel Subtract Byte
2056 * PADDH rd, rs, rt Parallel Add Halfword
2057 * PSUBH rd, rs, rt Parallel Subtract Halfword
2058 * PADDW rd, rs, rt Parallel Add Word
2059 * PSUBW rd, rs, rt Parallel Subtract Word
2060 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2061 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2062 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2063 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2064 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2065 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2066 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2067 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2068 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2069 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2070 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2071 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2072 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2073 *
2074 * Min/Max (4 instructions)
2075 * ------------------------
2076 * PMAXH rd, rs, rt Parallel Maximum Halfword
2077 * PMINH rd, rs, rt Parallel Minimum Halfword
2078 * PMAXW rd, rs, rt Parallel Maximum Word
2079 * PMINW rd, rs, rt Parallel Minimum Word
2080 *
2081 * Absolute (2 instructions)
2082 * -------------------------
2083 * PABSH rd, rt Parallel Absolute Halfword
2084 * PABSW rd, rt Parallel Absolute Word
2085 *
2086 * Logical (4 instructions)
2087 * ------------------------
2088 * PAND rd, rs, rt Parallel AND
2089 * POR rd, rs, rt Parallel OR
2090 * PXOR rd, rs, rt Parallel XOR
2091 * PNOR rd, rs, rt Parallel NOR
2092 *
2093 * Shift (9 instructions)
2094 * ----------------------
2095 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2096 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2097 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2098 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2099 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2100 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2101 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2102 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2103 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2104 *
2105 * Compare (6 instructions)
2106 * ------------------------
2107 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2108 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2109 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2110 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2111 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2112 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2113 *
2114 * LZC (1 instruction)
2115 * -------------------
2116 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2117 *
2118 * Quadword Load and Store (2 instructions)
2119 * ----------------------------------------
2120 * LQ rt, offset(base) Load Quadword
2121 * SQ rt, offset(base) Store Quadword
2122 *
2123 * Multiply and Divide (19 instructions)
2124 * -------------------------------------
2125 * PMULTW rd, rs, rt Parallel Multiply Word
2126 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2127 * PDIVW rs, rt Parallel Divide Word
2128 * PDIVUW rs, rt Parallel Divide Unsigned Word
2129 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2130 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2131 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2132 * PMULTH rd, rs, rt Parallel Multiply Halfword
2133 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2134 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2135 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2136 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2137 * PDIVBW rs, rt Parallel Divide Broadcast Word
2138 * PMFHI rd Parallel Move From HI Register
2139 * PMFLO rd Parallel Move From LO Register
2140 * PMTHI rs Parallel Move To HI Register
2141 * PMTLO rs Parallel Move To LO Register
2142 * PMFHL rd Parallel Move From HI/LO Register
2143 * PMTHL rs Parallel Move To HI/LO Register
2144 *
2145 * Pack/Extend (11 instructions)
2146 * -----------------------------
2147 * PPAC5 rd, rt Parallel Pack to 5 bits
2148 * PPACB rd, rs, rt Parallel Pack to Byte
2149 * PPACH rd, rs, rt Parallel Pack to Halfword
2150 * PPACW rd, rs, rt Parallel Pack to Word
2151 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2152 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2153 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2154 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2155 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2156 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2157 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2158 *
2159 * Others (16 instructions)
2160 * ------------------------
2161 * PCPYH rd, rt Parallel Copy Halfword
2162 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2163 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2164 * PREVH rd, rt Parallel Reverse Halfword
2165 * PINTH rd, rs, rt Parallel Interleave Halfword
2166 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2167 * PEXEH rd, rt Parallel Exchange Even Halfword
2168 * PEXCH rd, rt Parallel Exchange Center Halfword
2169 * PEXEW rd, rt Parallel Exchange Even Word
2170 * PEXCW rd, rt Parallel Exchange Center Word
2171 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2172 * MFSA rd Move from Shift Amount Register
2173 * MTSA rs Move to Shift Amount Register
2174 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2175 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2176 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d 2177 *
baa609db
AM
2178 * MMI (MultiMedia Instruction) encodings
2179 * ======================================
f99c0d6d 2180 *
baa609db 2181 * MMI instructions encoding table keys:
f99c0d6d
FN
2182 *
2183 * * This code is reserved for future use. An attempt to execute it
2184 * causes a Reserved Instruction exception.
2185 * % This code indicates an instruction class. The instruction word
2186 * must be further decoded by examining additional tables that show
2187 * the values for other instruction fields.
2188 * # This code is reserved for the unsupported instructions DMULT,
2189 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2190 * to execute it causes a Reserved Instruction exception.
2191 *
baa609db 2192 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
2193 *
2194 * 31 26 0
2195 * +--------+----------------------------------------+
2196 * | opcode | |
2197 * +--------+----------------------------------------+
2198 *
2199 * opcode bits 28..26
2200 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2201 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2202 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2203 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2204 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2205 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2206 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2207 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2208 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2209 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2210 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2211 */
b158d449 2212
f99c0d6d 2213enum {
baa609db
AM
2214 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2215 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2216 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
2217};
2218
d3297211 2219/*
baa609db 2220 * MMI instructions with opcode field = MMI:
d3297211
FN
2221 *
2222 * 31 26 5 0
2223 * +--------+-------------------------------+--------+
2224 * | MMI | |function|
2225 * +--------+-------------------------------+--------+
2226 *
2227 * function bits 2..0
2228 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2229 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2230 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2231 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2232 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2233 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2234 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2235 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2236 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2237 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2238 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2239 */
2240
c8341e00 2241#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 2242enum {
baa609db
AM
2243 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2244 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2245 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2249 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2250 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2251 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2252 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2253 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2254 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2255 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2256 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
d3297211
FN
2268};
2269
3ef65697 2270/*
baa609db 2271 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
3ef65697
FN
2272 *
2273 * 31 26 10 6 5 0
2274 * +--------+----------------------+--------+--------+
2275 * | MMI | |function| MMI0 |
2276 * +--------+----------------------+--------+--------+
2277 *
2278 * function bits 7..6
2279 * bits | 0 | 1 | 2 | 3
2280 * 10..8 | 00 | 01 | 10 | 11
2281 * -------+-------+-------+-------+-------
2282 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2283 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2284 * 2 010 | PADDB | PSUBB | PCGTB | *
2285 * 3 011 | * | * | * | *
2286 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2287 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2288 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2289 * 7 111 | * | * | PEXT5 | PPAC5
2290 */
2291
c8341e00 2292#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
3ef65697 2293enum {
baa609db
AM
2294 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
3ef65697
FN
2319};
2320
77596541 2321/*
baa609db 2322 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
77596541
FN
2323 *
2324 * 31 26 10 6 5 0
2325 * +--------+----------------------+--------+--------+
2326 * | MMI | |function| MMI1 |
2327 * +--------+----------------------+--------+--------+
2328 *
2329 * function bits 7..6
2330 * bits | 0 | 1 | 2 | 3
2331 * 10..8 | 00 | 01 | 10 | 11
2332 * -------+-------+-------+-------+-------
2333 * 0 000 | * | PABSW | PCEQW | PMINW
2334 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2335 * 2 010 | * | * | PCEQB | *
2336 * 3 011 | * | * | * | *
2337 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2338 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2339 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2340 * 7 111 | * | * | * | *
2341 */
2342
c8341e00 2343#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
77596541 2344enum {
baa609db
AM
2345 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
77596541
FN
2363};
2364
6c03ef6a 2365/*
baa609db 2366 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
6c03ef6a
FN
2367 *
2368 * 31 26 10 6 5 0
2369 * +--------+----------------------+--------+--------+
2370 * | MMI | |function| MMI2 |
2371 * +--------+----------------------+--------+--------+
2372 *
2373 * function bits 7..6
2374 * bits | 0 | 1 | 2 | 3
2375 * 10..8 | 00 | 01 | 10 | 11
2376 * -------+-------+-------+-------+-------
2377 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2378 * 1 001 | PMSUBW| * | * | *
2379 * 2 010 | PMFHI | PMFLO | PINTH | *
2380 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2381 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2382 * 5 101 | PMSUBH| PHMSBH| * | *
2383 * 6 110 | * | * | PEXEH | PREVH
2384 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2385 */
2386
c8341e00 2387#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
6c03ef6a 2388enum {
baa609db
AM
2389 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
6c03ef6a
FN
2411};
2412
dd581bf9 2413/*
baa609db 2414 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
dd581bf9
FN
2415 *
2416 * 31 26 10 6 5 0
2417 * +--------+----------------------+--------+--------+
2418 * | MMI | |function| MMI3 |
2419 * +--------+----------------------+--------+--------+
2420 *
2421 * function bits 7..6
2422 * bits | 0 | 1 | 2 | 3
2423 * 10..8 | 00 | 01 | 10 | 11
2424 * -------+-------+-------+-------+-------
2425 * 0 000 |PMADDUW| * | * | PSRAVW
2426 * 1 001 | * | * | * | *
2427 * 2 010 | PMTHI | PMTLO | PINTEH| *
2428 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2429 * 4 100 | * | * | POR | PNOR
2430 * 5 101 | * | * | * | *
2431 * 6 110 | * | * | PEXCH | PCPYH
2432 * 7 111 | * | * | PEXCW | *
2433 */
2434
c8341e00 2435#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
dd581bf9 2436enum {
baa609db
AM
2437 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
dd581bf9
FN
2450};
2451
39454628 2452/* global register indices */
a7812ae4 2453static TCGv cpu_gpr[32], cpu_PC;
340fff72 2454static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607 2455static TCGv cpu_dspctrl, btarget, bcond;
33a07fa2 2456static TCGv cpu_lladdr, cpu_llval;
41db4607 2457static TCGv_i32 hflags;
a7812ae4 2458static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2459static TCGv_i64 fpu_f64[32];
863f264d 2460static TCGv_i64 msa_wr_d[64];
aa0bf00b 2461
a168a796
FN
2462#if defined(TARGET_MIPS64)
2463/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2464static TCGv_i64 cpu_mmr[32];
2465#endif
2466
b621f018 2467#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2468/* MXU registers */
2469static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2470static TCGv mxu_CR;
b621f018 2471#endif
eb5559f6 2472
022c62cb 2473#include "exec/gen-icount.h"
2e70f6ef 2474
895c2d04 2475#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2476 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2477 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 2478 tcg_temp_free_i32(helper_tmp); \
71375b59 2479 } while (0)
be24bb4f 2480
895c2d04 2481#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2482 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2483 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 2484 tcg_temp_free_i32(helper_tmp); \
71375b59 2485 } while (0)
be24bb4f 2486
895c2d04
BS
2487#define gen_helper_1e0i(name, ret, arg1) do { \
2488 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2489 gen_helper_##name(ret, cpu_env, helper_tmp); \
2490 tcg_temp_free_i32(helper_tmp); \
71375b59 2491 } while (0)
895c2d04
BS
2492
2493#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2494 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2495 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2496 tcg_temp_free_i32(helper_tmp); \
71375b59 2497 } while (0)
895c2d04
BS
2498
2499#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2500 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2501 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2502 tcg_temp_free_i32(helper_tmp); \
71375b59 2503 } while (0)
895c2d04
BS
2504
2505#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2506 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2507 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 2508 tcg_temp_free_i32(helper_tmp); \
71375b59 2509 } while (0)
be24bb4f 2510
895c2d04 2511#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2512 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2513 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 2514 tcg_temp_free_i32(helper_tmp); \
71375b59 2515 } while (0)
c239529e 2516
8e9ade68 2517typedef struct DisasContext {
eeb3bba8
EC
2518 DisasContextBase base;
2519 target_ulong saved_pc;
18f440ed 2520 target_ulong page_start;
8e9ade68 2521 uint32_t opcode;
f9c9cd63 2522 uint64_t insn_flags;
5ab5c041 2523 int32_t CP0_Config1;
49735f76 2524 int32_t CP0_Config2;
ab77fc61
DN
2525 int32_t CP0_Config3;
2526 int32_t CP0_Config5;
8e9ade68
TS
2527 /* Routine used to access memory */
2528 int mem_idx;
14776ab5 2529 MemOp default_tcg_memop_mask;
8e9ade68 2530 uint32_t hflags, saved_hflags;
8e9ade68 2531 target_ulong btarget;
d279279e 2532 bool ulri;
e98c0d17 2533 int kscrexist;
7207c7f9 2534 bool rxi;
9456c2fb 2535 int ie;
aea14095
LA
2536 bool bi;
2537 bool bp;
5204ea79
LA
2538 uint64_t PAMask;
2539 bool mvh;
76964147 2540 bool eva;
cec56a73 2541 bool sc;
5204ea79 2542 int CP0_LLAddr_shift;
e29c9628 2543 bool ps;
01bc435b 2544 bool vp;
c870e3f5 2545 bool cmgcr;
f6d4dd81 2546 bool mrp;
87552089 2547 bool nan2008;
6be77480 2548 bool abs2008;
5fb2dcd1 2549 bool saar;
8e9ade68
TS
2550} DisasContext;
2551
b28425ba
EC
2552#define DISAS_STOP DISAS_TARGET_0
2553#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2554
d73ee8a2
RH
2555static const char * const regnames[] = {
2556 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2557 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2558 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2559 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2560};
6af0bf9c 2561
d73ee8a2
RH
2562static const char * const regnames_HI[] = {
2563 "HI0", "HI1", "HI2", "HI3",
2564};
4b2eb8d2 2565
d73ee8a2
RH
2566static const char * const regnames_LO[] = {
2567 "LO0", "LO1", "LO2", "LO3",
2568};
4b2eb8d2 2569
d73ee8a2
RH
2570static const char * const fregnames[] = {
2571 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2572 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2573 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2574 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2575};
958fb4a9 2576
863f264d
YK
2577static const char * const msaregnames[] = {
2578 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2579 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2580 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2581 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2582 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2583 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2584 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2585 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2586 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2587 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2588 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2589 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2590 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2591 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2592 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2593 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2594};
2595
b621f018 2596#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2597static const char * const mxuregnames[] = {
2598 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2599 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2600};
b621f018 2601#endif
eb5559f6 2602
9d68ac14 2603#define LOG_DISAS(...) \
fb7729e2
RH
2604 do { \
2605 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2606 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2607 } \
2608 } while (0)
2609
9d68ac14 2610#define MIPS_INVAL(op) \
fb7729e2
RH
2611 do { \
2612 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2613 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2614 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2615 ctx->base.pc_next, ctx->opcode, op, \
2616 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2617 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2618 } \
2619 } while (0)
958fb4a9 2620
8e9ade68 2621/* General purpose registers moves. */
235785e8 2622static inline void gen_load_gpr(TCGv t, int reg)
aaa9128a 2623{
1f8929d2 2624 if (reg == 0) {
8e9ade68 2625 tcg_gen_movi_tl(t, 0);
1f8929d2 2626 } else {
4b2eb8d2 2627 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 2628 }
aaa9128a
TS
2629}
2630
235785e8 2631static inline void gen_store_gpr(TCGv t, int reg)
aaa9128a 2632{
1f8929d2 2633 if (reg != 0) {
4b2eb8d2 2634 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 2635 }
aaa9128a
TS
2636}
2637
8e9ade68 2638/* Moves to/from shadow registers. */
235785e8 2639static inline void gen_load_srsgpr(int from, int to)
aaa9128a 2640{
d9bea114 2641 TCGv t0 = tcg_temp_new();
be24bb4f 2642
1f8929d2 2643 if (from == 0) {
d9bea114 2644 tcg_gen_movi_tl(t0, 0);
1f8929d2 2645 } else {
d9bea114 2646 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2647 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2648
7db13fae 2649 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2650 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2651 tcg_gen_andi_i32(t2, t2, 0xf);
2652 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2653 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2654 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2655
d9bea114 2656 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2657 tcg_temp_free_ptr(addr);
d9bea114 2658 tcg_temp_free_i32(t2);
8e9ade68 2659 }
d9bea114
AJ
2660 gen_store_gpr(t0, to);
2661 tcg_temp_free(t0);
aaa9128a
TS
2662}
2663
71375b59 2664static inline void gen_store_srsgpr(int from, int to)
aaa9128a 2665{
be24bb4f 2666 if (to != 0) {
d9bea114
AJ
2667 TCGv t0 = tcg_temp_new();
2668 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2669 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2670
d9bea114 2671 gen_load_gpr(t0, from);
7db13fae 2672 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2673 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2674 tcg_gen_andi_i32(t2, t2, 0xf);
2675 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2676 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2677 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2678
d9bea114 2679 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2680 tcg_temp_free_ptr(addr);
d9bea114
AJ
2681 tcg_temp_free_i32(t2);
2682 tcg_temp_free(t0);
8e9ade68 2683 }
aaa9128a
TS
2684}
2685
b621f018 2686#if !defined(TARGET_MIPS64)
96992d1a
CJ
2687/* MXU General purpose registers moves. */
2688static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2689{
2690 if (reg == 0) {
2691 tcg_gen_movi_tl(t, 0);
2692 } else if (reg <= 15) {
2693 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2694 }
2695}
2696
2697static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2698{
2699 if (reg > 0 && reg <= 15) {
2700 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2701 }
2702}
2703
2704/* MXU control register moves. */
2705static inline void gen_load_mxu_cr(TCGv t)
2706{
2707 tcg_gen_mov_tl(t, mxu_CR);
2708}
2709
2710static inline void gen_store_mxu_cr(TCGv t)
2711{
2712 /* TODO: Add handling of RW rules for MXU_CR. */
2713 tcg_gen_mov_tl(mxu_CR, t);
2714}
b621f018 2715#endif
96992d1a
CJ
2716
2717
eab9944c
LA
2718/* Tests */
2719static inline void gen_save_pc(target_ulong pc)
2720{
2721 tcg_gen_movi_tl(cpu_PC, pc);
2722}
2723
2724static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2725{
2726 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2727 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2728 gen_save_pc(ctx->base.pc_next);
2729 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2730 }
2731 if (ctx->hflags != ctx->saved_hflags) {
2732 tcg_gen_movi_i32(hflags, ctx->hflags);
2733 ctx->saved_hflags = ctx->hflags;
2734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2735 case MIPS_HFLAG_BR:
2736 break;
2737 case MIPS_HFLAG_BC:
2738 case MIPS_HFLAG_BL:
2739 case MIPS_HFLAG_B:
2740 tcg_gen_movi_tl(btarget, ctx->btarget);
2741 break;
2742 }
2743 }
2744}
2745
2746static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2747{
2748 ctx->saved_hflags = ctx->hflags;
2749 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2750 case MIPS_HFLAG_BR:
2751 break;
2752 case MIPS_HFLAG_BC:
2753 case MIPS_HFLAG_BL:
2754 case MIPS_HFLAG_B:
2755 ctx->btarget = env->btarget;
2756 break;
2757 }
2758}
2759
2760static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2761{
2762 TCGv_i32 texcp = tcg_const_i32(excp);
2763 TCGv_i32 terr = tcg_const_i32(err);
2764 save_cpu_state(ctx, 1);
2765 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2766 tcg_temp_free_i32(terr);
2767 tcg_temp_free_i32(texcp);
eeb3bba8 2768 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2769}
2770
2771static inline void generate_exception(DisasContext *ctx, int excp)
2772{
eab9944c
LA
2773 gen_helper_0e0i(raise_exception, excp);
2774}
2775
9c708c7f
PD
2776static inline void generate_exception_end(DisasContext *ctx, int excp)
2777{
2778 generate_exception_err(ctx, excp, 0);
2779}
2780
aaa9128a 2781/* Floating point register moves. */
7c979afd 2782static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2783{
7c979afd
LA
2784 if (ctx->hflags & MIPS_HFLAG_FRE) {
2785 generate_exception(ctx, EXCP_RI);
2786 }
ecc7b3aa 2787 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2788}
2789
7c979afd 2790static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2791{
7c979afd
LA
2792 TCGv_i64 t64;
2793 if (ctx->hflags & MIPS_HFLAG_FRE) {
2794 generate_exception(ctx, EXCP_RI);
2795 }
2796 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2797 tcg_gen_extu_i32_i64(t64, t);
2798 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2799 tcg_temp_free_i64(t64);
6d066274
AJ
2800}
2801
7f6613ce 2802static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2803{
7f6613ce 2804 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2805 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2806 } else {
7c979afd 2807 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2808 }
6d066274
AJ
2809}
2810
7f6613ce 2811static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2812{
7f6613ce
PJ
2813 if (ctx->hflags & MIPS_HFLAG_F64) {
2814 TCGv_i64 t64 = tcg_temp_new_i64();
2815 tcg_gen_extu_i32_i64(t64, t);
2816 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2817 tcg_temp_free_i64(t64);
2818 } else {
7c979afd 2819 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2820 }
aa0bf00b 2821}
6ea83fed 2822
d73ee8a2 2823static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2824{
f364515c 2825 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2826 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2827 } else {
d73ee8a2 2828 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2829 }
2830}
6ea83fed 2831
d73ee8a2 2832static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2833{
f364515c 2834 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2835 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2836 } else {
d73ee8a2
RH
2837 TCGv_i64 t0;
2838 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2839 t0 = tcg_temp_new_i64();
6d066274 2840 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2841 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2842 tcg_temp_free_i64(t0);
aa0bf00b
TS
2843 }
2844}
6ea83fed 2845
235785e8 2846static inline int get_fp_bit(int cc)
a16336e4 2847{
1f8929d2 2848 if (cc) {
d94536f4 2849 return 24 + cc;
1f8929d2 2850 } else {
d94536f4 2851 return 23;
1f8929d2 2852 }
a16336e4
TS
2853}
2854
48d38ca5 2855/* Addresses computation */
235785e8
AM
2856static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2857 TCGv arg1)
4ad40f36 2858{
941694d0 2859 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2860
2861#if defined(TARGET_MIPS64)
01f72885 2862 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2863 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2864 }
2865#endif
4ad40f36
FB
2866}
2867
bf0718c5
SM
2868static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2869 target_long ofs)
2870{
2871 tcg_gen_addi_tl(ret, base, ofs);
2872
2873#if defined(TARGET_MIPS64)
2874 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2875 tcg_gen_ext32s_i64(ret, ret);
2876 }
2877#endif
2878}
2879
31837be3
YK
2880/* Addresses computation (translation time) */
2881static target_long addr_add(DisasContext *ctx, target_long base,
2882 target_long offset)
2883{
2884 target_long sum = base + offset;
2885
2886#if defined(TARGET_MIPS64)
2887 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2888 sum = (int32_t)sum;
2889 }
2890#endif
2891 return sum;
2892}
2893
71f303cd 2894/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2895static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2896{
2897#if defined(TARGET_MIPS64)
71f303cd
RH
2898 tcg_gen_ext32s_i64(ret, arg);
2899#else
2900 tcg_gen_extrl_i64_i32(ret, arg);
2901#endif
2902}
2903
2904/* Sign-extract the high 32-bits to a target_long. */
2905static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2906{
2907#if defined(TARGET_MIPS64)
2908 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2909#else
71f303cd 2910 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2911#endif
2912}
2913
356265ae 2914static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2915{
1f8929d2 2916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
c2c65dab 2917 generate_exception_err(ctx, EXCP_CpU, 0);
1f8929d2 2918 }
387a8fe5
TS
2919}
2920
356265ae 2921static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2922{
1f8929d2 2923 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 2924 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 2925 }
5e755519
TS
2926}
2927
7480515f
AM
2928/*
2929 * Verify that the processor is running with COP1X instructions enabled.
2930 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2931 * opcode tables.
2932 */
356265ae 2933static inline void check_cop1x(DisasContext *ctx)
b8aa4598 2934{
1f8929d2 2935 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
9c708c7f 2936 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2937 }
b8aa4598
TS
2938}
2939
7480515f
AM
2940/*
2941 * Verify that the processor is running with 64-bit floating-point
2942 * operations enabled.
2943 */
356265ae 2944static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2945{
1f8929d2 2946 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
9c708c7f 2947 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2948 }
5e755519
TS
2949}
2950
2951/*
2952 * Verify if floating point register is valid; an operation is not defined
2953 * if bit 0 of any register specification is set and the FR bit in the
2954 * Status register equals zero, since the register numbers specify an
2955 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2956 * in the Status register equals one, both even and odd register numbers
2957 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2958 *
2959 * Multiple 64 bit wide registers can be checked by calling
2960 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2961 */
356265ae 2962static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2963{
1f8929d2 2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
9c708c7f 2965 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2966 }
5e755519
TS
2967}
2968
7480515f
AM
2969/*
2970 * Verify that the processor is running with DSP instructions enabled.
2971 * This is enabled by CP0 Status register MX(24) bit.
853c3240 2972 */
853c3240
JL
2973static inline void check_dsp(DisasContext *ctx)
2974{
2975 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2976 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2977 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2978 } else {
9c708c7f 2979 generate_exception_end(ctx, EXCP_RI);
ad153f15 2980 }
853c3240
JL
2981 }
2982}
2983
908f6be1 2984static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2985{
908f6be1 2986 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2987 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2988 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2989 } else {
9c708c7f 2990 generate_exception_end(ctx, EXCP_RI);
ad153f15 2991 }
853c3240
JL
2992 }
2993}
2994
908f6be1 2995static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2996{
908f6be1 2997 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
2998 if (ctx->insn_flags & ASE_DSP) {
2999 generate_exception_end(ctx, EXCP_DSPDIS);
3000 } else {
3001 generate_exception_end(ctx, EXCP_RI);
3002 }
3003 }
3004}
3005
7480515f
AM
3006/*
3007 * This code generates a "reserved instruction" exception if the
3008 * CPU does not support the instruction set corresponding to flags.
3009 */
f9c9cd63 3010static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 3011{
d75c135e 3012 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 3013 generate_exception_end(ctx, EXCP_RI);
d75c135e 3014 }
3a95e3a7
TS
3015}
3016
7480515f
AM
3017/*
3018 * This code generates a "reserved instruction" exception if the
3019 * CPU has corresponding flag set which indicates that the instruction
3020 * has been removed.
3021 */
f9c9cd63 3022static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3023{
3024 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3025 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3026 }
3027}
3028
96631327
FN
3029/*
3030 * The Linux kernel traps certain reserved instruction exceptions to
3031 * emulate the corresponding instructions. QEMU is the kernel in user
3032 * mode, so those traps are emulated by accepting the instructions.
3033 *
3034 * A reserved instruction exception is generated for flagged CPUs if
3035 * QEMU runs in system mode.
3036 */
3037static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3038{
3039#ifndef CONFIG_USER_ONLY
3040 check_insn_opc_removed(ctx, flags);
3041#endif
3042}
3043
7480515f
AM
3044/*
3045 * This code generates a "reserved instruction" exception if the
3046 * CPU does not support 64-bit paired-single (PS) floating point data type.
3047 */
e29c9628
YK
3048static inline void check_ps(DisasContext *ctx)
3049{
3050 if (unlikely(!ctx->ps)) {
3051 generate_exception(ctx, EXCP_RI);
3052 }
3053 check_cp1_64bitmode(ctx);
3054}
3055
c7986fd6 3056#ifdef TARGET_MIPS64
7480515f
AM
3057/*
3058 * This code generates a "reserved instruction" exception if 64-bit
3059 * instructions are not enabled.
3060 */
356265ae 3061static inline void check_mips_64(DisasContext *ctx)
e189e748 3062{
1f8929d2 3063 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
9c708c7f 3064 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3065 }
e189e748 3066}
c7986fd6 3067#endif
e189e748 3068
5204ea79
LA
3069#ifndef CONFIG_USER_ONLY
3070static inline void check_mvh(DisasContext *ctx)
3071{
3072 if (unlikely(!ctx->mvh)) {
3073 generate_exception(ctx, EXCP_RI);
3074 }
3075}
3076#endif
3077
0b16dcd1
AR
3078/*
3079 * This code generates a "reserved instruction" exception if the
3080 * Config5 XNP bit is set.
3081 */
3082static inline void check_xnp(DisasContext *ctx)
3083{
3084 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3085 generate_exception_end(ctx, EXCP_RI);
3086 }
3087}
3088
5e31fdd5
YK
3089#ifndef CONFIG_USER_ONLY
3090/*
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 PW bit is NOT set.
3093 */
3094static inline void check_pw(DisasContext *ctx)
3095{
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3097 generate_exception_end(ctx, EXCP_RI);
3098 }
3099}
3100#endif
3101
9affc1c5
AR
3102/*
3103 * This code generates a "reserved instruction" exception if the
3104 * Config3 MT bit is NOT set.
3105 */
3106static inline void check_mt(DisasContext *ctx)
3107{
3108 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3109 generate_exception_end(ctx, EXCP_RI);
3110 }
3111}
3112
3113#ifndef CONFIG_USER_ONLY
3114/*
3115 * This code generates a "coprocessor unusable" exception if CP0 is not
3116 * available, and, if that is not the case, generates a "reserved instruction"
3117 * exception if the Config5 MT bit is NOT set. This is needed for availability
3118 * control of some of MT ASE instructions.
3119 */
3120static inline void check_cp0_mt(DisasContext *ctx)
3121{
3122 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3123 generate_exception_err(ctx, EXCP_CpU, 0);
3124 } else {
3125 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3126 generate_exception_err(ctx, EXCP_RI, 0);
3127 }
3128 }
3129}
3130#endif
3131
fb32f8c8
DN
3132/*
3133 * This code generates a "reserved instruction" exception if the
3134 * Config5 NMS bit is set.
3135 */
3136static inline void check_nms(DisasContext *ctx)
3137{
3138 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3139 generate_exception_end(ctx, EXCP_RI);
3140 }
3141}
3142
d046a9ea
DN
3143/*
3144 * This code generates a "reserved instruction" exception if the
3145 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3146 * Config2 TL, and Config5 L2C are unset.
3147 */
3148static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3149{
1f8929d2
AM
3150 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3151 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3152 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3153 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3154 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3155 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
d046a9ea
DN
3156 generate_exception_end(ctx, EXCP_RI);
3157 }
3158}
3159
3160/*
3161 * This code generates a "reserved instruction" exception if the
3162 * Config5 EVA bit is NOT set.
3163 */
3164static inline void check_eva(DisasContext *ctx)
3165{
3166 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3167 generate_exception_end(ctx, EXCP_RI);
3168 }
3169}
3170
0b16dcd1 3171
7480515f
AM
3172/*
3173 * Define small wrappers for gen_load_fpr* so that we have a uniform
3174 * calling interface for 32 and 64-bit FPRs. No sense in changing
3175 * all callers for gen_load_fpr32 when we need the CTX parameter for
3176 * this one use.
3177 */
7c979afd 3178#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3179#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3180#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3181static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3182 int ft, int fs, int cc) \
3183{ \
71375b59
AM
3184 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3185 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
3186 switch (ifmt) { \
3187 case FMT_PS: \
e29c9628 3188 check_ps(ctx); \
8153667c
NF
3189 break; \
3190 case FMT_D: \
3191 if (abs) { \
3192 check_cop1x(ctx); \
3193 } \
3194 check_cp1_registers(ctx, fs | ft); \
3195 break; \
3196 case FMT_S: \
3197 if (abs) { \
3198 check_cop1x(ctx); \
3199 } \
3200 break; \
3201 } \
71375b59
AM
3202 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3203 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 3204 switch (n) { \
1f8929d2
AM
3205 case 0: \
3206 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3207 break; \
3208 case 1: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3210 break; \
3211 case 2: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3213 break; \
3214 case 3: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3216 break; \
3217 case 4: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3219 break; \
3220 case 5: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3222 break; \
3223 case 6: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3225 break; \
3226 case 7: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3228 break; \
3229 case 8: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3231 break; \
3232 case 9: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3234 break; \
3235 case 10: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3237 break; \
3238 case 11: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3240 break; \
3241 case 12: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3243 break; \
3244 case 13: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3246 break; \
3247 case 14: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3249 break; \
3250 case 15: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3252 break; \
3253 default: \
3254 abort(); \
8153667c 3255 } \
71375b59
AM
3256 tcg_temp_free_i##bits(fp0); \
3257 tcg_temp_free_i##bits(fp1); \
8153667c
NF
3258}
3259
3260FOP_CONDS(, 0, d, FMT_D, 64)
3261FOP_CONDS(abs, 1, d, FMT_D, 64)
3262FOP_CONDS(, 0, s, FMT_S, 32)
3263FOP_CONDS(abs, 1, s, FMT_S, 32)
3264FOP_CONDS(, 0, ps, FMT_PS, 64)
3265FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3266#undef FOP_CONDS
3f493883
YK
3267
3268#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 3269static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
3270 int ft, int fs, int fd) \
3271{ \
3272 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3273 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3274 if (ifmt == FMT_D) { \
3f493883 3275 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3276 } \
3277 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3278 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3279 switch (n) { \
3280 case 0: \
3281 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 1: \
3284 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 2: \
3287 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 3: \
3290 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 4: \
3293 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 5: \
3296 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 6: \
3299 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 7: \
3302 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 8: \
3305 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 9: \
3308 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 10: \
3311 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 11: \
3314 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 12: \
3317 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 13: \
3320 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 14: \
3323 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 15: \
3326 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 17: \
3329 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 18: \
3332 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 19: \
3335 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 25: \
3338 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 26: \
3341 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 27: \
3344 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 default: \
3347 abort(); \
3348 } \
3349 STORE; \
71375b59
AM
3350 tcg_temp_free_i ## bits(fp0); \
3351 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
3352}
3353
3354FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3355FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3356#undef FOP_CONDNS
8153667c
NF
3357#undef gen_ldcmp_fpr32
3358#undef gen_ldcmp_fpr64
3359
958fb4a9 3360/* load/store instructions. */
e7139c44 3361#ifdef CONFIG_USER_ONLY
71375b59 3362#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3363static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3364 DisasContext *ctx) \
d9bea114
AJ
3365{ \
3366 TCGv t0 = tcg_temp_new(); \
3367 tcg_gen_mov_tl(t0, arg1); \
3368 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
3369 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3370 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3371 tcg_temp_free(t0); \
aaa9128a 3372}
e7139c44 3373#else
71375b59 3374#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3375static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3376 DisasContext *ctx) \
e7139c44 3377{ \
dd4096cd 3378 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3379}
3380#endif
71375b59 3381OP_LD_ATOMIC(ll, ld32s);
aaa9128a 3382#if defined(TARGET_MIPS64)
71375b59 3383OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
3384#endif
3385#undef OP_LD_ATOMIC
3386
235785e8
AM
3387static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3388 int base, int offset)
662d7485
NF
3389{
3390 if (base == 0) {
3391 tcg_gen_movi_tl(addr, offset);
3392 } else if (offset == 0) {
3393 gen_load_gpr(addr, base);
3394 } else {
3395 tcg_gen_movi_tl(addr, offset);
3396 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3397 }
3398}
3399
235785e8 3400static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 3401{
eeb3bba8 3402 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3403
3404 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3405 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3406
3407 pc -= branch_bytes;
3408 }
3409
3410 pc &= ~(target_ulong)3;
3411 return pc;
3412}
3413
5c13fdfd 3414/* Load */
d75c135e 3415static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3416 int rt, int base, int offset)
6af0bf9c 3417{
fc40787a 3418 TCGv t0, t1, t2;
dd4096cd 3419 int mem_idx = ctx->mem_idx;
afa88c3a 3420
d75c135e 3421 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
7480515f
AM
3422 /*
3423 * Loongson CPU uses a load to zero register for prefetch.
3424 * We emulate it as a NOP. On other CPU we must perform the
3425 * actual memory access.
3426 */
afa88c3a
AJ
3427 return;
3428 }
6af0bf9c 3429
afa88c3a 3430 t0 = tcg_temp_new();
662d7485 3431 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3432
6af0bf9c 3433 switch (opc) {
d26bc211 3434#if defined(TARGET_MIPS64)
6e473128 3435 case OPC_LWU:
dd4096cd 3436 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3437 ctx->default_tcg_memop_mask);
78723684 3438 gen_store_gpr(t0, rt);
6e473128 3439 break;
6af0bf9c 3440 case OPC_LD:
dd4096cd 3441 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3442 ctx->default_tcg_memop_mask);
78723684 3443 gen_store_gpr(t0, rt);
6af0bf9c 3444 break;
7a387fff 3445 case OPC_LLD:
bf7910c6 3446 case R6_OPC_LLD:
dd4096cd 3447 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3448 gen_store_gpr(t0, rt);
7a387fff 3449 break;
6af0bf9c 3450 case OPC_LDL:
3cee3050 3451 t1 = tcg_temp_new();
7480515f
AM
3452 /*
3453 * Do a byte access to possibly trigger a page
3454 * fault with the unaligned address.
3455 */
dd4096cd 3456 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3457 tcg_gen_andi_tl(t1, t0, 7);
3458#ifndef TARGET_WORDS_BIGENDIAN
3459 tcg_gen_xori_tl(t1, t1, 7);
3460#endif
3461 tcg_gen_shli_tl(t1, t1, 3);
3462 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3463 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3464 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3465 t2 = tcg_const_tl(-1);
3466 tcg_gen_shl_tl(t2, t2, t1);
78723684 3467 gen_load_gpr(t1, rt);
eb02cc3f 3468 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3469 tcg_temp_free(t2);
3470 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3471 tcg_temp_free(t1);
fc40787a 3472 gen_store_gpr(t0, rt);
6af0bf9c 3473 break;
6af0bf9c 3474 case OPC_LDR:
3cee3050 3475 t1 = tcg_temp_new();
7480515f
AM
3476 /*
3477 * Do a byte access to possibly trigger a page
3478 * fault with the unaligned address.
3479 */
dd4096cd 3480 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3481 tcg_gen_andi_tl(t1, t0, 7);
3482#ifdef TARGET_WORDS_BIGENDIAN
3483 tcg_gen_xori_tl(t1, t1, 7);
3484#endif
3485 tcg_gen_shli_tl(t1, t1, 3);
3486 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3488 tcg_gen_shr_tl(t0, t0, t1);
3489 tcg_gen_xori_tl(t1, t1, 63);
3490 t2 = tcg_const_tl(0xfffffffffffffffeull);
3491 tcg_gen_shl_tl(t2, t2, t1);
78723684 3492 gen_load_gpr(t1, rt);
fc40787a
AJ
3493 tcg_gen_and_tl(t1, t1, t2);
3494 tcg_temp_free(t2);
3495 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3496 tcg_temp_free(t1);
fc40787a 3497 gen_store_gpr(t0, rt);
6af0bf9c 3498 break;
364d4831 3499 case OPC_LDPC:
3cee3050 3500 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3501 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3502 tcg_temp_free(t1);
dd4096cd 3503 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3504 gen_store_gpr(t0, rt);
3505 break;
6af0bf9c 3506#endif
364d4831 3507 case OPC_LWPC:
3cee3050 3508 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3509 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3510 tcg_temp_free(t1);
dd4096cd 3511 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3512 gen_store_gpr(t0, rt);
3513 break;
76964147
JH
3514 case OPC_LWE:
3515 mem_idx = MIPS_HFLAG_UM;
3516 /* fall through */
6af0bf9c 3517 case OPC_LW:
dd4096cd 3518 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3519 ctx->default_tcg_memop_mask);
78723684 3520 gen_store_gpr(t0, rt);
6af0bf9c 3521 break;
76964147
JH
3522 case OPC_LHE:
3523 mem_idx = MIPS_HFLAG_UM;
3524 /* fall through */
6af0bf9c 3525 case OPC_LH:
dd4096cd 3526 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3527 ctx->default_tcg_memop_mask);
78723684 3528 gen_store_gpr(t0, rt);
6af0bf9c 3529 break;
76964147
JH
3530 case OPC_LHUE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
6af0bf9c 3533 case OPC_LHU:
dd4096cd 3534 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3535 ctx->default_tcg_memop_mask);
78723684 3536 gen_store_gpr(t0, rt);
6af0bf9c 3537 break;
76964147
JH
3538 case OPC_LBE:
3539 mem_idx = MIPS_HFLAG_UM;
3540 /* fall through */
6af0bf9c 3541 case OPC_LB:
dd4096cd 3542 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3543 gen_store_gpr(t0, rt);
6af0bf9c 3544 break;
76964147
JH
3545 case OPC_LBUE:
3546 mem_idx = MIPS_HFLAG_UM;
3547 /* fall through */
6af0bf9c 3548 case OPC_LBU:
dd4096cd 3549 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3550 gen_store_gpr(t0, rt);
6af0bf9c 3551 break;
76964147
JH
3552 case OPC_LWLE:
3553 mem_idx = MIPS_HFLAG_UM;
3554 /* fall through */
6af0bf9c 3555 case OPC_LWL:
3cee3050 3556 t1 = tcg_temp_new();
7480515f
AM
3557 /*
3558 * Do a byte access to possibly trigger a page
3559 * fault with the unaligned address.
3560 */
dd4096cd 3561 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3562 tcg_gen_andi_tl(t1, t0, 3);
3563#ifndef TARGET_WORDS_BIGENDIAN
3564 tcg_gen_xori_tl(t1, t1, 3);
3565#endif
3566 tcg_gen_shli_tl(t1, t1, 3);
3567 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3569 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3570 t2 = tcg_const_tl(-1);
3571 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3572 gen_load_gpr(t1, rt);
eb02cc3f 3573 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3574 tcg_temp_free(t2);
3575 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3576 tcg_temp_free(t1);
fc40787a
AJ
3577 tcg_gen_ext32s_tl(t0, t0);
3578 gen_store_gpr(t0, rt);
6af0bf9c 3579 break;
76964147
JH
3580 case OPC_LWRE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
6af0bf9c 3583 case OPC_LWR:
3cee3050 3584 t1 = tcg_temp_new();
7480515f
AM
3585 /*
3586 * Do a byte access to possibly trigger a page
3587 * fault with the unaligned address.
3588 */
dd4096cd 3589 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3590 tcg_gen_andi_tl(t1, t0, 3);
3591#ifdef TARGET_WORDS_BIGENDIAN
3592 tcg_gen_xori_tl(t1, t1, 3);
3593#endif
3594 tcg_gen_shli_tl(t1, t1, 3);
3595 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3596 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3597 tcg_gen_shr_tl(t0, t0, t1);
3598 tcg_gen_xori_tl(t1, t1, 31);
3599 t2 = tcg_const_tl(0xfffffffeull);
3600 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3601 gen_load_gpr(t1, rt);
fc40787a
AJ
3602 tcg_gen_and_tl(t1, t1, t2);
3603 tcg_temp_free(t2);
3604 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3605 tcg_temp_free(t1);
c728154b 3606 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3607 gen_store_gpr(t0, rt);
6af0bf9c 3608 break;
76964147
JH
3609 case OPC_LLE:
3610 mem_idx = MIPS_HFLAG_UM;
3611 /* fall through */
6af0bf9c 3612 case OPC_LL:
4368b29a 3613 case R6_OPC_LL:
dd4096cd 3614 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3615 gen_store_gpr(t0, rt);
6af0bf9c 3616 break;
d66c7132 3617 }
d66c7132 3618 tcg_temp_free(t0);
d66c7132
AJ
3619}
3620
0b16dcd1
AR
3621static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3622 uint32_t reg1, uint32_t reg2)
3623{
3624 TCGv taddr = tcg_temp_new();
3625 TCGv_i64 tval = tcg_temp_new_i64();
3626 TCGv tmp1 = tcg_temp_new();
3627 TCGv tmp2 = tcg_temp_new();
3628
3629 gen_base_offset_addr(ctx, taddr, base, offset);
3630 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3631#ifdef TARGET_WORDS_BIGENDIAN
3632 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3633#else
3634 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3635#endif
3636 gen_store_gpr(tmp1, reg1);
3637 tcg_temp_free(tmp1);
3638 gen_store_gpr(tmp2, reg2);
3639 tcg_temp_free(tmp2);
3640 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3641 tcg_temp_free_i64(tval);
3642 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3643 tcg_temp_free(taddr);
3644}
3645
5c13fdfd 3646/* Store */
235785e8
AM
3647static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3648 int base, int offset)
5c13fdfd 3649{
5c13fdfd
AJ
3650 TCGv t0 = tcg_temp_new();
3651 TCGv t1 = tcg_temp_new();
dd4096cd 3652 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3653
3654 gen_base_offset_addr(ctx, t0, base, offset);
3655 gen_load_gpr(t1, rt);
3656 switch (opc) {
3657#if defined(TARGET_MIPS64)
3658 case OPC_SD:
dd4096cd 3659 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3660 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3661 break;
3662 case OPC_SDL:
dd4096cd 3663 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3664 break;
3665 case OPC_SDR:
dd4096cd 3666 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3667 break;
3668#endif
76964147
JH
3669 case OPC_SWE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
5c13fdfd 3672 case OPC_SW:
dd4096cd 3673 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3674 ctx->default_tcg_memop_mask);
5c13fdfd 3675 break;
76964147
JH
3676 case OPC_SHE:
3677 mem_idx = MIPS_HFLAG_UM;
3678 /* fall through */
5c13fdfd 3679 case OPC_SH:
dd4096cd 3680 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3681 ctx->default_tcg_memop_mask);
5c13fdfd 3682 break;
76964147
JH
3683 case OPC_SBE:
3684 mem_idx = MIPS_HFLAG_UM;
3685 /* fall through */
5c13fdfd 3686 case OPC_SB:
dd4096cd 3687 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3688 break;
76964147
JH
3689 case OPC_SWLE:
3690 mem_idx = MIPS_HFLAG_UM;
3691 /* fall through */
5c13fdfd 3692 case OPC_SWL:
dd4096cd 3693 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3694 break;
76964147
JH
3695 case OPC_SWRE:
3696 mem_idx = MIPS_HFLAG_UM;
3697 /* fall through */
5c13fdfd 3698 case OPC_SWR:
dd4096cd 3699 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3700 break;
3701 }
5c13fdfd
AJ
3702 tcg_temp_free(t0);
3703 tcg_temp_free(t1);
3704}
3705
3706
d66c7132 3707/* Store conditional */
33a07fa2 3708static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 3709 MemOp tcg_mo, bool eva)
d66c7132 3710{
33a07fa2
LA
3711 TCGv addr, t0, val;
3712 TCGLabel *l1 = gen_new_label();
3713 TCGLabel *done = gen_new_label();
d66c7132 3714
2d2826b9 3715 t0 = tcg_temp_new();
33a07fa2
LA
3716 addr = tcg_temp_new();
3717 /* compare the address against that of the preceeding LL */
3718 gen_base_offset_addr(ctx, addr, base, offset);
3719 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3720 tcg_temp_free(addr);
3721 tcg_gen_movi_tl(t0, 0);
3722 gen_store_gpr(t0, rt);
3723 tcg_gen_br(done);
3724
3725 gen_set_label(l1);
3726 /* generate cmpxchg */
3727 val = tcg_temp_new();
3728 gen_load_gpr(val, rt);
3729 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3730 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3731 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3732 gen_store_gpr(t0, rt);
3733 tcg_temp_free(val);
3734
3735 gen_set_label(done);
d66c7132 3736 tcg_temp_free(t0);
6af0bf9c
FB
3737}
3738
33a07fa2 3739
0b16dcd1 3740static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 3741 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
3742{
3743 TCGv taddr = tcg_temp_local_new();
3744 TCGv lladdr = tcg_temp_local_new();
3745 TCGv_i64 tval = tcg_temp_new_i64();
3746 TCGv_i64 llval = tcg_temp_new_i64();
3747 TCGv_i64 val = tcg_temp_new_i64();
3748 TCGv tmp1 = tcg_temp_new();
3749 TCGv tmp2 = tcg_temp_new();
3750 TCGLabel *lab_fail = gen_new_label();
3751 TCGLabel *lab_done = gen_new_label();
3752
3753 gen_base_offset_addr(ctx, taddr, base, offset);
3754
3755 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3756 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3757
3758 gen_load_gpr(tmp1, reg1);
3759 gen_load_gpr(tmp2, reg2);
3760
3761#ifdef TARGET_WORDS_BIGENDIAN
3762 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3763#else
3764 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3765#endif
3766
3767 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3768 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 3769 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
3770 if (reg1 != 0) {
3771 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3772 }
3773 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3774
3775 gen_set_label(lab_fail);
3776
3777 if (reg1 != 0) {
3778 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3779 }
3780 gen_set_label(lab_done);
3781 tcg_gen_movi_tl(lladdr, -1);
3782 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3783}
3784
6ea83fed 3785/* Load and store */
235785e8
AM
3786static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3787 TCGv t0)
6ea83fed 3788{
7480515f
AM
3789 /*
3790 * Don't do NOP if destination is zero: we must perform the actual
3791 * memory access.
3792 */
6ea83fed
FB
3793 switch (opc) {
3794 case OPC_LWC1:
b6d96bed 3795 {
a7812ae4 3796 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3797 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3798 ctx->default_tcg_memop_mask);
7c979afd 3799 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3800 tcg_temp_free_i32(fp0);
b6d96bed 3801 }
6ea83fed
FB
3802 break;
3803 case OPC_SWC1:
b6d96bed 3804 {
a7812ae4 3805 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3806 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3807 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3808 ctx->default_tcg_memop_mask);
a7812ae4 3809 tcg_temp_free_i32(fp0);
b6d96bed 3810 }
6ea83fed
FB
3811 break;
3812 case OPC_LDC1:
b6d96bed 3813 {
a7812ae4 3814 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3815 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3816 ctx->default_tcg_memop_mask);
b6d96bed 3817 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3818 tcg_temp_free_i64(fp0);
b6d96bed 3819 }
6ea83fed
FB
3820 break;
3821 case OPC_SDC1:
b6d96bed 3822 {
a7812ae4 3823 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3824 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3825 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3826 ctx->default_tcg_memop_mask);
a7812ae4 3827 tcg_temp_free_i64(fp0);
b6d96bed 3828 }
6ea83fed
FB
3829 break;
3830 default:
9d68ac14 3831 MIPS_INVAL("flt_ldst");
9c708c7f 3832 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3833 break;
6ea83fed 3834 }
6ea83fed 3835}
6ea83fed 3836
5ab5c041
AJ
3837static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3838 int rs, int16_t imm)
26ebe468 3839{
b52d3bfa
YK
3840 TCGv t0 = tcg_temp_new();
3841
5ab5c041 3842 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3843 check_cp1_enabled(ctx);
d9224450
MR
3844 switch (op) {
3845 case OPC_LDC1:
3846 case OPC_SDC1:
3847 check_insn(ctx, ISA_MIPS2);
3848 /* Fallthrough */
3849 default:
b52d3bfa
YK
3850 gen_base_offset_addr(ctx, t0, rs, imm);
3851 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3852 }
26ebe468
NF
3853 } else {
3854 generate_exception_err(ctx, EXCP_CpU, 1);
3855 }
b52d3bfa 3856 tcg_temp_free(t0);
26ebe468
NF
3857}
3858
6af0bf9c 3859/* Arithmetic with immediate operand */
d75c135e 3860static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3861 int rt, int rs, int imm)
6af0bf9c 3862{
324d9e32 3863 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3864
7a387fff 3865 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
3866 /*
3867 * If no destination, treat it as a NOP.
3868 * For addi, we must generate the overflow exception when needed.
3869 */
324d9e32 3870 return;
6af0bf9c
FB
3871 }
3872 switch (opc) {
3873 case OPC_ADDI:
48d38ca5 3874 {
324d9e32
AJ
3875 TCGv t0 = tcg_temp_local_new();
3876 TCGv t1 = tcg_temp_new();
3877 TCGv t2 = tcg_temp_new();
42a268c2 3878 TCGLabel *l1 = gen_new_label();
48d38ca5 3879
324d9e32
AJ
3880 gen_load_gpr(t1, rs);
3881 tcg_gen_addi_tl(t0, t1, uimm);
3882 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3883
324d9e32
AJ
3884 tcg_gen_xori_tl(t1, t1, ~uimm);
3885 tcg_gen_xori_tl(t2, t0, uimm);
3886 tcg_gen_and_tl(t1, t1, t2);
3887 tcg_temp_free(t2);
3888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3889 tcg_temp_free(t1);
48d38ca5
TS
3890 /* operands of same sign, result different sign */
3891 generate_exception(ctx, EXCP_OVERFLOW);
3892 gen_set_label(l1);
78723684 3893 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3894 gen_store_gpr(t0, rt);
3895 tcg_temp_free(t0);
48d38ca5 3896 }
6af0bf9c
FB
3897 break;
3898 case OPC_ADDIU:
324d9e32
AJ
3899 if (rs != 0) {
3900 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3901 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3902 } else {
3903 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3904 }
6af0bf9c 3905 break;
d26bc211 3906#if defined(TARGET_MIPS64)
7a387fff 3907 case OPC_DADDI:
48d38ca5 3908 {
324d9e32
AJ
3909 TCGv t0 = tcg_temp_local_new();
3910 TCGv t1 = tcg_temp_new();
3911 TCGv t2 = tcg_temp_new();
42a268c2 3912 TCGLabel *l1 = gen_new_label();
48d38ca5 3913
324d9e32
AJ
3914 gen_load_gpr(t1, rs);
3915 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3916
324d9e32
AJ
3917 tcg_gen_xori_tl(t1, t1, ~uimm);
3918 tcg_gen_xori_tl(t2, t0, uimm);
3919 tcg_gen_and_tl(t1, t1, t2);
3920 tcg_temp_free(t2);
3921 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3922 tcg_temp_free(t1);
48d38ca5
TS
3923 /* operands of same sign, result different sign */
3924 generate_exception(ctx, EXCP_OVERFLOW);
3925 gen_set_label(l1);
324d9e32
AJ
3926 gen_store_gpr(t0, rt);
3927 tcg_temp_free(t0);
48d38ca5 3928 }
7a387fff
TS
3929 break;
3930 case OPC_DADDIU:
324d9e32
AJ
3931 if (rs != 0) {
3932 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3933 } else {
3934 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3935 }
7a387fff
TS
3936 break;
3937#endif
324d9e32 3938 }
324d9e32
AJ
3939}
3940
3941/* Logic with immediate operand */
d75c135e 3942static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3943 int rt, int rs, int16_t imm)
324d9e32
AJ
3944{
3945 target_ulong uimm;
324d9e32
AJ
3946
3947 if (rt == 0) {
3948 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3949 return;
3950 }
3951 uimm = (uint16_t)imm;
3952 switch (opc) {
6af0bf9c 3953 case OPC_ANDI:
1f8929d2 3954 if (likely(rs != 0)) {
324d9e32 3955 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3956 } else {
324d9e32 3957 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 3958 }
6af0bf9c
FB
3959 break;
3960 case OPC_ORI:
1f8929d2 3961 if (rs != 0) {
324d9e32 3962 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3963 } else {
324d9e32 3964 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3965 }
6af0bf9c
FB
3966 break;
3967 case OPC_XORI:
1f8929d2 3968 if (likely(rs != 0)) {
324d9e32 3969 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3970 } else {
324d9e32 3971 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 3972 }
6af0bf9c
FB
3973 break;
3974 case OPC_LUI:
d4ea6acd
LA
3975 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3976 /* OPC_AUI */
3977 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3979 } else {
3980 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3981 }
7c2c3ea3
EJ
3982 break;
3983
3984 default:
6af0bf9c 3985 break;
324d9e32 3986 }
324d9e32
AJ
3987}
3988
3989/* Set on less than with immediate operand */
d75c135e 3990static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3991 int rt, int rs, int16_t imm)
324d9e32
AJ
3992{
3993 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3994 TCGv t0;
3995
3996 if (rt == 0) {
3997 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3998 return;
3999 }
4000 t0 = tcg_temp_new();
4001 gen_load_gpr(t0, rs);
4002 switch (opc) {
4003 case OPC_SLTI:
e68dd28f 4004 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4005 break;
4006 case OPC_SLTIU:
e68dd28f 4007 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4008 break;
4009 }
324d9e32
AJ
4010 tcg_temp_free(t0);
4011}
4012
4013/* Shifts with immediate operand */
d75c135e 4014static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
4015 int rt, int rs, int16_t imm)
4016{
4017 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
4018 TCGv t0;
4019
4020 if (rt == 0) {
4021 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4022 return;
4023 }
4024
4025 t0 = tcg_temp_new();
4026 gen_load_gpr(t0, rs);
4027 switch (opc) {
6af0bf9c 4028 case OPC_SLL:
78723684 4029 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 4030 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4031 break;
4032 case OPC_SRA:
324d9e32 4033 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4034 break;
4035 case OPC_SRL:
ea63e2c3
NF
4036 if (uimm != 0) {
4037 tcg_gen_ext32u_tl(t0, t0);
4038 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4039 } else {
4040 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4041 }
ea63e2c3
NF
4042 break;
4043 case OPC_ROTR:
4044 if (uimm != 0) {
4045 TCGv_i32 t1 = tcg_temp_new_i32();
4046
4047 tcg_gen_trunc_tl_i32(t1, t0);
4048 tcg_gen_rotri_i32(t1, t1, uimm);
4049 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4050 tcg_temp_free_i32(t1);
3399e30f
NF
4051 } else {
4052 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4053 }
7a387fff 4054 break;
d26bc211 4055#if defined(TARGET_MIPS64)
7a387fff 4056 case OPC_DSLL:
324d9e32 4057 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4058 break;
4059 case OPC_DSRA:
324d9e32 4060 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4061 break;
4062 case OPC_DSRL:
ea63e2c3 4063 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4064 break;
4065 case OPC_DROTR:
4066 if (uimm != 0) {
4067 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4068 } else {
4069 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4070 }
7a387fff
TS
4071 break;
4072 case OPC_DSLL32:
324d9e32 4073 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4074 break;
4075 case OPC_DSRA32:
324d9e32 4076 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4077 break;
4078 case OPC_DSRL32:
ea63e2c3 4079 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4080 break;
4081 case OPC_DROTR32:
4082 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4083 break;
7a387fff 4084#endif
6af0bf9c 4085 }
78723684 4086 tcg_temp_free(t0);
6af0bf9c
FB
4087}
4088
4089/* Arithmetic */
d75c135e
AJ
4090static void gen_arith(DisasContext *ctx, uint32_t opc,
4091 int rd, int rs, int rt)
6af0bf9c 4092{
7a387fff
TS
4093 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4094 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
4095 /*
4096 * If no destination, treat it as a NOP.
4097 * For add & sub, we must generate the overflow exception when needed.
4098 */
460f00c4 4099 return;
185f0762 4100 }
460f00c4 4101
6af0bf9c
FB
4102 switch (opc) {
4103 case OPC_ADD:
48d38ca5 4104 {
460f00c4
AJ
4105 TCGv t0 = tcg_temp_local_new();
4106 TCGv t1 = tcg_temp_new();
4107 TCGv t2 = tcg_temp_new();
42a268c2 4108 TCGLabel *l1 = gen_new_label();
48d38ca5 4109
460f00c4
AJ
4110 gen_load_gpr(t1, rs);
4111 gen_load_gpr(t2, rt);
4112 tcg_gen_add_tl(t0, t1, t2);
4113 tcg_gen_ext32s_tl(t0, t0);
4114 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4115 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4116 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4117 tcg_temp_free(t2);
4118 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4119 tcg_temp_free(t1);
48d38ca5
TS
4120 /* operands of same sign, result different sign */
4121 generate_exception(ctx, EXCP_OVERFLOW);
4122 gen_set_label(l1);
460f00c4
AJ
4123 gen_store_gpr(t0, rd);
4124 tcg_temp_free(t0);
48d38ca5 4125 }
6af0bf9c
FB
4126 break;
4127 case OPC_ADDU:
460f00c4
AJ
4128 if (rs != 0 && rt != 0) {
4129 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4130 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4131 } else if (rs == 0 && rt != 0) {
4132 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4133 } else if (rs != 0 && rt == 0) {
4134 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4135 } else {
4136 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4137 }
6af0bf9c
FB
4138 break;
4139 case OPC_SUB:
48d38ca5 4140 {
460f00c4
AJ
4141 TCGv t0 = tcg_temp_local_new();
4142 TCGv t1 = tcg_temp_new();
4143 TCGv t2 = tcg_temp_new();
42a268c2 4144 TCGLabel *l1 = gen_new_label();
48d38ca5 4145
460f00c4
AJ
4146 gen_load_gpr(t1, rs);
4147 gen_load_gpr(t2, rt);
4148 tcg_gen_sub_tl(t0, t1, t2);
4149 tcg_gen_ext32s_tl(t0, t0);
4150 tcg_gen_xor_tl(t2, t1, t2);
4151 tcg_gen_xor_tl(t1, t0, t1);
4152 tcg_gen_and_tl(t1, t1, t2);
4153 tcg_temp_free(t2);
4154 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4155 tcg_temp_free(t1);
7480515f
AM
4156 /*
4157 * operands of different sign, first operand and the result
4158 * of different sign
4159 */
48d38ca5
TS
4160 generate_exception(ctx, EXCP_OVERFLOW);
4161 gen_set_label(l1);
460f00c4
AJ
4162 gen_store_gpr(t0, rd);
4163 tcg_temp_free(t0);
48d38ca5 4164 }
6af0bf9c
FB
4165 break;
4166 case OPC_SUBU:
460f00c4
AJ
4167 if (rs != 0 && rt != 0) {
4168 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4169 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4173 } else if (rs != 0 && rt == 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4175 } else {
4176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4177 }
6af0bf9c 4178 break;
d26bc211 4179#if defined(TARGET_MIPS64)
7a387fff 4180 case OPC_DADD:
48d38ca5 4181 {
460f00c4
AJ
4182 TCGv t0 = tcg_temp_local_new();
4183 TCGv t1 = tcg_temp_new();
4184 TCGv t2 = tcg_temp_new();
42a268c2 4185 TCGLabel *l1 = gen_new_label();
48d38ca5 4186
460f00c4
AJ
4187 gen_load_gpr(t1, rs);
4188 gen_load_gpr(t2, rt);
4189 tcg_gen_add_tl(t0, t1, t2);
4190 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4191 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4192 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4193 tcg_temp_free(t2);
4194 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4195 tcg_temp_free(t1);
48d38ca5
TS
4196 /* operands of same sign, result different sign */
4197 generate_exception(ctx, EXCP_OVERFLOW);
4198 gen_set_label(l1);
460f00c4
AJ
4199 gen_store_gpr(t0, rd);
4200 tcg_temp_free(t0);
48d38ca5 4201 }
7a387fff
TS
4202 break;
4203 case OPC_DADDU:
460f00c4
AJ
4204 if (rs != 0 && rt != 0) {
4205 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4206 } else if (rs == 0 && rt != 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4208 } else if (rs != 0 && rt == 0) {
4209 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4210 } else {
4211 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4212 }
7a387fff
TS
4213 break;
4214 case OPC_DSUB:
48d38ca5 4215 {
460f00c4
AJ
4216 TCGv t0 = tcg_temp_local_new();
4217 TCGv t1 = tcg_temp_new();
4218 TCGv t2 = tcg_temp_new();
42a268c2 4219 TCGLabel *l1 = gen_new_label();
48d38ca5 4220
460f00c4
AJ
4221 gen_load_gpr(t1, rs);
4222 gen_load_gpr(t2, rt);
4223 tcg_gen_sub_tl(t0, t1, t2);
4224 tcg_gen_xor_tl(t2, t1, t2);
4225 tcg_gen_xor_tl(t1, t0, t1);
4226 tcg_gen_and_tl(t1, t1, t2);
4227 tcg_temp_free(t2);
4228 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4229 tcg_temp_free(t1);
71375b59
AM
4230 /*
4231 * Operands of different sign, first operand and result different
4232 * sign.
4233 */
48d38ca5
TS
4234 generate_exception(ctx, EXCP_OVERFLOW);
4235 gen_set_label(l1);
460f00c4
AJ
4236 gen_store_gpr(t0, rd);
4237 tcg_temp_free(t0);
48d38ca5 4238 }
7a387fff
TS
4239 break;
4240 case OPC_DSUBU:
460f00c4
AJ
4241 if (rs != 0 && rt != 0) {
4242 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4243 } else if (rs == 0 && rt != 0) {
4244 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4245 } else if (rs != 0 && rt == 0) {
4246 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4247 } else {
4248 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4249 }
7a387fff
TS
4250 break;
4251#endif
460f00c4
AJ
4252 case OPC_MUL:
4253 if (likely(rs != 0 && rt != 0)) {
4254 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4255 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4256 } else {
4257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4258 }
6af0bf9c 4259 break;
460f00c4 4260 }
460f00c4
AJ
4261}
4262
4263/* Conditional move */
d75c135e 4264static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4265 int rd, int rs, int rt)
460f00c4 4266{
acf12465 4267 TCGv t0, t1, t2;
460f00c4
AJ
4268
4269 if (rd == 0) {
acf12465 4270 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4271 return;
4272 }
4273
acf12465
AJ
4274 t0 = tcg_temp_new();
4275 gen_load_gpr(t0, rt);
4276 t1 = tcg_const_tl(0);
4277 t2 = tcg_temp_new();
4278 gen_load_gpr(t2, rs);
460f00c4
AJ
4279 switch (opc) {
4280 case OPC_MOVN:
acf12465 4281 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4282 break;
460f00c4 4283 case OPC_MOVZ:
acf12465 4284 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4285 break;
b691d9d2
LA
4286 case OPC_SELNEZ:
4287 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4288 break;
4289 case OPC_SELEQZ:
4290 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4291 break;
460f00c4 4292 }
acf12465
AJ
4293 tcg_temp_free(t2);
4294 tcg_temp_free(t1);
4295 tcg_temp_free(t0);
460f00c4
AJ
4296}
4297
4298/* Logic */
d75c135e 4299static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4300 int rd, int rs, int rt)
460f00c4 4301{
460f00c4
AJ
4302 if (rd == 0) {
4303 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4304 return;
4305 }
4306
4307 switch (opc) {
6af0bf9c 4308 case OPC_AND:
460f00c4
AJ
4309 if (likely(rs != 0 && rt != 0)) {
4310 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4311 } else {
4312 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4313 }
6af0bf9c
FB
4314 break;
4315 case OPC_NOR:
460f00c4
AJ
4316 if (rs != 0 && rt != 0) {
4317 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4318 } else if (rs == 0 && rt != 0) {
4319 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4320 } else if (rs != 0 && rt == 0) {
4321 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4322 } else {
4323 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4324 }
6af0bf9c
FB
4325 break;
4326 case OPC_OR:
460f00c4
AJ
4327 if (likely(rs != 0 && rt != 0)) {
4328 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4329 } else if (rs == 0 && rt != 0) {
4330 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4331 } else if (rs != 0 && rt == 0) {
4332 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4333 } else {
4334 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4335 }
6af0bf9c
FB
4336 break;
4337 case OPC_XOR:
460f00c4
AJ
4338 if (likely(rs != 0 && rt != 0)) {
4339 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4340 } else if (rs == 0 && rt != 0) {
4341 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4342 } else if (rs != 0 && rt == 0) {
4343 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4344 } else {
4345 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4346 }
6af0bf9c 4347 break;
460f00c4 4348 }
460f00c4
AJ
4349}
4350
4351/* Set on lower than */
d75c135e 4352static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4353 int rd, int rs, int rt)
460f00c4 4354{
460f00c4
AJ
4355 TCGv t0, t1;
4356
4357 if (rd == 0) {
4358 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4359 return;
4360 }
4361
4362 t0 = tcg_temp_new();
4363 t1 = tcg_temp_new();
4364 gen_load_gpr(t0, rs);
4365 gen_load_gpr(t1, rt);
4366 switch (opc) {
4367 case OPC_SLT:
e68dd28f 4368 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4369 break;
460f00c4 4370 case OPC_SLTU:
e68dd28f 4371 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4372 break;
4373 }
460f00c4
AJ
4374 tcg_temp_free(t0);
4375 tcg_temp_free(t1);
4376}
20c4c97c 4377
460f00c4 4378/* Shifts */
d75c135e
AJ
4379static void gen_shift(DisasContext *ctx, uint32_t opc,
4380 int rd, int rs, int rt)
460f00c4 4381{
460f00c4 4382 TCGv t0, t1;
20c4c97c 4383
460f00c4 4384 if (rd == 0) {
7480515f
AM
4385 /*
4386 * If no destination, treat it as a NOP.
4387 * For add & sub, we must generate the overflow exception when needed.
4388 */
460f00c4
AJ
4389 return;
4390 }
4391
4392 t0 = tcg_temp_new();
4393 t1 = tcg_temp_new();
4394 gen_load_gpr(t0, rs);
4395 gen_load_gpr(t1, rt);
4396 switch (opc) {
6af0bf9c 4397 case OPC_SLLV:
78723684
TS
4398 tcg_gen_andi_tl(t0, t0, 0x1f);
4399 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4400 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4401 break;
4402 case OPC_SRAV:
78723684 4403 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4404 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4405 break;
4406 case OPC_SRLV:
ea63e2c3
NF
4407 tcg_gen_ext32u_tl(t1, t1);
4408 tcg_gen_andi_tl(t0, t0, 0x1f);
4409 tcg_gen_shr_tl(t0, t1, t0);
4410 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4411 break;
4412 case OPC_ROTRV:
4413 {
4414 TCGv_i32 t2 = tcg_temp_new_i32();
4415 TCGv_i32 t3 = tcg_temp_new_i32();
4416
4417 tcg_gen_trunc_tl_i32(t2, t0);
4418 tcg_gen_trunc_tl_i32(t3, t1);
4419 tcg_gen_andi_i32(t2, t2, 0x1f);
4420 tcg_gen_rotr_i32(t2, t3, t2);
4421 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4422 tcg_temp_free_i32(t2);
4423 tcg_temp_free_i32(t3);
5a63bcb2 4424 }
7a387fff 4425 break;
d26bc211 4426#if defined(TARGET_MIPS64)
7a387fff 4427 case OPC_DSLLV:
78723684 4428 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4429 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4430 break;
4431 case OPC_DSRAV:
78723684 4432 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4433 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4434 break;
4435 case OPC_DSRLV:
ea63e2c3
NF
4436 tcg_gen_andi_tl(t0, t0, 0x3f);
4437 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4438 break;
4439 case OPC_DROTRV:
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4442 break;
7a387fff 4443#endif
6af0bf9c 4444 }
78723684
TS
4445 tcg_temp_free(t0);
4446 tcg_temp_free(t1);
6af0bf9c
FB
4447}
4448
37b9aae2 4449#if defined(TARGET_MIPS64)
86efbfb6
FN
4450/* Copy GPR to and from TX79 HI1/LO1 register. */
4451static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4452{
baa609db 4453 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4454 /* Treat as NOP. */
4455 return;
4456 }
4457
4458 switch (opc) {
baa609db 4459 case MMI_OPC_MFHI1:
86efbfb6
FN
4460 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4461 break;
baa609db 4462 case MMI_OPC_MFLO1:
86efbfb6
FN
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4464 break;
baa609db 4465 case MMI_OPC_MTHI1:
86efbfb6
FN
4466 if (reg != 0) {
4467 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4468 } else {
4469 tcg_gen_movi_tl(cpu_HI[1], 0);
4470 }
4471 break;
baa609db 4472 case MMI_OPC_MTLO1:
86efbfb6
FN
4473 if (reg != 0) {
4474 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4475 } else {
4476 tcg_gen_movi_tl(cpu_LO[1], 0);
4477 }
4478 break;
4479 default:
4480 MIPS_INVAL("mfthilo1 TX79");
4481 generate_exception_end(ctx, EXCP_RI);
4482 break;
4483 }
4484}
37b9aae2 4485#endif
86efbfb6 4486
6af0bf9c 4487/* Arithmetic on HI/LO registers */
26135ead 4488static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4489{
86efbfb6 4490 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4491 /* Treat as NOP. */
a1f6684d 4492 return;
6af0bf9c 4493 }
4133498f 4494
4133498f 4495 if (acc != 0) {
86efbfb6 4496 check_dsp(ctx);
4133498f
JL
4497 }
4498
6af0bf9c
FB
4499 switch (opc) {
4500 case OPC_MFHI:
4133498f
JL
4501#if defined(TARGET_MIPS64)
4502 if (acc != 0) {
4503 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4504 } else
4505#endif
4506 {
4507 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4508 }
6af0bf9c
FB
4509 break;
4510 case OPC_MFLO:
4133498f
JL
4511#if defined(TARGET_MIPS64)
4512 if (acc != 0) {
4513 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4514 } else
4515#endif
4516 {
4517 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4518 }
6af0bf9c
FB
4519 break;
4520 case OPC_MTHI:
4133498f
JL
4521 if (reg != 0) {
4522#if defined(TARGET_MIPS64)
4523 if (acc != 0) {
4524 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4525 } else
4526#endif
4527 {
4528 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4529 }
4530 } else {
4531 tcg_gen_movi_tl(cpu_HI[acc], 0);
4532 }
6af0bf9c
FB
4533 break;
4534 case OPC_MTLO:
4133498f
JL
4535 if (reg != 0) {
4536#if defined(TARGET_MIPS64)
4537 if (acc != 0) {
4538 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4539 } else
4540#endif
4541 {
4542 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4543 }
4544 } else {
4545 tcg_gen_movi_tl(cpu_LO[acc], 0);
4546 }
6af0bf9c 4547 break;
6af0bf9c 4548 }
6af0bf9c
FB
4549}
4550
d4ea6acd 4551static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 4552 MemOp memop)
d4ea6acd
LA
4553{
4554 TCGv t0 = tcg_const_tl(addr);
4555 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4556 gen_store_gpr(t0, reg);
4557 tcg_temp_free(t0);
4558}
4559
ab39ee45
YK
4560static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4561 int rs)
d4ea6acd
LA
4562{
4563 target_long offset;
4564 target_long addr;
4565
ab39ee45 4566 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4567 case OPC_ADDIUPC:
4568 if (rs != 0) {
4569 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4570 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4571 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4572 }
4573 break;
4574 case R6_OPC_LWPC:
4575 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4576 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4577 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4578 break;
4579#if defined(TARGET_MIPS64)
4580 case OPC_LWUPC:
4581 check_mips_64(ctx);
4582 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4583 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4584 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4585 break;
4586#endif
4587 default:
ab39ee45 4588 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4589 case OPC_AUIPC:
4590 if (rs != 0) {
ab39ee45
YK
4591 offset = sextract32(ctx->opcode, 0, 16) << 16;
4592 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4593 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4594 }
4595 break;
4596 case OPC_ALUIPC:
4597 if (rs != 0) {
ab39ee45
YK
4598 offset = sextract32(ctx->opcode, 0, 16) << 16;
4599 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4600 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4601 }
4602 break;
4603#if defined(TARGET_MIPS64)
4604 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4605 case R6_OPC_LDPC + (1 << 16):
4606 case R6_OPC_LDPC + (2 << 16):
4607 case R6_OPC_LDPC + (3 << 16):
4608 check_mips_64(ctx);
4609 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4610 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4611 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4612 break;
4613#endif
4614 default:
4615 MIPS_INVAL("OPC_PCREL");
9c708c7f 4616 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4617 break;
4618 }
4619 break;
4620 }
4621}
4622
b42ee5e1
LA
4623static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4624{
b42ee5e1
LA
4625 TCGv t0, t1;
4626
4627 if (rd == 0) {
4628 /* Treat as NOP. */
b42ee5e1
LA
4629 return;
4630 }
4631
4632 t0 = tcg_temp_new();
4633 t1 = tcg_temp_new();
4634
4635 gen_load_gpr(t0, rs);
4636 gen_load_gpr(t1, rt);
4637
4638 switch (opc) {
4639 case R6_OPC_DIV:
4640 {
4641 TCGv t2 = tcg_temp_new();
4642 TCGv t3 = tcg_temp_new();
4643 tcg_gen_ext32s_tl(t0, t0);
4644 tcg_gen_ext32s_tl(t1, t1);
4645 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4646 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4647 tcg_gen_and_tl(t2, t2, t3);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4649 tcg_gen_or_tl(t2, t2, t3);
4650 tcg_gen_movi_tl(t3, 0);
4651 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4652 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4653 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4654 tcg_temp_free(t3);
4655 tcg_temp_free(t2);
4656 }
b42ee5e1
LA
4657 break;
4658 case R6_OPC_MOD:
4659 {
4660 TCGv t2 = tcg_temp_new();
4661 TCGv t3 = tcg_temp_new();
4662 tcg_gen_ext32s_tl(t0, t0);
4663 tcg_gen_ext32s_tl(t1, t1);
4664 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4665 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4666 tcg_gen_and_tl(t2, t2, t3);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4668 tcg_gen_or_tl(t2, t2, t3);
4669 tcg_gen_movi_tl(t3, 0);
4670 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4671 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4672 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4673 tcg_temp_free(t3);
4674 tcg_temp_free(t2);
4675 }
b42ee5e1
LA
4676 break;
4677 case R6_OPC_DIVU:
4678 {
4679 TCGv t2 = tcg_const_tl(0);
4680 TCGv t3 = tcg_const_tl(1);
4681 tcg_gen_ext32u_tl(t0, t0);
4682 tcg_gen_ext32u_tl(t1, t1);
4683 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4684 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4685 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4686 tcg_temp_free(t3);
4687 tcg_temp_free(t2);
4688 }
b42ee5e1
LA
4689 break;
4690 case R6_OPC_MODU:
4691 {
4692 TCGv t2 = tcg_const_tl(0);
4693 TCGv t3 = tcg_const_tl(1);
4694 tcg_gen_ext32u_tl(t0, t0);
4695 tcg_gen_ext32u_tl(t1, t1);
4696 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4697 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4698 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4699 tcg_temp_free(t3);
4700 tcg_temp_free(t2);
4701 }
b42ee5e1
LA
4702 break;
4703 case R6_OPC_MUL:
4704 {
4705 TCGv_i32 t2 = tcg_temp_new_i32();
4706 TCGv_i32 t3 = tcg_temp_new_i32();
4707 tcg_gen_trunc_tl_i32(t2, t0);
4708 tcg_gen_trunc_tl_i32(t3, t1);
4709 tcg_gen_mul_i32(t2, t2, t3);
4710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4711 tcg_temp_free_i32(t2);
4712 tcg_temp_free_i32(t3);
4713 }
b42ee5e1
LA
4714 break;
4715 case R6_OPC_MUH:
4716 {
4717 TCGv_i32 t2 = tcg_temp_new_i32();
4718 TCGv_i32 t3 = tcg_temp_new_i32();
4719 tcg_gen_trunc_tl_i32(t2, t0);
4720 tcg_gen_trunc_tl_i32(t3, t1);
4721 tcg_gen_muls2_i32(t2, t3, t2, t3);
4722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4725 }
b42ee5e1
LA
4726 break;
4727 case R6_OPC_MULU:
4728 {
4729 TCGv_i32 t2 = tcg_temp_new_i32();
4730 TCGv_i32 t3 = tcg_temp_new_i32();
4731 tcg_gen_trunc_tl_i32(t2, t0);
4732 tcg_gen_trunc_tl_i32(t3, t1);
4733 tcg_gen_mul_i32(t2, t2, t3);
4734 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4735 tcg_temp_free_i32(t2);
4736 tcg_temp_free_i32(t3);
4737 }
b42ee5e1
LA
4738 break;
4739 case R6_OPC_MUHU:
4740 {
4741 TCGv_i32 t2 = tcg_temp_new_i32();
4742 TCGv_i32 t3 = tcg_temp_new_i32();
4743 tcg_gen_trunc_tl_i32(t2, t0);
4744 tcg_gen_trunc_tl_i32(t3, t1);
4745 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4746 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4747 tcg_temp_free_i32(t2);
4748 tcg_temp_free_i32(t3);
4749 }
b42ee5e1
LA
4750 break;
4751#if defined(TARGET_MIPS64)
4752 case R6_OPC_DDIV:
4753 {
4754 TCGv t2 = tcg_temp_new();
4755 TCGv t3 = tcg_temp_new();
4756 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4757 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4758 tcg_gen_and_tl(t2, t2, t3);
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4760 tcg_gen_or_tl(t2, t2, t3);
4761 tcg_gen_movi_tl(t3, 0);
4762 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4763 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4764 tcg_temp_free(t3);
4765 tcg_temp_free(t2);
4766 }
b42ee5e1
LA
4767 break;
4768 case R6_OPC_DMOD:
4769 {
4770 TCGv t2 = tcg_temp_new();
4771 TCGv t3 = tcg_temp_new();
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4774 tcg_gen_and_tl(t2, t2, t3);
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4776 tcg_gen_or_tl(t2, t2, t3);
4777 tcg_gen_movi_tl(t3, 0);
4778 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4779 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4782 }
b42ee5e1
LA
4783 break;
4784 case R6_OPC_DDIVU:
4785 {
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4789 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4790 tcg_temp_free(t3);
4791 tcg_temp_free(t2);
4792 }
b42ee5e1
LA
4793 break;
4794 case R6_OPC_DMODU:
4795 {
4796 TCGv t2 = tcg_const_tl(0);
4797 TCGv t3 = tcg_const_tl(1);
4798 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4799 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4800 tcg_temp_free(t3);
4801 tcg_temp_free(t2);
4802 }
b42ee5e1
LA
4803 break;
4804 case R6_OPC_DMUL:
4805 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4806 break;
4807 case R6_OPC_DMUH:
4808 {
4809 TCGv t2 = tcg_temp_new();
4810 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4811 tcg_temp_free(t2);
4812 }
b42ee5e1
LA
4813 break;
4814 case R6_OPC_DMULU:
4815 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4816 break;
4817 case R6_OPC_DMUHU:
4818 {
4819 TCGv t2 = tcg_temp_new();
4820 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4821 tcg_temp_free(t2);
4822 }
b42ee5e1
LA
4823 break;
4824#endif
4825 default:
9d68ac14 4826 MIPS_INVAL("r6 mul/div");
9c708c7f 4827 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4828 goto out;
4829 }
b42ee5e1
LA
4830 out:
4831 tcg_temp_free(t0);
4832 tcg_temp_free(t1);
4833}
4834
37b9aae2 4835#if defined(TARGET_MIPS64)
c42171c3
FN
4836static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4837{
4838 TCGv t0, t1;
4839
4840 t0 = tcg_temp_new();
4841 t1 = tcg_temp_new();
4842
4843 gen_load_gpr(t0, rs);
4844 gen_load_gpr(t1, rt);
4845
4846 switch (opc) {
baa609db 4847 case MMI_OPC_DIV1:
c42171c3
FN
4848 {
4849 TCGv t2 = tcg_temp_new();
4850 TCGv t3 = tcg_temp_new();
4851 tcg_gen_ext32s_tl(t0, t0);
4852 tcg_gen_ext32s_tl(t1, t1);
4853 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4854 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4855 tcg_gen_and_tl(t2, t2, t3);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4857 tcg_gen_or_tl(t2, t2, t3);
4858 tcg_gen_movi_tl(t3, 0);
4859 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4860 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4861 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4862 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4863 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4864 tcg_temp_free(t3);
4865 tcg_temp_free(t2);
4866 }
4867 break;
baa609db 4868 case MMI_OPC_DIVU1:
c42171c3
FN
4869 {
4870 TCGv t2 = tcg_const_tl(0);
4871 TCGv t3 = tcg_const_tl(1);
4872 tcg_gen_ext32u_tl(t0, t0);
4873 tcg_gen_ext32u_tl(t1, t1);
4874 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4875 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4876 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4877 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4878 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4879 tcg_temp_free(t3);
4880 tcg_temp_free(t2);
4881 }
4882 break;
4883 default:
4884 MIPS_INVAL("div1 TX79");
4885 generate_exception_end(ctx, EXCP_RI);
4886 goto out;
4887 }
4888 out:
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4891}
37b9aae2 4892#endif
c42171c3 4893
26135ead
RS
4894static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4895 int acc, int rs, int rt)
6af0bf9c 4896{
d45f89f4
AJ
4897 TCGv t0, t1;
4898
51127181
AJ
4899 t0 = tcg_temp_new();
4900 t1 = tcg_temp_new();
6af0bf9c 4901
78723684
TS
4902 gen_load_gpr(t0, rs);
4903 gen_load_gpr(t1, rt);
51127181 4904
26135ead 4905 if (acc != 0) {
c42171c3 4906 check_dsp(ctx);
26135ead
RS
4907 }
4908
6af0bf9c
FB
4909 switch (opc) {
4910 case OPC_DIV:
48d38ca5 4911 {
51127181
AJ
4912 TCGv t2 = tcg_temp_new();
4913 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4914 tcg_gen_ext32s_tl(t0, t0);
4915 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4916 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4917 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4918 tcg_gen_and_tl(t2, t2, t3);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4920 tcg_gen_or_tl(t2, t2, t3);
4921 tcg_gen_movi_tl(t3, 0);
4922 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4923 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4924 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4925 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4926 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4927 tcg_temp_free(t3);
4928 tcg_temp_free(t2);
48d38ca5 4929 }
6af0bf9c
FB
4930 break;
4931 case OPC_DIVU:
48d38ca5 4932 {
51127181
AJ
4933 TCGv t2 = tcg_const_tl(0);
4934 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4935 tcg_gen_ext32u_tl(t0, t0);
4936 tcg_gen_ext32u_tl(t1, t1);
51127181 4937 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4938 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4939 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4940 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4941 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4942 tcg_temp_free(t3);
4943 tcg_temp_free(t2);
48d38ca5 4944 }
6af0bf9c
FB
4945 break;
4946 case OPC_MULT:
214c465f 4947 {
ce1dd5d1
RH
4948 TCGv_i32 t2 = tcg_temp_new_i32();
4949 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4950 tcg_gen_trunc_tl_i32(t2, t0);
4951 tcg_gen_trunc_tl_i32(t3, t1);
4952 tcg_gen_muls2_i32(t2, t3, t2, t3);
4953 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4954 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4955 tcg_temp_free_i32(t2);
4956 tcg_temp_free_i32(t3);
214c465f 4957 }
6af0bf9c
FB
4958 break;
4959 case OPC_MULTU:
214c465f 4960 {
ce1dd5d1
RH
4961 TCGv_i32 t2 = tcg_temp_new_i32();
4962 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4963 tcg_gen_trunc_tl_i32(t2, t0);
4964 tcg_gen_trunc_tl_i32(t3, t1);
4965 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4966 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4967 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4968 tcg_temp_free_i32(t2);
4969 tcg_temp_free_i32(t3);
214c465f 4970 }
6af0bf9c 4971 break;
d26bc211 4972#if defined(TARGET_MIPS64)
7a387fff 4973 case OPC_DDIV:
48d38ca5 4974 {
51127181
AJ
4975 TCGv t2 = tcg_temp_new();
4976 TCGv t3 = tcg_temp_new();
4977 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4978 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4979 tcg_gen_and_tl(t2, t2, t3);
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4981 tcg_gen_or_tl(t2, t2, t3);
4982 tcg_gen_movi_tl(t3, 0);
4983 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4984 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4985 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4986 tcg_temp_free(t3);
4987 tcg_temp_free(t2);
48d38ca5 4988 }
7a387fff
TS
4989 break;
4990 case OPC_DDIVU:
48d38ca5 4991 {
51127181
AJ
4992 TCGv t2 = tcg_const_tl(0);
4993 TCGv t3 = tcg_const_tl(1);
4994 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4995 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4996 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
4997 tcg_temp_free(t3);
4998 tcg_temp_free(t2);
48d38ca5 4999 }
7a387fff
TS
5000 break;
5001 case OPC_DMULT:
26135ead 5002 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5003 break;
5004 case OPC_DMULTU:
26135ead 5005 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5006 break;
5007#endif
6af0bf9c 5008 case OPC_MADD:
214c465f 5009 {
d45f89f4
AJ
5010 TCGv_i64 t2 = tcg_temp_new_i64();
5011 TCGv_i64 t3 = tcg_temp_new_i64();
5012
5013 tcg_gen_ext_tl_i64(t2, t0);
5014 tcg_gen_ext_tl_i64(t3, t1);
5015 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5016 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5017 tcg_gen_add_i64(t2, t2, t3);
5018 tcg_temp_free_i64(t3);
71f303cd
RH
5019 gen_move_low32(cpu_LO[acc], t2);
5020 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5021 tcg_temp_free_i64(t2);
214c465f 5022 }
6af0bf9c
FB
5023 break;
5024 case OPC_MADDU:
4133498f 5025 {
d45f89f4
AJ
5026 TCGv_i64 t2 = tcg_temp_new_i64();
5027 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5028
78723684
TS
5029 tcg_gen_ext32u_tl(t0, t0);
5030 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5031 tcg_gen_extu_tl_i64(t2, t0);
5032 tcg_gen_extu_tl_i64(t3, t1);
5033 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5034 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5035 tcg_gen_add_i64(t2, t2, t3);
5036 tcg_temp_free_i64(t3);
71f303cd
RH
5037 gen_move_low32(cpu_LO[acc], t2);
5038 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5039 tcg_temp_free_i64(t2);
214c465f 5040 }
6af0bf9c
FB
5041 break;
5042 case OPC_MSUB:
214c465f 5043 {
d45f89f4
AJ
5044 TCGv_i64 t2 = tcg_temp_new_i64();
5045 TCGv_i64 t3 = tcg_temp_new_i64();
5046
5047 tcg_gen_ext_tl_i64(t2, t0);
5048 tcg_gen_ext_tl_i64(t3, t1);
5049 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5050 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5051 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5052 tcg_temp_free_i64(t3);
71f303cd
RH
5053 gen_move_low32(cpu_LO[acc], t2);
5054 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5055 tcg_temp_free_i64(t2);
214c465f 5056 }
6af0bf9c
FB
5057 break;
5058 case OPC_MSUBU:
214c465f 5059 {
d45f89f4
AJ
5060 TCGv_i64 t2 = tcg_temp_new_i64();
5061 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5062
78723684
TS
5063 tcg_gen_ext32u_tl(t0, t0);
5064 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5065 tcg_gen_extu_tl_i64(t2, t0);
5066 tcg_gen_extu_tl_i64(t3, t1);
5067 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5068 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5069 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5070 tcg_temp_free_i64(t3);
71f303cd
RH
5071 gen_move_low32(cpu_LO[acc], t2);
5072 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5073 tcg_temp_free_i64(t2);
214c465f 5074 }
6af0bf9c
FB
5075 break;
5076 default:
9d68ac14 5077 MIPS_INVAL("mul/div");
9c708c7f 5078 generate_exception_end(ctx, EXCP_RI);
78723684 5079 goto out;
6af0bf9c 5080 }
78723684
TS
5081 out:
5082 tcg_temp_free(t0);
5083 tcg_temp_free(t1);
6af0bf9c
FB
5084}
5085
21e8e8b2 5086/*
3b948f05
PMD
5087 * These MULT[U] and MADD[U] instructions implemented in for example
5088 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5089 * architectures are special three-operand variants with the syntax
5090 *
06de726b 5091 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5092 *
5093 * such that
5094 *
5095 * (rd, LO, HI) <- rs * rt
5096 *
3b948f05
PMD
5097 * and
5098 *
a95c4c26 5099 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5100 *
5101 * such that
5102 *
5103 * (rd, LO, HI) <- (LO, HI) + rs * rt
5104 *
21e8e8b2
FN
5105 * where the low-order 32-bits of the result is placed into both the
5106 * GPR rd and the special register LO. The high-order 32-bits of the
5107 * result is placed into the special register HI.
5108 *
5109 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5110 * which is the zero register that always reads as 0.
5111 */
5112static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5113 int rd, int rs, int rt)
5114{
5115 TCGv t0 = tcg_temp_new();
5116 TCGv t1 = tcg_temp_new();
5117 int acc = 0;
5118
5119 gen_load_gpr(t0, rs);
5120 gen_load_gpr(t1, rt);
5121
5122 switch (opc) {
baa609db 5123 case MMI_OPC_MULT1:
06de726b
FN
5124 acc = 1;
5125 /* Fall through */
21e8e8b2
FN
5126 case OPC_MULT:
5127 {
5128 TCGv_i32 t2 = tcg_temp_new_i32();
5129 TCGv_i32 t3 = tcg_temp_new_i32();
5130 tcg_gen_trunc_tl_i32(t2, t0);
5131 tcg_gen_trunc_tl_i32(t3, t1);
5132 tcg_gen_muls2_i32(t2, t3, t2, t3);
5133 if (rd) {
5134 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5135 }
5136 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5137 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5138 tcg_temp_free_i32(t2);
5139 tcg_temp_free_i32(t3);
5140 }
5141 break;
baa609db 5142 case MMI_OPC_MULTU1:
06de726b
FN
5143 acc = 1;
5144 /* Fall through */
21e8e8b2
FN
5145 case OPC_MULTU:
5146 {
5147 TCGv_i32 t2 = tcg_temp_new_i32();
5148 TCGv_i32 t3 = tcg_temp_new_i32();
5149 tcg_gen_trunc_tl_i32(t2, t0);
5150 tcg_gen_trunc_tl_i32(t3, t1);
5151 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5152 if (rd) {
5153 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5154 }
5155 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5156 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5157 tcg_temp_free_i32(t2);
5158 tcg_temp_free_i32(t3);
5159 }
5160 break;
a95c4c26
FN
5161 case MMI_OPC_MADD1:
5162 acc = 1;
5163 /* Fall through */
3b948f05
PMD
5164 case MMI_OPC_MADD:
5165 {
5166 TCGv_i64 t2 = tcg_temp_new_i64();
5167 TCGv_i64 t3 = tcg_temp_new_i64();
5168
5169 tcg_gen_ext_tl_i64(t2, t0);
5170 tcg_gen_ext_tl_i64(t3, t1);
5171 tcg_gen_mul_i64(t2, t2, t3);
5172 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5173 tcg_gen_add_i64(t2, t2, t3);
5174 tcg_temp_free_i64(t3);
5175 gen_move_low32(cpu_LO[acc], t2);
5176 gen_move_high32(cpu_HI[acc], t2);
5177 if (rd) {
5178 gen_move_low32(cpu_gpr[rd], t2);
5179 }
5180 tcg_temp_free_i64(t2);
5181 }
5182 break;
a95c4c26
FN
5183 case MMI_OPC_MADDU1:
5184 acc = 1;
5185 /* Fall through */
3b948f05
PMD
5186 case MMI_OPC_MADDU:
5187 {
5188 TCGv_i64 t2 = tcg_temp_new_i64();
5189 TCGv_i64 t3 = tcg_temp_new_i64();
5190
5191 tcg_gen_ext32u_tl(t0, t0);
5192 tcg_gen_ext32u_tl(t1, t1);
5193 tcg_gen_extu_tl_i64(t2, t0);
5194 tcg_gen_extu_tl_i64(t3, t1);
5195 tcg_gen_mul_i64(t2, t2, t3);
5196 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5197 tcg_gen_add_i64(t2, t2, t3);
5198 tcg_temp_free_i64(t3);
5199 gen_move_low32(cpu_LO[acc], t2);
5200 gen_move_high32(cpu_HI[acc], t2);
5201 if (rd) {
5202 gen_move_low32(cpu_gpr[rd], t2);
5203 }
5204 tcg_temp_free_i64(t2);
5205 }
5206 break;
21e8e8b2 5207 default:
3b948f05 5208 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5209 generate_exception_end(ctx, EXCP_RI);
5210 goto out;
5211 }
5212
5213 out:
5214 tcg_temp_free(t0);
5215 tcg_temp_free(t1);
5216}
5217
235785e8
AM
5218static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5219 int rd, int rs, int rt)
e9c71dd1 5220{
f157bfe1
AJ
5221 TCGv t0 = tcg_temp_new();
5222 TCGv t1 = tcg_temp_new();
e9c71dd1 5223
6c5c1e20
TS
5224 gen_load_gpr(t0, rs);
5225 gen_load_gpr(t1, rt);
e9c71dd1
TS
5226
5227 switch (opc) {
5228 case OPC_VR54XX_MULS:
895c2d04 5229 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5230 break;
e9c71dd1 5231 case OPC_VR54XX_MULSU:
895c2d04 5232 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5233 break;
e9c71dd1 5234 case OPC_VR54XX_MACC:
895c2d04 5235 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5236 break;
e9c71dd1 5237 case OPC_VR54XX_MACCU:
895c2d04 5238 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5239 break;
e9c71dd1 5240 case OPC_VR54XX_MSAC:
895c2d04 5241 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5242 break;
e9c71dd1 5243 case OPC_VR54XX_MSACU:
895c2d04 5244 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5245 break;
e9c71dd1 5246 case OPC_VR54XX_MULHI:
895c2d04 5247 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5248 break;
e9c71dd1 5249 case OPC_VR54XX_MULHIU:
895c2d04 5250 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5251 break;
e9c71dd1 5252 case OPC_VR54XX_MULSHI:
895c2d04 5253 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5254 break;
e9c71dd1 5255 case OPC_VR54XX_MULSHIU:
895c2d04 5256 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5257 break;
e9c71dd1 5258 case OPC_VR54XX_MACCHI:
895c2d04 5259 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5260 break;
e9c71dd1 5261 case OPC_VR54XX_MACCHIU:
895c2d04 5262 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5263 break;
e9c71dd1 5264 case OPC_VR54XX_MSACHI:
895c2d04 5265 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5266 break;
e9c71dd1 5267 case OPC_VR54XX_MSACHIU:
895c2d04 5268 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5269 break;
e9c71dd1
TS
5270 default:
5271 MIPS_INVAL("mul vr54xx");
9c708c7f 5272 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5273 goto out;
e9c71dd1 5274 }
6c5c1e20 5275 gen_store_gpr(t0, rd);
6c5c1e20
TS
5276
5277 out:
5278 tcg_temp_free(t0);
5279 tcg_temp_free(t1);
e9c71dd1
TS
5280}
5281
235785e8
AM
5282static void gen_cl(DisasContext *ctx, uint32_t opc,
5283 int rd, int rs)
6af0bf9c 5284{
20e1fb52 5285 TCGv t0;
6c5c1e20 5286
6af0bf9c 5287 if (rd == 0) {
ead9360e 5288 /* Treat as NOP. */
20e1fb52 5289 return;
6af0bf9c 5290 }
1a0196c5 5291 t0 = cpu_gpr[rd];
6c5c1e20 5292 gen_load_gpr(t0, rs);
1a0196c5 5293
6af0bf9c
FB
5294 switch (opc) {
5295 case OPC_CLO:
4267d3e6 5296 case R6_OPC_CLO:
1a0196c5
RH
5297#if defined(TARGET_MIPS64)
5298 case OPC_DCLO:
5299 case R6_OPC_DCLO:
5300#endif
5301 tcg_gen_not_tl(t0, t0);
6af0bf9c 5302 break;
1a0196c5
RH
5303 }
5304
5305 switch (opc) {
5306 case OPC_CLO:
5307 case R6_OPC_CLO:
6af0bf9c 5308 case OPC_CLZ:
4267d3e6 5309 case R6_OPC_CLZ:
1a0196c5
RH
5310 tcg_gen_ext32u_tl(t0, t0);
5311 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5312 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5313 break;
d26bc211 5314#if defined(TARGET_MIPS64)
7a387fff 5315 case OPC_DCLO:
4267d3e6 5316 case R6_OPC_DCLO:
7a387fff 5317 case OPC_DCLZ:
4267d3e6 5318 case R6_OPC_DCLZ:
1a0196c5 5319 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5320 break;
5321#endif
6af0bf9c 5322 }
6af0bf9c
FB
5323}
5324
161f85e6 5325/* Godson integer instructions */
bd277fa1
RH
5326static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5327 int rd, int rs, int rt)
161f85e6 5328{
161f85e6
AJ
5329 TCGv t0, t1;
5330
5331 if (rd == 0) {
5332 /* Treat as NOP. */
161f85e6
AJ
5333 return;
5334 }
5335
5336 switch (opc) {
5337 case OPC_MULT_G_2E:
5338 case OPC_MULT_G_2F:
5339 case OPC_MULTU_G_2E:
5340 case OPC_MULTU_G_2F:
5341#if defined(TARGET_MIPS64)
5342 case OPC_DMULT_G_2E:
5343 case OPC_DMULT_G_2F:
5344 case OPC_DMULTU_G_2E:
5345 case OPC_DMULTU_G_2F:
5346#endif
5347 t0 = tcg_temp_new();
5348 t1 = tcg_temp_new();
5349 break;
5350 default:
5351 t0 = tcg_temp_local_new();
5352 t1 = tcg_temp_local_new();
5353 break;
5354 }
5355
5356 gen_load_gpr(t0, rs);
5357 gen_load_gpr(t1, rt);
5358
5359 switch (opc) {
5360 case OPC_MULT_G_2E:
5361 case OPC_MULT_G_2F:
5362 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5363 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5364 break;
5365 case OPC_MULTU_G_2E:
5366 case OPC_MULTU_G_2F:
5367 tcg_gen_ext32u_tl(t0, t0);
5368 tcg_gen_ext32u_tl(t1, t1);
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5371 break;
5372 case OPC_DIV_G_2E:
5373 case OPC_DIV_G_2F:
5374 {
42a268c2
RH
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5378 tcg_gen_ext32s_tl(t0, t0);
5379 tcg_gen_ext32s_tl(t1, t1);
5380 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5381 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5382 tcg_gen_br(l3);
5383 gen_set_label(l1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5385 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5386 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5387 tcg_gen_br(l3);
5388 gen_set_label(l2);
5389 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5390 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5391 gen_set_label(l3);
5392 }
161f85e6
AJ
5393 break;
5394 case OPC_DIVU_G_2E:
5395 case OPC_DIVU_G_2F:
5396 {
42a268c2
RH
5397 TCGLabel *l1 = gen_new_label();
5398 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5399 tcg_gen_ext32u_tl(t0, t0);
5400 tcg_gen_ext32u_tl(t1, t1);
5401 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5402 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5403 tcg_gen_br(l2);
5404 gen_set_label(l1);
5405 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5406 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5407 gen_set_label(l2);
5408 }
161f85e6
AJ
5409 break;
5410 case OPC_MOD_G_2E:
5411 case OPC_MOD_G_2F:
5412 {
42a268c2
RH
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5416 tcg_gen_ext32u_tl(t0, t0);
5417 tcg_gen_ext32u_tl(t1, t1);
5418 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5419 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5421 gen_set_label(l1);
5422 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5426 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5427 gen_set_label(l3);
5428 }
161f85e6
AJ
5429 break;
5430 case OPC_MODU_G_2E:
5431 case OPC_MODU_G_2F:
5432 {
42a268c2
RH
5433 TCGLabel *l1 = gen_new_label();
5434 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5435 tcg_gen_ext32u_tl(t0, t0);
5436 tcg_gen_ext32u_tl(t1, t1);
5437 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5439 tcg_gen_br(l2);
5440 gen_set_label(l1);
5441 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5442 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5443 gen_set_label(l2);
5444 }
161f85e6
AJ
5445 break;
5446#if defined(TARGET_MIPS64)
5447 case OPC_DMULT_G_2E:
5448 case OPC_DMULT_G_2F:
5449 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5450 break;
5451 case OPC_DMULTU_G_2E:
5452 case OPC_DMULTU_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5454 break;
5455 case OPC_DDIV_G_2E:
5456 case OPC_DDIV_G_2F:
5457 {
42a268c2
RH
5458 TCGLabel *l1 = gen_new_label();
5459 TCGLabel *l2 = gen_new_label();
5460 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5462 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5463 tcg_gen_br(l3);
5464 gen_set_label(l1);
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5467 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5468 tcg_gen_br(l3);
5469 gen_set_label(l2);
5470 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5471 gen_set_label(l3);
5472 }
161f85e6
AJ
5473 break;
5474 case OPC_DDIVU_G_2E:
5475 case OPC_DDIVU_G_2F:
5476 {
42a268c2
RH
5477 TCGLabel *l1 = gen_new_label();
5478 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5479 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5480 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5481 tcg_gen_br(l2);
5482 gen_set_label(l1);
5483 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5484 gen_set_label(l2);
5485 }
161f85e6
AJ
5486 break;
5487 case OPC_DMOD_G_2E:
5488 case OPC_DMOD_G_2F:
5489 {
42a268c2
RH
5490 TCGLabel *l1 = gen_new_label();
5491 TCGLabel *l2 = gen_new_label();
5492 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5493 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5494 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5495 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5496 gen_set_label(l1);
5497 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5498 tcg_gen_br(l3);
5499 gen_set_label(l2);
5500 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5501 gen_set_label(l3);
5502 }
161f85e6
AJ
5503 break;
5504 case OPC_DMODU_G_2E:
5505 case OPC_DMODU_G_2F:
5506 {
42a268c2
RH
5507 TCGLabel *l1 = gen_new_label();
5508 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5509 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5510 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5511 tcg_gen_br(l2);
5512 gen_set_label(l1);
5513 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5514 gen_set_label(l2);
5515 }
161f85e6
AJ
5516 break;
5517#endif
5518 }
5519
161f85e6
AJ
5520 tcg_temp_free(t0);
5521 tcg_temp_free(t1);
5522}
5523
bd277fa1
RH
5524/* Loongson multimedia instructions */
5525static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5526{
bd277fa1
RH
5527 uint32_t opc, shift_max;
5528 TCGv_i64 t0, t1;
5529
5530 opc = MASK_LMI(ctx->opcode);
5531 switch (opc) {
5532 case OPC_ADD_CP2:
5533 case OPC_SUB_CP2:
5534 case OPC_DADD_CP2:
5535 case OPC_DSUB_CP2:
5536 t0 = tcg_temp_local_new_i64();
5537 t1 = tcg_temp_local_new_i64();
5538 break;
5539 default:
5540 t0 = tcg_temp_new_i64();
5541 t1 = tcg_temp_new_i64();
5542 break;
5543 }
5544
b5a587b6 5545 check_cp1_enabled(ctx);
bd277fa1
RH
5546 gen_load_fpr64(ctx, t0, rs);
5547 gen_load_fpr64(ctx, t1, rt);
5548
5549#define LMI_HELPER(UP, LO) \
9d68ac14 5550 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 5551#define LMI_HELPER_1(UP, LO) \
9d68ac14 5552 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 5553#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 5554 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
5555
5556 switch (opc) {
5557 LMI_HELPER(PADDSH, paddsh);
5558 LMI_HELPER(PADDUSH, paddush);
5559 LMI_HELPER(PADDH, paddh);
5560 LMI_HELPER(PADDW, paddw);
5561 LMI_HELPER(PADDSB, paddsb);
5562 LMI_HELPER(PADDUSB, paddusb);
5563 LMI_HELPER(PADDB, paddb);
5564
5565 LMI_HELPER(PSUBSH, psubsh);
5566 LMI_HELPER(PSUBUSH, psubush);
5567 LMI_HELPER(PSUBH, psubh);
5568 LMI_HELPER(PSUBW, psubw);
5569 LMI_HELPER(PSUBSB, psubsb);
5570 LMI_HELPER(PSUBUSB, psubusb);
5571 LMI_HELPER(PSUBB, psubb);
5572
5573 LMI_HELPER(PSHUFH, pshufh);
5574 LMI_HELPER(PACKSSWH, packsswh);
5575 LMI_HELPER(PACKSSHB, packsshb);
5576 LMI_HELPER(PACKUSHB, packushb);
5577
5578 LMI_HELPER(PUNPCKLHW, punpcklhw);
5579 LMI_HELPER(PUNPCKHHW, punpckhhw);
5580 LMI_HELPER(PUNPCKLBH, punpcklbh);
5581 LMI_HELPER(PUNPCKHBH, punpckhbh);
5582 LMI_HELPER(PUNPCKLWD, punpcklwd);
5583 LMI_HELPER(PUNPCKHWD, punpckhwd);
5584
5585 LMI_HELPER(PAVGH, pavgh);
5586 LMI_HELPER(PAVGB, pavgb);
5587 LMI_HELPER(PMAXSH, pmaxsh);
5588 LMI_HELPER(PMINSH, pminsh);
5589 LMI_HELPER(PMAXUB, pmaxub);
5590 LMI_HELPER(PMINUB, pminub);
5591
5592 LMI_HELPER(PCMPEQW, pcmpeqw);
5593 LMI_HELPER(PCMPGTW, pcmpgtw);
5594 LMI_HELPER(PCMPEQH, pcmpeqh);
5595 LMI_HELPER(PCMPGTH, pcmpgth);
5596 LMI_HELPER(PCMPEQB, pcmpeqb);
5597 LMI_HELPER(PCMPGTB, pcmpgtb);
5598
5599 LMI_HELPER(PSLLW, psllw);
5600 LMI_HELPER(PSLLH, psllh);
5601 LMI_HELPER(PSRLW, psrlw);
5602 LMI_HELPER(PSRLH, psrlh);
5603 LMI_HELPER(PSRAW, psraw);
5604 LMI_HELPER(PSRAH, psrah);
5605
5606 LMI_HELPER(PMULLH, pmullh);
5607 LMI_HELPER(PMULHH, pmulhh);
5608 LMI_HELPER(PMULHUH, pmulhuh);
5609 LMI_HELPER(PMADDHW, pmaddhw);
5610
5611 LMI_HELPER(PASUBUB, pasubub);
5612 LMI_HELPER_1(BIADD, biadd);
5613 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5614
5615 LMI_DIRECT(PADDD, paddd, add);
5616 LMI_DIRECT(PSUBD, psubd, sub);
5617 LMI_DIRECT(XOR_CP2, xor, xor);
5618 LMI_DIRECT(NOR_CP2, nor, nor);
5619 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 5620 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 5621
9099a36b
H
5622 case OPC_PANDN:
5623 tcg_gen_andc_i64(t0, t1, t0);
5624 break;
5625
bd277fa1
RH
5626 case OPC_PINSRH_0:
5627 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5628 break;
5629 case OPC_PINSRH_1:
5630 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5631 break;
5632 case OPC_PINSRH_2:
5633 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5634 break;
5635 case OPC_PINSRH_3:
5636 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5637 break;
5638
5639 case OPC_PEXTRH:
5640 tcg_gen_andi_i64(t1, t1, 3);
5641 tcg_gen_shli_i64(t1, t1, 4);
5642 tcg_gen_shr_i64(t0, t0, t1);
5643 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5644 break;
5645
5646 case OPC_ADDU_CP2:
5647 tcg_gen_add_i64(t0, t0, t1);
5648 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5649 break;
5650 case OPC_SUBU_CP2:
5651 tcg_gen_sub_i64(t0, t0, t1);
5652 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5653 break;
5654
5655 case OPC_SLL_CP2:
bd277fa1
RH
5656 shift_max = 32;
5657 goto do_shift;
5658 case OPC_SRL_CP2:
bd277fa1
RH
5659 shift_max = 32;
5660 goto do_shift;
5661 case OPC_SRA_CP2:
bd277fa1
RH
5662 shift_max = 32;
5663 goto do_shift;
5664 case OPC_DSLL_CP2:
bd277fa1
RH
5665 shift_max = 64;
5666 goto do_shift;
5667 case OPC_DSRL_CP2:
bd277fa1
RH
5668 shift_max = 64;
5669 goto do_shift;
5670 case OPC_DSRA_CP2:
bd277fa1
RH
5671 shift_max = 64;
5672 goto do_shift;
5673 do_shift:
5674 /* Make sure shift count isn't TCG undefined behaviour. */
5675 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5676
5677 switch (opc) {
5678 case OPC_SLL_CP2:
5679 case OPC_DSLL_CP2:
5680 tcg_gen_shl_i64(t0, t0, t1);
5681 break;
5682 case OPC_SRA_CP2:
5683 case OPC_DSRA_CP2:
7480515f
AM
5684 /*
5685 * Since SRA is UndefinedResult without sign-extended inputs,
5686 * we can treat SRA and DSRA the same.
5687 */
bd277fa1
RH
5688 tcg_gen_sar_i64(t0, t0, t1);
5689 break;
5690 case OPC_SRL_CP2:
5691 /* We want to shift in zeros for SRL; zero-extend first. */
5692 tcg_gen_ext32u_i64(t0, t0);
5693 /* FALLTHRU */
5694 case OPC_DSRL_CP2:
5695 tcg_gen_shr_i64(t0, t0, t1);
5696 break;
5697 }
5698
5699 if (shift_max == 32) {
5700 tcg_gen_ext32s_i64(t0, t0);
5701 }
5702
5703 /* Shifts larger than MAX produce zero. */
5704 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5705 tcg_gen_neg_i64(t1, t1);
5706 tcg_gen_and_i64(t0, t0, t1);
5707 break;
5708
5709 case OPC_ADD_CP2:
5710 case OPC_DADD_CP2:
5711 {
5712 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5713 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5714
5715 tcg_gen_mov_i64(t2, t0);
5716 tcg_gen_add_i64(t0, t1, t2);
5717 if (opc == OPC_ADD_CP2) {
5718 tcg_gen_ext32s_i64(t0, t0);
5719 }
5720 tcg_gen_xor_i64(t1, t1, t2);
5721 tcg_gen_xor_i64(t2, t2, t0);
5722 tcg_gen_andc_i64(t1, t2, t1);
5723 tcg_temp_free_i64(t2);
5724 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5725 generate_exception(ctx, EXCP_OVERFLOW);
5726 gen_set_label(lab);
bd277fa1
RH
5727 break;
5728 }
5729
5730 case OPC_SUB_CP2:
5731 case OPC_DSUB_CP2:
5732 {
5733 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5734 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5735
5736 tcg_gen_mov_i64(t2, t0);
5737 tcg_gen_sub_i64(t0, t1, t2);
5738 if (opc == OPC_SUB_CP2) {
5739 tcg_gen_ext32s_i64(t0, t0);
5740 }
5741 tcg_gen_xor_i64(t1, t1, t2);
5742 tcg_gen_xor_i64(t2, t2, t0);
5743 tcg_gen_and_i64(t1, t1, t2);
5744 tcg_temp_free_i64(t2);
5745 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5746 generate_exception(ctx, EXCP_OVERFLOW);
5747 gen_set_label(lab);
bd277fa1
RH
5748 break;
5749 }
5750
5751 case OPC_PMULUW:
5752 tcg_gen_ext32u_i64(t0, t0);
5753 tcg_gen_ext32u_i64(t1, t1);
5754 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5755 break;
5756
5757 case OPC_SEQU_CP2:
5758 case OPC_SEQ_CP2:
5759 case OPC_SLTU_CP2:
5760 case OPC_SLT_CP2:
5761 case OPC_SLEU_CP2:
5762 case OPC_SLE_CP2:
7480515f
AM
5763 /*
5764 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5765 * FD field is the CC field?
5766 */
bd277fa1 5767 default:
9d68ac14 5768 MIPS_INVAL("loongson_cp2");
9c708c7f 5769 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5770 return;
5771 }
5772
5773#undef LMI_HELPER
5774#undef LMI_DIRECT
5775
5776 gen_store_fpr64(ctx, t0, rd);
5777
bd277fa1
RH
5778 tcg_temp_free_i64(t0);
5779 tcg_temp_free_i64(t1);
5780}
5781
6af0bf9c 5782/* Traps */
71375b59
AM
5783static void gen_trap(DisasContext *ctx, uint32_t opc,
5784 int rs, int rt, int16_t imm)
6af0bf9c
FB
5785{
5786 int cond;
cdc0faa6 5787 TCGv t0 = tcg_temp_new();
1ba74fb8 5788 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5789
5790 cond = 0;
5791 /* Load needed operands */
5792 switch (opc) {
5793 case OPC_TEQ:
5794 case OPC_TGE:
5795 case OPC_TGEU:
5796 case OPC_TLT:
5797 case OPC_TLTU:
5798 case OPC_TNE:
5799 /* Compare two registers */
5800 if (rs != rt) {
be24bb4f
TS
5801 gen_load_gpr(t0, rs);
5802 gen_load_gpr(t1, rt);
6af0bf9c
FB
5803 cond = 1;
5804 }
179e32bb 5805 break;
6af0bf9c
FB
5806 case OPC_TEQI:
5807 case OPC_TGEI:
5808 case OPC_TGEIU:
5809 case OPC_TLTI:
5810 case OPC_TLTIU:
5811 case OPC_TNEI:
5812 /* Compare register to immediate */
5813 if (rs != 0 || imm != 0) {
be24bb4f
TS
5814 gen_load_gpr(t0, rs);
5815 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5816 cond = 1;
5817 }
5818 break;
5819 }
5820 if (cond == 0) {
5821 switch (opc) {
5822 case OPC_TEQ: /* rs == rs */
5823 case OPC_TEQI: /* r0 == 0 */
5824 case OPC_TGE: /* rs >= rs */
5825 case OPC_TGEI: /* r0 >= 0 */
5826 case OPC_TGEU: /* rs >= rs unsigned */
5827 case OPC_TGEIU: /* r0 >= 0 unsigned */
5828 /* Always trap */
9c708c7f 5829 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5830 break;
5831 case OPC_TLT: /* rs < rs */
5832 case OPC_TLTI: /* r0 < 0 */
5833 case OPC_TLTU: /* rs < rs unsigned */
5834 case OPC_TLTIU: /* r0 < 0 unsigned */
5835 case OPC_TNE: /* rs != rs */
5836 case OPC_TNEI: /* r0 != 0 */
ead9360e 5837 /* Never trap: treat as NOP. */
cdc0faa6 5838 break;
6af0bf9c
FB
5839 }
5840 } else {
42a268c2 5841 TCGLabel *l1 = gen_new_label();
cdc0faa6 5842
6af0bf9c
FB
5843 switch (opc) {
5844 case OPC_TEQ:
5845 case OPC_TEQI:
cdc0faa6 5846 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5847 break;
5848 case OPC_TGE:
5849 case OPC_TGEI:
cdc0faa6 5850 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5851 break;
5852 case OPC_TGEU:
5853 case OPC_TGEIU:
cdc0faa6 5854 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5855 break;
5856 case OPC_TLT:
5857 case OPC_TLTI:
cdc0faa6 5858 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5859 break;
5860 case OPC_TLTU:
5861 case OPC_TLTIU:
cdc0faa6 5862 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5863 break;
5864 case OPC_TNE:
5865 case OPC_TNEI:
cdc0faa6 5866 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5867 break;
6af0bf9c 5868 }
cdc0faa6 5869 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5870 gen_set_label(l1);
5871 }
be24bb4f
TS
5872 tcg_temp_free(t0);
5873 tcg_temp_free(t1);
6af0bf9c
FB
5874}
5875
90aa39a1
SF
5876static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5877{
eeb3bba8 5878 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5879 return false;
5880 }
5881
5882#ifndef CONFIG_USER_ONLY
eeb3bba8 5883 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5884#else
5885 return true;
5886#endif
5887}
5888
356265ae 5889static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5890{
90aa39a1 5891 if (use_goto_tb(ctx, dest)) {
57fec1fe 5892 tcg_gen_goto_tb(n);
9b9e4393 5893 gen_save_pc(dest);
07ea28b4 5894 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5895 } else {
9b9e4393 5896 gen_save_pc(dest);
eeb3bba8 5897 if (ctx->base.singlestep_enabled) {
7b270ef2 5898 save_cpu_state(ctx, 0);
9c708c7f 5899 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5900 }
7f11636d 5901 tcg_gen_lookup_and_goto_ptr();
6e256c93 5902 }
c53be334
FB
5903}
5904
6af0bf9c 5905/* Branches (before delay slot) */
71375b59
AM
5906static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5907 int insn_bytes,
5908 int rs, int rt, int32_t offset,
5909 int delayslot_size)
6af0bf9c 5910{
d077b6f7 5911 target_ulong btgt = -1;
3ad4bb2d 5912 int blink = 0;
2fdbad25 5913 int bcond_compute = 0;
1ba74fb8
AJ
5914 TCGv t0 = tcg_temp_new();
5915 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5916
5917 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5918#ifdef MIPS_DEBUG_DISAS
339cd2a8 5919 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5920 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5921#endif
9c708c7f 5922 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5923 goto out;
3ad4bb2d 5924 }
6af0bf9c 5925
6af0bf9c
FB
5926 /* Load needed operands */
5927 switch (opc) {
5928 case OPC_BEQ:
5929 case OPC_BEQL:
5930 case OPC_BNE:
5931 case OPC_BNEL:
5932 /* Compare two registers */
5933 if (rs != rt) {
6c5c1e20
TS
5934 gen_load_gpr(t0, rs);
5935 gen_load_gpr(t1, rt);
2fdbad25 5936 bcond_compute = 1;
6af0bf9c 5937 }
eeb3bba8 5938 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5939 break;
5940 case OPC_BGEZ:
5941 case OPC_BGEZAL:
5942 case OPC_BGEZALL:
5943 case OPC_BGEZL:
5944 case OPC_BGTZ:
5945 case OPC_BGTZL:
5946 case OPC_BLEZ:
5947 case OPC_BLEZL:
5948 case OPC_BLTZ:
5949 case OPC_BLTZAL:
5950 case OPC_BLTZALL:
5951 case OPC_BLTZL:
5952 /* Compare to zero */
5953 if (rs != 0) {
6c5c1e20 5954 gen_load_gpr(t0, rs);
2fdbad25 5955 bcond_compute = 1;
6af0bf9c 5956 }
eeb3bba8 5957 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5958 break;
e45a93e2
JL
5959 case OPC_BPOSGE32:
5960#if defined(TARGET_MIPS64)
5961 case OPC_BPOSGE64:
5962 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5963#else
5964 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5965#endif
5966 bcond_compute = 1;
eeb3bba8 5967 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5968 break;
6af0bf9c
FB
5969 case OPC_J:
5970 case OPC_JAL:
364d4831 5971 case OPC_JALX:
6af0bf9c 5972 /* Jump to immediate */
eeb3bba8
EC
5973 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5974 (uint32_t)offset;
6af0bf9c
FB
5975 break;
5976 case OPC_JR:
5977 case OPC_JALR:
5978 /* Jump to register */
7a387fff 5979 if (offset != 0 && offset != 16) {
7480515f
AM
5980 /*
5981 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5982 * others are reserved.
5983 */
923617a3 5984 MIPS_INVAL("jump hint");
9c708c7f 5985 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5986 goto out;
6af0bf9c 5987 }
d077b6f7 5988 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5989 break;
5990 default:
5991 MIPS_INVAL("branch/jump");
9c708c7f 5992 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5993 goto out;
6af0bf9c 5994 }
2fdbad25 5995 if (bcond_compute == 0) {
6af0bf9c
FB
5996 /* No condition to be computed */
5997 switch (opc) {
5998 case OPC_BEQ: /* rx == rx */
5999 case OPC_BEQL: /* rx == rx likely */
6000 case OPC_BGEZ: /* 0 >= 0 */
6001 case OPC_BGEZL: /* 0 >= 0 likely */
6002 case OPC_BLEZ: /* 0 <= 0 */
6003 case OPC_BLEZL: /* 0 <= 0 likely */
6004 /* Always take */
4ad40f36 6005 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6006 break;
6007 case OPC_BGEZAL: /* 0 >= 0 */
6008 case OPC_BGEZALL: /* 0 >= 0 likely */
6009 /* Always take and link */
6010 blink = 31;
4ad40f36 6011 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6012 break;
6013 case OPC_BNE: /* rx != rx */
6014 case OPC_BGTZ: /* 0 > 0 */
6015 case OPC_BLTZ: /* 0 < 0 */
ead9360e 6016 /* Treat as NOP. */
6c5c1e20 6017 goto out;
eeef26cd 6018 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
6019 /*
6020 * Handle as an unconditional branch to get correct delay
6021 * slot checking.
6022 */
3c824109 6023 blink = 31;
eeb3bba8 6024 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 6025 ctx->hflags |= MIPS_HFLAG_B;
3c824109 6026 break;
eeef26cd 6027 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 6028 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 6029 /* Skip the instruction in the delay slot */
eeb3bba8 6030 ctx->base.pc_next += 4;
6c5c1e20 6031 goto out;
6af0bf9c
FB
6032 case OPC_BNEL: /* rx != rx likely */
6033 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
6034 case OPC_BLTZL: /* 0 < 0 likely */
6035 /* Skip the instruction in the delay slot */
eeb3bba8 6036 ctx->base.pc_next += 4;
6c5c1e20 6037 goto out;
6af0bf9c 6038 case OPC_J:
4ad40f36 6039 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 6040 break;
364d4831
NF
6041 case OPC_JALX:
6042 ctx->hflags |= MIPS_HFLAG_BX;
6043 /* Fallthrough */
6af0bf9c
FB
6044 case OPC_JAL:
6045 blink = 31;
4ad40f36 6046 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6047 break;
6048 case OPC_JR:
4ad40f36 6049 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6050 break;
6051 case OPC_JALR:
6052 blink = rt;
4ad40f36 6053 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6054 break;
6055 default:
6056 MIPS_INVAL("branch/jump");
9c708c7f 6057 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6058 goto out;
6af0bf9c
FB
6059 }
6060 } else {
6061 switch (opc) {
6062 case OPC_BEQ:
e68dd28f 6063 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6064 goto not_likely;
6065 case OPC_BEQL:
e68dd28f 6066 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6067 goto likely;
6068 case OPC_BNE:
e68dd28f 6069 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6070 goto not_likely;
6071 case OPC_BNEL:
e68dd28f 6072 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6073 goto likely;
6074 case OPC_BGEZ:
e68dd28f 6075 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6076 goto not_likely;
6077 case OPC_BGEZL:
e68dd28f 6078 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6079 goto likely;
6080 case OPC_BGEZAL:
e68dd28f 6081 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6082 blink = 31;
6083 goto not_likely;
6084 case OPC_BGEZALL:
e68dd28f 6085 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6086 blink = 31;
6af0bf9c
FB
6087 goto likely;
6088 case OPC_BGTZ:
e68dd28f 6089 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6090 goto not_likely;
6091 case OPC_BGTZL:
e68dd28f 6092 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6093 goto likely;
6094 case OPC_BLEZ:
e68dd28f 6095 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6096 goto not_likely;
6097 case OPC_BLEZL:
e68dd28f 6098 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6099 goto likely;
6100 case OPC_BLTZ:
e68dd28f 6101 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6102 goto not_likely;
6103 case OPC_BLTZL:
e68dd28f 6104 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6105 goto likely;
e45a93e2
JL
6106 case OPC_BPOSGE32:
6107 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6108 goto not_likely;
6109#if defined(TARGET_MIPS64)
6110 case OPC_BPOSGE64:
6111 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6112 goto not_likely;
6113#endif
6af0bf9c 6114 case OPC_BLTZAL:
e68dd28f 6115 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6116 blink = 31;
6af0bf9c 6117 not_likely:
4ad40f36 6118 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6119 break;
6120 case OPC_BLTZALL:
e68dd28f 6121 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6122 blink = 31;
6af0bf9c 6123 likely:
4ad40f36 6124 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6125 break;
c53f4a62
TS
6126 default:
6127 MIPS_INVAL("conditional branch/jump");
9c708c7f 6128 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6129 goto out;
6af0bf9c 6130 }
6af0bf9c 6131 }
9b9e4393 6132
d077b6f7 6133 ctx->btarget = btgt;
b231c103
YK
6134
6135 switch (delayslot_size) {
6136 case 2:
6137 ctx->hflags |= MIPS_HFLAG_BDS16;
6138 break;
6139 case 4:
6140 ctx->hflags |= MIPS_HFLAG_BDS32;
6141 break;
6142 }
6143
6af0bf9c 6144 if (blink > 0) {
b231c103 6145 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6146 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6147
eeb3bba8
EC
6148 tcg_gen_movi_tl(cpu_gpr[blink],
6149 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6150 }
6c5c1e20
TS
6151
6152 out:
1f8929d2 6153 if (insn_bytes == 2) {
364d4831 6154 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 6155 }
6c5c1e20
TS
6156 tcg_temp_free(t0);
6157 tcg_temp_free(t1);
6af0bf9c
FB
6158}
6159
764371d2
SM
6160
6161/* nanoMIPS Branches */
6162static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6163 int insn_bytes,
6164 int rs, int rt, int32_t offset)
6165{
6166 target_ulong btgt = -1;
6167 int bcond_compute = 0;
6168 TCGv t0 = tcg_temp_new();
6169 TCGv t1 = tcg_temp_new();
6170
6171 /* Load needed operands */
6172 switch (opc) {
6173 case OPC_BEQ:
6174 case OPC_BNE:
6175 /* Compare two registers */
6176 if (rs != rt) {
6177 gen_load_gpr(t0, rs);
6178 gen_load_gpr(t1, rt);
6179 bcond_compute = 1;
6180 }
6181 btgt = ctx->base.pc_next + insn_bytes + offset;
6182 break;
6183 case OPC_BGEZAL:
6184 /* Compare to zero */
6185 if (rs != 0) {
6186 gen_load_gpr(t0, rs);
6187 bcond_compute = 1;
6188 }
6189 btgt = ctx->base.pc_next + insn_bytes + offset;
6190 break;
6191 case OPC_BPOSGE32:
6192 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6193 bcond_compute = 1;
6194 btgt = ctx->base.pc_next + insn_bytes + offset;
6195 break;
6196 case OPC_JR:
6197 case OPC_JALR:
6198 /* Jump to register */
6199 if (offset != 0 && offset != 16) {
7480515f
AM
6200 /*
6201 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6202 * others are reserved.
6203 */
764371d2
SM
6204 MIPS_INVAL("jump hint");
6205 generate_exception_end(ctx, EXCP_RI);
6206 goto out;
6207 }
6208 gen_load_gpr(btarget, rs);
6209 break;
6210 default:
6211 MIPS_INVAL("branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6214 }
6215 if (bcond_compute == 0) {
6216 /* No condition to be computed */
6217 switch (opc) {
6218 case OPC_BEQ: /* rx == rx */
6219 /* Always take */
6220 ctx->hflags |= MIPS_HFLAG_B;
6221 break;
6222 case OPC_BGEZAL: /* 0 >= 0 */
6223 /* Always take and link */
6224 tcg_gen_movi_tl(cpu_gpr[31],
6225 ctx->base.pc_next + insn_bytes);
6226 ctx->hflags |= MIPS_HFLAG_B;
6227 break;
6228 case OPC_BNE: /* rx != rx */
6229 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6230 /* Skip the instruction in the delay slot */
6231 ctx->base.pc_next += 4;
6232 goto out;
6233 case OPC_JR:
6234 ctx->hflags |= MIPS_HFLAG_BR;
6235 break;
6236 case OPC_JALR:
6237 if (rt > 0) {
6238 tcg_gen_movi_tl(cpu_gpr[rt],
6239 ctx->base.pc_next + insn_bytes);
6240 }
6241 ctx->hflags |= MIPS_HFLAG_BR;
6242 break;
6243 default:
6244 MIPS_INVAL("branch/jump");
6245 generate_exception_end(ctx, EXCP_RI);
6246 goto out;
6247 }
6248 } else {
6249 switch (opc) {
6250 case OPC_BEQ:
6251 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6252 goto not_likely;
6253 case OPC_BNE:
6254 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6255 goto not_likely;
6256 case OPC_BGEZAL:
6257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6258 tcg_gen_movi_tl(cpu_gpr[31],
6259 ctx->base.pc_next + insn_bytes);
6260 goto not_likely;
6261 case OPC_BPOSGE32:
6262 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6263 not_likely:
6264 ctx->hflags |= MIPS_HFLAG_BC;
6265 break;
6266 default:
6267 MIPS_INVAL("conditional branch/jump");
6268 generate_exception_end(ctx, EXCP_RI);
6269 goto out;
6270 }
6271 }
6272
6273 ctx->btarget = btgt;
6274
6275 out:
6276 if (insn_bytes == 2) {
6277 ctx->hflags |= MIPS_HFLAG_B16;
6278 }
6279 tcg_temp_free(t0);
6280 tcg_temp_free(t1);
6281}
6282
6283
7a387fff 6284/* special3 bitfield operations */
235785e8
AM
6285static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6286 int rs, int lsb, int msb)
7a387fff 6287{
a7812ae4
PB
6288 TCGv t0 = tcg_temp_new();
6289 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6290
6291 gen_load_gpr(t1, rs);
7a387fff
TS
6292 switch (opc) {
6293 case OPC_EXT:
b7f26e52 6294 if (lsb + msb > 31) {
7a387fff 6295 goto fail;
b7f26e52 6296 }
505ad7c2 6297 if (msb != 31) {
6eebb7a4 6298 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6299 } else {
7480515f
AM
6300 /*
6301 * The two checks together imply that lsb == 0,
6302 * so this is a simple sign-extension.
6303 */
6eebb7a4 6304 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6305 }
7a387fff 6306 break;
c6d6dd7c 6307#if defined(TARGET_MIPS64)
7a387fff 6308 case OPC_DEXTU:
b7f26e52
RH
6309 lsb += 32;
6310 goto do_dext;
6311 case OPC_DEXTM:
6312 msb += 32;
6313 goto do_dext;
7a387fff 6314 case OPC_DEXT:
b7f26e52
RH
6315 do_dext:
6316 if (lsb + msb > 63) {
6317 goto fail;
6318 }
6eebb7a4 6319 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6320 break;
c6d6dd7c 6321#endif
7a387fff 6322 case OPC_INS:
b7f26e52 6323 if (lsb > msb) {
7a387fff 6324 goto fail;
b7f26e52 6325 }
6c5c1e20 6326 gen_load_gpr(t0, rt);
e0d002f1 6327 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6328 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6329 break;
c6d6dd7c 6330#if defined(TARGET_MIPS64)
7a387fff 6331 case OPC_DINSU:
b7f26e52
RH
6332 lsb += 32;
6333 /* FALLTHRU */
6334 case OPC_DINSM:
6335 msb += 32;
6336 /* FALLTHRU */
7a387fff 6337 case OPC_DINS:
b7f26e52
RH
6338 if (lsb > msb) {
6339 goto fail;
6340 }
6c5c1e20 6341 gen_load_gpr(t0, rt);
e0d002f1 6342 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6343 break;
c6d6dd7c 6344#endif
7a387fff
TS
6345 default:
6346fail:
6347 MIPS_INVAL("bitops");
9c708c7f 6348 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6349 tcg_temp_free(t0);
6350 tcg_temp_free(t1);
7a387fff
TS
6351 return;
6352 }
6c5c1e20
TS
6353 gen_store_gpr(t0, rt);
6354 tcg_temp_free(t0);
6355 tcg_temp_free(t1);
7a387fff
TS
6356}
6357
235785e8 6358static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 6359{
3a55fa47 6360 TCGv t0;
49bcf33c 6361
3a55fa47
AJ
6362 if (rd == 0) {
6363 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6364 return;
6365 }
6366
6367 t0 = tcg_temp_new();
6368 gen_load_gpr(t0, rt);
49bcf33c
AJ
6369 switch (op2) {
6370 case OPC_WSBH:
3a55fa47
AJ
6371 {
6372 TCGv t1 = tcg_temp_new();
06a57e5c 6373 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6374
6375 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6376 tcg_gen_and_tl(t1, t1, t2);
6377 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6378 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6379 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6380 tcg_temp_free(t2);
3a55fa47
AJ
6381 tcg_temp_free(t1);
6382 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6383 }
49bcf33c
AJ
6384 break;
6385 case OPC_SEB:
3a55fa47 6386 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6387 break;
6388 case OPC_SEH:
3a55fa47 6389 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6390 break;
6391#if defined(TARGET_MIPS64)
6392 case OPC_DSBH:
3a55fa47
AJ
6393 {
6394 TCGv t1 = tcg_temp_new();
06a57e5c 6395 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6396
6397 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6398 tcg_gen_and_tl(t1, t1, t2);
6399 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6400 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6401 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6402 tcg_temp_free(t2);
3a55fa47
AJ
6403 tcg_temp_free(t1);
6404 }
49bcf33c
AJ
6405 break;
6406 case OPC_DSHD:
3a55fa47
AJ
6407 {
6408 TCGv t1 = tcg_temp_new();
06a57e5c 6409 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6410
6411 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6412 tcg_gen_and_tl(t1, t1, t2);
6413 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6414 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6415 tcg_gen_or_tl(t0, t0, t1);
6416 tcg_gen_shri_tl(t1, t0, 32);
6417 tcg_gen_shli_tl(t0, t0, 32);
6418 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6419 tcg_temp_free(t2);
3a55fa47
AJ
6420 tcg_temp_free(t1);
6421 }
49bcf33c
AJ
6422 break;
6423#endif
6424 default:
6425 MIPS_INVAL("bsfhl");
9c708c7f 6426 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6427 tcg_temp_free(t0);
49bcf33c
AJ
6428 return;
6429 }
49bcf33c 6430 tcg_temp_free(t0);
49bcf33c
AJ
6431}
6432
1f1b4c00
YK
6433static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6434 int imm2)
6435{
6436 TCGv t0;
6437 TCGv t1;
6438 if (rd == 0) {
6439 /* Treat as NOP. */
6440 return;
6441 }
6442 t0 = tcg_temp_new();
6443 t1 = tcg_temp_new();
6444 gen_load_gpr(t0, rs);
6445 gen_load_gpr(t1, rt);
6446 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6447 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6448 if (opc == OPC_LSA) {
6449 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6450 }
6451
6452 tcg_temp_free(t1);
6453 tcg_temp_free(t0);
6454
6455 return;
6456}
6457
821f2008
JH
6458static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6459 int rt, int bits)
284b731a 6460{
1f1b4c00
YK
6461 TCGv t0;
6462 if (rd == 0) {
6463 /* Treat as NOP. */
6464 return;
6465 }
6466 t0 = tcg_temp_new();
821f2008
JH
6467 if (bits == 0 || bits == wordsz) {
6468 if (bits == 0) {
6469 gen_load_gpr(t0, rt);
6470 } else {
6471 gen_load_gpr(t0, rs);
6472 }
6473 switch (wordsz) {
6474 case 32:
51243852
MD
6475 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6476 break;
6477#if defined(TARGET_MIPS64)
821f2008 6478 case 64:
51243852
MD
6479 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6480 break;
6481#endif
6482 }
1f1b4c00
YK
6483 } else {
6484 TCGv t1 = tcg_temp_new();
821f2008 6485 gen_load_gpr(t0, rt);
1f1b4c00 6486 gen_load_gpr(t1, rs);
821f2008
JH
6487 switch (wordsz) {
6488 case 32:
1f1b4c00
YK
6489 {
6490 TCGv_i64 t2 = tcg_temp_new_i64();
6491 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6492 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6493 gen_move_low32(cpu_gpr[rd], t2);
6494 tcg_temp_free_i64(t2);
6495 }
6496 break;
284b731a 6497#if defined(TARGET_MIPS64)
821f2008
JH
6498 case 64:
6499 tcg_gen_shli_tl(t0, t0, bits);
6500 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6501 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6502 break;
284b731a 6503#endif
1f1b4c00
YK
6504 }
6505 tcg_temp_free(t1);
6506 }
6507
6508 tcg_temp_free(t0);
6509}
6510
821f2008
JH
6511static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6512 int bp)
6513{
6514 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6515}
6516
6517static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6518 int shift)
6519{
6520 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6521}
6522
1f1b4c00
YK
6523static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6524{
6525 TCGv t0;
6526 if (rd == 0) {
6527 /* Treat as NOP. */
6528 return;
6529 }
6530 t0 = tcg_temp_new();
6531 gen_load_gpr(t0, rt);
6532 switch (opc) {
6533 case OPC_BITSWAP:
6534 gen_helper_bitswap(cpu_gpr[rd], t0);
6535 break;
6536#if defined(TARGET_MIPS64)
6537 case OPC_DBITSWAP:
6538 gen_helper_dbitswap(cpu_gpr[rd], t0);
6539 break;
6540#endif
6541 }
6542 tcg_temp_free(t0);
284b731a
LA
6543}
6544
1f1b4c00
YK
6545#ifndef CONFIG_USER_ONLY
6546/* CP0 (MMU and control) */
5204ea79
LA
6547static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6548{
6549 TCGv_i64 t0 = tcg_temp_new_i64();
6550 TCGv_i64 t1 = tcg_temp_new_i64();
6551
6552 tcg_gen_ext_tl_i64(t0, arg);
6553 tcg_gen_ld_i64(t1, cpu_env, off);
6554#if defined(TARGET_MIPS64)
6555 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6556#else
6557 tcg_gen_concat32_i64(t1, t1, t0);
6558#endif
6559 tcg_gen_st_i64(t1, cpu_env, off);
6560 tcg_temp_free_i64(t1);
6561 tcg_temp_free_i64(t0);
6562}
6563
6564static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6565{
6566 TCGv_i64 t0 = tcg_temp_new_i64();
6567 TCGv_i64 t1 = tcg_temp_new_i64();
6568
6569 tcg_gen_ext_tl_i64(t0, arg);
6570 tcg_gen_ld_i64(t1, cpu_env, off);
6571 tcg_gen_concat32_i64(t1, t1, t0);
6572 tcg_gen_st_i64(t1, cpu_env, off);
6573 tcg_temp_free_i64(t1);
6574 tcg_temp_free_i64(t0);
6575}
6576
6577static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6578{
6579 TCGv_i64 t0 = tcg_temp_new_i64();
6580
6581 tcg_gen_ld_i64(t0, cpu_env, off);
6582#if defined(TARGET_MIPS64)
6583 tcg_gen_shri_i64(t0, t0, 30);
6584#else
6585 tcg_gen_shri_i64(t0, t0, 32);
6586#endif
6587 gen_move_low32(arg, t0);
6588 tcg_temp_free_i64(t0);
6589}
6590
6591static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6592{
6593 TCGv_i64 t0 = tcg_temp_new_i64();
6594
6595 tcg_gen_ld_i64(t0, cpu_env, off);
6596 tcg_gen_shri_i64(t0, t0, 32 + shift);
6597 gen_move_low32(arg, t0);
6598 tcg_temp_free_i64(t0);
6599}
6600
235785e8 6601static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 6602{
d9bea114 6603 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6604
d9bea114
AJ
6605 tcg_gen_ld_i32(t0, cpu_env, off);
6606 tcg_gen_ext_i32_tl(arg, t0);
6607 tcg_temp_free_i32(t0);
4f57689a
TS
6608}
6609
235785e8 6610static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 6611{
d9bea114
AJ
6612 tcg_gen_ld_tl(arg, cpu_env, off);
6613 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6614}
6615
235785e8 6616static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 6617{
d9bea114 6618 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6619
d9bea114
AJ
6620 tcg_gen_trunc_tl_i32(t0, arg);
6621 tcg_gen_st_i32(t0, cpu_env, off);
6622 tcg_temp_free_i32(t0);
f1aa6320
TS
6623}
6624
c98d3d79
YK
6625#define CP0_CHECK(c) \
6626 do { \
6627 if (!(c)) { \
6628 goto cp0_unimplemented; \
6629 } \
6630 } while (0)
6631
5204ea79
LA
6632static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6633{
294fc2ea 6634 const char *register_name = "invalid";
5204ea79 6635
5204ea79 6636 switch (reg) {
04992c8c 6637 case CP0_REGISTER_02:
5204ea79
LA
6638 switch (sel) {
6639 case 0:
59488dda 6640 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6641 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6642 register_name = "EntryLo0";
5204ea79
LA
6643 break;
6644 default:
c98d3d79 6645 goto cp0_unimplemented;
5204ea79
LA
6646 }
6647 break;
04992c8c 6648 case CP0_REGISTER_03:
5204ea79 6649 switch (sel) {
acd37316 6650 case CP0_REG03__ENTRYLO1:
59488dda 6651 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6652 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6653 register_name = "EntryLo1";
5204ea79
LA
6654 break;
6655 default:
c98d3d79 6656 goto cp0_unimplemented;
5204ea79
LA
6657 }
6658 break;
04992c8c 6659 case CP0_REGISTER_09:
5fb2dcd1 6660 switch (sel) {
e5a98a72 6661 case CP0_REG09__SAAR:
5fb2dcd1
YK
6662 CP0_CHECK(ctx->saar);
6663 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 6664 register_name = "SAAR";
5fb2dcd1
YK
6665 break;
6666 default:
6667 goto cp0_unimplemented;
6668 }
6669 break;
04992c8c 6670 case CP0_REGISTER_17:
5204ea79 6671 switch (sel) {
706ce142 6672 case CP0_REG17__LLADDR:
c7c7e1e9 6673 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 6674 ctx->CP0_LLAddr_shift);
294fc2ea 6675 register_name = "LLAddr";
5204ea79 6676 break;
706ce142 6677 case CP0_REG17__MAAR:
f6d4dd81
YK
6678 CP0_CHECK(ctx->mrp);
6679 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 6680 register_name = "MAAR";
f6d4dd81 6681 break;
5204ea79 6682 default:
c98d3d79 6683 goto cp0_unimplemented;
5204ea79
LA
6684 }
6685 break;
04992c8c 6686 case CP0_REGISTER_28:
5204ea79
LA
6687 switch (sel) {
6688 case 0:
6689 case 2:
6690 case 4:
6691 case 6:
6692 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 6693 register_name = "TagLo";
5204ea79
LA
6694 break;
6695 default:
c98d3d79 6696 goto cp0_unimplemented;
5204ea79
LA
6697 }
6698 break;
6699 default:
c98d3d79 6700 goto cp0_unimplemented;
5204ea79 6701 }
294fc2ea 6702 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
6703 return;
6704
c98d3d79 6705cp0_unimplemented:
294fc2ea
AM
6706 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6707 register_name, reg, sel);
5204ea79
LA
6708 tcg_gen_movi_tl(arg, 0);
6709}
6710
6711static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6712{
294fc2ea 6713 const char *register_name = "invalid";
5204ea79
LA
6714 uint64_t mask = ctx->PAMask >> 36;
6715
5204ea79 6716 switch (reg) {
04992c8c 6717 case CP0_REGISTER_02:
5204ea79
LA
6718 switch (sel) {
6719 case 0:
59488dda 6720 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6721 tcg_gen_andi_tl(arg, arg, mask);
6722 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6723 register_name = "EntryLo0";
5204ea79
LA
6724 break;
6725 default:
c98d3d79 6726 goto cp0_unimplemented;
5204ea79
LA
6727 }
6728 break;
04992c8c 6729 case CP0_REGISTER_03:
5204ea79 6730 switch (sel) {
acd37316 6731 case CP0_REG03__ENTRYLO1:
59488dda 6732 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6733 tcg_gen_andi_tl(arg, arg, mask);
6734 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6735 register_name = "EntryLo1";
5204ea79
LA
6736 break;
6737 default:
c98d3d79 6738 goto cp0_unimplemented;
5204ea79
LA
6739 }
6740 break;
04992c8c 6741 case CP0_REGISTER_09:
5fb2dcd1 6742 switch (sel) {
e5a98a72 6743 case CP0_REG09__SAAR:
5fb2dcd1
YK
6744 CP0_CHECK(ctx->saar);
6745 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 6746 register_name = "SAAR";
5fb2dcd1
YK
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6750 }
ab8c3410 6751 break;
04992c8c 6752 case CP0_REGISTER_17:
5204ea79 6753 switch (sel) {
706ce142 6754 case CP0_REG17__LLADDR:
7480515f
AM
6755 /*
6756 * LLAddr is read-only (the only exception is bit 0 if LLB is
6757 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6758 * relevant for modern MIPS cores supporting MTHC0, therefore
6759 * treating MTHC0 to LLAddr as NOP.
6760 */
294fc2ea 6761 register_name = "LLAddr";
5204ea79 6762 break;
706ce142 6763 case CP0_REG17__MAAR:
f6d4dd81
YK
6764 CP0_CHECK(ctx->mrp);
6765 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 6766 register_name = "MAAR";
f6d4dd81 6767 break;
5204ea79 6768 default:
c98d3d79 6769 goto cp0_unimplemented;
5204ea79
LA
6770 }
6771 break;
04992c8c 6772 case CP0_REGISTER_28:
5204ea79
LA
6773 switch (sel) {
6774 case 0:
6775 case 2:
6776 case 4:
6777 case 6:
6778 tcg_gen_andi_tl(arg, arg, mask);
6779 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 6780 register_name = "TagLo";
5204ea79
LA
6781 break;
6782 default:
c98d3d79 6783 goto cp0_unimplemented;
5204ea79
LA
6784 }
6785 break;
6786 default:
c98d3d79 6787 goto cp0_unimplemented;
5204ea79 6788 }
294fc2ea 6789 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 6790
c98d3d79 6791cp0_unimplemented:
294fc2ea
AM
6792 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6793 register_name, reg, sel);
5204ea79
LA
6794}
6795
e98c0d17
LA
6796static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6797{
6798 if (ctx->insn_flags & ISA_MIPS32R6) {
6799 tcg_gen_movi_tl(arg, 0);
6800 } else {
6801 tcg_gen_movi_tl(arg, ~0);
6802 }
6803}
6804
d75c135e 6805static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6806{
294fc2ea 6807 const char *register_name = "invalid";
873eb012 6808
1f8929d2 6809 if (sel != 0) {
d75c135e 6810 check_insn(ctx, ISA_MIPS32);
1f8929d2 6811 }
e189e748 6812
873eb012 6813 switch (reg) {
04992c8c 6814 case CP0_REGISTER_00:
7a387fff 6815 switch (sel) {
1b142da5 6816 case CP0_REG00__INDEX:
7db13fae 6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6818 register_name = "Index";
7a387fff 6819 break;
1b142da5 6820 case CP0_REG00__MVPCONTROL:
f31b035a 6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6822 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 6823 register_name = "MVPControl";
ead9360e 6824 break;
1b142da5 6825 case CP0_REG00__MVPCONF0:
f31b035a 6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6827 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 6828 register_name = "MVPConf0";
ead9360e 6829 break;
1b142da5 6830 case CP0_REG00__MVPCONF1:
f31b035a 6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6832 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 6833 register_name = "MVPConf1";
ead9360e 6834 break;
1b142da5 6835 case CP0_REG00__VPCONTROL:
01bc435b
YK
6836 CP0_CHECK(ctx->vp);
6837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 6838 register_name = "VPControl";
01bc435b 6839 break;
7a387fff 6840 default:
f31b035a 6841 goto cp0_unimplemented;
7a387fff 6842 }
873eb012 6843 break;
04992c8c 6844 case CP0_REGISTER_01:
7a387fff 6845 switch (sel) {
30deb460 6846 case CP0_REG01__RANDOM:
f31b035a 6847 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6848 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6849 register_name = "Random";
2423f660 6850 break;
30deb460 6851 case CP0_REG01__VPECONTROL:
f31b035a 6852 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6854 register_name = "VPEControl";
ead9360e 6855 break;
30deb460 6856 case CP0_REG01__VPECONF0:
f31b035a 6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6859 register_name = "VPEConf0";
ead9360e 6860 break;
30deb460 6861 case CP0_REG01__VPECONF1:
f31b035a 6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6864 register_name = "VPEConf1";
ead9360e 6865 break;
30deb460 6866 case CP0_REG01__YQMASK:
f31b035a 6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6868 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6869 register_name = "YQMask";
ead9360e 6870 break;
30deb460 6871 case CP0_REG01__VPESCHEDULE:
f31b035a 6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6873 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6874 register_name = "VPESchedule";
ead9360e 6875 break;
30deb460 6876 case CP0_REG01__VPESCHEFBACK:
f31b035a 6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6878 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6879 register_name = "VPEScheFBack";
ead9360e 6880 break;
30deb460 6881 case CP0_REG01__VPEOPT:
f31b035a 6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6884 register_name = "VPEOpt";
ead9360e 6885 break;
7a387fff 6886 default:
f31b035a 6887 goto cp0_unimplemented;
7a387fff 6888 }
873eb012 6889 break;
04992c8c 6890 case CP0_REGISTER_02:
7a387fff 6891 switch (sel) {
6d27d5bd 6892 case CP0_REG02__ENTRYLO0:
284b731a
LA
6893 {
6894 TCGv_i64 tmp = tcg_temp_new_i64();
6895 tcg_gen_ld_i64(tmp, cpu_env,
6896 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6897#if defined(TARGET_MIPS64)
284b731a
LA
6898 if (ctx->rxi) {
6899 /* Move RI/XI fields to bits 31:30 */
6900 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6901 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6902 }
7207c7f9 6903#endif
284b731a
LA
6904 gen_move_low32(arg, tmp);
6905 tcg_temp_free_i64(tmp);
6906 }
294fc2ea 6907 register_name = "EntryLo0";
2423f660 6908 break;
6d27d5bd 6909 case CP0_REG02__TCSTATUS:
f31b035a 6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6911 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 6912 register_name = "TCStatus";
ead9360e 6913 break;
6d27d5bd 6914 case CP0_REG02__TCBIND:
f31b035a 6915 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6916 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 6917 register_name = "TCBind";
ead9360e 6918 break;
6d27d5bd 6919 case CP0_REG02__TCRESTART:
f31b035a 6920 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6921 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 6922 register_name = "TCRestart";
ead9360e 6923 break;
6d27d5bd 6924 case CP0_REG02__TCHALT:
f31b035a 6925 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6926 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 6927 register_name = "TCHalt";
ead9360e 6928 break;
6d27d5bd 6929 case CP0_REG02__TCCONTEXT:
f31b035a 6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6931 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 6932 register_name = "TCContext";
ead9360e 6933 break;
6d27d5bd 6934 case CP0_REG02__TCSCHEDULE:
f31b035a 6935 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6936 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 6937 register_name = "TCSchedule";
ead9360e 6938 break;
6d27d5bd 6939 case CP0_REG02__TCSCHEFBACK:
f31b035a 6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6941 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 6942 register_name = "TCScheFBack";
ead9360e 6943 break;
7a387fff 6944 default:
f31b035a 6945 goto cp0_unimplemented;
7a387fff 6946 }
873eb012 6947 break;
04992c8c 6948 case CP0_REGISTER_03:
7a387fff 6949 switch (sel) {
acd37316 6950 case CP0_REG03__ENTRYLO1:
284b731a
LA
6951 {
6952 TCGv_i64 tmp = tcg_temp_new_i64();
6953 tcg_gen_ld_i64(tmp, cpu_env,
6954 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6955#if defined(TARGET_MIPS64)
284b731a
LA
6956 if (ctx->rxi) {
6957 /* Move RI/XI fields to bits 31:30 */
6958 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6959 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6960 }
7207c7f9 6961#endif
284b731a
LA
6962 gen_move_low32(arg, tmp);
6963 tcg_temp_free_i64(tmp);
6964 }
294fc2ea 6965 register_name = "EntryLo1";
2423f660 6966 break;
acd37316 6967 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6968 CP0_CHECK(ctx->vp);
6969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 6970 register_name = "GlobalNumber";
01bc435b 6971 break;
7a387fff 6972 default:
f31b035a 6973 goto cp0_unimplemented;
1579a72e 6974 }
873eb012 6975 break;
04992c8c 6976 case CP0_REGISTER_04:
7a387fff 6977 switch (sel) {
020fe379 6978 case CP0_REG04__CONTEXT:
7db13fae 6979 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6980 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6981 register_name = "Context";
2423f660 6982 break;
020fe379
AM
6983 case CP0_REG04__CONTEXTCONFIG:
6984 /* SmartMIPS ASE */
6985 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 6986 register_name = "ContextConfig";
f31b035a 6987 goto cp0_unimplemented;
020fe379 6988 case CP0_REG04__USERLOCAL:
f31b035a 6989 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6990 tcg_gen_ld_tl(arg, cpu_env,
6991 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6992 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6993 register_name = "UserLocal";
d279279e 6994 break;
7a387fff 6995 default:
f31b035a 6996 goto cp0_unimplemented;
1579a72e 6997 }
873eb012 6998 break;
04992c8c 6999 case CP0_REGISTER_05:
7a387fff 7000 switch (sel) {
a1e76353 7001 case CP0_REG05__PAGEMASK:
7db13fae 7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7003 register_name = "PageMask";
2423f660 7004 break;
a1e76353 7005 case CP0_REG05__PAGEGRAIN:
d75c135e 7006 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7008 register_name = "PageGrain";
2423f660 7009 break;
a1e76353 7010 case CP0_REG05__SEGCTL0:
cec56a73
JH
7011 CP0_CHECK(ctx->sc);
7012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7013 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7014 register_name = "SegCtl0";
cec56a73 7015 break;
a1e76353 7016 case CP0_REG05__SEGCTL1:
cec56a73
JH
7017 CP0_CHECK(ctx->sc);
7018 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7019 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7020 register_name = "SegCtl1";
cec56a73 7021 break;
a1e76353 7022 case CP0_REG05__SEGCTL2:
cec56a73
JH
7023 CP0_CHECK(ctx->sc);
7024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7025 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7026 register_name = "SegCtl2";
cec56a73 7027 break;
a1e76353 7028 case CP0_REG05__PWBASE:
5e31fdd5
YK
7029 check_pw(ctx);
7030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7031 register_name = "PWBase";
5e31fdd5 7032 break;
a1e76353 7033 case CP0_REG05__PWFIELD:
fa75ad14
YK
7034 check_pw(ctx);
7035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7036 register_name = "PWField";
fa75ad14 7037 break;
a1e76353 7038 case CP0_REG05__PWSIZE:
20b28ebc
YK
7039 check_pw(ctx);
7040 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7041 register_name = "PWSize";
20b28ebc 7042 break;
7a387fff 7043 default:
f31b035a 7044 goto cp0_unimplemented;
1579a72e 7045 }
873eb012 7046 break;
04992c8c 7047 case CP0_REGISTER_06:
7a387fff 7048 switch (sel) {
9023594b 7049 case CP0_REG06__WIRED:
7db13fae 7050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7051 register_name = "Wired";
2423f660 7052 break;
9023594b 7053 case CP0_REG06__SRSCONF0:
d75c135e 7054 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7056 register_name = "SRSConf0";
ead9360e 7057 break;
9023594b 7058 case CP0_REG06__SRSCONF1:
d75c135e 7059 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7061 register_name = "SRSConf1";
ead9360e 7062 break;
9023594b 7063 case CP0_REG06__SRSCONF2:
d75c135e 7064 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7066 register_name = "SRSConf2";
ead9360e 7067 break;
9023594b 7068 case CP0_REG06__SRSCONF3:
d75c135e 7069 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7071 register_name = "SRSConf3";
ead9360e 7072 break;
9023594b 7073 case CP0_REG06__SRSCONF4:
d75c135e 7074 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7075 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7076 register_name = "SRSConf4";
ead9360e 7077 break;
9023594b 7078 case CP0_REG06__PWCTL:
103be64c
YK
7079 check_pw(ctx);
7080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7081 register_name = "PWCtl";
103be64c 7082 break;
7a387fff 7083 default:
f31b035a 7084 goto cp0_unimplemented;
1579a72e 7085 }
873eb012 7086 break;
04992c8c 7087 case CP0_REGISTER_07:
7a387fff 7088 switch (sel) {
143a9875 7089 case CP0_REG07__HWRENA:
d75c135e 7090 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7092 register_name = "HWREna";
2423f660 7093 break;
7a387fff 7094 default:
f31b035a 7095 goto cp0_unimplemented;
1579a72e 7096 }
8c0fdd85 7097 break;
04992c8c 7098 case CP0_REGISTER_08:
7a387fff 7099 switch (sel) {
67d167d2 7100 case CP0_REG08__BADVADDR:
7db13fae 7101 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7102 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7103 register_name = "BadVAddr";
2423f660 7104 break;
67d167d2 7105 case CP0_REG08__BADINSTR:
f31b035a
LA
7106 CP0_CHECK(ctx->bi);
7107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7108 register_name = "BadInstr";
aea14095 7109 break;
67d167d2 7110 case CP0_REG08__BADINSTRP:
f31b035a
LA
7111 CP0_CHECK(ctx->bp);
7112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7113 register_name = "BadInstrP";
aea14095 7114 break;
67d167d2 7115 case CP0_REG08__BADINSTRX:
25beba9b
SM
7116 CP0_CHECK(ctx->bi);
7117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7118 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7119 register_name = "BadInstrX";
25beba9b 7120 break;
05aa7e93 7121 default:
f31b035a 7122 goto cp0_unimplemented;
aea14095 7123 }
873eb012 7124 break;
04992c8c 7125 case CP0_REGISTER_09:
7a387fff 7126 switch (sel) {
e5a98a72 7127 case CP0_REG09__COUNT:
2e70f6ef 7128 /* Mark as an IO operation because we read the time. */
eeb3bba8 7129 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7130 gen_io_start();
7d37435b 7131 }
895c2d04 7132 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7133 /*
7134 * Break the TB to be able to take timer interrupts immediately
7135 * after reading count. DISAS_STOP isn't sufficient, we need to
7136 * ensure we break completely out of translated code.
7137 */
eeb3bba8
EC
7138 gen_save_pc(ctx->base.pc_next + 4);
7139 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7140 register_name = "Count";
2423f660 7141 break;
e5a98a72 7142 case CP0_REG09__SAARI:
5fb2dcd1
YK
7143 CP0_CHECK(ctx->saar);
7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7145 register_name = "SAARI";
5fb2dcd1 7146 break;
e5a98a72 7147 case CP0_REG09__SAAR:
5fb2dcd1
YK
7148 CP0_CHECK(ctx->saar);
7149 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7150 register_name = "SAAR";
5fb2dcd1 7151 break;
7a387fff 7152 default:
f31b035a 7153 goto cp0_unimplemented;
2423f660 7154 }
873eb012 7155 break;
04992c8c 7156 case CP0_REGISTER_10:
7a387fff 7157 switch (sel) {
860ffef0 7158 case CP0_REG10__ENTRYHI:
7db13fae 7159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7160 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7161 register_name = "EntryHi";
2423f660 7162 break;
7a387fff 7163 default:
f31b035a 7164 goto cp0_unimplemented;
1579a72e 7165 }
873eb012 7166 break;
04992c8c 7167 case CP0_REGISTER_11:
7a387fff 7168 switch (sel) {
f5f3834f 7169 case CP0_REG11__COMPARE:
7db13fae 7170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7171 register_name = "Compare";
2423f660
TS
7172 break;
7173 /* 6,7 are implementation dependent */
7a387fff 7174 default:
f31b035a 7175 goto cp0_unimplemented;
2423f660 7176 }
873eb012 7177 break;
04992c8c 7178 case CP0_REGISTER_12:
7a387fff 7179 switch (sel) {
2b084867 7180 case CP0_REG12__STATUS:
7db13fae 7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7182 register_name = "Status";
2423f660 7183 break;
2b084867 7184 case CP0_REG12__INTCTL:
d75c135e 7185 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7187 register_name = "IntCtl";
2423f660 7188 break;
2b084867 7189 case CP0_REG12__SRSCTL:
d75c135e 7190 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7192 register_name = "SRSCtl";
2423f660 7193 break;
2b084867 7194 case CP0_REG12__SRSMAP:
d75c135e 7195 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7197 register_name = "SRSMap";
fd88b6ab 7198 break;
7a387fff 7199 default:
f31b035a 7200 goto cp0_unimplemented;
7a387fff 7201 }
873eb012 7202 break;
04992c8c 7203 case CP0_REGISTER_13:
7a387fff 7204 switch (sel) {
e3c7559d 7205 case CP0_REG13__CAUSE:
7db13fae 7206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7207 register_name = "Cause";
2423f660 7208 break;
7a387fff 7209 default:
f31b035a 7210 goto cp0_unimplemented;
7a387fff 7211 }
873eb012 7212 break;
04992c8c 7213 case CP0_REGISTER_14:
7a387fff 7214 switch (sel) {
35e4b54d 7215 case CP0_REG14__EPC:
7db13fae 7216 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7217 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7218 register_name = "EPC";
2423f660 7219 break;
7a387fff 7220 default:
f31b035a 7221 goto cp0_unimplemented;
1579a72e 7222 }
873eb012 7223 break;
04992c8c 7224 case CP0_REGISTER_15:
7a387fff 7225 switch (sel) {
4466cd49 7226 case CP0_REG15__PRID:
7db13fae 7227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7228 register_name = "PRid";
2423f660 7229 break;
4466cd49 7230 case CP0_REG15__EBASE:
d75c135e 7231 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
7232 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7233 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7234 register_name = "EBase";
2423f660 7235 break;
4466cd49 7236 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
7237 check_insn(ctx, ISA_MIPS32R2);
7238 CP0_CHECK(ctx->cmgcr);
7239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7240 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7241 register_name = "CMGCRBase";
c870e3f5 7242 break;
7a387fff 7243 default:
f31b035a 7244 goto cp0_unimplemented;
7a387fff 7245 }
873eb012 7246 break;
04992c8c 7247 case CP0_REGISTER_16:
873eb012 7248 switch (sel) {
433efb4c 7249 case CP0_REG16__CONFIG:
7db13fae 7250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7251 register_name = "Config";
873eb012 7252 break;
433efb4c 7253 case CP0_REG16__CONFIG1:
7db13fae 7254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7255 register_name = "Config1";
873eb012 7256 break;
433efb4c 7257 case CP0_REG16__CONFIG2:
7db13fae 7258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7259 register_name = "Config2";
7a387fff 7260 break;
433efb4c 7261 case CP0_REG16__CONFIG3:
7db13fae 7262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7263 register_name = "Config3";
7a387fff 7264 break;
433efb4c 7265 case CP0_REG16__CONFIG4:
b4160af1 7266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7267 register_name = "Config4";
b4160af1 7268 break;
433efb4c 7269 case CP0_REG16__CONFIG5:
b4dd99a3 7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7271 register_name = "Config5";
b4dd99a3 7272 break;
e397ee33 7273 /* 6,7 are implementation dependent */
433efb4c 7274 case CP0_REG16__CONFIG6:
7db13fae 7275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7276 register_name = "Config6";
e397ee33 7277 break;
433efb4c 7278 case CP0_REG16__CONFIG7:
7db13fae 7279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7280 register_name = "Config7";
e397ee33 7281 break;
873eb012 7282 default:
f31b035a 7283 goto cp0_unimplemented;
873eb012
TS
7284 }
7285 break;
04992c8c 7286 case CP0_REGISTER_17:
7a387fff 7287 switch (sel) {
706ce142 7288 case CP0_REG17__LLADDR:
895c2d04 7289 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7290 register_name = "LLAddr";
2423f660 7291 break;
706ce142 7292 case CP0_REG17__MAAR:
f6d4dd81
YK
7293 CP0_CHECK(ctx->mrp);
7294 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7295 register_name = "MAAR";
f6d4dd81 7296 break;
706ce142 7297 case CP0_REG17__MAARI:
f6d4dd81
YK
7298 CP0_CHECK(ctx->mrp);
7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7300 register_name = "MAARI";
f6d4dd81 7301 break;
7a387fff 7302 default:
f31b035a 7303 goto cp0_unimplemented;
7a387fff 7304 }
873eb012 7305 break;
04992c8c 7306 case CP0_REGISTER_18:
7a387fff 7307 switch (sel) {
e8dcfe82
AM
7308 case CP0_REG18__WATCHLO0:
7309 case CP0_REG18__WATCHLO1:
7310 case CP0_REG18__WATCHLO2:
7311 case CP0_REG18__WATCHLO3:
7312 case CP0_REG18__WATCHLO4:
7313 case CP0_REG18__WATCHLO5:
7314 case CP0_REG18__WATCHLO6:
7315 case CP0_REG18__WATCHLO7:
fa192d49 7316 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7317 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7318 register_name = "WatchLo";
2423f660 7319 break;
7a387fff 7320 default:
f31b035a 7321 goto cp0_unimplemented;
7a387fff 7322 }
873eb012 7323 break;
04992c8c 7324 case CP0_REGISTER_19:
7a387fff 7325 switch (sel) {
be274dc1
AM
7326 case CP0_REG19__WATCHHI0:
7327 case CP0_REG19__WATCHHI1:
7328 case CP0_REG19__WATCHHI2:
7329 case CP0_REG19__WATCHHI3:
7330 case CP0_REG19__WATCHHI4:
7331 case CP0_REG19__WATCHHI5:
7332 case CP0_REG19__WATCHHI6:
7333 case CP0_REG19__WATCHHI7:
fa192d49 7334 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7335 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7336 register_name = "WatchHi";
2423f660 7337 break;
7a387fff 7338 default:
f31b035a 7339 goto cp0_unimplemented;
7a387fff 7340 }
873eb012 7341 break;
04992c8c 7342 case CP0_REGISTER_20:
7a387fff 7343 switch (sel) {
14f92b0b 7344 case CP0_REG20__XCONTEXT:
d26bc211 7345#if defined(TARGET_MIPS64)
d75c135e 7346 check_insn(ctx, ISA_MIPS3);
7db13fae 7347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7348 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7349 register_name = "XContext";
2423f660 7350 break;
703eaf37 7351#endif
7a387fff 7352 default:
f31b035a 7353 goto cp0_unimplemented;
7a387fff 7354 }
8c0fdd85 7355 break;
04992c8c 7356 case CP0_REGISTER_21:
7a387fff 7357 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7358 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7359 switch (sel) {
7360 case 0:
7db13fae 7361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7362 register_name = "Framemask";
2423f660 7363 break;
7a387fff 7364 default:
f31b035a 7365 goto cp0_unimplemented;
7a387fff 7366 }
8c0fdd85 7367 break;
04992c8c 7368 case CP0_REGISTER_22:
d9bea114 7369 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7370 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7371 break;
04992c8c 7372 case CP0_REGISTER_23:
7a387fff 7373 switch (sel) {
4cbf4b6d 7374 case CP0_REG23__DEBUG:
895c2d04 7375 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7376 register_name = "Debug";
2423f660 7377 break;
4cbf4b6d
AM
7378 case CP0_REG23__TRACECONTROL:
7379 /* PDtrace support */
7380 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 7381 register_name = "TraceControl";
3570d7f6 7382 goto cp0_unimplemented;
4cbf4b6d
AM
7383 case CP0_REG23__TRACECONTROL2:
7384 /* PDtrace support */
7385 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 7386 register_name = "TraceControl2";
3570d7f6 7387 goto cp0_unimplemented;
4cbf4b6d
AM
7388 case CP0_REG23__USERTRACEDATA1:
7389 /* PDtrace support */
7390 /* gen_helper_mfc0_usertracedata1(arg);*/
7391 register_name = "UserTraceData1";
3570d7f6 7392 goto cp0_unimplemented;
4cbf4b6d
AM
7393 case CP0_REG23__TRACEIBPC:
7394 /* PDtrace support */
7395 /* gen_helper_mfc0_traceibpc(arg); */
7396 register_name = "TraceIBPC";
7397 goto cp0_unimplemented;
7398 case CP0_REG23__TRACEDBPC:
7399 /* PDtrace support */
7400 /* gen_helper_mfc0_tracedbpc(arg); */
7401 register_name = "TraceDBPC";
3570d7f6 7402 goto cp0_unimplemented;
7a387fff 7403 default:
f31b035a 7404 goto cp0_unimplemented;
7a387fff 7405 }
873eb012 7406 break;
04992c8c 7407 case CP0_REGISTER_24:
7a387fff 7408 switch (sel) {
8d7b4b6e 7409 case CP0_REG24__DEPC:
f0b3f3ae 7410 /* EJTAG support */
7db13fae 7411 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7412 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7413 register_name = "DEPC";
2423f660 7414 break;
7a387fff 7415 default:
f31b035a 7416 goto cp0_unimplemented;
7a387fff 7417 }
873eb012 7418 break;
04992c8c 7419 case CP0_REGISTER_25:
7a387fff 7420 switch (sel) {
1176b328 7421 case CP0_REG25__PERFCTL0:
7db13fae 7422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7423 register_name = "Performance0";
7a387fff 7424 break;
1176b328 7425 case CP0_REG25__PERFCNT0:
7480515f 7426 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 7427 register_name = "Performance1";
3570d7f6 7428 goto cp0_unimplemented;
1176b328 7429 case CP0_REG25__PERFCTL1:
7480515f 7430 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 7431 register_name = "Performance2";
3570d7f6 7432 goto cp0_unimplemented;
1176b328 7433 case CP0_REG25__PERFCNT1:
7480515f 7434 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 7435 register_name = "Performance3";
3570d7f6 7436 goto cp0_unimplemented;
1176b328 7437 case CP0_REG25__PERFCTL2:
7480515f 7438 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 7439 register_name = "Performance4";
3570d7f6 7440 goto cp0_unimplemented;
1176b328 7441 case CP0_REG25__PERFCNT2:
7480515f 7442 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 7443 register_name = "Performance5";
3570d7f6 7444 goto cp0_unimplemented;
1176b328 7445 case CP0_REG25__PERFCTL3:
7480515f 7446 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 7447 register_name = "Performance6";
3570d7f6 7448 goto cp0_unimplemented;
1176b328 7449 case CP0_REG25__PERFCNT3:
7480515f 7450 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 7451 register_name = "Performance7";
3570d7f6 7452 goto cp0_unimplemented;
7a387fff 7453 default:
f31b035a 7454 goto cp0_unimplemented;
7a387fff 7455 }
8c0fdd85 7456 break;
04992c8c 7457 case CP0_REGISTER_26:
0d74a222 7458 switch (sel) {
dbbf08b2 7459 case CP0_REG26__ERRCTL:
0d74a222 7460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7461 register_name = "ErrCtl";
0d74a222
LA
7462 break;
7463 default:
7464 goto cp0_unimplemented;
7465 }
da80682b 7466 break;
04992c8c 7467 case CP0_REGISTER_27:
7a387fff 7468 switch (sel) {
5a10873d 7469 case CP0_REG27__CACHERR:
d9bea114 7470 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7471 register_name = "CacheErr";
2423f660 7472 break;
7a387fff 7473 default:
f31b035a 7474 goto cp0_unimplemented;
7a387fff 7475 }
8c0fdd85 7476 break;
04992c8c 7477 case CP0_REGISTER_28:
873eb012 7478 switch (sel) {
a30e2f21
AM
7479 case CP0_REG28__TAGLO:
7480 case CP0_REG28__TAGLO1:
7481 case CP0_REG28__TAGLO2:
7482 case CP0_REG28__TAGLO3:
284b731a
LA
7483 {
7484 TCGv_i64 tmp = tcg_temp_new_i64();
7485 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7486 gen_move_low32(arg, tmp);
7487 tcg_temp_free_i64(tmp);
7488 }
294fc2ea 7489 register_name = "TagLo";
873eb012 7490 break;
a30e2f21
AM
7491 case CP0_REG28__DATALO:
7492 case CP0_REG28__DATALO1:
7493 case CP0_REG28__DATALO2:
7494 case CP0_REG28__DATALO3:
7db13fae 7495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7496 register_name = "DataLo";
873eb012
TS
7497 break;
7498 default:
f31b035a 7499 goto cp0_unimplemented;
873eb012
TS
7500 }
7501 break;
04992c8c 7502 case CP0_REGISTER_29:
7a387fff 7503 switch (sel) {
af4bb6da
AM
7504 case CP0_REG29__TAGHI:
7505 case CP0_REG29__TAGHI1:
7506 case CP0_REG29__TAGHI2:
7507 case CP0_REG29__TAGHI3:
7db13fae 7508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7509 register_name = "TagHi";
7a387fff 7510 break;
af4bb6da
AM
7511 case CP0_REG29__DATAHI:
7512 case CP0_REG29__DATAHI1:
7513 case CP0_REG29__DATAHI2:
7514 case CP0_REG29__DATAHI3:
7db13fae 7515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7516 register_name = "DataHi";
7a387fff
TS
7517 break;
7518 default:
f31b035a 7519 goto cp0_unimplemented;
7a387fff 7520 }
8c0fdd85 7521 break;
04992c8c 7522 case CP0_REGISTER_30:
7a387fff 7523 switch (sel) {
4bcf121e 7524 case CP0_REG30__ERROREPC:
7db13fae 7525 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7526 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7527 register_name = "ErrorEPC";
2423f660 7528 break;
7a387fff 7529 default:
f31b035a 7530 goto cp0_unimplemented;
7a387fff 7531 }
873eb012 7532 break;
04992c8c 7533 case CP0_REGISTER_31:
7a387fff 7534 switch (sel) {
14d92efd 7535 case CP0_REG31__DESAVE:
f0b3f3ae 7536 /* EJTAG support */
7db13fae 7537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7538 register_name = "DESAVE";
2423f660 7539 break;
14d92efd
AM
7540 case CP0_REG31__KSCRATCH1:
7541 case CP0_REG31__KSCRATCH2:
7542 case CP0_REG31__KSCRATCH3:
7543 case CP0_REG31__KSCRATCH4:
7544 case CP0_REG31__KSCRATCH5:
7545 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7546 CP0_CHECK(ctx->kscrexist & (1 << sel));
7547 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 7548 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 7549 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7550 register_name = "KScratch";
e98c0d17 7551 break;
7a387fff 7552 default:
f31b035a 7553 goto cp0_unimplemented;
7a387fff 7554 }
873eb012
TS
7555 break;
7556 default:
f31b035a 7557 goto cp0_unimplemented;
873eb012 7558 }
294fc2ea 7559 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
7560 return;
7561
f31b035a 7562cp0_unimplemented:
294fc2ea
AM
7563 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7564 register_name, reg, sel);
f31b035a 7565 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7566}
7567
d75c135e 7568static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7569{
294fc2ea 7570 const char *register_name = "invalid";
7a387fff 7571
1f8929d2 7572 if (sel != 0) {
d75c135e 7573 check_insn(ctx, ISA_MIPS32);
1f8929d2 7574 }
e189e748 7575
eeb3bba8 7576 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7577 gen_io_start();
bd79255d 7578 }
2e70f6ef 7579
8c0fdd85 7580 switch (reg) {
04992c8c 7581 case CP0_REGISTER_00:
7a387fff 7582 switch (sel) {
1b142da5 7583 case CP0_REG00__INDEX:
895c2d04 7584 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 7585 register_name = "Index";
7a387fff 7586 break;
1b142da5 7587 case CP0_REG00__MVPCONTROL:
f31b035a 7588 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7589 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 7590 register_name = "MVPControl";
ead9360e 7591 break;
1b142da5 7592 case CP0_REG00__MVPCONF0:
f31b035a 7593 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7594 /* ignored */
294fc2ea 7595 register_name = "MVPConf0";
ead9360e 7596 break;
1b142da5 7597 case CP0_REG00__MVPCONF1:
f31b035a 7598 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7599 /* ignored */
294fc2ea 7600 register_name = "MVPConf1";
ead9360e 7601 break;
1b142da5 7602 case CP0_REG00__VPCONTROL:
01bc435b
YK
7603 CP0_CHECK(ctx->vp);
7604 /* ignored */
294fc2ea 7605 register_name = "VPControl";
01bc435b 7606 break;
7a387fff 7607 default:
f31b035a 7608 goto cp0_unimplemented;
7a387fff 7609 }
8c0fdd85 7610 break;
04992c8c 7611 case CP0_REGISTER_01:
7a387fff 7612 switch (sel) {
30deb460 7613 case CP0_REG01__RANDOM:
2423f660 7614 /* ignored */
294fc2ea 7615 register_name = "Random";
2423f660 7616 break;
30deb460 7617 case CP0_REG01__VPECONTROL:
f31b035a 7618 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7619 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 7620 register_name = "VPEControl";
ead9360e 7621 break;
30deb460 7622 case CP0_REG01__VPECONF0:
f31b035a 7623 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7624 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 7625 register_name = "VPEConf0";
ead9360e 7626 break;
30deb460 7627 case CP0_REG01__VPECONF1:
f31b035a 7628 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7629 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 7630 register_name = "VPEConf1";
ead9360e 7631 break;
30deb460 7632 case CP0_REG01__YQMASK:
f31b035a 7633 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7634 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 7635 register_name = "YQMask";
ead9360e 7636 break;
30deb460 7637 case CP0_REG01__VPESCHEDULE:
f31b035a 7638 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7639 tcg_gen_st_tl(arg, cpu_env,
7640 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7641 register_name = "VPESchedule";
ead9360e 7642 break;
30deb460 7643 case CP0_REG01__VPESCHEFBACK:
f31b035a 7644 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7645 tcg_gen_st_tl(arg, cpu_env,
7646 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7647 register_name = "VPEScheFBack";
ead9360e 7648 break;
30deb460 7649 case CP0_REG01__VPEOPT:
f31b035a 7650 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7651 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 7652 register_name = "VPEOpt";
ead9360e 7653 break;
7a387fff 7654 default:
f31b035a 7655 goto cp0_unimplemented;
7a387fff 7656 }
8c0fdd85 7657 break;
04992c8c 7658 case CP0_REGISTER_02:
7a387fff 7659 switch (sel) {
6d27d5bd 7660 case CP0_REG02__ENTRYLO0:
895c2d04 7661 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 7662 register_name = "EntryLo0";
2423f660 7663 break;
6d27d5bd 7664 case CP0_REG02__TCSTATUS:
f31b035a 7665 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7666 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 7667 register_name = "TCStatus";
ead9360e 7668 break;
6d27d5bd 7669 case CP0_REG02__TCBIND:
f31b035a 7670 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7671 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 7672 register_name = "TCBind";
ead9360e 7673 break;
6d27d5bd 7674 case CP0_REG02__TCRESTART:
f31b035a 7675 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7676 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 7677 register_name = "TCRestart";
ead9360e 7678 break;
6d27d5bd 7679 case CP0_REG02__TCHALT:
f31b035a 7680 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7681 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 7682 register_name = "TCHalt";
ead9360e 7683 break;
6d27d5bd 7684 case CP0_REG02__TCCONTEXT:
f31b035a 7685 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7686 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 7687 register_name = "TCContext";
ead9360e 7688 break;
6d27d5bd 7689 case CP0_REG02__TCSCHEDULE:
f31b035a 7690 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7691 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 7692 register_name = "TCSchedule";
ead9360e 7693 break;
6d27d5bd 7694 case CP0_REG02__TCSCHEFBACK:
f31b035a 7695 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7696 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 7697 register_name = "TCScheFBack";
ead9360e 7698 break;
7a387fff 7699 default:
f31b035a 7700 goto cp0_unimplemented;
7a387fff 7701 }
8c0fdd85 7702 break;
04992c8c 7703 case CP0_REGISTER_03:
7a387fff 7704 switch (sel) {
acd37316 7705 case CP0_REG03__ENTRYLO1:
895c2d04 7706 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 7707 register_name = "EntryLo1";
2423f660 7708 break;
acd37316 7709 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7710 CP0_CHECK(ctx->vp);
7711 /* ignored */
294fc2ea 7712 register_name = "GlobalNumber";
01bc435b 7713 break;
7a387fff 7714 default:
f31b035a 7715 goto cp0_unimplemented;
876d4b07 7716 }
8c0fdd85 7717 break;
04992c8c 7718 case CP0_REGISTER_04:
7a387fff 7719 switch (sel) {
020fe379 7720 case CP0_REG04__CONTEXT:
895c2d04 7721 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 7722 register_name = "Context";
2423f660 7723 break;
020fe379
AM
7724 case CP0_REG04__CONTEXTCONFIG:
7725 /* SmartMIPS ASE */
7726 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 7727 register_name = "ContextConfig";
f31b035a 7728 goto cp0_unimplemented;
020fe379 7729 case CP0_REG04__USERLOCAL:
f31b035a
LA
7730 CP0_CHECK(ctx->ulri);
7731 tcg_gen_st_tl(arg, cpu_env,
7732 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7733 register_name = "UserLocal";
d279279e 7734 break;
7a387fff 7735 default:
f31b035a 7736 goto cp0_unimplemented;
876d4b07 7737 }
8c0fdd85 7738 break;
04992c8c 7739 case CP0_REGISTER_05:
7a387fff 7740 switch (sel) {
a1e76353 7741 case CP0_REG05__PAGEMASK:
895c2d04 7742 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 7743 register_name = "PageMask";
2423f660 7744 break;
a1e76353 7745 case CP0_REG05__PAGEGRAIN:
d75c135e 7746 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7747 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 7748 register_name = "PageGrain";
eeb3bba8 7749 ctx->base.is_jmp = DISAS_STOP;
2423f660 7750 break;
a1e76353 7751 case CP0_REG05__SEGCTL0:
cec56a73
JH
7752 CP0_CHECK(ctx->sc);
7753 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 7754 register_name = "SegCtl0";
cec56a73 7755 break;
a1e76353 7756 case CP0_REG05__SEGCTL1:
cec56a73
JH
7757 CP0_CHECK(ctx->sc);
7758 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 7759 register_name = "SegCtl1";
cec56a73 7760 break;
a1e76353 7761 case CP0_REG05__SEGCTL2:
cec56a73
JH
7762 CP0_CHECK(ctx->sc);
7763 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 7764 register_name = "SegCtl2";
cec56a73 7765 break;
a1e76353 7766 case CP0_REG05__PWBASE:
5e31fdd5
YK
7767 check_pw(ctx);
7768 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7769 register_name = "PWBase";
5e31fdd5 7770 break;
a1e76353 7771 case CP0_REG05__PWFIELD:
fa75ad14
YK
7772 check_pw(ctx);
7773 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 7774 register_name = "PWField";
fa75ad14 7775 break;
a1e76353 7776 case CP0_REG05__PWSIZE:
20b28ebc
YK
7777 check_pw(ctx);
7778 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 7779 register_name = "PWSize";
20b28ebc 7780 break;
7a387fff 7781 default:
f31b035a 7782 goto cp0_unimplemented;
876d4b07 7783 }
8c0fdd85 7784 break;
04992c8c 7785 case CP0_REGISTER_06:
7a387fff 7786 switch (sel) {
9023594b 7787 case CP0_REG06__WIRED:
895c2d04 7788 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 7789 register_name = "Wired";
2423f660 7790 break;
9023594b 7791 case CP0_REG06__SRSCONF0:
d75c135e 7792 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7793 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 7794 register_name = "SRSConf0";
ead9360e 7795 break;
9023594b 7796 case CP0_REG06__SRSCONF1:
d75c135e 7797 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7798 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 7799 register_name = "SRSConf1";
ead9360e 7800 break;
9023594b 7801 case CP0_REG06__SRSCONF2:
d75c135e 7802 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7803 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 7804 register_name = "SRSConf2";
ead9360e 7805 break;
9023594b 7806 case CP0_REG06__SRSCONF3:
d75c135e 7807 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7808 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 7809 register_name = "SRSConf3";
ead9360e 7810 break;
9023594b 7811 case CP0_REG06__SRSCONF4:
d75c135e 7812 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7813 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 7814 register_name = "SRSConf4";
ead9360e 7815 break;
9023594b 7816 case CP0_REG06__PWCTL:
103be64c
YK
7817 check_pw(ctx);
7818 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 7819 register_name = "PWCtl";
103be64c 7820 break;
7a387fff 7821 default:
f31b035a 7822 goto cp0_unimplemented;
876d4b07 7823 }
8c0fdd85 7824 break;
04992c8c 7825 case CP0_REGISTER_07:
7a387fff 7826 switch (sel) {
143a9875 7827 case CP0_REG07__HWRENA:
d75c135e 7828 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7829 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7830 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7831 register_name = "HWREna";
2423f660 7832 break;
7a387fff 7833 default:
f31b035a 7834 goto cp0_unimplemented;
876d4b07 7835 }
8c0fdd85 7836 break;
04992c8c 7837 case CP0_REGISTER_08:
aea14095 7838 switch (sel) {
67d167d2 7839 case CP0_REG08__BADVADDR:
aea14095 7840 /* ignored */
294fc2ea 7841 register_name = "BadVAddr";
aea14095 7842 break;
67d167d2 7843 case CP0_REG08__BADINSTR:
aea14095 7844 /* ignored */
294fc2ea 7845 register_name = "BadInstr";
aea14095 7846 break;
67d167d2 7847 case CP0_REG08__BADINSTRP:
aea14095 7848 /* ignored */
294fc2ea 7849 register_name = "BadInstrP";
aea14095 7850 break;
67d167d2 7851 case CP0_REG08__BADINSTRX:
25beba9b 7852 /* ignored */
294fc2ea 7853 register_name = "BadInstrX";
25beba9b 7854 break;
aea14095 7855 default:
f31b035a 7856 goto cp0_unimplemented;
aea14095 7857 }
8c0fdd85 7858 break;
04992c8c 7859 case CP0_REGISTER_09:
7a387fff 7860 switch (sel) {
e5a98a72 7861 case CP0_REG09__COUNT:
895c2d04 7862 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 7863 register_name = "Count";
2423f660 7864 break;
e5a98a72 7865 case CP0_REG09__SAARI:
5fb2dcd1
YK
7866 CP0_CHECK(ctx->saar);
7867 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 7868 register_name = "SAARI";
5fb2dcd1 7869 break;
e5a98a72 7870 case CP0_REG09__SAAR:
5fb2dcd1
YK
7871 CP0_CHECK(ctx->saar);
7872 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 7873 register_name = "SAAR";
5fb2dcd1 7874 break;
7a387fff 7875 default:
f31b035a 7876 goto cp0_unimplemented;
876d4b07 7877 }
8c0fdd85 7878 break;
04992c8c 7879 case CP0_REGISTER_10:
7a387fff 7880 switch (sel) {
860ffef0 7881 case CP0_REG10__ENTRYHI:
895c2d04 7882 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 7883 register_name = "EntryHi";
2423f660 7884 break;
7a387fff 7885 default:
f31b035a 7886 goto cp0_unimplemented;
876d4b07 7887 }
8c0fdd85 7888 break;
04992c8c 7889 case CP0_REGISTER_11:
7a387fff 7890 switch (sel) {
f5f3834f 7891 case CP0_REG11__COMPARE:
895c2d04 7892 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 7893 register_name = "Compare";
2423f660
TS
7894 break;
7895 /* 6,7 are implementation dependent */
7a387fff 7896 default:
f31b035a 7897 goto cp0_unimplemented;
876d4b07 7898 }
8c0fdd85 7899 break;
04992c8c 7900 case CP0_REGISTER_12:
7a387fff 7901 switch (sel) {
2b084867 7902 case CP0_REG12__STATUS:
867abc7e 7903 save_cpu_state(ctx, 1);
895c2d04 7904 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7905 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7906 gen_save_pc(ctx->base.pc_next + 4);
7907 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7908 register_name = "Status";
2423f660 7909 break;
2b084867 7910 case CP0_REG12__INTCTL:
d75c135e 7911 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7912 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7913 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7914 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7915 register_name = "IntCtl";
2423f660 7916 break;
2b084867 7917 case CP0_REG12__SRSCTL:
d75c135e 7918 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7919 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7920 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7921 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7922 register_name = "SRSCtl";
2423f660 7923 break;
2b084867 7924 case CP0_REG12__SRSMAP:
d75c135e 7925 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7926 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7927 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7928 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7929 register_name = "SRSMap";
fd88b6ab 7930 break;
7a387fff 7931 default:
f31b035a 7932 goto cp0_unimplemented;
876d4b07 7933 }
8c0fdd85 7934 break;
04992c8c 7935 case CP0_REGISTER_13:
7a387fff 7936 switch (sel) {
e3c7559d 7937 case CP0_REG13__CAUSE:
867abc7e 7938 save_cpu_state(ctx, 1);
895c2d04 7939 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
7940 /*
7941 * Stop translation as we may have triggered an interrupt.
b28425ba 7942 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
7943 * translated code to check for pending interrupts.
7944 */
eeb3bba8
EC
7945 gen_save_pc(ctx->base.pc_next + 4);
7946 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7947 register_name = "Cause";
2423f660 7948 break;
7a387fff 7949 default:
f31b035a 7950 goto cp0_unimplemented;
876d4b07 7951 }
8c0fdd85 7952 break;
04992c8c 7953 case CP0_REGISTER_14:
7a387fff 7954 switch (sel) {
35e4b54d 7955 case CP0_REG14__EPC:
d54a299b 7956 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7957 register_name = "EPC";
2423f660 7958 break;
7a387fff 7959 default:
f31b035a 7960 goto cp0_unimplemented;
876d4b07 7961 }
8c0fdd85 7962 break;
04992c8c 7963 case CP0_REGISTER_15:
7a387fff 7964 switch (sel) {
4466cd49 7965 case CP0_REG15__PRID:
2423f660 7966 /* ignored */
294fc2ea 7967 register_name = "PRid";
2423f660 7968 break;
4466cd49 7969 case CP0_REG15__EBASE:
d75c135e 7970 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7971 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 7972 register_name = "EBase";
2423f660 7973 break;
7a387fff 7974 default:
f31b035a 7975 goto cp0_unimplemented;
1579a72e 7976 }
8c0fdd85 7977 break;
04992c8c 7978 case CP0_REGISTER_16:
8c0fdd85 7979 switch (sel) {
433efb4c 7980 case CP0_REG16__CONFIG:
895c2d04 7981 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 7982 register_name = "Config";
2423f660 7983 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7984 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7985 break;
433efb4c 7986 case CP0_REG16__CONFIG1:
e397ee33 7987 /* ignored, read only */
294fc2ea 7988 register_name = "Config1";
7a387fff 7989 break;
433efb4c 7990 case CP0_REG16__CONFIG2:
895c2d04 7991 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 7992 register_name = "Config2";
2423f660 7993 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7994 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7995 break;
433efb4c 7996 case CP0_REG16__CONFIG3:
90f12d73 7997 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 7998 register_name = "Config3";
90f12d73 7999 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8000 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8001 break;
433efb4c 8002 case CP0_REG16__CONFIG4:
b4160af1 8003 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 8004 register_name = "Config4";
eeb3bba8 8005 ctx->base.is_jmp = DISAS_STOP;
b4160af1 8006 break;
433efb4c 8007 case CP0_REG16__CONFIG5:
b4dd99a3 8008 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8009 register_name = "Config5";
b4dd99a3 8010 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8011 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 8012 break;
e397ee33 8013 /* 6,7 are implementation dependent */
433efb4c 8014 case CP0_REG16__CONFIG6:
e397ee33 8015 /* ignored */
294fc2ea 8016 register_name = "Config6";
e397ee33 8017 break;
433efb4c 8018 case CP0_REG16__CONFIG7:
e397ee33 8019 /* ignored */
294fc2ea 8020 register_name = "Config7";
e397ee33 8021 break;
8c0fdd85 8022 default:
294fc2ea 8023 register_name = "Invalid config selector";
f31b035a 8024 goto cp0_unimplemented;
8c0fdd85
TS
8025 }
8026 break;
04992c8c 8027 case CP0_REGISTER_17:
7a387fff 8028 switch (sel) {
706ce142 8029 case CP0_REG17__LLADDR:
895c2d04 8030 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8031 register_name = "LLAddr";
2423f660 8032 break;
706ce142 8033 case CP0_REG17__MAAR:
f6d4dd81
YK
8034 CP0_CHECK(ctx->mrp);
8035 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8036 register_name = "MAAR";
f6d4dd81 8037 break;
706ce142 8038 case CP0_REG17__MAARI:
f6d4dd81
YK
8039 CP0_CHECK(ctx->mrp);
8040 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8041 register_name = "MAARI";
f6d4dd81 8042 break;
7a387fff 8043 default:
f31b035a 8044 goto cp0_unimplemented;
7a387fff 8045 }
8c0fdd85 8046 break;
04992c8c 8047 case CP0_REGISTER_18:
7a387fff 8048 switch (sel) {
e8dcfe82
AM
8049 case CP0_REG18__WATCHLO0:
8050 case CP0_REG18__WATCHLO1:
8051 case CP0_REG18__WATCHLO2:
8052 case CP0_REG18__WATCHLO3:
8053 case CP0_REG18__WATCHLO4:
8054 case CP0_REG18__WATCHLO5:
8055 case CP0_REG18__WATCHLO6:
8056 case CP0_REG18__WATCHLO7:
fa192d49 8057 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8058 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8059 register_name = "WatchLo";
2423f660 8060 break;
7a387fff 8061 default:
f31b035a 8062 goto cp0_unimplemented;
7a387fff 8063 }
8c0fdd85 8064 break;
04992c8c 8065 case CP0_REGISTER_19:
7a387fff 8066 switch (sel) {
be274dc1
AM
8067 case CP0_REG19__WATCHHI0:
8068 case CP0_REG19__WATCHHI1:
8069 case CP0_REG19__WATCHHI2:
8070 case CP0_REG19__WATCHHI3:
8071 case CP0_REG19__WATCHHI4:
8072 case CP0_REG19__WATCHHI5:
8073 case CP0_REG19__WATCHHI6:
8074 case CP0_REG19__WATCHHI7:
fa192d49 8075 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8076 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8077 register_name = "WatchHi";
2423f660 8078 break;
7a387fff 8079 default:
f31b035a 8080 goto cp0_unimplemented;
7a387fff 8081 }
8c0fdd85 8082 break;
04992c8c 8083 case CP0_REGISTER_20:
7a387fff 8084 switch (sel) {
14f92b0b 8085 case CP0_REG20__XCONTEXT:
d26bc211 8086#if defined(TARGET_MIPS64)
d75c135e 8087 check_insn(ctx, ISA_MIPS3);
895c2d04 8088 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8089 register_name = "XContext";
2423f660 8090 break;
703eaf37 8091#endif
7a387fff 8092 default:
f31b035a 8093 goto cp0_unimplemented;
7a387fff 8094 }
8c0fdd85 8095 break;
04992c8c 8096 case CP0_REGISTER_21:
7a387fff 8097 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8098 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
8099 switch (sel) {
8100 case 0:
895c2d04 8101 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8102 register_name = "Framemask";
2423f660 8103 break;
7a387fff 8104 default:
f31b035a 8105 goto cp0_unimplemented;
7a387fff
TS
8106 }
8107 break;
04992c8c 8108 case CP0_REGISTER_22:
7a387fff 8109 /* ignored */
294fc2ea 8110 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8111 break;
04992c8c 8112 case CP0_REGISTER_23:
7a387fff 8113 switch (sel) {
4cbf4b6d 8114 case CP0_REG23__DEBUG:
895c2d04 8115 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8116 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8117 gen_save_pc(ctx->base.pc_next + 4);
8118 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8119 register_name = "Debug";
2423f660 8120 break;
4cbf4b6d
AM
8121 case CP0_REG23__TRACECONTROL:
8122 /* PDtrace support */
8123 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 8124 register_name = "TraceControl";
8487327a 8125 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8126 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8127 goto cp0_unimplemented;
4cbf4b6d
AM
8128 case CP0_REG23__TRACECONTROL2:
8129 /* PDtrace support */
8130 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 8131 register_name = "TraceControl2";
8487327a 8132 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8133 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8134 goto cp0_unimplemented;
4cbf4b6d 8135 case CP0_REG23__USERTRACEDATA1:
8487327a 8136 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8137 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8138 /* PDtrace support */
8139 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 8140 register_name = "UserTraceData";
8487327a 8141 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8142 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8143 goto cp0_unimplemented;
4cbf4b6d
AM
8144 case CP0_REG23__TRACEIBPC:
8145 /* PDtrace support */
8146 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 8147 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8148 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8149 register_name = "TraceIBPC";
8150 goto cp0_unimplemented;
8151 case CP0_REG23__TRACEDBPC:
8152 /* PDtrace support */
8153 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8154 /* Stop translation as we may have switched the execution mode */
8155 ctx->base.is_jmp = DISAS_STOP;
8156 register_name = "TraceDBPC";
3570d7f6 8157 goto cp0_unimplemented;
7a387fff 8158 default:
f31b035a 8159 goto cp0_unimplemented;
7a387fff 8160 }
8c0fdd85 8161 break;
04992c8c 8162 case CP0_REGISTER_24:
7a387fff 8163 switch (sel) {
8d7b4b6e 8164 case CP0_REG24__DEPC:
f1aa6320 8165 /* EJTAG support */
d54a299b 8166 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8167 register_name = "DEPC";
2423f660 8168 break;
7a387fff 8169 default:
f31b035a 8170 goto cp0_unimplemented;
7a387fff 8171 }
8c0fdd85 8172 break;
04992c8c 8173 case CP0_REGISTER_25:
7a387fff 8174 switch (sel) {
1176b328 8175 case CP0_REG25__PERFCTL0:
895c2d04 8176 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8177 register_name = "Performance0";
2423f660 8178 break;
1176b328 8179 case CP0_REG25__PERFCNT0:
7480515f 8180 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 8181 register_name = "Performance1";
3570d7f6 8182 goto cp0_unimplemented;
1176b328 8183 case CP0_REG25__PERFCTL1:
7480515f 8184 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 8185 register_name = "Performance2";
3570d7f6 8186 goto cp0_unimplemented;
1176b328 8187 case CP0_REG25__PERFCNT1:
7480515f 8188 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 8189 register_name = "Performance3";
3570d7f6 8190 goto cp0_unimplemented;
1176b328 8191 case CP0_REG25__PERFCTL2:
7480515f 8192 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 8193 register_name = "Performance4";
3570d7f6 8194 goto cp0_unimplemented;
1176b328 8195 case CP0_REG25__PERFCNT2:
7480515f 8196 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 8197 register_name = "Performance5";
3570d7f6 8198 goto cp0_unimplemented;
1176b328 8199 case CP0_REG25__PERFCTL3:
7480515f 8200 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 8201 register_name = "Performance6";
3570d7f6 8202 goto cp0_unimplemented;
1176b328 8203 case CP0_REG25__PERFCNT3:
7480515f 8204 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 8205 register_name = "Performance7";
3570d7f6 8206 goto cp0_unimplemented;
7a387fff 8207 default:
f31b035a 8208 goto cp0_unimplemented;
7a387fff 8209 }
8c0fdd85 8210 break;
04992c8c 8211 case CP0_REGISTER_26:
0d74a222 8212 switch (sel) {
dbbf08b2 8213 case CP0_REG26__ERRCTL:
0d74a222 8214 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8215 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8216 register_name = "ErrCtl";
0d74a222
LA
8217 break;
8218 default:
8219 goto cp0_unimplemented;
8220 }
2423f660 8221 break;
04992c8c 8222 case CP0_REGISTER_27:
7a387fff 8223 switch (sel) {
5a10873d 8224 case CP0_REG27__CACHERR:
2423f660 8225 /* ignored */
294fc2ea 8226 register_name = "CacheErr";
2423f660 8227 break;
7a387fff 8228 default:
f31b035a 8229 goto cp0_unimplemented;
7a387fff 8230 }
8c0fdd85 8231 break;
04992c8c 8232 case CP0_REGISTER_28:
8c0fdd85 8233 switch (sel) {
a30e2f21
AM
8234 case CP0_REG28__TAGLO:
8235 case CP0_REG28__TAGLO1:
8236 case CP0_REG28__TAGLO2:
8237 case CP0_REG28__TAGLO3:
895c2d04 8238 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8239 register_name = "TagLo";
8c0fdd85 8240 break;
a30e2f21
AM
8241 case CP0_REG28__DATALO:
8242 case CP0_REG28__DATALO1:
8243 case CP0_REG28__DATALO2:
8244 case CP0_REG28__DATALO3:
895c2d04 8245 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8246 register_name = "DataLo";
7a387fff 8247 break;
8c0fdd85 8248 default:
f31b035a 8249 goto cp0_unimplemented;
8c0fdd85
TS
8250 }
8251 break;
04992c8c 8252 case CP0_REGISTER_29:
7a387fff 8253 switch (sel) {
af4bb6da
AM
8254 case CP0_REG29__TAGHI:
8255 case CP0_REG29__TAGHI1:
8256 case CP0_REG29__TAGHI2:
8257 case CP0_REG29__TAGHI3:
895c2d04 8258 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8259 register_name = "TagHi";
7a387fff 8260 break;
af4bb6da
AM
8261 case CP0_REG29__DATAHI:
8262 case CP0_REG29__DATAHI1:
8263 case CP0_REG29__DATAHI2:
8264 case CP0_REG29__DATAHI3:
895c2d04 8265 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8266 register_name = "DataHi";
7a387fff
TS
8267 break;
8268 default:
294fc2ea 8269 register_name = "invalid sel";
f31b035a 8270 goto cp0_unimplemented;
7a387fff 8271 }
8c0fdd85 8272 break;
04992c8c 8273 case CP0_REGISTER_30:
7a387fff 8274 switch (sel) {
4bcf121e 8275 case CP0_REG30__ERROREPC:
d54a299b 8276 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8277 register_name = "ErrorEPC";
2423f660 8278 break;
7a387fff 8279 default:
f31b035a 8280 goto cp0_unimplemented;
7a387fff 8281 }
8c0fdd85 8282 break;
04992c8c 8283 case CP0_REGISTER_31:
7a387fff 8284 switch (sel) {
14d92efd 8285 case CP0_REG31__DESAVE:
f1aa6320 8286 /* EJTAG support */
7db13fae 8287 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8288 register_name = "DESAVE";
2423f660 8289 break;
14d92efd
AM
8290 case CP0_REG31__KSCRATCH1:
8291 case CP0_REG31__KSCRATCH2:
8292 case CP0_REG31__KSCRATCH3:
8293 case CP0_REG31__KSCRATCH4:
8294 case CP0_REG31__KSCRATCH5:
8295 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8296 CP0_CHECK(ctx->kscrexist & (1 << sel));
8297 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 8298 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8299 register_name = "KScratch";
e98c0d17 8300 break;
7a387fff 8301 default:
f31b035a 8302 goto cp0_unimplemented;
7a387fff 8303 }
8c0fdd85
TS
8304 break;
8305 default:
f31b035a 8306 goto cp0_unimplemented;
8c0fdd85 8307 }
294fc2ea 8308 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8309
bf20dc07 8310 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8311 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8312 /*
8313 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8314 * translated code to check for pending interrupts.
8315 */
eeb3bba8
EC
8316 gen_save_pc(ctx->base.pc_next + 4);
8317 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8318 }
8c0fdd85
TS
8319 return;
8320
f31b035a 8321cp0_unimplemented:
294fc2ea
AM
8322 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8323 register_name, reg, sel);
8c0fdd85
TS
8324}
8325
d26bc211 8326#if defined(TARGET_MIPS64)
d75c135e 8327static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8328{
294fc2ea 8329 const char *register_name = "invalid";
9c2149c8 8330
1f8929d2 8331 if (sel != 0) {
d75c135e 8332 check_insn(ctx, ISA_MIPS64);
1f8929d2 8333 }
e189e748 8334
9c2149c8 8335 switch (reg) {
04992c8c 8336 case CP0_REGISTER_00:
9c2149c8 8337 switch (sel) {
1b142da5 8338 case CP0_REG00__INDEX:
7db13fae 8339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8340 register_name = "Index";
9c2149c8 8341 break;
1b142da5 8342 case CP0_REG00__MVPCONTROL:
f31b035a 8343 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8344 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8345 register_name = "MVPControl";
ead9360e 8346 break;
1b142da5 8347 case CP0_REG00__MVPCONF0:
f31b035a 8348 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8349 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8350 register_name = "MVPConf0";
ead9360e 8351 break;
1b142da5 8352 case CP0_REG00__MVPCONF1:
f31b035a 8353 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8354 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8355 register_name = "MVPConf1";
ead9360e 8356 break;
1b142da5 8357 case CP0_REG00__VPCONTROL:
01bc435b
YK
8358 CP0_CHECK(ctx->vp);
8359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8360 register_name = "VPControl";
01bc435b 8361 break;
9c2149c8 8362 default:
f31b035a 8363 goto cp0_unimplemented;
9c2149c8
TS
8364 }
8365 break;
04992c8c 8366 case CP0_REGISTER_01:
9c2149c8 8367 switch (sel) {
30deb460 8368 case CP0_REG01__RANDOM:
f31b035a 8369 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 8370 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8371 register_name = "Random";
2423f660 8372 break;
30deb460 8373 case CP0_REG01__VPECONTROL:
f31b035a 8374 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8376 register_name = "VPEControl";
ead9360e 8377 break;
30deb460 8378 case CP0_REG01__VPECONF0:
f31b035a 8379 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8381 register_name = "VPEConf0";
ead9360e 8382 break;
30deb460 8383 case CP0_REG01__VPECONF1:
f31b035a 8384 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 8386 register_name = "VPEConf1";
ead9360e 8387 break;
30deb460 8388 case CP0_REG01__YQMASK:
f31b035a 8389 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8390 tcg_gen_ld_tl(arg, cpu_env,
8391 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 8392 register_name = "YQMask";
ead9360e 8393 break;
30deb460 8394 case CP0_REG01__VPESCHEDULE:
f31b035a 8395 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8396 tcg_gen_ld_tl(arg, cpu_env,
8397 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8398 register_name = "VPESchedule";
ead9360e 8399 break;
30deb460 8400 case CP0_REG01__VPESCHEFBACK:
f31b035a 8401 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8402 tcg_gen_ld_tl(arg, cpu_env,
8403 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8404 register_name = "VPEScheFBack";
ead9360e 8405 break;
30deb460 8406 case CP0_REG01__VPEOPT:
f31b035a 8407 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 8409 register_name = "VPEOpt";
ead9360e 8410 break;
9c2149c8 8411 default:
f31b035a 8412 goto cp0_unimplemented;
9c2149c8
TS
8413 }
8414 break;
04992c8c 8415 case CP0_REGISTER_02:
9c2149c8 8416 switch (sel) {
6d27d5bd 8417 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
8418 tcg_gen_ld_tl(arg, cpu_env,
8419 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 8420 register_name = "EntryLo0";
2423f660 8421 break;
6d27d5bd 8422 case CP0_REG02__TCSTATUS:
f31b035a 8423 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8424 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 8425 register_name = "TCStatus";
ead9360e 8426 break;
6d27d5bd 8427 case CP0_REG02__TCBIND:
f31b035a 8428 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8429 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 8430 register_name = "TCBind";
ead9360e 8431 break;
6d27d5bd 8432 case CP0_REG02__TCRESTART:
f31b035a 8433 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8434 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 8435 register_name = "TCRestart";
ead9360e 8436 break;
6d27d5bd 8437 case CP0_REG02__TCHALT:
f31b035a 8438 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8439 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 8440 register_name = "TCHalt";
ead9360e 8441 break;
6d27d5bd 8442 case CP0_REG02__TCCONTEXT:
f31b035a 8443 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8444 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 8445 register_name = "TCContext";
ead9360e 8446 break;
6d27d5bd 8447 case CP0_REG02__TCSCHEDULE:
f31b035a 8448 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8449 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 8450 register_name = "TCSchedule";
ead9360e 8451 break;
6d27d5bd 8452 case CP0_REG02__TCSCHEFBACK:
f31b035a 8453 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8454 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 8455 register_name = "TCScheFBack";
ead9360e 8456 break;
9c2149c8 8457 default:
f31b035a 8458 goto cp0_unimplemented;
9c2149c8
TS
8459 }
8460 break;
04992c8c 8461 case CP0_REGISTER_03:
9c2149c8 8462 switch (sel) {
acd37316 8463 case CP0_REG03__ENTRYLO1:
7db13fae 8464 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 8465 register_name = "EntryLo1";
2423f660 8466 break;
acd37316 8467 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8468 CP0_CHECK(ctx->vp);
8469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 8470 register_name = "GlobalNumber";
01bc435b 8471 break;
9c2149c8 8472 default:
f31b035a 8473 goto cp0_unimplemented;
1579a72e 8474 }
9c2149c8 8475 break;
04992c8c 8476 case CP0_REGISTER_04:
9c2149c8 8477 switch (sel) {
020fe379 8478 case CP0_REG04__CONTEXT:
7db13fae 8479 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 8480 register_name = "Context";
2423f660 8481 break;
020fe379
AM
8482 case CP0_REG04__CONTEXTCONFIG:
8483 /* SmartMIPS ASE */
8484 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 8485 register_name = "ContextConfig";
f31b035a 8486 goto cp0_unimplemented;
020fe379 8487 case CP0_REG04__USERLOCAL:
f31b035a
LA
8488 CP0_CHECK(ctx->ulri);
8489 tcg_gen_ld_tl(arg, cpu_env,
8490 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8491 register_name = "UserLocal";
d279279e 8492 break;
9c2149c8 8493 default:
f31b035a 8494 goto cp0_unimplemented;
876d4b07 8495 }
9c2149c8 8496 break;
04992c8c 8497 case CP0_REGISTER_05:
9c2149c8 8498 switch (sel) {
a1e76353 8499 case CP0_REG05__PAGEMASK:
7db13fae 8500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 8501 register_name = "PageMask";
2423f660 8502 break;
a1e76353 8503 case CP0_REG05__PAGEGRAIN:
d75c135e 8504 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 8506 register_name = "PageGrain";
2423f660 8507 break;
a1e76353 8508 case CP0_REG05__SEGCTL0:
cec56a73
JH
8509 CP0_CHECK(ctx->sc);
8510 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 8511 register_name = "SegCtl0";
cec56a73 8512 break;
a1e76353 8513 case CP0_REG05__SEGCTL1:
cec56a73
JH
8514 CP0_CHECK(ctx->sc);
8515 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 8516 register_name = "SegCtl1";
cec56a73 8517 break;
a1e76353 8518 case CP0_REG05__SEGCTL2:
cec56a73
JH
8519 CP0_CHECK(ctx->sc);
8520 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 8521 register_name = "SegCtl2";
cec56a73 8522 break;
a1e76353 8523 case CP0_REG05__PWBASE:
5e31fdd5
YK
8524 check_pw(ctx);
8525 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8526 register_name = "PWBase";
5e31fdd5 8527 break;
a1e76353 8528 case CP0_REG05__PWFIELD:
fa75ad14
YK
8529 check_pw(ctx);
8530 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 8531 register_name = "PWField";
fa75ad14 8532 break;
a1e76353 8533 case CP0_REG05__PWSIZE:
20b28ebc
YK
8534 check_pw(ctx);
8535 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 8536 register_name = "PWSize";
20b28ebc 8537 break;
9c2149c8 8538 default:
f31b035a 8539 goto cp0_unimplemented;
876d4b07 8540 }
9c2149c8 8541 break;
04992c8c 8542 case CP0_REGISTER_06:
9c2149c8 8543 switch (sel) {
9023594b 8544 case CP0_REG06__WIRED:
7db13fae 8545 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 8546 register_name = "Wired";
2423f660 8547 break;
9023594b 8548 case CP0_REG06__SRSCONF0:
d75c135e 8549 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 8551 register_name = "SRSConf0";
ead9360e 8552 break;
9023594b 8553 case CP0_REG06__SRSCONF1:
d75c135e 8554 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 8556 register_name = "SRSConf1";
ead9360e 8557 break;
9023594b 8558 case CP0_REG06__SRSCONF2:
d75c135e 8559 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 8561 register_name = "SRSConf2";
ead9360e 8562 break;
9023594b 8563 case CP0_REG06__SRSCONF3:
d75c135e 8564 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 8566 register_name = "SRSConf3";
ead9360e 8567 break;
9023594b 8568 case CP0_REG06__SRSCONF4:
d75c135e 8569 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 8571 register_name = "SRSConf4";
ead9360e 8572 break;
9023594b 8573 case CP0_REG06__PWCTL:
103be64c
YK
8574 check_pw(ctx);
8575 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 8576 register_name = "PWCtl";
103be64c 8577 break;
9c2149c8 8578 default:
f31b035a 8579 goto cp0_unimplemented;
876d4b07 8580 }
9c2149c8 8581 break;
04992c8c 8582 case CP0_REGISTER_07:
9c2149c8 8583 switch (sel) {
143a9875 8584 case CP0_REG07__HWRENA:
d75c135e 8585 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 8587 register_name = "HWREna";
2423f660 8588 break;
9c2149c8 8589 default:
f31b035a 8590 goto cp0_unimplemented;
876d4b07 8591 }
9c2149c8 8592 break;
04992c8c 8593 case CP0_REGISTER_08:
9c2149c8 8594 switch (sel) {
67d167d2 8595 case CP0_REG08__BADVADDR:
7db13fae 8596 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 8597 register_name = "BadVAddr";
2423f660 8598 break;
67d167d2 8599 case CP0_REG08__BADINSTR:
f31b035a
LA
8600 CP0_CHECK(ctx->bi);
8601 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 8602 register_name = "BadInstr";
aea14095 8603 break;
67d167d2 8604 case CP0_REG08__BADINSTRP:
f31b035a
LA
8605 CP0_CHECK(ctx->bp);
8606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 8607 register_name = "BadInstrP";
aea14095 8608 break;
67d167d2 8609 case CP0_REG08__BADINSTRX:
25beba9b
SM
8610 CP0_CHECK(ctx->bi);
8611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8612 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 8613 register_name = "BadInstrX";
25beba9b 8614 break;
9c2149c8 8615 default:
f31b035a 8616 goto cp0_unimplemented;
876d4b07 8617 }
9c2149c8 8618 break;
04992c8c 8619 case CP0_REGISTER_09:
9c2149c8 8620 switch (sel) {
e5a98a72 8621 case CP0_REG09__COUNT:
2e70f6ef 8622 /* Mark as an IO operation because we read the time. */
eeb3bba8 8623 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8624 gen_io_start();
bd79255d 8625 }
895c2d04 8626 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
8627 /*
8628 * Break the TB to be able to take timer interrupts immediately
8629 * after reading count. DISAS_STOP isn't sufficient, we need to
8630 * ensure we break completely out of translated code.
8631 */
eeb3bba8
EC
8632 gen_save_pc(ctx->base.pc_next + 4);
8633 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8634 register_name = "Count";
2423f660 8635 break;
e5a98a72 8636 case CP0_REG09__SAARI:
5fb2dcd1
YK
8637 CP0_CHECK(ctx->saar);
8638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 8639 register_name = "SAARI";
5fb2dcd1 8640 break;
e5a98a72 8641 case CP0_REG09__SAAR:
5fb2dcd1
YK
8642 CP0_CHECK(ctx->saar);
8643 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 8644 register_name = "SAAR";
5fb2dcd1 8645 break;
9c2149c8 8646 default:
f31b035a 8647 goto cp0_unimplemented;
876d4b07 8648 }
9c2149c8 8649 break;
04992c8c 8650 case CP0_REGISTER_10:
9c2149c8 8651 switch (sel) {
860ffef0 8652 case CP0_REG10__ENTRYHI:
7db13fae 8653 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 8654 register_name = "EntryHi";
2423f660 8655 break;
9c2149c8 8656 default:
f31b035a 8657 goto cp0_unimplemented;
876d4b07 8658 }
9c2149c8 8659 break;
04992c8c 8660 case CP0_REGISTER_11:
9c2149c8 8661 switch (sel) {
f5f3834f 8662 case CP0_REG11__COMPARE:
7db13fae 8663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 8664 register_name = "Compare";
2423f660 8665 break;
876d4b07 8666 /* 6,7 are implementation dependent */
9c2149c8 8667 default:
f31b035a 8668 goto cp0_unimplemented;
876d4b07 8669 }
9c2149c8 8670 break;
04992c8c 8671 case CP0_REGISTER_12:
9c2149c8 8672 switch (sel) {
2b084867 8673 case CP0_REG12__STATUS:
7db13fae 8674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 8675 register_name = "Status";
2423f660 8676 break;
2b084867 8677 case CP0_REG12__INTCTL:
d75c135e 8678 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 8680 register_name = "IntCtl";
2423f660 8681 break;
2b084867 8682 case CP0_REG12__SRSCTL:
d75c135e 8683 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 8685 register_name = "SRSCtl";
2423f660 8686 break;
2b084867 8687 case CP0_REG12__SRSMAP:
d75c135e 8688 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 8690 register_name = "SRSMap";
2423f660 8691 break;
9c2149c8 8692 default:
f31b035a 8693 goto cp0_unimplemented;
876d4b07 8694 }
9c2149c8 8695 break;
04992c8c 8696 case CP0_REGISTER_13:
9c2149c8 8697 switch (sel) {
e3c7559d 8698 case CP0_REG13__CAUSE:
7db13fae 8699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 8700 register_name = "Cause";
2423f660 8701 break;
9c2149c8 8702 default:
f31b035a 8703 goto cp0_unimplemented;
876d4b07 8704 }
9c2149c8 8705 break;
04992c8c 8706 case CP0_REGISTER_14:
9c2149c8 8707 switch (sel) {
35e4b54d 8708 case CP0_REG14__EPC:
7db13fae 8709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8710 register_name = "EPC";
2423f660 8711 break;
9c2149c8 8712 default:
f31b035a 8713 goto cp0_unimplemented;
876d4b07 8714 }
9c2149c8 8715 break;
04992c8c 8716 case CP0_REGISTER_15:
9c2149c8 8717 switch (sel) {
4466cd49 8718 case CP0_REG15__PRID:
7db13fae 8719 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 8720 register_name = "PRid";
2423f660 8721 break;
4466cd49 8722 case CP0_REG15__EBASE:
d75c135e 8723 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8724 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 8725 register_name = "EBase";
2423f660 8726 break;
4466cd49 8727 case CP0_REG15__CMGCRBASE:
c870e3f5
YK
8728 check_insn(ctx, ISA_MIPS32R2);
8729 CP0_CHECK(ctx->cmgcr);
8730 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 8731 register_name = "CMGCRBase";
c870e3f5 8732 break;
9c2149c8 8733 default:
f31b035a 8734 goto cp0_unimplemented;
876d4b07 8735 }
9c2149c8 8736 break;
04992c8c 8737 case CP0_REGISTER_16:
9c2149c8 8738 switch (sel) {
433efb4c 8739 case CP0_REG16__CONFIG:
7db13fae 8740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 8741 register_name = "Config";
9c2149c8 8742 break;
433efb4c 8743 case CP0_REG16__CONFIG1:
7db13fae 8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 8745 register_name = "Config1";
9c2149c8 8746 break;
433efb4c 8747 case CP0_REG16__CONFIG2:
7db13fae 8748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 8749 register_name = "Config2";
9c2149c8 8750 break;
433efb4c 8751 case CP0_REG16__CONFIG3:
7db13fae 8752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 8753 register_name = "Config3";
9c2149c8 8754 break;
433efb4c 8755 case CP0_REG16__CONFIG4:
faf1f68b 8756 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 8757 register_name = "Config4";
faf1f68b 8758 break;
433efb4c 8759 case CP0_REG16__CONFIG5:
faf1f68b 8760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 8761 register_name = "Config5";
faf1f68b 8762 break;
05aa7e93 8763 /* 6,7 are implementation dependent */
433efb4c 8764 case CP0_REG16__CONFIG6:
7db13fae 8765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 8766 register_name = "Config6";
f0b3f3ae 8767 break;
433efb4c 8768 case CP0_REG16__CONFIG7:
7db13fae 8769 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 8770 register_name = "Config7";
f0b3f3ae 8771 break;
9c2149c8 8772 default:
f31b035a 8773 goto cp0_unimplemented;
9c2149c8
TS
8774 }
8775 break;
04992c8c 8776 case CP0_REGISTER_17:
9c2149c8 8777 switch (sel) {
706ce142 8778 case CP0_REG17__LLADDR:
895c2d04 8779 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 8780 register_name = "LLAddr";
2423f660 8781 break;
706ce142 8782 case CP0_REG17__MAAR:
f6d4dd81
YK
8783 CP0_CHECK(ctx->mrp);
8784 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 8785 register_name = "MAAR";
f6d4dd81 8786 break;
706ce142 8787 case CP0_REG17__MAARI:
f6d4dd81
YK
8788 CP0_CHECK(ctx->mrp);
8789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 8790 register_name = "MAARI";
f6d4dd81 8791 break;
9c2149c8 8792 default:
f31b035a 8793 goto cp0_unimplemented;
9c2149c8
TS
8794 }
8795 break;
04992c8c 8796 case CP0_REGISTER_18:
9c2149c8 8797 switch (sel) {
e8dcfe82
AM
8798 case CP0_REG18__WATCHLO0:
8799 case CP0_REG18__WATCHLO1:
8800 case CP0_REG18__WATCHLO2:
8801 case CP0_REG18__WATCHLO3:
8802 case CP0_REG18__WATCHLO4:
8803 case CP0_REG18__WATCHLO5:
8804 case CP0_REG18__WATCHLO6:
8805 case CP0_REG18__WATCHLO7:
fa192d49 8806 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8807 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 8808 register_name = "WatchLo";
2423f660 8809 break;
9c2149c8 8810 default:
f31b035a 8811 goto cp0_unimplemented;
9c2149c8
TS
8812 }
8813 break;
04992c8c 8814 case CP0_REGISTER_19:
9c2149c8 8815 switch (sel) {
be274dc1
AM
8816 case CP0_REG19__WATCHHI0:
8817 case CP0_REG19__WATCHHI1:
8818 case CP0_REG19__WATCHHI2:
8819 case CP0_REG19__WATCHHI3:
8820 case CP0_REG19__WATCHHI4:
8821 case CP0_REG19__WATCHHI5:
8822 case CP0_REG19__WATCHHI6:
8823 case CP0_REG19__WATCHHI7:
fa192d49 8824 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8825 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 8826 register_name = "WatchHi";
2423f660 8827 break;
9c2149c8 8828 default:
f31b035a 8829 goto cp0_unimplemented;
9c2149c8
TS
8830 }
8831 break;
04992c8c 8832 case CP0_REGISTER_20:
9c2149c8 8833 switch (sel) {
14f92b0b 8834 case CP0_REG20__XCONTEXT:
d75c135e 8835 check_insn(ctx, ISA_MIPS3);
7db13fae 8836 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8837 register_name = "XContext";
2423f660 8838 break;
9c2149c8 8839 default:
f31b035a 8840 goto cp0_unimplemented;
9c2149c8
TS
8841 }
8842 break;
04992c8c 8843 case CP0_REGISTER_21:
05aa7e93 8844 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8845 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8846 switch (sel) {
8847 case 0:
7db13fae 8848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8849 register_name = "Framemask";
2423f660 8850 break;
9c2149c8 8851 default:
f31b035a 8852 goto cp0_unimplemented;
9c2149c8
TS
8853 }
8854 break;
04992c8c 8855 case CP0_REGISTER_22:
d9bea114 8856 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8857 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8858 break;
04992c8c 8859 case CP0_REGISTER_23:
9c2149c8 8860 switch (sel) {
4cbf4b6d 8861 case CP0_REG23__DEBUG:
895c2d04 8862 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 8863 register_name = "Debug";
2423f660 8864 break;
4cbf4b6d
AM
8865 case CP0_REG23__TRACECONTROL:
8866 /* PDtrace support */
8867 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 8868 register_name = "TraceControl";
3570d7f6 8869 goto cp0_unimplemented;
4cbf4b6d
AM
8870 case CP0_REG23__TRACECONTROL2:
8871 /* PDtrace support */
8872 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 8873 register_name = "TraceControl2";
3570d7f6 8874 goto cp0_unimplemented;
4cbf4b6d
AM
8875 case CP0_REG23__USERTRACEDATA1:
8876 /* PDtrace support */
8877 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8878 register_name = "UserTraceData1";
3570d7f6 8879 goto cp0_unimplemented;
4cbf4b6d
AM
8880 case CP0_REG23__TRACEIBPC:
8881 /* PDtrace support */
8882 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8883 register_name = "TraceIBPC";
8884 goto cp0_unimplemented;
8885 case CP0_REG23__TRACEDBPC:
8886 /* PDtrace support */
8887 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8888 register_name = "TraceDBPC";
3570d7f6 8889 goto cp0_unimplemented;
9c2149c8 8890 default:
f31b035a 8891 goto cp0_unimplemented;
9c2149c8
TS
8892 }
8893 break;
04992c8c 8894 case CP0_REGISTER_24:
9c2149c8 8895 switch (sel) {
8d7b4b6e 8896 case CP0_REG24__DEPC:
f0b3f3ae 8897 /* EJTAG support */
7db13fae 8898 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8899 register_name = "DEPC";
2423f660 8900 break;
9c2149c8 8901 default:
f31b035a 8902 goto cp0_unimplemented;
9c2149c8
TS
8903 }
8904 break;
04992c8c 8905 case CP0_REGISTER_25:
9c2149c8 8906 switch (sel) {
1176b328 8907 case CP0_REG25__PERFCTL0:
7db13fae 8908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8909 register_name = "Performance0";
9c2149c8 8910 break;
1176b328 8911 case CP0_REG25__PERFCNT0:
7480515f 8912 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 8913 register_name = "Performance1";
3570d7f6 8914 goto cp0_unimplemented;
1176b328 8915 case CP0_REG25__PERFCTL1:
7480515f 8916 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 8917 register_name = "Performance2";
3570d7f6 8918 goto cp0_unimplemented;
1176b328 8919 case CP0_REG25__PERFCNT1:
7480515f 8920 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 8921 register_name = "Performance3";
3570d7f6 8922 goto cp0_unimplemented;
1176b328 8923 case CP0_REG25__PERFCTL2:
7480515f 8924 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 8925 register_name = "Performance4";
3570d7f6 8926 goto cp0_unimplemented;
1176b328 8927 case CP0_REG25__PERFCNT2:
7480515f 8928 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 8929 register_name = "Performance5";
3570d7f6 8930 goto cp0_unimplemented;
1176b328 8931 case CP0_REG25__PERFCTL3:
7480515f 8932 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 8933 register_name = "Performance6";
3570d7f6 8934 goto cp0_unimplemented;
1176b328 8935 case CP0_REG25__PERFCNT3:
7480515f 8936 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 8937 register_name = "Performance7";
3570d7f6 8938 goto cp0_unimplemented;
9c2149c8 8939 default:
f31b035a 8940 goto cp0_unimplemented;
9c2149c8
TS
8941 }
8942 break;
04992c8c 8943 case CP0_REGISTER_26:
0d74a222 8944 switch (sel) {
dbbf08b2 8945 case CP0_REG26__ERRCTL:
0d74a222 8946 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8947 register_name = "ErrCtl";
0d74a222
LA
8948 break;
8949 default:
8950 goto cp0_unimplemented;
8951 }
da80682b 8952 break;
04992c8c 8953 case CP0_REGISTER_27:
9c2149c8
TS
8954 switch (sel) {
8955 /* ignored */
5a10873d 8956 case CP0_REG27__CACHERR:
d9bea114 8957 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8958 register_name = "CacheErr";
2423f660 8959 break;
9c2149c8 8960 default:
f31b035a 8961 goto cp0_unimplemented;
9c2149c8
TS
8962 }
8963 break;
04992c8c 8964 case CP0_REGISTER_28:
9c2149c8 8965 switch (sel) {
a30e2f21
AM
8966 case CP0_REG28__TAGLO:
8967 case CP0_REG28__TAGLO1:
8968 case CP0_REG28__TAGLO2:
8969 case CP0_REG28__TAGLO3:
7db13fae 8970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 8971 register_name = "TagLo";
9c2149c8 8972 break;
a30e2f21
AM
8973 case CP0_REG28__DATALO:
8974 case CP0_REG28__DATALO1:
8975 case CP0_REG28__DATALO2:
8976 case CP0_REG28__DATALO3:
7db13fae 8977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8978 register_name = "DataLo";
9c2149c8
TS
8979 break;
8980 default:
f31b035a 8981 goto cp0_unimplemented;
9c2149c8
TS
8982 }
8983 break;
04992c8c 8984 case CP0_REGISTER_29:
9c2149c8 8985 switch (sel) {
af4bb6da
AM
8986 case CP0_REG29__TAGHI:
8987 case CP0_REG29__TAGHI1:
8988 case CP0_REG29__TAGHI2:
8989 case CP0_REG29__TAGHI3:
7db13fae 8990 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8991 register_name = "TagHi";
9c2149c8 8992 break;
af4bb6da
AM
8993 case CP0_REG29__DATAHI:
8994 case CP0_REG29__DATAHI1:
8995 case CP0_REG29__DATAHI2:
8996 case CP0_REG29__DATAHI3:
7db13fae 8997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8998 register_name = "DataHi";
9c2149c8
TS
8999 break;
9000 default:
f31b035a 9001 goto cp0_unimplemented;
9c2149c8
TS
9002 }
9003 break;
04992c8c 9004 case CP0_REGISTER_30:
9c2149c8 9005 switch (sel) {
4bcf121e 9006 case CP0_REG30__ERROREPC:
7db13fae 9007 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9008 register_name = "ErrorEPC";
2423f660 9009 break;
9c2149c8 9010 default:
f31b035a 9011 goto cp0_unimplemented;
9c2149c8
TS
9012 }
9013 break;
04992c8c 9014 case CP0_REGISTER_31:
9c2149c8 9015 switch (sel) {
14d92efd 9016 case CP0_REG31__DESAVE:
f0b3f3ae 9017 /* EJTAG support */
7db13fae 9018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9019 register_name = "DESAVE";
2423f660 9020 break;
14d92efd
AM
9021 case CP0_REG31__KSCRATCH1:
9022 case CP0_REG31__KSCRATCH2:
9023 case CP0_REG31__KSCRATCH3:
9024 case CP0_REG31__KSCRATCH4:
9025 case CP0_REG31__KSCRATCH5:
9026 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9027 CP0_CHECK(ctx->kscrexist & (1 << sel));
9028 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 9029 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9030 register_name = "KScratch";
e98c0d17 9031 break;
9c2149c8 9032 default:
f31b035a 9033 goto cp0_unimplemented;
9c2149c8
TS
9034 }
9035 break;
9036 default:
f31b035a 9037 goto cp0_unimplemented;
9c2149c8 9038 }
294fc2ea 9039 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
9040 return;
9041
f31b035a 9042cp0_unimplemented:
294fc2ea
AM
9043 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9044 register_name, reg, sel);
f31b035a 9045 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
9046}
9047
d75c135e 9048static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 9049{
294fc2ea 9050 const char *register_name = "invalid";
9c2149c8 9051
1f8929d2 9052 if (sel != 0) {
d75c135e 9053 check_insn(ctx, ISA_MIPS64);
1f8929d2 9054 }
e189e748 9055
eeb3bba8 9056 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9057 gen_io_start();
bd79255d 9058 }
2e70f6ef 9059
9c2149c8 9060 switch (reg) {
04992c8c 9061 case CP0_REGISTER_00:
9c2149c8 9062 switch (sel) {
1b142da5 9063 case CP0_REG00__INDEX:
895c2d04 9064 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 9065 register_name = "Index";
9c2149c8 9066 break;
1b142da5 9067 case CP0_REG00__MVPCONTROL:
f31b035a 9068 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9069 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 9070 register_name = "MVPControl";
ead9360e 9071 break;
1b142da5 9072 case CP0_REG00__MVPCONF0:
f31b035a 9073 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9074 /* ignored */
294fc2ea 9075 register_name = "MVPConf0";
ead9360e 9076 break;
1b142da5 9077 case CP0_REG00__MVPCONF1:
f31b035a 9078 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9079 /* ignored */
294fc2ea 9080 register_name = "MVPConf1";
ead9360e 9081 break;
1b142da5 9082 case CP0_REG00__VPCONTROL:
01bc435b
YK
9083 CP0_CHECK(ctx->vp);
9084 /* ignored */
294fc2ea 9085 register_name = "VPControl";
01bc435b 9086 break;
9c2149c8 9087 default:
f31b035a 9088 goto cp0_unimplemented;
9c2149c8
TS
9089 }
9090 break;
04992c8c 9091 case CP0_REGISTER_01:
9c2149c8 9092 switch (sel) {
30deb460 9093 case CP0_REG01__RANDOM:
2423f660 9094 /* ignored */
294fc2ea 9095 register_name = "Random";
2423f660 9096 break;
30deb460 9097 case CP0_REG01__VPECONTROL:
f31b035a 9098 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9099 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9100 register_name = "VPEControl";
ead9360e 9101 break;
30deb460 9102 case CP0_REG01__VPECONF0:
f31b035a 9103 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9104 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9105 register_name = "VPEConf0";
ead9360e 9106 break;
30deb460 9107 case CP0_REG01__VPECONF1:
f31b035a 9108 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9109 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9110 register_name = "VPEConf1";
ead9360e 9111 break;
30deb460 9112 case CP0_REG01__YQMASK:
f31b035a 9113 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9114 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9115 register_name = "YQMask";
ead9360e 9116 break;
30deb460 9117 case CP0_REG01__VPESCHEDULE:
f31b035a 9118 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9119 tcg_gen_st_tl(arg, cpu_env,
9120 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9121 register_name = "VPESchedule";
ead9360e 9122 break;
30deb460 9123 case CP0_REG01__VPESCHEFBACK:
f31b035a 9124 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9125 tcg_gen_st_tl(arg, cpu_env,
9126 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9127 register_name = "VPEScheFBack";
ead9360e 9128 break;
30deb460 9129 case CP0_REG01__VPEOPT:
f31b035a 9130 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9131 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9132 register_name = "VPEOpt";
ead9360e 9133 break;
9c2149c8 9134 default:
f31b035a 9135 goto cp0_unimplemented;
9c2149c8
TS
9136 }
9137 break;
04992c8c 9138 case CP0_REGISTER_02:
9c2149c8 9139 switch (sel) {
6d27d5bd 9140 case CP0_REG02__ENTRYLO0:
7207c7f9 9141 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9142 register_name = "EntryLo0";
2423f660 9143 break;
6d27d5bd 9144 case CP0_REG02__TCSTATUS:
f31b035a 9145 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9146 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9147 register_name = "TCStatus";
ead9360e 9148 break;
6d27d5bd 9149 case CP0_REG02__TCBIND:
f31b035a 9150 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9151 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9152 register_name = "TCBind";
ead9360e 9153 break;
6d27d5bd 9154 case CP0_REG02__TCRESTART:
f31b035a 9155 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9156 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9157 register_name = "TCRestart";
ead9360e 9158 break;
6d27d5bd 9159 case CP0_REG02__TCHALT:
f31b035a 9160 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9161 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9162 register_name = "TCHalt";
ead9360e 9163 break;
6d27d5bd 9164 case CP0_REG02__TCCONTEXT:
f31b035a 9165 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9166 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9167 register_name = "TCContext";
ead9360e 9168 break;
6d27d5bd 9169 case CP0_REG02__TCSCHEDULE:
f31b035a 9170 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9171 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9172 register_name = "TCSchedule";
ead9360e 9173 break;
6d27d5bd 9174 case CP0_REG02__TCSCHEFBACK:
f31b035a 9175 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9176 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9177 register_name = "TCScheFBack";
ead9360e 9178 break;
9c2149c8 9179 default:
f31b035a 9180 goto cp0_unimplemented;
9c2149c8
TS
9181 }
9182 break;
04992c8c 9183 case CP0_REGISTER_03:
9c2149c8 9184 switch (sel) {
acd37316 9185 case CP0_REG03__ENTRYLO1:
7207c7f9 9186 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9187 register_name = "EntryLo1";
2423f660 9188 break;
acd37316 9189 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9190 CP0_CHECK(ctx->vp);
9191 /* ignored */
294fc2ea 9192 register_name = "GlobalNumber";
01bc435b 9193 break;
9c2149c8 9194 default:
f31b035a 9195 goto cp0_unimplemented;
876d4b07 9196 }
9c2149c8 9197 break;
04992c8c 9198 case CP0_REGISTER_04:
9c2149c8 9199 switch (sel) {
020fe379 9200 case CP0_REG04__CONTEXT:
895c2d04 9201 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9202 register_name = "Context";
2423f660 9203 break;
020fe379
AM
9204 case CP0_REG04__CONTEXTCONFIG:
9205 /* SmartMIPS ASE */
9206 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 9207 register_name = "ContextConfig";
f31b035a 9208 goto cp0_unimplemented;
020fe379 9209 case CP0_REG04__USERLOCAL:
f31b035a
LA
9210 CP0_CHECK(ctx->ulri);
9211 tcg_gen_st_tl(arg, cpu_env,
9212 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9213 register_name = "UserLocal";
d279279e 9214 break;
9c2149c8 9215 default:
f31b035a 9216 goto cp0_unimplemented;
876d4b07 9217 }
9c2149c8 9218 break;
04992c8c 9219 case CP0_REGISTER_05:
9c2149c8 9220 switch (sel) {
a1e76353 9221 case CP0_REG05__PAGEMASK:
895c2d04 9222 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9223 register_name = "PageMask";
2423f660 9224 break;
a1e76353 9225 case CP0_REG05__PAGEGRAIN:
d75c135e 9226 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9227 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9228 register_name = "PageGrain";
2423f660 9229 break;
a1e76353 9230 case CP0_REG05__SEGCTL0:
cec56a73
JH
9231 CP0_CHECK(ctx->sc);
9232 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9233 register_name = "SegCtl0";
cec56a73 9234 break;
a1e76353 9235 case CP0_REG05__SEGCTL1:
cec56a73
JH
9236 CP0_CHECK(ctx->sc);
9237 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9238 register_name = "SegCtl1";
cec56a73 9239 break;
a1e76353 9240 case CP0_REG05__SEGCTL2:
cec56a73
JH
9241 CP0_CHECK(ctx->sc);
9242 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9243 register_name = "SegCtl2";
cec56a73 9244 break;
a1e76353 9245 case CP0_REG05__PWBASE:
5e31fdd5
YK
9246 check_pw(ctx);
9247 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9248 register_name = "PWBase";
5e31fdd5 9249 break;
a1e76353 9250 case CP0_REG05__PWFIELD:
fa75ad14
YK
9251 check_pw(ctx);
9252 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9253 register_name = "PWField";
fa75ad14 9254 break;
a1e76353 9255 case CP0_REG05__PWSIZE:
20b28ebc
YK
9256 check_pw(ctx);
9257 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9258 register_name = "PWSize";
20b28ebc 9259 break;
9c2149c8 9260 default:
f31b035a 9261 goto cp0_unimplemented;
876d4b07 9262 }
9c2149c8 9263 break;
04992c8c 9264 case CP0_REGISTER_06:
9c2149c8 9265 switch (sel) {
9023594b 9266 case CP0_REG06__WIRED:
895c2d04 9267 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9268 register_name = "Wired";
2423f660 9269 break;
9023594b 9270 case CP0_REG06__SRSCONF0:
d75c135e 9271 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9272 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9273 register_name = "SRSConf0";
ead9360e 9274 break;
9023594b 9275 case CP0_REG06__SRSCONF1:
d75c135e 9276 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9277 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9278 register_name = "SRSConf1";
ead9360e 9279 break;
9023594b 9280 case CP0_REG06__SRSCONF2:
d75c135e 9281 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9282 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9283 register_name = "SRSConf2";
ead9360e 9284 break;
9023594b 9285 case CP0_REG06__SRSCONF3:
d75c135e 9286 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9287 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9288 register_name = "SRSConf3";
ead9360e 9289 break;
9023594b 9290 case CP0_REG06__SRSCONF4:
d75c135e 9291 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9292 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9293 register_name = "SRSConf4";
ead9360e 9294 break;
9023594b 9295 case CP0_REG06__PWCTL:
103be64c
YK
9296 check_pw(ctx);
9297 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9298 register_name = "PWCtl";
103be64c 9299 break;
9c2149c8 9300 default:
f31b035a 9301 goto cp0_unimplemented;
876d4b07 9302 }
9c2149c8 9303 break;
04992c8c 9304 case CP0_REGISTER_07:
9c2149c8 9305 switch (sel) {
143a9875 9306 case CP0_REG07__HWRENA:
d75c135e 9307 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9308 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9309 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9310 register_name = "HWREna";
2423f660 9311 break;
9c2149c8 9312 default:
f31b035a 9313 goto cp0_unimplemented;
876d4b07 9314 }
9c2149c8 9315 break;
04992c8c 9316 case CP0_REGISTER_08:
aea14095 9317 switch (sel) {
67d167d2 9318 case CP0_REG08__BADVADDR:
aea14095 9319 /* ignored */
294fc2ea 9320 register_name = "BadVAddr";
aea14095 9321 break;
67d167d2 9322 case CP0_REG08__BADINSTR:
aea14095 9323 /* ignored */
294fc2ea 9324 register_name = "BadInstr";
aea14095 9325 break;
67d167d2 9326 case CP0_REG08__BADINSTRP:
aea14095 9327 /* ignored */
294fc2ea 9328 register_name = "BadInstrP";
aea14095 9329 break;
67d167d2 9330 case CP0_REG08__BADINSTRX:
25beba9b 9331 /* ignored */
294fc2ea 9332 register_name = "BadInstrX";
25beba9b 9333 break;
aea14095 9334 default:
f31b035a 9335 goto cp0_unimplemented;
aea14095 9336 }
9c2149c8 9337 break;
04992c8c 9338 case CP0_REGISTER_09:
9c2149c8 9339 switch (sel) {
e5a98a72 9340 case CP0_REG09__COUNT:
895c2d04 9341 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9342 register_name = "Count";
2423f660 9343 break;
e5a98a72 9344 case CP0_REG09__SAARI:
5fb2dcd1
YK
9345 CP0_CHECK(ctx->saar);
9346 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9347 register_name = "SAARI";
5fb2dcd1 9348 break;
e5a98a72 9349 case CP0_REG09__SAAR:
5fb2dcd1
YK
9350 CP0_CHECK(ctx->saar);
9351 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9352 register_name = "SAAR";
5fb2dcd1 9353 break;
9c2149c8 9354 default:
f31b035a 9355 goto cp0_unimplemented;
876d4b07
TS
9356 }
9357 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9358 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9359 break;
04992c8c 9360 case CP0_REGISTER_10:
9c2149c8 9361 switch (sel) {
860ffef0 9362 case CP0_REG10__ENTRYHI:
895c2d04 9363 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9364 register_name = "EntryHi";
2423f660 9365 break;
9c2149c8 9366 default:
f31b035a 9367 goto cp0_unimplemented;
876d4b07 9368 }
9c2149c8 9369 break;
04992c8c 9370 case CP0_REGISTER_11:
9c2149c8 9371 switch (sel) {
f5f3834f 9372 case CP0_REG11__COMPARE:
895c2d04 9373 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9374 register_name = "Compare";
2423f660 9375 break;
876d4b07 9376 /* 6,7 are implementation dependent */
9c2149c8 9377 default:
f31b035a 9378 goto cp0_unimplemented;
876d4b07 9379 }
de9a95f0 9380 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9381 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9382 break;
04992c8c 9383 case CP0_REGISTER_12:
9c2149c8 9384 switch (sel) {
2b084867 9385 case CP0_REG12__STATUS:
867abc7e 9386 save_cpu_state(ctx, 1);
895c2d04 9387 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 9388 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9389 gen_save_pc(ctx->base.pc_next + 4);
9390 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9391 register_name = "Status";
2423f660 9392 break;
2b084867 9393 case CP0_REG12__INTCTL:
d75c135e 9394 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9395 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 9396 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9397 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9398 register_name = "IntCtl";
2423f660 9399 break;
2b084867 9400 case CP0_REG12__SRSCTL:
d75c135e 9401 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9402 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 9403 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9404 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9405 register_name = "SRSCtl";
2423f660 9406 break;
2b084867 9407 case CP0_REG12__SRSMAP:
d75c135e 9408 check_insn(ctx, ISA_MIPS32R2);
7db13fae 9409 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 9410 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9411 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9412 register_name = "SRSMap";
2423f660
TS
9413 break;
9414 default:
f31b035a 9415 goto cp0_unimplemented;
876d4b07 9416 }
9c2149c8 9417 break;
04992c8c 9418 case CP0_REGISTER_13:
9c2149c8 9419 switch (sel) {
e3c7559d 9420 case CP0_REG13__CAUSE:
867abc7e 9421 save_cpu_state(ctx, 1);
895c2d04 9422 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
9423 /*
9424 * Stop translation as we may have triggered an interrupt.
b28425ba 9425 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
9426 * translated code to check for pending interrupts.
9427 */
eeb3bba8
EC
9428 gen_save_pc(ctx->base.pc_next + 4);
9429 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9430 register_name = "Cause";
2423f660 9431 break;
9c2149c8 9432 default:
f31b035a 9433 goto cp0_unimplemented;
876d4b07 9434 }
9c2149c8 9435 break;
04992c8c 9436 case CP0_REGISTER_14:
9c2149c8 9437 switch (sel) {
35e4b54d 9438 case CP0_REG14__EPC:
7db13fae 9439 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9440 register_name = "EPC";
2423f660 9441 break;
9c2149c8 9442 default:
f31b035a 9443 goto cp0_unimplemented;
876d4b07 9444 }
9c2149c8 9445 break;
04992c8c 9446 case CP0_REGISTER_15:
9c2149c8 9447 switch (sel) {
4466cd49 9448 case CP0_REG15__PRID:
2423f660 9449 /* ignored */
294fc2ea 9450 register_name = "PRid";
2423f660 9451 break;
4466cd49 9452 case CP0_REG15__EBASE:
d75c135e 9453 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9454 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 9455 register_name = "EBase";
2423f660 9456 break;
9c2149c8 9457 default:
f31b035a 9458 goto cp0_unimplemented;
876d4b07 9459 }
9c2149c8 9460 break;
04992c8c 9461 case CP0_REGISTER_16:
9c2149c8 9462 switch (sel) {
433efb4c 9463 case CP0_REG16__CONFIG:
895c2d04 9464 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 9465 register_name = "Config";
2423f660 9466 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9467 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9468 break;
433efb4c 9469 case CP0_REG16__CONFIG1:
1fc7bf6e 9470 /* ignored, read only */
294fc2ea 9471 register_name = "Config1";
9c2149c8 9472 break;
433efb4c 9473 case CP0_REG16__CONFIG2:
895c2d04 9474 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 9475 register_name = "Config2";
2423f660 9476 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9477 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9478 break;
433efb4c 9479 case CP0_REG16__CONFIG3:
90f12d73 9480 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 9481 register_name = "Config3";
90f12d73 9482 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9483 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9484 break;
433efb4c 9485 case CP0_REG16__CONFIG4:
faf1f68b 9486 /* currently ignored */
294fc2ea 9487 register_name = "Config4";
faf1f68b 9488 break;
433efb4c 9489 case CP0_REG16__CONFIG5:
faf1f68b 9490 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 9491 register_name = "Config5";
faf1f68b 9492 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9493 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9494 break;
9c2149c8
TS
9495 /* 6,7 are implementation dependent */
9496 default:
294fc2ea 9497 register_name = "Invalid config selector";
f31b035a 9498 goto cp0_unimplemented;
9c2149c8 9499 }
9c2149c8 9500 break;
04992c8c 9501 case CP0_REGISTER_17:
9c2149c8 9502 switch (sel) {
706ce142 9503 case CP0_REG17__LLADDR:
895c2d04 9504 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 9505 register_name = "LLAddr";
2423f660 9506 break;
706ce142 9507 case CP0_REG17__MAAR:
f6d4dd81
YK
9508 CP0_CHECK(ctx->mrp);
9509 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 9510 register_name = "MAAR";
f6d4dd81 9511 break;
706ce142 9512 case CP0_REG17__MAARI:
f6d4dd81
YK
9513 CP0_CHECK(ctx->mrp);
9514 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 9515 register_name = "MAARI";
f6d4dd81 9516 break;
9c2149c8 9517 default:
f31b035a 9518 goto cp0_unimplemented;
9c2149c8
TS
9519 }
9520 break;
04992c8c 9521 case CP0_REGISTER_18:
9c2149c8 9522 switch (sel) {
e8dcfe82
AM
9523 case CP0_REG18__WATCHLO0:
9524 case CP0_REG18__WATCHLO1:
9525 case CP0_REG18__WATCHLO2:
9526 case CP0_REG18__WATCHLO3:
9527 case CP0_REG18__WATCHLO4:
9528 case CP0_REG18__WATCHLO5:
9529 case CP0_REG18__WATCHLO6:
9530 case CP0_REG18__WATCHLO7:
fa192d49 9531 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9532 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 9533 register_name = "WatchLo";
2423f660 9534 break;
9c2149c8 9535 default:
f31b035a 9536 goto cp0_unimplemented;
9c2149c8
TS
9537 }
9538 break;
04992c8c 9539 case CP0_REGISTER_19:
9c2149c8 9540 switch (sel) {
be274dc1
AM
9541 case CP0_REG19__WATCHHI0:
9542 case CP0_REG19__WATCHHI1:
9543 case CP0_REG19__WATCHHI2:
9544 case CP0_REG19__WATCHHI3:
9545 case CP0_REG19__WATCHHI4:
9546 case CP0_REG19__WATCHHI5:
9547 case CP0_REG19__WATCHHI6:
9548 case CP0_REG19__WATCHHI7:
fa192d49 9549 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9550 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 9551 register_name = "WatchHi";
2423f660 9552 break;
9c2149c8 9553 default:
f31b035a 9554 goto cp0_unimplemented;
9c2149c8
TS
9555 }
9556 break;
04992c8c 9557 case CP0_REGISTER_20:
9c2149c8 9558 switch (sel) {
14f92b0b 9559 case CP0_REG20__XCONTEXT:
d75c135e 9560 check_insn(ctx, ISA_MIPS3);
895c2d04 9561 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 9562 register_name = "XContext";
2423f660 9563 break;
9c2149c8 9564 default:
f31b035a 9565 goto cp0_unimplemented;
9c2149c8
TS
9566 }
9567 break;
04992c8c 9568 case CP0_REGISTER_21:
9c2149c8 9569 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9570 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9571 switch (sel) {
9572 case 0:
895c2d04 9573 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 9574 register_name = "Framemask";
2423f660 9575 break;
9c2149c8 9576 default:
f31b035a 9577 goto cp0_unimplemented;
9c2149c8
TS
9578 }
9579 break;
04992c8c 9580 case CP0_REGISTER_22:
9c2149c8 9581 /* ignored */
294fc2ea 9582 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 9583 break;
04992c8c 9584 case CP0_REGISTER_23:
9c2149c8 9585 switch (sel) {
4cbf4b6d 9586 case CP0_REG23__DEBUG:
895c2d04 9587 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9588 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9589 gen_save_pc(ctx->base.pc_next + 4);
9590 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9591 register_name = "Debug";
2423f660 9592 break;
4cbf4b6d
AM
9593 case CP0_REG23__TRACECONTROL:
9594 /* PDtrace support */
9595 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 9596 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9597 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9598 register_name = "TraceControl";
3570d7f6 9599 goto cp0_unimplemented;
4cbf4b6d
AM
9600 case CP0_REG23__TRACECONTROL2:
9601 /* PDtrace support */
9602 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 9603 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9604 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9605 register_name = "TraceControl2";
3570d7f6 9606 goto cp0_unimplemented;
4cbf4b6d
AM
9607 case CP0_REG23__USERTRACEDATA1:
9608 /* PDtrace support */
9609 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 9610 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9611 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9612 register_name = "UserTraceData1";
3570d7f6 9613 goto cp0_unimplemented;
4cbf4b6d
AM
9614 case CP0_REG23__TRACEIBPC:
9615 /* PDtrace support */
9616 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9617 /* Stop translation as we may have switched the execution mode */
9618 ctx->base.is_jmp = DISAS_STOP;
9619 register_name = "TraceIBPC";
9620 goto cp0_unimplemented;
9621 case CP0_REG23__TRACEDBPC:
9622 /* PDtrace support */
9623 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 9624 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9625 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 9626 register_name = "TraceDBPC";
3570d7f6 9627 goto cp0_unimplemented;
9c2149c8 9628 default:
f31b035a 9629 goto cp0_unimplemented;
9c2149c8 9630 }
9c2149c8 9631 break;
04992c8c 9632 case CP0_REGISTER_24:
9c2149c8 9633 switch (sel) {
8d7b4b6e 9634 case CP0_REG24__DEPC:
f1aa6320 9635 /* EJTAG support */
7db13fae 9636 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9637 register_name = "DEPC";
2423f660 9638 break;
9c2149c8 9639 default:
f31b035a 9640 goto cp0_unimplemented;
9c2149c8
TS
9641 }
9642 break;
04992c8c 9643 case CP0_REGISTER_25:
9c2149c8 9644 switch (sel) {
1176b328 9645 case CP0_REG25__PERFCTL0:
895c2d04 9646 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 9647 register_name = "Performance0";
2423f660 9648 break;
1176b328 9649 case CP0_REG25__PERFCNT0:
7480515f 9650 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 9651 register_name = "Performance1";
3570d7f6 9652 goto cp0_unimplemented;
1176b328 9653 case CP0_REG25__PERFCTL1:
7480515f 9654 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 9655 register_name = "Performance2";
3570d7f6 9656 goto cp0_unimplemented;
1176b328 9657 case CP0_REG25__PERFCNT1:
7480515f 9658 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 9659 register_name = "Performance3";
3570d7f6 9660 goto cp0_unimplemented;
1176b328 9661 case CP0_REG25__PERFCTL2:
7480515f 9662 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 9663 register_name = "Performance4";
3570d7f6 9664 goto cp0_unimplemented;
1176b328 9665 case CP0_REG25__PERFCNT2:
7480515f 9666 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 9667 register_name = "Performance5";
3570d7f6 9668 goto cp0_unimplemented;
1176b328 9669 case CP0_REG25__PERFCTL3:
7480515f 9670 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 9671 register_name = "Performance6";
3570d7f6 9672 goto cp0_unimplemented;
1176b328 9673 case CP0_REG25__PERFCNT3:
7480515f 9674 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 9675 register_name = "Performance7";
3570d7f6 9676 goto cp0_unimplemented;
9c2149c8 9677 default:
f31b035a 9678 goto cp0_unimplemented;
9c2149c8 9679 }
876d4b07 9680 break;
04992c8c 9681 case CP0_REGISTER_26:
0d74a222 9682 switch (sel) {
dbbf08b2 9683 case CP0_REG26__ERRCTL:
0d74a222 9684 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9685 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9686 register_name = "ErrCtl";
0d74a222
LA
9687 break;
9688 default:
9689 goto cp0_unimplemented;
9690 }
876d4b07 9691 break;
04992c8c 9692 case CP0_REGISTER_27:
9c2149c8 9693 switch (sel) {
5a10873d 9694 case CP0_REG27__CACHERR:
2423f660 9695 /* ignored */
294fc2ea 9696 register_name = "CacheErr";
2423f660 9697 break;
9c2149c8 9698 default:
f31b035a 9699 goto cp0_unimplemented;
9c2149c8 9700 }
876d4b07 9701 break;
04992c8c 9702 case CP0_REGISTER_28:
9c2149c8 9703 switch (sel) {
a30e2f21
AM
9704 case CP0_REG28__TAGLO:
9705 case CP0_REG28__TAGLO1:
9706 case CP0_REG28__TAGLO2:
9707 case CP0_REG28__TAGLO3:
895c2d04 9708 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 9709 register_name = "TagLo";
9c2149c8 9710 break;
a30e2f21
AM
9711 case CP0_REG28__DATALO:
9712 case CP0_REG28__DATALO1:
9713 case CP0_REG28__DATALO2:
9714 case CP0_REG28__DATALO3:
895c2d04 9715 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 9716 register_name = "DataLo";
9c2149c8
TS
9717 break;
9718 default:
f31b035a 9719 goto cp0_unimplemented;
9c2149c8
TS
9720 }
9721 break;
04992c8c 9722 case CP0_REGISTER_29:
9c2149c8 9723 switch (sel) {
af4bb6da
AM
9724 case CP0_REG29__TAGHI:
9725 case CP0_REG29__TAGHI1:
9726 case CP0_REG29__TAGHI2:
9727 case CP0_REG29__TAGHI3:
895c2d04 9728 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 9729 register_name = "TagHi";
9c2149c8 9730 break;
af4bb6da
AM
9731 case CP0_REG29__DATAHI:
9732 case CP0_REG29__DATAHI1:
9733 case CP0_REG29__DATAHI2:
9734 case CP0_REG29__DATAHI3:
895c2d04 9735 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 9736 register_name = "DataHi";
9c2149c8
TS
9737 break;
9738 default:
294fc2ea 9739 register_name = "invalid sel";
f31b035a 9740 goto cp0_unimplemented;
9c2149c8 9741 }
876d4b07 9742 break;
04992c8c 9743 case CP0_REGISTER_30:
9c2149c8 9744 switch (sel) {
4bcf121e 9745 case CP0_REG30__ERROREPC:
7db13fae 9746 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9747 register_name = "ErrorEPC";
2423f660 9748 break;
9c2149c8 9749 default:
f31b035a 9750 goto cp0_unimplemented;
9c2149c8
TS
9751 }
9752 break;
04992c8c 9753 case CP0_REGISTER_31:
9c2149c8 9754 switch (sel) {
14d92efd 9755 case CP0_REG31__DESAVE:
f1aa6320 9756 /* EJTAG support */
7db13fae 9757 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9758 register_name = "DESAVE";
2423f660 9759 break;
14d92efd
AM
9760 case CP0_REG31__KSCRATCH1:
9761 case CP0_REG31__KSCRATCH2:
9762 case CP0_REG31__KSCRATCH3:
9763 case CP0_REG31__KSCRATCH4:
9764 case CP0_REG31__KSCRATCH5:
9765 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9766 CP0_CHECK(ctx->kscrexist & (1 << sel));
9767 tcg_gen_st_tl(arg, cpu_env,
71375b59 9768 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9769 register_name = "KScratch";
e98c0d17 9770 break;
9c2149c8 9771 default:
f31b035a 9772 goto cp0_unimplemented;
9c2149c8 9773 }
9c2149c8
TS
9774 break;
9775 default:
f31b035a 9776 goto cp0_unimplemented;
9c2149c8 9777 }
294fc2ea 9778 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 9779
bf20dc07 9780 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9781 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
9782 /*
9783 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9784 * translated code to check for pending interrupts.
9785 */
eeb3bba8
EC
9786 gen_save_pc(ctx->base.pc_next + 4);
9787 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9788 }
9c2149c8
TS
9789 return;
9790
f31b035a 9791cp0_unimplemented:
294fc2ea
AM
9792 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9793 register_name, reg, sel);
9c2149c8 9794}
d26bc211 9795#endif /* TARGET_MIPS64 */
9c2149c8 9796
7db13fae 9797static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9798 int u, int sel, int h)
9799{
9800 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9801 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9802
9803 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9804 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9805 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 9806 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
9807 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9808 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 9809 tcg_gen_movi_tl(t0, -1);
1f8929d2 9810 } else if (u == 0) {
ead9360e 9811 switch (rt) {
5a25ce94
EI
9812 case 1:
9813 switch (sel) {
9814 case 1:
895c2d04 9815 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
9816 break;
9817 case 2:
895c2d04 9818 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9819 break;
9820 default:
9821 goto die;
9822 break;
9823 }
9824 break;
ead9360e
TS
9825 case 2:
9826 switch (sel) {
9827 case 1:
895c2d04 9828 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9829 break;
9830 case 2:
895c2d04 9831 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9832 break;
9833 case 3:
895c2d04 9834 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9835 break;
9836 case 4:
895c2d04 9837 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9838 break;
9839 case 5:
895c2d04 9840 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9841 break;
9842 case 6:
895c2d04 9843 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9844 break;
9845 case 7:
895c2d04 9846 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9847 break;
9848 default:
d75c135e 9849 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9850 break;
9851 }
9852 break;
9853 case 10:
9854 switch (sel) {
9855 case 0:
895c2d04 9856 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9857 break;
9858 default:
d75c135e 9859 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9860 break;
9861 }
f1fadbb2 9862 break;
ead9360e
TS
9863 case 12:
9864 switch (sel) {
9865 case 0:
895c2d04 9866 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9867 break;
9868 default:
d75c135e 9869 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9870 break;
9871 }
f1fadbb2 9872 break;
5a25ce94
EI
9873 case 13:
9874 switch (sel) {
9875 case 0:
895c2d04 9876 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9877 break;
9878 default:
9879 goto die;
9880 break;
9881 }
9882 break;
9883 case 14:
9884 switch (sel) {
9885 case 0:
895c2d04 9886 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9887 break;
9888 default:
9889 goto die;
9890 break;
9891 }
9892 break;
9893 case 15:
9894 switch (sel) {
9895 case 1:
895c2d04 9896 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9897 break;
9898 default:
9899 goto die;
9900 break;
9901 }
9902 break;
9903 case 16:
9904 switch (sel) {
c2e19f3c
AM
9905 case 0:
9906 case 1:
9907 case 2:
9908 case 3:
9909 case 4:
9910 case 5:
9911 case 6:
9912 case 7:
895c2d04 9913 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9914 break;
9915 default:
9916 goto die;
9917 break;
9918 }
9919 break;
ead9360e
TS
9920 case 23:
9921 switch (sel) {
9922 case 0:
895c2d04 9923 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9924 break;
9925 default:
d75c135e 9926 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9927 break;
9928 }
9929 break;
9930 default:
d75c135e 9931 gen_mfc0(ctx, t0, rt, sel);
ead9360e 9932 }
71375b59
AM
9933 } else {
9934 switch (sel) {
9935 /* GPR registers. */
ead9360e 9936 case 0:
71375b59 9937 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 9938 break;
71375b59 9939 /* Auxiliary CPU registers */
ead9360e 9940 case 1:
71375b59
AM
9941 switch (rt) {
9942 case 0:
9943 gen_helper_1e0i(mftlo, t0, 0);
9944 break;
9945 case 1:
9946 gen_helper_1e0i(mfthi, t0, 0);
9947 break;
9948 case 2:
9949 gen_helper_1e0i(mftacx, t0, 0);
9950 break;
9951 case 4:
9952 gen_helper_1e0i(mftlo, t0, 1);
9953 break;
9954 case 5:
9955 gen_helper_1e0i(mfthi, t0, 1);
9956 break;
9957 case 6:
9958 gen_helper_1e0i(mftacx, t0, 1);
9959 break;
9960 case 8:
9961 gen_helper_1e0i(mftlo, t0, 2);
9962 break;
9963 case 9:
9964 gen_helper_1e0i(mfthi, t0, 2);
9965 break;
9966 case 10:
9967 gen_helper_1e0i(mftacx, t0, 2);
9968 break;
9969 case 12:
9970 gen_helper_1e0i(mftlo, t0, 3);
9971 break;
9972 case 13:
9973 gen_helper_1e0i(mfthi, t0, 3);
9974 break;
9975 case 14:
9976 gen_helper_1e0i(mftacx, t0, 3);
9977 break;
9978 case 16:
9979 gen_helper_mftdsp(t0, cpu_env);
9980 break;
9981 default:
9982 goto die;
9983 }
ead9360e 9984 break;
71375b59 9985 /* Floating point (COP1). */
ead9360e 9986 case 2:
71375b59
AM
9987 /* XXX: For now we support only a single FPU context. */
9988 if (h == 0) {
9989 TCGv_i32 fp0 = tcg_temp_new_i32();
9990
9991 gen_load_fpr32(ctx, fp0, rt);
9992 tcg_gen_ext_i32_tl(t0, fp0);
9993 tcg_temp_free_i32(fp0);
9994 } else {
9995 TCGv_i32 fp0 = tcg_temp_new_i32();
9996
9997 gen_load_fpr32h(ctx, fp0, rt);
9998 tcg_gen_ext_i32_tl(t0, fp0);
9999 tcg_temp_free_i32(fp0);
10000 }
ead9360e 10001 break;
71375b59
AM
10002 case 3:
10003 /* XXX: For now we support only a single FPU context. */
10004 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 10005 break;
71375b59
AM
10006 /* COP2: Not implemented. */
10007 case 4:
ead9360e 10008 case 5:
71375b59 10009 /* fall through */
ead9360e
TS
10010 default:
10011 goto die;
10012 }
ead9360e 10013 }
b44a7fb1 10014 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
10015 gen_store_gpr(t0, rd);
10016 tcg_temp_free(t0);
ead9360e
TS
10017 return;
10018
10019die:
1a3fd9c3 10020 tcg_temp_free(t0);
d12d51d5 10021 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 10022 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10023}
10024
7db13fae 10025static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
10026 int u, int sel, int h)
10027{
10028 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10029 TCGv t0 = tcg_temp_local_new();
ead9360e 10030
1a3fd9c3 10031 gen_load_gpr(t0, rt);
ead9360e 10032 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10033 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10034 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
10035 /* NOP */
10036 ;
1f8929d2
AM
10037 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10038 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
10039 /* NOP */
10040 ;
1f8929d2 10041 } else if (u == 0) {
ead9360e 10042 switch (rd) {
5a25ce94
EI
10043 case 1:
10044 switch (sel) {
10045 case 1:
895c2d04 10046 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
10047 break;
10048 case 2:
895c2d04 10049 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
10050 break;
10051 default:
10052 goto die;
10053 break;
10054 }
10055 break;
ead9360e
TS
10056 case 2:
10057 switch (sel) {
10058 case 1:
895c2d04 10059 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
10060 break;
10061 case 2:
895c2d04 10062 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
10063 break;
10064 case 3:
895c2d04 10065 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
10066 break;
10067 case 4:
895c2d04 10068 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
10069 break;
10070 case 5:
895c2d04 10071 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
10072 break;
10073 case 6:
895c2d04 10074 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
10075 break;
10076 case 7:
895c2d04 10077 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
10078 break;
10079 default:
d75c135e 10080 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10081 break;
10082 }
10083 break;
10084 case 10:
10085 switch (sel) {
10086 case 0:
895c2d04 10087 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
10088 break;
10089 default:
d75c135e 10090 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10091 break;
10092 }
0d0304f2 10093 break;
ead9360e
TS
10094 case 12:
10095 switch (sel) {
10096 case 0:
895c2d04 10097 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
10098 break;
10099 default:
d75c135e 10100 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10101 break;
10102 }
0d0304f2 10103 break;
5a25ce94
EI
10104 case 13:
10105 switch (sel) {
10106 case 0:
895c2d04 10107 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
10108 break;
10109 default:
10110 goto die;
10111 break;
10112 }
10113 break;
10114 case 15:
10115 switch (sel) {
10116 case 1:
895c2d04 10117 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10118 break;
10119 default:
10120 goto die;
10121 break;
10122 }
10123 break;
ead9360e
TS
10124 case 23:
10125 switch (sel) {
10126 case 0:
895c2d04 10127 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10128 break;
10129 default:
d75c135e 10130 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10131 break;
10132 }
10133 break;
10134 default:
d75c135e 10135 gen_mtc0(ctx, t0, rd, sel);
ead9360e 10136 }
71375b59
AM
10137 } else {
10138 switch (sel) {
10139 /* GPR registers. */
ead9360e 10140 case 0:
71375b59 10141 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 10142 break;
71375b59 10143 /* Auxiliary CPU registers */
ead9360e 10144 case 1:
71375b59
AM
10145 switch (rd) {
10146 case 0:
10147 gen_helper_0e1i(mttlo, t0, 0);
10148 break;
10149 case 1:
10150 gen_helper_0e1i(mtthi, t0, 0);
10151 break;
10152 case 2:
10153 gen_helper_0e1i(mttacx, t0, 0);
10154 break;
10155 case 4:
10156 gen_helper_0e1i(mttlo, t0, 1);
10157 break;
10158 case 5:
10159 gen_helper_0e1i(mtthi, t0, 1);
10160 break;
10161 case 6:
10162 gen_helper_0e1i(mttacx, t0, 1);
10163 break;
10164 case 8:
10165 gen_helper_0e1i(mttlo, t0, 2);
10166 break;
10167 case 9:
10168 gen_helper_0e1i(mtthi, t0, 2);
10169 break;
10170 case 10:
10171 gen_helper_0e1i(mttacx, t0, 2);
10172 break;
10173 case 12:
10174 gen_helper_0e1i(mttlo, t0, 3);
10175 break;
10176 case 13:
10177 gen_helper_0e1i(mtthi, t0, 3);
10178 break;
10179 case 14:
10180 gen_helper_0e1i(mttacx, t0, 3);
10181 break;
10182 case 16:
10183 gen_helper_mttdsp(cpu_env, t0);
10184 break;
10185 default:
10186 goto die;
10187 }
ead9360e 10188 break;
71375b59 10189 /* Floating point (COP1). */
ead9360e 10190 case 2:
71375b59
AM
10191 /* XXX: For now we support only a single FPU context. */
10192 if (h == 0) {
10193 TCGv_i32 fp0 = tcg_temp_new_i32();
10194
10195 tcg_gen_trunc_tl_i32(fp0, t0);
10196 gen_store_fpr32(ctx, fp0, rd);
10197 tcg_temp_free_i32(fp0);
10198 } else {
10199 TCGv_i32 fp0 = tcg_temp_new_i32();
10200
10201 tcg_gen_trunc_tl_i32(fp0, t0);
10202 gen_store_fpr32h(ctx, fp0, rd);
10203 tcg_temp_free_i32(fp0);
10204 }
ead9360e 10205 break;
71375b59
AM
10206 case 3:
10207 /* XXX: For now we support only a single FPU context. */
10208 {
10209 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10210
10211 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10212 tcg_temp_free_i32(fs_tmp);
10213 }
10214 /* Stop translation as we may have changed hflags */
10215 ctx->base.is_jmp = DISAS_STOP;
ead9360e 10216 break;
71375b59
AM
10217 /* COP2: Not implemented. */
10218 case 4:
ead9360e 10219 case 5:
71375b59 10220 /* fall through */
ead9360e
TS
10221 default:
10222 goto die;
10223 }
ead9360e 10224 }
b44a7fb1 10225 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10226 tcg_temp_free(t0);
ead9360e
TS
10227 return;
10228
10229die:
1a3fd9c3 10230 tcg_temp_free(t0);
d12d51d5 10231 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10232 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10233}
10234
235785e8
AM
10235static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10236 int rt, int rd)
6af0bf9c 10237{
287c4b84 10238 const char *opn = "ldst";
6af0bf9c 10239
2e15497c 10240 check_cp0_enabled(ctx);
6af0bf9c
FB
10241 switch (opc) {
10242 case OPC_MFC0:
10243 if (rt == 0) {
ead9360e 10244 /* Treat as NOP. */
6af0bf9c
FB
10245 return;
10246 }
d75c135e 10247 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10248 opn = "mfc0";
10249 break;
10250 case OPC_MTC0:
1a3fd9c3 10251 {
1fc7bf6e 10252 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10253
10254 gen_load_gpr(t0, rt);
d75c135e 10255 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10256 tcg_temp_free(t0);
10257 }
6af0bf9c
FB
10258 opn = "mtc0";
10259 break;
d26bc211 10260#if defined(TARGET_MIPS64)
9c2149c8 10261 case OPC_DMFC0:
d75c135e 10262 check_insn(ctx, ISA_MIPS3);
9c2149c8 10263 if (rt == 0) {
ead9360e 10264 /* Treat as NOP. */
9c2149c8
TS
10265 return;
10266 }
d75c135e 10267 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10268 opn = "dmfc0";
10269 break;
10270 case OPC_DMTC0:
d75c135e 10271 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10272 {
1fc7bf6e 10273 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10274
10275 gen_load_gpr(t0, rt);
d75c135e 10276 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10277 tcg_temp_free(t0);
10278 }
9c2149c8
TS
10279 opn = "dmtc0";
10280 break;
534ce69f 10281#endif
5204ea79
LA
10282 case OPC_MFHC0:
10283 check_mvh(ctx);
10284 if (rt == 0) {
10285 /* Treat as NOP. */
10286 return;
10287 }
10288 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10289 opn = "mfhc0";
10290 break;
10291 case OPC_MTHC0:
10292 check_mvh(ctx);
10293 {
10294 TCGv t0 = tcg_temp_new();
10295 gen_load_gpr(t0, rt);
10296 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10297 tcg_temp_free(t0);
10298 }
10299 opn = "mthc0";
10300 break;
ead9360e 10301 case OPC_MFTR:
9affc1c5 10302 check_cp0_enabled(ctx);
ead9360e
TS
10303 if (rd == 0) {
10304 /* Treat as NOP. */
10305 return;
10306 }
6c5c1e20 10307 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10308 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10309 opn = "mftr";
10310 break;
10311 case OPC_MTTR:
9affc1c5 10312 check_cp0_enabled(ctx);
6c5c1e20 10313 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10314 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10315 opn = "mttr";
10316 break;
6af0bf9c 10317 case OPC_TLBWI:
6af0bf9c 10318 opn = "tlbwi";
1f8929d2 10319 if (!env->tlb->helper_tlbwi) {
29929e34 10320 goto die;
1f8929d2 10321 }
895c2d04 10322 gen_helper_tlbwi(cpu_env);
6af0bf9c 10323 break;
9456c2fb
LA
10324 case OPC_TLBINV:
10325 opn = "tlbinv";
10326 if (ctx->ie >= 2) {
10327 if (!env->tlb->helper_tlbinv) {
10328 goto die;
10329 }
10330 gen_helper_tlbinv(cpu_env);
10331 } /* treat as nop if TLBINV not supported */
10332 break;
10333 case OPC_TLBINVF:
10334 opn = "tlbinvf";
10335 if (ctx->ie >= 2) {
10336 if (!env->tlb->helper_tlbinvf) {
10337 goto die;
10338 }
10339 gen_helper_tlbinvf(cpu_env);
10340 } /* treat as nop if TLBINV not supported */
10341 break;
6af0bf9c 10342 case OPC_TLBWR:
6af0bf9c 10343 opn = "tlbwr";
1f8929d2 10344 if (!env->tlb->helper_tlbwr) {
29929e34 10345 goto die;
1f8929d2 10346 }
895c2d04 10347 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10348 break;
10349 case OPC_TLBP:
6af0bf9c 10350 opn = "tlbp";
1f8929d2 10351 if (!env->tlb->helper_tlbp) {
29929e34 10352 goto die;
1f8929d2 10353 }
895c2d04 10354 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10355 break;
10356 case OPC_TLBR:
6af0bf9c 10357 opn = "tlbr";
1f8929d2 10358 if (!env->tlb->helper_tlbr) {
29929e34 10359 goto die;
1f8929d2 10360 }
895c2d04 10361 gen_helper_tlbr(cpu_env);
6af0bf9c 10362 break;
ce9782f4 10363 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
10364 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10365 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10366 goto die;
ce9782f4
LA
10367 } else {
10368 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10369 if (ctx->opcode & (1 << bit_shift)) {
10370 /* OPC_ERETNC */
10371 opn = "eretnc";
10372 check_insn(ctx, ISA_MIPS32R5);
10373 gen_helper_eretnc(cpu_env);
10374 } else {
10375 /* OPC_ERET */
10376 opn = "eret";
10377 check_insn(ctx, ISA_MIPS2);
10378 gen_helper_eret(cpu_env);
10379 }
eeb3bba8 10380 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 10381 }
6af0bf9c
FB
10382 break;
10383 case OPC_DERET:
10384 opn = "deret";
d75c135e 10385 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
10386 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10387 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10388 goto die;
10389 }
6af0bf9c 10390 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 10391 MIPS_INVAL(opn);
9c708c7f 10392 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 10393 } else {
895c2d04 10394 gen_helper_deret(cpu_env);
eeb3bba8 10395 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
10396 }
10397 break;
4ad40f36
FB
10398 case OPC_WAIT:
10399 opn = "wait";
d75c135e 10400 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
10401 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10402 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10403 goto die;
10404 }
4ad40f36 10405 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 10406 ctx->base.pc_next += 4;
4ad40f36 10407 save_cpu_state(ctx, 1);
eeb3bba8 10408 ctx->base.pc_next -= 4;
895c2d04 10409 gen_helper_wait(cpu_env);
eeb3bba8 10410 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 10411 break;
6af0bf9c 10412 default:
29929e34 10413 die:
923617a3 10414 MIPS_INVAL(opn);
9c708c7f 10415 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
10416 return;
10417 }
2abf314d 10418 (void)opn; /* avoid a compiler warning */
6af0bf9c 10419}
f1aa6320 10420#endif /* !CONFIG_USER_ONLY */
6af0bf9c 10421
6ea83fed 10422/* CP1 Branches (before delay slot) */
d75c135e
AJ
10423static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10424 int32_t cc, int32_t offset)
6ea83fed
FB
10425{
10426 target_ulong btarget;
a7812ae4 10427 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 10428
339cd2a8 10429 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 10430 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
10431 goto out;
10432 }
10433
1f8929d2 10434 if (cc != 0) {
d75c135e 10435 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
1f8929d2 10436 }
e189e748 10437
eeb3bba8 10438 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 10439
7a387fff
TS
10440 switch (op) {
10441 case OPC_BC1F:
d94536f4
AJ
10442 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10443 tcg_gen_not_i32(t0, t0);
10444 tcg_gen_andi_i32(t0, t0, 1);
10445 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10446 goto not_likely;
7a387fff 10447 case OPC_BC1FL:
d94536f4
AJ
10448 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10449 tcg_gen_not_i32(t0, t0);
10450 tcg_gen_andi_i32(t0, t0, 1);
10451 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10452 goto likely;
7a387fff 10453 case OPC_BC1T:
d94536f4
AJ
10454 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10455 tcg_gen_andi_i32(t0, t0, 1);
10456 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10457 goto not_likely;
7a387fff 10458 case OPC_BC1TL:
d94536f4
AJ
10459 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10460 tcg_gen_andi_i32(t0, t0, 1);
10461 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10462 likely:
10463 ctx->hflags |= MIPS_HFLAG_BL;
10464 break;
5a5012ec 10465 case OPC_BC1FANY2:
a16336e4 10466 {
d94536f4
AJ
10467 TCGv_i32 t1 = tcg_temp_new_i32();
10468 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10469 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10470 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10471 tcg_temp_free_i32(t1);
d94536f4
AJ
10472 tcg_gen_andi_i32(t0, t0, 1);
10473 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10474 }
5a5012ec
TS
10475 goto not_likely;
10476 case OPC_BC1TANY2:
a16336e4 10477 {
d94536f4
AJ
10478 TCGv_i32 t1 = tcg_temp_new_i32();
10479 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10480 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
10481 tcg_gen_or_i32(t0, t0, t1);
10482 tcg_temp_free_i32(t1);
10483 tcg_gen_andi_i32(t0, t0, 1);
10484 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10485 }
5a5012ec
TS
10486 goto not_likely;
10487 case OPC_BC1FANY4:
a16336e4 10488 {
d94536f4
AJ
10489 TCGv_i32 t1 = tcg_temp_new_i32();
10490 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10491 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 10492 tcg_gen_and_i32(t0, t0, t1);
71375b59 10493 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 10494 tcg_gen_and_i32(t0, t0, t1);
71375b59 10495 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 10496 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10497 tcg_temp_free_i32(t1);
d94536f4
AJ
10498 tcg_gen_andi_i32(t0, t0, 1);
10499 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10500 }
5a5012ec
TS
10501 goto not_likely;
10502 case OPC_BC1TANY4:
a16336e4 10503 {
d94536f4
AJ
10504 TCGv_i32 t1 = tcg_temp_new_i32();
10505 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 10506 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 10507 tcg_gen_or_i32(t0, t0, t1);
71375b59 10508 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 10509 tcg_gen_or_i32(t0, t0, t1);
71375b59 10510 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
10511 tcg_gen_or_i32(t0, t0, t1);
10512 tcg_temp_free_i32(t1);
10513 tcg_gen_andi_i32(t0, t0, 1);
10514 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10515 }
5a5012ec
TS
10516 not_likely:
10517 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10518 break;
10519 default:
9d68ac14 10520 MIPS_INVAL("cp1 cond branch");
9c708c7f 10521 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10522 goto out;
6ea83fed 10523 }
6ea83fed 10524 ctx->btarget = btarget;
b231c103 10525 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10526 out:
a7812ae4 10527 tcg_temp_free_i32(t0);
6ea83fed
FB
10528}
10529
31837be3
YK
10530/* R6 CP1 Branches */
10531static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10532 int32_t ft, int32_t offset,
10533 int delayslot_size)
31837be3
YK
10534{
10535 target_ulong btarget;
31837be3
YK
10536 TCGv_i64 t0 = tcg_temp_new_i64();
10537
10538 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10539#ifdef MIPS_DEBUG_DISAS
339cd2a8 10540 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10541 "\n", ctx->base.pc_next);
31837be3 10542#endif
9c708c7f 10543 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10544 goto out;
10545 }
10546
10547 gen_load_fpr64(ctx, t0, ft);
10548 tcg_gen_andi_i64(t0, t0, 1);
10549
eeb3bba8 10550 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10551
10552 switch (op) {
10553 case OPC_BC1EQZ:
10554 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10555 ctx->hflags |= MIPS_HFLAG_BC;
10556 break;
10557 case OPC_BC1NEZ:
10558 /* t0 already set */
31837be3
YK
10559 ctx->hflags |= MIPS_HFLAG_BC;
10560 break;
10561 default:
9d68ac14 10562 MIPS_INVAL("cp1 cond branch");
9c708c7f 10563 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10564 goto out;
10565 }
10566
10567 tcg_gen_trunc_i64_tl(bcond, t0);
10568
31837be3 10569 ctx->btarget = btarget;
65935f07
YK
10570
10571 switch (delayslot_size) {
10572 case 2:
10573 ctx->hflags |= MIPS_HFLAG_BDS16;
10574 break;
10575 case 4:
10576 ctx->hflags |= MIPS_HFLAG_BDS32;
10577 break;
10578 }
31837be3
YK
10579
10580out:
10581 tcg_temp_free_i64(t0);
10582}
10583
6af0bf9c 10584/* Coprocessor 1 (FPU) */
5a5012ec 10585
5a5012ec
TS
10586#define FOP(func, fmt) (((fmt) << 21) | (func))
10587
bf4120ad
NF
10588enum fopcode {
10589 OPC_ADD_S = FOP(0, FMT_S),
10590 OPC_SUB_S = FOP(1, FMT_S),
10591 OPC_MUL_S = FOP(2, FMT_S),
10592 OPC_DIV_S = FOP(3, FMT_S),
10593 OPC_SQRT_S = FOP(4, FMT_S),
10594 OPC_ABS_S = FOP(5, FMT_S),
10595 OPC_MOV_S = FOP(6, FMT_S),
10596 OPC_NEG_S = FOP(7, FMT_S),
10597 OPC_ROUND_L_S = FOP(8, FMT_S),
10598 OPC_TRUNC_L_S = FOP(9, FMT_S),
10599 OPC_CEIL_L_S = FOP(10, FMT_S),
10600 OPC_FLOOR_L_S = FOP(11, FMT_S),
10601 OPC_ROUND_W_S = FOP(12, FMT_S),
10602 OPC_TRUNC_W_S = FOP(13, FMT_S),
10603 OPC_CEIL_W_S = FOP(14, FMT_S),
10604 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10605 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10606 OPC_MOVCF_S = FOP(17, FMT_S),
10607 OPC_MOVZ_S = FOP(18, FMT_S),
10608 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10609 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10610 OPC_RECIP_S = FOP(21, FMT_S),
10611 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10612 OPC_SELNEZ_S = FOP(23, FMT_S),
10613 OPC_MADDF_S = FOP(24, FMT_S),
10614 OPC_MSUBF_S = FOP(25, FMT_S),
10615 OPC_RINT_S = FOP(26, FMT_S),
10616 OPC_CLASS_S = FOP(27, FMT_S),
10617 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10618 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10619 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10620 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10621 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10622 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10623 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10624 OPC_RSQRT2_S = FOP(31, FMT_S),
10625 OPC_CVT_D_S = FOP(33, FMT_S),
10626 OPC_CVT_W_S = FOP(36, FMT_S),
10627 OPC_CVT_L_S = FOP(37, FMT_S),
10628 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
10629 OPC_CMP_F_S = FOP(48, FMT_S),
10630 OPC_CMP_UN_S = FOP(49, FMT_S),
10631 OPC_CMP_EQ_S = FOP(50, FMT_S),
10632 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10633 OPC_CMP_OLT_S = FOP(52, FMT_S),
10634 OPC_CMP_ULT_S = FOP(53, FMT_S),
10635 OPC_CMP_OLE_S = FOP(54, FMT_S),
10636 OPC_CMP_ULE_S = FOP(55, FMT_S),
10637 OPC_CMP_SF_S = FOP(56, FMT_S),
10638 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10639 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10640 OPC_CMP_NGL_S = FOP(59, FMT_S),
10641 OPC_CMP_LT_S = FOP(60, FMT_S),
10642 OPC_CMP_NGE_S = FOP(61, FMT_S),
10643 OPC_CMP_LE_S = FOP(62, FMT_S),
10644 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
10645
10646 OPC_ADD_D = FOP(0, FMT_D),
10647 OPC_SUB_D = FOP(1, FMT_D),
10648 OPC_MUL_D = FOP(2, FMT_D),
10649 OPC_DIV_D = FOP(3, FMT_D),
10650 OPC_SQRT_D = FOP(4, FMT_D),
10651 OPC_ABS_D = FOP(5, FMT_D),
10652 OPC_MOV_D = FOP(6, FMT_D),
10653 OPC_NEG_D = FOP(7, FMT_D),
10654 OPC_ROUND_L_D = FOP(8, FMT_D),
10655 OPC_TRUNC_L_D = FOP(9, FMT_D),
10656 OPC_CEIL_L_D = FOP(10, FMT_D),
10657 OPC_FLOOR_L_D = FOP(11, FMT_D),
10658 OPC_ROUND_W_D = FOP(12, FMT_D),
10659 OPC_TRUNC_W_D = FOP(13, FMT_D),
10660 OPC_CEIL_W_D = FOP(14, FMT_D),
10661 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10662 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10663 OPC_MOVCF_D = FOP(17, FMT_D),
10664 OPC_MOVZ_D = FOP(18, FMT_D),
10665 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10666 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10667 OPC_RECIP_D = FOP(21, FMT_D),
10668 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10669 OPC_SELNEZ_D = FOP(23, FMT_D),
10670 OPC_MADDF_D = FOP(24, FMT_D),
10671 OPC_MSUBF_D = FOP(25, FMT_D),
10672 OPC_RINT_D = FOP(26, FMT_D),
10673 OPC_CLASS_D = FOP(27, FMT_D),
10674 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10675 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10676 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10677 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10678 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10679 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10680 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10681 OPC_RSQRT2_D = FOP(31, FMT_D),
10682 OPC_CVT_S_D = FOP(32, FMT_D),
10683 OPC_CVT_W_D = FOP(36, FMT_D),
10684 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
10685 OPC_CMP_F_D = FOP(48, FMT_D),
10686 OPC_CMP_UN_D = FOP(49, FMT_D),
10687 OPC_CMP_EQ_D = FOP(50, FMT_D),
10688 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10689 OPC_CMP_OLT_D = FOP(52, FMT_D),
10690 OPC_CMP_ULT_D = FOP(53, FMT_D),
10691 OPC_CMP_OLE_D = FOP(54, FMT_D),
10692 OPC_CMP_ULE_D = FOP(55, FMT_D),
10693 OPC_CMP_SF_D = FOP(56, FMT_D),
10694 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10695 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10696 OPC_CMP_NGL_D = FOP(59, FMT_D),
10697 OPC_CMP_LT_D = FOP(60, FMT_D),
10698 OPC_CMP_NGE_D = FOP(61, FMT_D),
10699 OPC_CMP_LE_D = FOP(62, FMT_D),
10700 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
10701
10702 OPC_CVT_S_W = FOP(32, FMT_W),
10703 OPC_CVT_D_W = FOP(33, FMT_W),
10704 OPC_CVT_S_L = FOP(32, FMT_L),
10705 OPC_CVT_D_L = FOP(33, FMT_L),
10706 OPC_CVT_PS_PW = FOP(38, FMT_W),
10707
10708 OPC_ADD_PS = FOP(0, FMT_PS),
10709 OPC_SUB_PS = FOP(1, FMT_PS),
10710 OPC_MUL_PS = FOP(2, FMT_PS),
10711 OPC_DIV_PS = FOP(3, FMT_PS),
10712 OPC_ABS_PS = FOP(5, FMT_PS),
10713 OPC_MOV_PS = FOP(6, FMT_PS),
10714 OPC_NEG_PS = FOP(7, FMT_PS),
10715 OPC_MOVCF_PS = FOP(17, FMT_PS),
10716 OPC_MOVZ_PS = FOP(18, FMT_PS),
10717 OPC_MOVN_PS = FOP(19, FMT_PS),
10718 OPC_ADDR_PS = FOP(24, FMT_PS),
10719 OPC_MULR_PS = FOP(26, FMT_PS),
10720 OPC_RECIP2_PS = FOP(28, FMT_PS),
10721 OPC_RECIP1_PS = FOP(29, FMT_PS),
10722 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10723 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10724
10725 OPC_CVT_S_PU = FOP(32, FMT_PS),
10726 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10727 OPC_CVT_S_PL = FOP(40, FMT_PS),
10728 OPC_PLL_PS = FOP(44, FMT_PS),
10729 OPC_PLU_PS = FOP(45, FMT_PS),
10730 OPC_PUL_PS = FOP(46, FMT_PS),
10731 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
10732 OPC_CMP_F_PS = FOP(48, FMT_PS),
10733 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10734 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10735 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10736 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10737 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10738 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10739 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10740 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10741 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10742 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10743 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10744 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10745 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10746 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10747 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
10748};
10749
3f493883
YK
10750enum r6_f_cmp_op {
10751 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10752 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10753 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10754 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10755 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10756 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10757 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10758 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10759 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10760 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10761 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10762 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10763 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10764 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10765 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10766 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10767 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10768 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10769 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10770 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10771 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10772 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10773
10774 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10775 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10776 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10777 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10778 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10779 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10780 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10781 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10782 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10783 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10784 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10785 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10786 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10787 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10788 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10789 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10790 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10791 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10792 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10793 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10794 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10795 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10796};
235785e8
AM
10797
10798static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10799{
72c3a3ee 10800 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10801
10802 switch (opc) {
10803 case OPC_MFC1:
b6d96bed 10804 {
a7812ae4 10805 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10806
7c979afd 10807 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10808 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10809 tcg_temp_free_i32(fp0);
6958549d 10810 }
6c5c1e20 10811 gen_store_gpr(t0, rt);
6ea83fed
FB
10812 break;
10813 case OPC_MTC1:
6c5c1e20 10814 gen_load_gpr(t0, rt);
b6d96bed 10815 {
a7812ae4 10816 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10817
10818 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10819 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10820 tcg_temp_free_i32(fp0);
6958549d 10821 }
6ea83fed
FB
10822 break;
10823 case OPC_CFC1:
895c2d04 10824 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10825 gen_store_gpr(t0, rt);
6ea83fed
FB
10826 break;
10827 case OPC_CTC1:
6c5c1e20 10828 gen_load_gpr(t0, rt);
9c708c7f 10829 save_cpu_state(ctx, 0);
736d120a
PJ
10830 {
10831 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10832
10833 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10834 tcg_temp_free_i32(fs_tmp);
10835 }
4cf8a45f 10836 /* Stop translation as we may have changed hflags */
eeb3bba8 10837 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10838 break;
72c3a3ee 10839#if defined(TARGET_MIPS64)
9c2149c8 10840 case OPC_DMFC1:
72c3a3ee 10841 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10842 gen_store_gpr(t0, rt);
5a5012ec 10843 break;
9c2149c8 10844 case OPC_DMTC1:
6c5c1e20 10845 gen_load_gpr(t0, rt);
72c3a3ee 10846 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10847 break;
72c3a3ee 10848#endif
5a5012ec 10849 case OPC_MFHC1:
b6d96bed 10850 {
a7812ae4 10851 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10852
7f6613ce 10853 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10854 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10855 tcg_temp_free_i32(fp0);
6958549d 10856 }
6c5c1e20 10857 gen_store_gpr(t0, rt);
5a5012ec
TS
10858 break;
10859 case OPC_MTHC1:
6c5c1e20 10860 gen_load_gpr(t0, rt);
b6d96bed 10861 {
a7812ae4 10862 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10863
10864 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10865 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10866 tcg_temp_free_i32(fp0);
6958549d 10867 }
5a5012ec 10868 break;
6ea83fed 10869 default:
9d68ac14 10870 MIPS_INVAL("cp1 move");
9c708c7f 10871 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10872 goto out;
6ea83fed 10873 }
6c5c1e20
TS
10874
10875 out:
10876 tcg_temp_free(t0);
6ea83fed
FB
10877}
10878
235785e8 10879static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 10880{
42a268c2 10881 TCGLabel *l1;
e214b9bb 10882 TCGCond cond;
af58f9ca
AJ
10883 TCGv_i32 t0;
10884
10885 if (rd == 0) {
10886 /* Treat as NOP. */
10887 return;
10888 }
6ea83fed 10889
1f8929d2 10890 if (tf) {
e214b9bb 10891 cond = TCG_COND_EQ;
1f8929d2 10892 } else {
27848470 10893 cond = TCG_COND_NE;
1f8929d2 10894 }
27848470 10895
af58f9ca
AJ
10896 l1 = gen_new_label();
10897 t0 = tcg_temp_new_i32();
fa31af0e 10898 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10899 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10900 tcg_temp_free_i32(t0);
af58f9ca
AJ
10901 if (rs == 0) {
10902 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10903 } else {
10904 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10905 }
e214b9bb 10906 gen_set_label(l1);
5a5012ec
TS
10907}
10908
7c979afd
LA
10909static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10910 int tf)
a16336e4 10911{
a16336e4 10912 int cond;
cbc37b28 10913 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10914 TCGLabel *l1 = gen_new_label();
a16336e4 10915
1f8929d2 10916 if (tf) {
a16336e4 10917 cond = TCG_COND_EQ;
1f8929d2 10918 } else {
a16336e4 10919 cond = TCG_COND_NE;
1f8929d2 10920 }
a16336e4 10921
fa31af0e 10922 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10923 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10924 gen_load_fpr32(ctx, t0, fs);
10925 gen_store_fpr32(ctx, t0, fd);
a16336e4 10926 gen_set_label(l1);
cbc37b28 10927 tcg_temp_free_i32(t0);
5a5012ec 10928}
a16336e4 10929
235785e8
AM
10930static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10931 int tf)
a16336e4 10932{
a16336e4 10933 int cond;
cbc37b28
AJ
10934 TCGv_i32 t0 = tcg_temp_new_i32();
10935 TCGv_i64 fp0;
42a268c2 10936 TCGLabel *l1 = gen_new_label();
a16336e4 10937
1f8929d2 10938 if (tf) {
a16336e4 10939 cond = TCG_COND_EQ;
1f8929d2 10940 } else {
a16336e4 10941 cond = TCG_COND_NE;
1f8929d2 10942 }
a16336e4 10943
fa31af0e 10944 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10945 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10946 tcg_temp_free_i32(t0);
11f94258 10947 fp0 = tcg_temp_new_i64();
9bf3eb2c 10948 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10949 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10950 tcg_temp_free_i64(fp0);
cbc37b28 10951 gen_set_label(l1);
a16336e4
TS
10952}
10953
7f6613ce
PJ
10954static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10955 int cc, int tf)
a16336e4
TS
10956{
10957 int cond;
cbc37b28 10958 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10959 TCGLabel *l1 = gen_new_label();
10960 TCGLabel *l2 = gen_new_label();
a16336e4 10961
1f8929d2 10962 if (tf) {
a16336e4 10963 cond = TCG_COND_EQ;
1f8929d2 10964 } else {
a16336e4 10965 cond = TCG_COND_NE;
1f8929d2 10966 }
a16336e4 10967
fa31af0e 10968 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10969 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10970 gen_load_fpr32(ctx, t0, fs);
10971 gen_store_fpr32(ctx, t0, fd);
a16336e4 10972 gen_set_label(l1);
9bf3eb2c 10973
71375b59 10974 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 10975 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10976 gen_load_fpr32h(ctx, t0, fs);
10977 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10978 tcg_temp_free_i32(t0);
a16336e4 10979 gen_set_label(l2);
a16336e4
TS
10980}
10981
e7f16abb
LA
10982static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10983 int fs)
10984{
10985 TCGv_i32 t1 = tcg_const_i32(0);
10986 TCGv_i32 fp0 = tcg_temp_new_i32();
10987 TCGv_i32 fp1 = tcg_temp_new_i32();
10988 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10989 gen_load_fpr32(ctx, fp0, fd);
10990 gen_load_fpr32(ctx, fp1, ft);
10991 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10992
10993 switch (op1) {
10994 case OPC_SEL_S:
10995 tcg_gen_andi_i32(fp0, fp0, 1);
10996 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10997 break;
10998 case OPC_SELEQZ_S:
10999 tcg_gen_andi_i32(fp1, fp1, 1);
11000 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11001 break;
11002 case OPC_SELNEZ_S:
11003 tcg_gen_andi_i32(fp1, fp1, 1);
11004 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11005 break;
11006 default:
11007 MIPS_INVAL("gen_sel_s");
9c708c7f 11008 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11009 break;
11010 }
11011
7c979afd 11012 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11013 tcg_temp_free_i32(fp2);
11014 tcg_temp_free_i32(fp1);
11015 tcg_temp_free_i32(fp0);
11016 tcg_temp_free_i32(t1);
11017}
11018
11019static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11020 int fs)
11021{
11022 TCGv_i64 t1 = tcg_const_i64(0);
11023 TCGv_i64 fp0 = tcg_temp_new_i64();
11024 TCGv_i64 fp1 = tcg_temp_new_i64();
11025 TCGv_i64 fp2 = tcg_temp_new_i64();
11026 gen_load_fpr64(ctx, fp0, fd);
11027 gen_load_fpr64(ctx, fp1, ft);
11028 gen_load_fpr64(ctx, fp2, fs);
11029
11030 switch (op1) {
11031 case OPC_SEL_D:
11032 tcg_gen_andi_i64(fp0, fp0, 1);
11033 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11034 break;
11035 case OPC_SELEQZ_D:
11036 tcg_gen_andi_i64(fp1, fp1, 1);
11037 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11038 break;
11039 case OPC_SELNEZ_D:
11040 tcg_gen_andi_i64(fp1, fp1, 1);
11041 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11042 break;
11043 default:
11044 MIPS_INVAL("gen_sel_d");
9c708c7f 11045 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11046 break;
11047 }
11048
11049 gen_store_fpr64(ctx, fp0, fd);
11050 tcg_temp_free_i64(fp2);
11051 tcg_temp_free_i64(fp1);
11052 tcg_temp_free_i64(fp0);
11053 tcg_temp_free_i64(t1);
11054}
6ea83fed 11055
235785e8
AM
11056static void gen_farith(DisasContext *ctx, enum fopcode op1,
11057 int ft, int fs, int fd, int cc)
6ea83fed 11058{
7a387fff 11059 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
11060 switch (op1) {
11061 case OPC_ADD_S:
b6d96bed 11062 {
a7812ae4
PB
11063 TCGv_i32 fp0 = tcg_temp_new_i32();
11064 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11065
7c979afd
LA
11066 gen_load_fpr32(ctx, fp0, fs);
11067 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11068 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11069 tcg_temp_free_i32(fp1);
7c979afd 11070 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11071 tcg_temp_free_i32(fp0);
b6d96bed 11072 }
5a5012ec 11073 break;
bf4120ad 11074 case OPC_SUB_S:
b6d96bed 11075 {
a7812ae4
PB
11076 TCGv_i32 fp0 = tcg_temp_new_i32();
11077 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11078
7c979afd
LA
11079 gen_load_fpr32(ctx, fp0, fs);
11080 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11081 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11082 tcg_temp_free_i32(fp1);
7c979afd 11083 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11084 tcg_temp_free_i32(fp0);
b6d96bed 11085 }
5a5012ec 11086 break;
bf4120ad 11087 case OPC_MUL_S:
b6d96bed 11088 {
a7812ae4
PB
11089 TCGv_i32 fp0 = tcg_temp_new_i32();
11090 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11091
7c979afd
LA
11092 gen_load_fpr32(ctx, fp0, fs);
11093 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11094 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11095 tcg_temp_free_i32(fp1);
7c979afd 11096 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11097 tcg_temp_free_i32(fp0);
b6d96bed 11098 }
5a5012ec 11099 break;
bf4120ad 11100 case OPC_DIV_S:
b6d96bed 11101 {
a7812ae4
PB
11102 TCGv_i32 fp0 = tcg_temp_new_i32();
11103 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11104
7c979afd
LA
11105 gen_load_fpr32(ctx, fp0, fs);
11106 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11107 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11108 tcg_temp_free_i32(fp1);
7c979afd 11109 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11110 tcg_temp_free_i32(fp0);
b6d96bed 11111 }
5a5012ec 11112 break;
bf4120ad 11113 case OPC_SQRT_S:
b6d96bed 11114 {
a7812ae4 11115 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11116
7c979afd 11117 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11118 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 11119 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11120 tcg_temp_free_i32(fp0);
b6d96bed 11121 }
5a5012ec 11122 break;
bf4120ad 11123 case OPC_ABS_S:
b6d96bed 11124 {
a7812ae4 11125 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11126
7c979afd 11127 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11128 if (ctx->abs2008) {
11129 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11130 } else {
11131 gen_helper_float_abs_s(fp0, fp0);
11132 }
7c979afd 11133 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11134 tcg_temp_free_i32(fp0);
b6d96bed 11135 }
5a5012ec 11136 break;
bf4120ad 11137 case OPC_MOV_S:
b6d96bed 11138 {
a7812ae4 11139 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11140
7c979afd
LA
11141 gen_load_fpr32(ctx, fp0, fs);
11142 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11143 tcg_temp_free_i32(fp0);
b6d96bed 11144 }
5a5012ec 11145 break;
bf4120ad 11146 case OPC_NEG_S:
b6d96bed 11147 {
a7812ae4 11148 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11149
7c979afd 11150 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11151 if (ctx->abs2008) {
11152 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11153 } else {
11154 gen_helper_float_chs_s(fp0, fp0);
11155 }
7c979afd 11156 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11157 tcg_temp_free_i32(fp0);
b6d96bed 11158 }
5a5012ec 11159 break;
bf4120ad 11160 case OPC_ROUND_L_S:
5e755519 11161 check_cp1_64bitmode(ctx);
b6d96bed 11162 {
a7812ae4
PB
11163 TCGv_i32 fp32 = tcg_temp_new_i32();
11164 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11165
7c979afd 11166 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11167 if (ctx->nan2008) {
11168 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11169 } else {
11170 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11171 }
a7812ae4 11172 tcg_temp_free_i32(fp32);
b6d96bed 11173 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11174 tcg_temp_free_i64(fp64);
b6d96bed 11175 }
5a5012ec 11176 break;
bf4120ad 11177 case OPC_TRUNC_L_S:
5e755519 11178 check_cp1_64bitmode(ctx);
b6d96bed 11179 {
a7812ae4
PB
11180 TCGv_i32 fp32 = tcg_temp_new_i32();
11181 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11182
7c979afd 11183 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11184 if (ctx->nan2008) {
11185 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11186 } else {
11187 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11188 }
a7812ae4 11189 tcg_temp_free_i32(fp32);
b6d96bed 11190 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11191 tcg_temp_free_i64(fp64);
b6d96bed 11192 }
5a5012ec 11193 break;
bf4120ad 11194 case OPC_CEIL_L_S:
5e755519 11195 check_cp1_64bitmode(ctx);
b6d96bed 11196 {
a7812ae4
PB
11197 TCGv_i32 fp32 = tcg_temp_new_i32();
11198 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11199
7c979afd 11200 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11201 if (ctx->nan2008) {
11202 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11203 } else {
11204 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11205 }
a7812ae4 11206 tcg_temp_free_i32(fp32);
b6d96bed 11207 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11208 tcg_temp_free_i64(fp64);
b6d96bed 11209 }
5a5012ec 11210 break;
bf4120ad 11211 case OPC_FLOOR_L_S:
5e755519 11212 check_cp1_64bitmode(ctx);
b6d96bed 11213 {
a7812ae4
PB
11214 TCGv_i32 fp32 = tcg_temp_new_i32();
11215 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11216
7c979afd 11217 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11218 if (ctx->nan2008) {
11219 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11220 } else {
11221 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11222 }
a7812ae4 11223 tcg_temp_free_i32(fp32);
b6d96bed 11224 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11225 tcg_temp_free_i64(fp64);
b6d96bed 11226 }
5a5012ec 11227 break;
bf4120ad 11228 case OPC_ROUND_W_S:
b6d96bed 11229 {
a7812ae4 11230 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11231
7c979afd 11232 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11233 if (ctx->nan2008) {
11234 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11235 } else {
11236 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11237 }
7c979afd 11238 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11239 tcg_temp_free_i32(fp0);
b6d96bed 11240 }
5a5012ec 11241 break;
bf4120ad 11242 case OPC_TRUNC_W_S:
b6d96bed 11243 {
a7812ae4 11244 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11245
7c979afd 11246 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11247 if (ctx->nan2008) {
11248 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11249 } else {
11250 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11251 }
7c979afd 11252 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11253 tcg_temp_free_i32(fp0);
b6d96bed 11254 }
5a5012ec 11255 break;
bf4120ad 11256 case OPC_CEIL_W_S:
b6d96bed 11257 {
a7812ae4 11258 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11259
7c979afd 11260 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11261 if (ctx->nan2008) {
11262 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11263 } else {
11264 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11265 }
7c979afd 11266 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11267 tcg_temp_free_i32(fp0);
b6d96bed 11268 }
5a5012ec 11269 break;
bf4120ad 11270 case OPC_FLOOR_W_S:
b6d96bed 11271 {
a7812ae4 11272 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11273
7c979afd 11274 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11275 if (ctx->nan2008) {
11276 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11277 } else {
11278 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11279 }
7c979afd 11280 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11281 tcg_temp_free_i32(fp0);
b6d96bed 11282 }
5a5012ec 11283 break;
e7f16abb
LA
11284 case OPC_SEL_S:
11285 check_insn(ctx, ISA_MIPS32R6);
11286 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11287 break;
11288 case OPC_SELEQZ_S:
11289 check_insn(ctx, ISA_MIPS32R6);
11290 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11291 break;
11292 case OPC_SELNEZ_S:
11293 check_insn(ctx, ISA_MIPS32R6);
11294 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11295 break;
bf4120ad 11296 case OPC_MOVCF_S:
fecd2646 11297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 11298 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11299 break;
bf4120ad 11300 case OPC_MOVZ_S:
fecd2646 11301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11302 {
42a268c2 11303 TCGLabel *l1 = gen_new_label();
c9297f4d 11304 TCGv_i32 fp0;
a16336e4 11305
c9297f4d
AJ
11306 if (ft != 0) {
11307 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11308 }
11309 fp0 = tcg_temp_new_i32();
7c979afd
LA
11310 gen_load_fpr32(ctx, fp0, fs);
11311 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11312 tcg_temp_free_i32(fp0);
a16336e4
TS
11313 gen_set_label(l1);
11314 }
5a5012ec 11315 break;
bf4120ad 11316 case OPC_MOVN_S:
fecd2646 11317 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11318 {
42a268c2 11319 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11320 TCGv_i32 fp0;
11321
11322 if (ft != 0) {
11323 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11324 fp0 = tcg_temp_new_i32();
7c979afd
LA
11325 gen_load_fpr32(ctx, fp0, fs);
11326 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11327 tcg_temp_free_i32(fp0);
11328 gen_set_label(l1);
11329 }
a16336e4 11330 }
5a5012ec 11331 break;
bf4120ad 11332 case OPC_RECIP_S:
b6d96bed 11333 {
a7812ae4 11334 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11335
7c979afd 11336 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11337 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11338 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11339 tcg_temp_free_i32(fp0);
b6d96bed 11340 }
57fa1fb3 11341 break;
bf4120ad 11342 case OPC_RSQRT_S:
b6d96bed 11343 {
a7812ae4 11344 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11345
7c979afd 11346 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11347 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11348 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11349 tcg_temp_free_i32(fp0);
b6d96bed 11350 }
57fa1fb3 11351 break;
e7f16abb
LA
11352 case OPC_MADDF_S:
11353 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11354 {
a7812ae4
PB
11355 TCGv_i32 fp0 = tcg_temp_new_i32();
11356 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11357 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11358 gen_load_fpr32(ctx, fp0, fs);
11359 gen_load_fpr32(ctx, fp1, ft);
11360 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11361 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11362 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11363 tcg_temp_free_i32(fp2);
a7812ae4 11364 tcg_temp_free_i32(fp1);
a7812ae4 11365 tcg_temp_free_i32(fp0);
b6d96bed 11366 }
57fa1fb3 11367 break;
e7f16abb
LA
11368 case OPC_MSUBF_S:
11369 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11370 {
a7812ae4 11371 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11372 TCGv_i32 fp1 = tcg_temp_new_i32();
11373 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11374 gen_load_fpr32(ctx, fp0, fs);
11375 gen_load_fpr32(ctx, fp1, ft);
11376 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11377 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11378 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11379 tcg_temp_free_i32(fp2);
11380 tcg_temp_free_i32(fp1);
a7812ae4 11381 tcg_temp_free_i32(fp0);
b6d96bed 11382 }
57fa1fb3 11383 break;
e7f16abb
LA
11384 case OPC_RINT_S:
11385 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11386 {
a7812ae4 11387 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11388 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11389 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 11390 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11391 tcg_temp_free_i32(fp0);
b6d96bed 11392 }
57fa1fb3 11393 break;
e7f16abb
LA
11394 case OPC_CLASS_S:
11395 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11396 {
e7f16abb 11397 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11398 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 11399 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 11400 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 11401 tcg_temp_free_i32(fp0);
e7f16abb
LA
11402 }
11403 break;
11404 case OPC_MIN_S: /* OPC_RECIP2_S */
11405 if (ctx->insn_flags & ISA_MIPS32R6) {
11406 /* OPC_MIN_S */
a7812ae4
PB
11407 TCGv_i32 fp0 = tcg_temp_new_i32();
11408 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11409 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11410 gen_load_fpr32(ctx, fp0, fs);
11411 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11412 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 11413 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11414 tcg_temp_free_i32(fp2);
11415 tcg_temp_free_i32(fp1);
11416 tcg_temp_free_i32(fp0);
e7f16abb
LA
11417 } else {
11418 /* OPC_RECIP2_S */
11419 check_cp1_64bitmode(ctx);
11420 {
11421 TCGv_i32 fp0 = tcg_temp_new_i32();
11422 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11423
7c979afd
LA
11424 gen_load_fpr32(ctx, fp0, fs);
11425 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11426 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11427 tcg_temp_free_i32(fp1);
7c979afd 11428 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11429 tcg_temp_free_i32(fp0);
11430 }
e7f16abb
LA
11431 }
11432 break;
11433 case OPC_MINA_S: /* OPC_RECIP1_S */
11434 if (ctx->insn_flags & ISA_MIPS32R6) {
11435 /* OPC_MINA_S */
11436 TCGv_i32 fp0 = tcg_temp_new_i32();
11437 TCGv_i32 fp1 = tcg_temp_new_i32();
11438 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11439 gen_load_fpr32(ctx, fp0, fs);
11440 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11441 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 11442 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11443 tcg_temp_free_i32(fp2);
11444 tcg_temp_free_i32(fp1);
11445 tcg_temp_free_i32(fp0);
e7f16abb
LA
11446 } else {
11447 /* OPC_RECIP1_S */
11448 check_cp1_64bitmode(ctx);
11449 {
11450 TCGv_i32 fp0 = tcg_temp_new_i32();
11451
7c979afd 11452 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11453 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 11454 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11455 tcg_temp_free_i32(fp0);
11456 }
e7f16abb
LA
11457 }
11458 break;
11459 case OPC_MAX_S: /* OPC_RSQRT1_S */
11460 if (ctx->insn_flags & ISA_MIPS32R6) {
11461 /* OPC_MAX_S */
11462 TCGv_i32 fp0 = tcg_temp_new_i32();
11463 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11464 gen_load_fpr32(ctx, fp0, fs);
11465 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11466 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11467 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11468 tcg_temp_free_i32(fp1);
11469 tcg_temp_free_i32(fp0);
e7f16abb
LA
11470 } else {
11471 /* OPC_RSQRT1_S */
11472 check_cp1_64bitmode(ctx);
11473 {
11474 TCGv_i32 fp0 = tcg_temp_new_i32();
11475
7c979afd 11476 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11477 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11478 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11479 tcg_temp_free_i32(fp0);
11480 }
e7f16abb
LA
11481 }
11482 break;
11483 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11484 if (ctx->insn_flags & ISA_MIPS32R6) {
11485 /* OPC_MAXA_S */
11486 TCGv_i32 fp0 = tcg_temp_new_i32();
11487 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11488 gen_load_fpr32(ctx, fp0, fs);
11489 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11490 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11491 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11492 tcg_temp_free_i32(fp1);
a7812ae4 11493 tcg_temp_free_i32(fp0);
e7f16abb
LA
11494 } else {
11495 /* OPC_RSQRT2_S */
11496 check_cp1_64bitmode(ctx);
11497 {
11498 TCGv_i32 fp0 = tcg_temp_new_i32();
11499 TCGv_i32 fp1 = tcg_temp_new_i32();
11500
7c979afd
LA
11501 gen_load_fpr32(ctx, fp0, fs);
11502 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11503 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11504 tcg_temp_free_i32(fp1);
7c979afd 11505 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11506 tcg_temp_free_i32(fp0);
11507 }
b6d96bed 11508 }
57fa1fb3 11509 break;
bf4120ad 11510 case OPC_CVT_D_S:
5e755519 11511 check_cp1_registers(ctx, fd);
b6d96bed 11512 {
a7812ae4
PB
11513 TCGv_i32 fp32 = tcg_temp_new_i32();
11514 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11515
7c979afd 11516 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11517 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11518 tcg_temp_free_i32(fp32);
b6d96bed 11519 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11520 tcg_temp_free_i64(fp64);
b6d96bed 11521 }
5a5012ec 11522 break;
bf4120ad 11523 case OPC_CVT_W_S:
b6d96bed 11524 {
a7812ae4 11525 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11526
7c979afd 11527 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11528 if (ctx->nan2008) {
11529 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11530 } else {
11531 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11532 }
7c979afd 11533 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11534 tcg_temp_free_i32(fp0);
b6d96bed 11535 }
5a5012ec 11536 break;
bf4120ad 11537 case OPC_CVT_L_S:
5e755519 11538 check_cp1_64bitmode(ctx);
b6d96bed 11539 {
a7812ae4
PB
11540 TCGv_i32 fp32 = tcg_temp_new_i32();
11541 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11542
7c979afd 11543 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11544 if (ctx->nan2008) {
11545 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11546 } else {
11547 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11548 }
a7812ae4 11549 tcg_temp_free_i32(fp32);
b6d96bed 11550 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11551 tcg_temp_free_i64(fp64);
b6d96bed 11552 }
5a5012ec 11553 break;
bf4120ad 11554 case OPC_CVT_PS_S:
e29c9628 11555 check_ps(ctx);
b6d96bed 11556 {
a7812ae4
PB
11557 TCGv_i64 fp64 = tcg_temp_new_i64();
11558 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11559 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11560
7c979afd
LA
11561 gen_load_fpr32(ctx, fp32_0, fs);
11562 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11563 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11564 tcg_temp_free_i32(fp32_1);
11565 tcg_temp_free_i32(fp32_0);
36aa55dc 11566 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11567 tcg_temp_free_i64(fp64);
b6d96bed 11568 }
5a5012ec 11569 break;
bf4120ad
NF
11570 case OPC_CMP_F_S:
11571 case OPC_CMP_UN_S:
11572 case OPC_CMP_EQ_S:
11573 case OPC_CMP_UEQ_S:
11574 case OPC_CMP_OLT_S:
11575 case OPC_CMP_ULT_S:
11576 case OPC_CMP_OLE_S:
11577 case OPC_CMP_ULE_S:
11578 case OPC_CMP_SF_S:
11579 case OPC_CMP_NGLE_S:
11580 case OPC_CMP_SEQ_S:
11581 case OPC_CMP_NGL_S:
11582 case OPC_CMP_LT_S:
11583 case OPC_CMP_NGE_S:
11584 case OPC_CMP_LE_S:
11585 case OPC_CMP_NGT_S:
fecd2646 11586 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 11587 if (ctx->opcode & (1 << 6)) {
71375b59 11588 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 11589 } else {
71375b59 11590 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11591 }
5a5012ec 11592 break;
bf4120ad 11593 case OPC_ADD_D:
5e755519 11594 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11595 {
a7812ae4
PB
11596 TCGv_i64 fp0 = tcg_temp_new_i64();
11597 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11598
11599 gen_load_fpr64(ctx, fp0, fs);
11600 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11601 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11602 tcg_temp_free_i64(fp1);
b6d96bed 11603 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11604 tcg_temp_free_i64(fp0);
b6d96bed 11605 }
6ea83fed 11606 break;
bf4120ad 11607 case OPC_SUB_D:
5e755519 11608 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11609 {
a7812ae4
PB
11610 TCGv_i64 fp0 = tcg_temp_new_i64();
11611 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11612
11613 gen_load_fpr64(ctx, fp0, fs);
11614 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11615 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11616 tcg_temp_free_i64(fp1);
b6d96bed 11617 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11618 tcg_temp_free_i64(fp0);
b6d96bed 11619 }
6ea83fed 11620 break;
bf4120ad 11621 case OPC_MUL_D:
5e755519 11622 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11623 {
a7812ae4
PB
11624 TCGv_i64 fp0 = tcg_temp_new_i64();
11625 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11626
11627 gen_load_fpr64(ctx, fp0, fs);
11628 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11629 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11630 tcg_temp_free_i64(fp1);
b6d96bed 11631 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11632 tcg_temp_free_i64(fp0);
b6d96bed 11633 }
6ea83fed 11634 break;
bf4120ad 11635 case OPC_DIV_D:
5e755519 11636 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11637 {
a7812ae4
PB
11638 TCGv_i64 fp0 = tcg_temp_new_i64();
11639 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11640
11641 gen_load_fpr64(ctx, fp0, fs);
11642 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11643 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11644 tcg_temp_free_i64(fp1);
b6d96bed 11645 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11646 tcg_temp_free_i64(fp0);
b6d96bed 11647 }
6ea83fed 11648 break;
bf4120ad 11649 case OPC_SQRT_D:
5e755519 11650 check_cp1_registers(ctx, fs | fd);
b6d96bed 11651 {
a7812ae4 11652 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11653
11654 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11655 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11656 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11657 tcg_temp_free_i64(fp0);
b6d96bed 11658 }
6ea83fed 11659 break;
bf4120ad 11660 case OPC_ABS_D:
5e755519 11661 check_cp1_registers(ctx, fs | fd);
b6d96bed 11662 {
a7812ae4 11663 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11664
11665 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11666 if (ctx->abs2008) {
11667 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11668 } else {
11669 gen_helper_float_abs_d(fp0, fp0);
11670 }
b6d96bed 11671 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11672 tcg_temp_free_i64(fp0);
b6d96bed 11673 }
6ea83fed 11674 break;
bf4120ad 11675 case OPC_MOV_D:
5e755519 11676 check_cp1_registers(ctx, fs | fd);
b6d96bed 11677 {
a7812ae4 11678 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11679
11680 gen_load_fpr64(ctx, fp0, fs);
11681 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11682 tcg_temp_free_i64(fp0);
b6d96bed 11683 }
6ea83fed 11684 break;
bf4120ad 11685 case OPC_NEG_D:
5e755519 11686 check_cp1_registers(ctx, fs | fd);
b6d96bed 11687 {
a7812ae4 11688 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11689
11690 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11691 if (ctx->abs2008) {
11692 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11693 } else {
11694 gen_helper_float_chs_d(fp0, fp0);
11695 }
b6d96bed 11696 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11697 tcg_temp_free_i64(fp0);
b6d96bed 11698 }
6ea83fed 11699 break;
bf4120ad 11700 case OPC_ROUND_L_D:
5e755519 11701 check_cp1_64bitmode(ctx);
b6d96bed 11702 {
a7812ae4 11703 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11704
11705 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11706 if (ctx->nan2008) {
11707 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11708 } else {
11709 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11710 }
b6d96bed 11711 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11712 tcg_temp_free_i64(fp0);
b6d96bed 11713 }
5a5012ec 11714 break;
bf4120ad 11715 case OPC_TRUNC_L_D:
5e755519 11716 check_cp1_64bitmode(ctx);
b6d96bed 11717 {
a7812ae4 11718 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11719
11720 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11721 if (ctx->nan2008) {
11722 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11723 } else {
11724 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11725 }
b6d96bed 11726 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11727 tcg_temp_free_i64(fp0);
b6d96bed 11728 }
5a5012ec 11729 break;
bf4120ad 11730 case OPC_CEIL_L_D:
5e755519 11731 check_cp1_64bitmode(ctx);
b6d96bed 11732 {
a7812ae4 11733 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11734
11735 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11736 if (ctx->nan2008) {
11737 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11738 } else {
11739 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11740 }
b6d96bed 11741 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11742 tcg_temp_free_i64(fp0);
b6d96bed 11743 }
5a5012ec 11744 break;
bf4120ad 11745 case OPC_FLOOR_L_D:
5e755519 11746 check_cp1_64bitmode(ctx);
b6d96bed 11747 {
a7812ae4 11748 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11749
11750 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11751 if (ctx->nan2008) {
11752 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11753 } else {
11754 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11755 }
b6d96bed 11756 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11757 tcg_temp_free_i64(fp0);
b6d96bed 11758 }
5a5012ec 11759 break;
bf4120ad 11760 case OPC_ROUND_W_D:
5e755519 11761 check_cp1_registers(ctx, fs);
b6d96bed 11762 {
a7812ae4
PB
11763 TCGv_i32 fp32 = tcg_temp_new_i32();
11764 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11765
11766 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11767 if (ctx->nan2008) {
11768 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11769 } else {
11770 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11771 }
a7812ae4 11772 tcg_temp_free_i64(fp64);
7c979afd 11773 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11774 tcg_temp_free_i32(fp32);
b6d96bed 11775 }
6ea83fed 11776 break;
bf4120ad 11777 case OPC_TRUNC_W_D:
5e755519 11778 check_cp1_registers(ctx, fs);
b6d96bed 11779 {
a7812ae4
PB
11780 TCGv_i32 fp32 = tcg_temp_new_i32();
11781 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11782
11783 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11784 if (ctx->nan2008) {
11785 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11786 } else {
11787 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11788 }
a7812ae4 11789 tcg_temp_free_i64(fp64);
7c979afd 11790 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11791 tcg_temp_free_i32(fp32);
b6d96bed 11792 }
6ea83fed 11793 break;
bf4120ad 11794 case OPC_CEIL_W_D:
5e755519 11795 check_cp1_registers(ctx, fs);
b6d96bed 11796 {
a7812ae4
PB
11797 TCGv_i32 fp32 = tcg_temp_new_i32();
11798 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11799
11800 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11801 if (ctx->nan2008) {
11802 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11803 } else {
11804 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11805 }
a7812ae4 11806 tcg_temp_free_i64(fp64);
7c979afd 11807 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11808 tcg_temp_free_i32(fp32);
b6d96bed 11809 }
6ea83fed 11810 break;
bf4120ad 11811 case OPC_FLOOR_W_D:
5e755519 11812 check_cp1_registers(ctx, fs);
b6d96bed 11813 {
a7812ae4
PB
11814 TCGv_i32 fp32 = tcg_temp_new_i32();
11815 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11816
11817 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11818 if (ctx->nan2008) {
11819 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11820 } else {
11821 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11822 }
a7812ae4 11823 tcg_temp_free_i64(fp64);
7c979afd 11824 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11825 tcg_temp_free_i32(fp32);
b6d96bed 11826 }
6ea83fed 11827 break;
e7f16abb
LA
11828 case OPC_SEL_D:
11829 check_insn(ctx, ISA_MIPS32R6);
11830 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11831 break;
11832 case OPC_SELEQZ_D:
11833 check_insn(ctx, ISA_MIPS32R6);
11834 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11835 break;
11836 case OPC_SELNEZ_D:
11837 check_insn(ctx, ISA_MIPS32R6);
11838 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11839 break;
bf4120ad 11840 case OPC_MOVCF_D:
fecd2646 11841 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 11842 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11843 break;
bf4120ad 11844 case OPC_MOVZ_D:
fecd2646 11845 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11846 {
42a268c2 11847 TCGLabel *l1 = gen_new_label();
c9297f4d 11848 TCGv_i64 fp0;
a16336e4 11849
c9297f4d
AJ
11850 if (ft != 0) {
11851 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11852 }
11853 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11854 gen_load_fpr64(ctx, fp0, fs);
11855 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11856 tcg_temp_free_i64(fp0);
a16336e4
TS
11857 gen_set_label(l1);
11858 }
5a5012ec 11859 break;
bf4120ad 11860 case OPC_MOVN_D:
fecd2646 11861 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11862 {
42a268c2 11863 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11864 TCGv_i64 fp0;
11865
11866 if (ft != 0) {
11867 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11868 fp0 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_store_fpr64(ctx, fp0, fd);
11871 tcg_temp_free_i64(fp0);
11872 gen_set_label(l1);
11873 }
a16336e4 11874 }
6ea83fed 11875 break;
bf4120ad 11876 case OPC_RECIP_D:
ca6c7803 11877 check_cp1_registers(ctx, fs | fd);
b6d96bed 11878 {
a7812ae4 11879 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11880
11881 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11882 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11883 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11884 tcg_temp_free_i64(fp0);
b6d96bed 11885 }
57fa1fb3 11886 break;
bf4120ad 11887 case OPC_RSQRT_D:
ca6c7803 11888 check_cp1_registers(ctx, fs | fd);
b6d96bed 11889 {
a7812ae4 11890 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11891
11892 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11893 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11894 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11895 tcg_temp_free_i64(fp0);
b6d96bed 11896 }
57fa1fb3 11897 break;
e7f16abb
LA
11898 case OPC_MADDF_D:
11899 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11900 {
a7812ae4
PB
11901 TCGv_i64 fp0 = tcg_temp_new_i64();
11902 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11903 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11904 gen_load_fpr64(ctx, fp0, fs);
11905 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11906 gen_load_fpr64(ctx, fp2, fd);
11907 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11908 gen_store_fpr64(ctx, fp2, fd);
11909 tcg_temp_free_i64(fp2);
a7812ae4 11910 tcg_temp_free_i64(fp1);
a7812ae4 11911 tcg_temp_free_i64(fp0);
b6d96bed 11912 }
57fa1fb3 11913 break;
e7f16abb
LA
11914 case OPC_MSUBF_D:
11915 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11916 {
a7812ae4 11917 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11918 TCGv_i64 fp1 = tcg_temp_new_i64();
11919 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11920 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11921 gen_load_fpr64(ctx, fp1, ft);
11922 gen_load_fpr64(ctx, fp2, fd);
11923 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11924 gen_store_fpr64(ctx, fp2, fd);
11925 tcg_temp_free_i64(fp2);
11926 tcg_temp_free_i64(fp1);
a7812ae4 11927 tcg_temp_free_i64(fp0);
b6d96bed 11928 }
57fa1fb3 11929 break;
e7f16abb
LA
11930 case OPC_RINT_D:
11931 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11932 {
a7812ae4 11933 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11934 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11935 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11936 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11937 tcg_temp_free_i64(fp0);
b6d96bed 11938 }
57fa1fb3 11939 break;
e7f16abb
LA
11940 case OPC_CLASS_D:
11941 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11942 {
e7f16abb
LA
11943 TCGv_i64 fp0 = tcg_temp_new_i64();
11944 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11945 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11946 gen_store_fpr64(ctx, fp0, fd);
11947 tcg_temp_free_i64(fp0);
e7f16abb
LA
11948 }
11949 break;
11950 case OPC_MIN_D: /* OPC_RECIP2_D */
11951 if (ctx->insn_flags & ISA_MIPS32R6) {
11952 /* OPC_MIN_D */
a7812ae4
PB
11953 TCGv_i64 fp0 = tcg_temp_new_i64();
11954 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11955 gen_load_fpr64(ctx, fp0, fs);
11956 gen_load_fpr64(ctx, fp1, ft);
11957 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11958 gen_store_fpr64(ctx, fp1, fd);
11959 tcg_temp_free_i64(fp1);
11960 tcg_temp_free_i64(fp0);
e7f16abb
LA
11961 } else {
11962 /* OPC_RECIP2_D */
11963 check_cp1_64bitmode(ctx);
11964 {
11965 TCGv_i64 fp0 = tcg_temp_new_i64();
11966 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11967
e7f16abb
LA
11968 gen_load_fpr64(ctx, fp0, fs);
11969 gen_load_fpr64(ctx, fp1, ft);
11970 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11971 tcg_temp_free_i64(fp1);
11972 gen_store_fpr64(ctx, fp0, fd);
11973 tcg_temp_free_i64(fp0);
11974 }
e7f16abb
LA
11975 }
11976 break;
11977 case OPC_MINA_D: /* OPC_RECIP1_D */
11978 if (ctx->insn_flags & ISA_MIPS32R6) {
11979 /* OPC_MINA_D */
11980 TCGv_i64 fp0 = tcg_temp_new_i64();
11981 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11982 gen_load_fpr64(ctx, fp0, fs);
11983 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11984 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11985 gen_store_fpr64(ctx, fp1, fd);
11986 tcg_temp_free_i64(fp1);
11987 tcg_temp_free_i64(fp0);
e7f16abb
LA
11988 } else {
11989 /* OPC_RECIP1_D */
11990 check_cp1_64bitmode(ctx);
11991 {
11992 TCGv_i64 fp0 = tcg_temp_new_i64();
11993
11994 gen_load_fpr64(ctx, fp0, fs);
11995 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11996 gen_store_fpr64(ctx, fp0, fd);
11997 tcg_temp_free_i64(fp0);
11998 }
e7f16abb
LA
11999 }
12000 break;
12001 case OPC_MAX_D: /* OPC_RSQRT1_D */
12002 if (ctx->insn_flags & ISA_MIPS32R6) {
12003 /* OPC_MAX_D */
12004 TCGv_i64 fp0 = tcg_temp_new_i64();
12005 TCGv_i64 fp1 = tcg_temp_new_i64();
12006 gen_load_fpr64(ctx, fp0, fs);
12007 gen_load_fpr64(ctx, fp1, ft);
12008 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12009 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 12010 tcg_temp_free_i64(fp1);
a7812ae4 12011 tcg_temp_free_i64(fp0);
e7f16abb
LA
12012 } else {
12013 /* OPC_RSQRT1_D */
12014 check_cp1_64bitmode(ctx);
12015 {
12016 TCGv_i64 fp0 = tcg_temp_new_i64();
12017
12018 gen_load_fpr64(ctx, fp0, fs);
12019 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12020 gen_store_fpr64(ctx, fp0, fd);
12021 tcg_temp_free_i64(fp0);
12022 }
e7f16abb
LA
12023 }
12024 break;
12025 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12026 if (ctx->insn_flags & ISA_MIPS32R6) {
12027 /* OPC_MAXA_D */
12028 TCGv_i64 fp0 = tcg_temp_new_i64();
12029 TCGv_i64 fp1 = tcg_temp_new_i64();
12030 gen_load_fpr64(ctx, fp0, fs);
12031 gen_load_fpr64(ctx, fp1, ft);
12032 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12033 gen_store_fpr64(ctx, fp1, fd);
12034 tcg_temp_free_i64(fp1);
12035 tcg_temp_free_i64(fp0);
e7f16abb
LA
12036 } else {
12037 /* OPC_RSQRT2_D */
12038 check_cp1_64bitmode(ctx);
12039 {
12040 TCGv_i64 fp0 = tcg_temp_new_i64();
12041 TCGv_i64 fp1 = tcg_temp_new_i64();
12042
12043 gen_load_fpr64(ctx, fp0, fs);
12044 gen_load_fpr64(ctx, fp1, ft);
12045 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12046 tcg_temp_free_i64(fp1);
12047 gen_store_fpr64(ctx, fp0, fd);
12048 tcg_temp_free_i64(fp0);
12049 }
b6d96bed 12050 }
57fa1fb3 12051 break;
bf4120ad
NF
12052 case OPC_CMP_F_D:
12053 case OPC_CMP_UN_D:
12054 case OPC_CMP_EQ_D:
12055 case OPC_CMP_UEQ_D:
12056 case OPC_CMP_OLT_D:
12057 case OPC_CMP_ULT_D:
12058 case OPC_CMP_OLE_D:
12059 case OPC_CMP_ULE_D:
12060 case OPC_CMP_SF_D:
12061 case OPC_CMP_NGLE_D:
12062 case OPC_CMP_SEQ_D:
12063 case OPC_CMP_NGL_D:
12064 case OPC_CMP_LT_D:
12065 case OPC_CMP_NGE_D:
12066 case OPC_CMP_LE_D:
12067 case OPC_CMP_NGT_D:
fecd2646 12068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c 12069 if (ctx->opcode & (1 << 6)) {
71375b59 12070 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 12071 } else {
71375b59 12072 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12073 }
6ea83fed 12074 break;
bf4120ad 12075 case OPC_CVT_S_D:
5e755519 12076 check_cp1_registers(ctx, fs);
b6d96bed 12077 {
a7812ae4
PB
12078 TCGv_i32 fp32 = tcg_temp_new_i32();
12079 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12080
12081 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12082 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 12083 tcg_temp_free_i64(fp64);
7c979afd 12084 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12085 tcg_temp_free_i32(fp32);
b6d96bed 12086 }
5a5012ec 12087 break;
bf4120ad 12088 case OPC_CVT_W_D:
5e755519 12089 check_cp1_registers(ctx, fs);
b6d96bed 12090 {
a7812ae4
PB
12091 TCGv_i32 fp32 = tcg_temp_new_i32();
12092 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12093
12094 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12095 if (ctx->nan2008) {
12096 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12097 } else {
12098 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12099 }
a7812ae4 12100 tcg_temp_free_i64(fp64);
7c979afd 12101 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12102 tcg_temp_free_i32(fp32);
b6d96bed 12103 }
5a5012ec 12104 break;
bf4120ad 12105 case OPC_CVT_L_D:
5e755519 12106 check_cp1_64bitmode(ctx);
b6d96bed 12107 {
a7812ae4 12108 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12109
12110 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12111 if (ctx->nan2008) {
12112 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12113 } else {
12114 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12115 }
b6d96bed 12116 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12117 tcg_temp_free_i64(fp0);
b6d96bed 12118 }
5a5012ec 12119 break;
bf4120ad 12120 case OPC_CVT_S_W:
b6d96bed 12121 {
a7812ae4 12122 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12123
7c979afd 12124 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12125 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 12126 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12127 tcg_temp_free_i32(fp0);
b6d96bed 12128 }
6ea83fed 12129 break;
bf4120ad 12130 case OPC_CVT_D_W:
5e755519 12131 check_cp1_registers(ctx, fd);
b6d96bed 12132 {
a7812ae4
PB
12133 TCGv_i32 fp32 = tcg_temp_new_i32();
12134 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12135
7c979afd 12136 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12137 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12138 tcg_temp_free_i32(fp32);
b6d96bed 12139 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12140 tcg_temp_free_i64(fp64);
b6d96bed 12141 }
5a5012ec 12142 break;
bf4120ad 12143 case OPC_CVT_S_L:
5e755519 12144 check_cp1_64bitmode(ctx);
b6d96bed 12145 {
a7812ae4
PB
12146 TCGv_i32 fp32 = tcg_temp_new_i32();
12147 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12148
12149 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12150 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12151 tcg_temp_free_i64(fp64);
7c979afd 12152 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12153 tcg_temp_free_i32(fp32);
b6d96bed 12154 }
5a5012ec 12155 break;
bf4120ad 12156 case OPC_CVT_D_L:
5e755519 12157 check_cp1_64bitmode(ctx);
b6d96bed 12158 {
a7812ae4 12159 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12160
12161 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12162 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12163 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12164 tcg_temp_free_i64(fp0);
b6d96bed 12165 }
5a5012ec 12166 break;
bf4120ad 12167 case OPC_CVT_PS_PW:
e29c9628 12168 check_ps(ctx);
b6d96bed 12169 {
a7812ae4 12170 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12171
12172 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12173 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12174 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12175 tcg_temp_free_i64(fp0);
b6d96bed 12176 }
5a5012ec 12177 break;
bf4120ad 12178 case OPC_ADD_PS:
e29c9628 12179 check_ps(ctx);
b6d96bed 12180 {
a7812ae4
PB
12181 TCGv_i64 fp0 = tcg_temp_new_i64();
12182 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12183
12184 gen_load_fpr64(ctx, fp0, fs);
12185 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12186 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12187 tcg_temp_free_i64(fp1);
b6d96bed 12188 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12189 tcg_temp_free_i64(fp0);
b6d96bed 12190 }
6ea83fed 12191 break;
bf4120ad 12192 case OPC_SUB_PS:
e29c9628 12193 check_ps(ctx);
b6d96bed 12194 {
a7812ae4
PB
12195 TCGv_i64 fp0 = tcg_temp_new_i64();
12196 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12197
12198 gen_load_fpr64(ctx, fp0, fs);
12199 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12200 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12201 tcg_temp_free_i64(fp1);
b6d96bed 12202 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12203 tcg_temp_free_i64(fp0);
b6d96bed 12204 }
6ea83fed 12205 break;
bf4120ad 12206 case OPC_MUL_PS:
e29c9628 12207 check_ps(ctx);
b6d96bed 12208 {
a7812ae4
PB
12209 TCGv_i64 fp0 = tcg_temp_new_i64();
12210 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12211
12212 gen_load_fpr64(ctx, fp0, fs);
12213 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12214 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12215 tcg_temp_free_i64(fp1);
b6d96bed 12216 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12217 tcg_temp_free_i64(fp0);
b6d96bed 12218 }
6ea83fed 12219 break;
bf4120ad 12220 case OPC_ABS_PS:
e29c9628 12221 check_ps(ctx);
b6d96bed 12222 {
a7812ae4 12223 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12224
12225 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12226 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12227 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12228 tcg_temp_free_i64(fp0);
b6d96bed 12229 }
6ea83fed 12230 break;
bf4120ad 12231 case OPC_MOV_PS:
e29c9628 12232 check_ps(ctx);
b6d96bed 12233 {
a7812ae4 12234 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12235
12236 gen_load_fpr64(ctx, fp0, fs);
12237 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12238 tcg_temp_free_i64(fp0);
b6d96bed 12239 }
6ea83fed 12240 break;
bf4120ad 12241 case OPC_NEG_PS:
e29c9628 12242 check_ps(ctx);
b6d96bed 12243 {
a7812ae4 12244 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12245
12246 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12247 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12248 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12249 tcg_temp_free_i64(fp0);
b6d96bed 12250 }
6ea83fed 12251 break;
bf4120ad 12252 case OPC_MOVCF_PS:
e29c9628 12253 check_ps(ctx);
7f6613ce 12254 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12255 break;
bf4120ad 12256 case OPC_MOVZ_PS:
e29c9628 12257 check_ps(ctx);
a16336e4 12258 {
42a268c2 12259 TCGLabel *l1 = gen_new_label();
30a3848b 12260 TCGv_i64 fp0;
a16336e4 12261
1f8929d2 12262 if (ft != 0) {
c9297f4d 12263 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 12264 }
c9297f4d
AJ
12265 fp0 = tcg_temp_new_i64();
12266 gen_load_fpr64(ctx, fp0, fs);
12267 gen_store_fpr64(ctx, fp0, fd);
12268 tcg_temp_free_i64(fp0);
a16336e4
TS
12269 gen_set_label(l1);
12270 }
6ea83fed 12271 break;
bf4120ad 12272 case OPC_MOVN_PS:
e29c9628 12273 check_ps(ctx);
a16336e4 12274 {
42a268c2 12275 TCGLabel *l1 = gen_new_label();
30a3848b 12276 TCGv_i64 fp0;
c9297f4d
AJ
12277
12278 if (ft != 0) {
12279 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12280 fp0 = tcg_temp_new_i64();
12281 gen_load_fpr64(ctx, fp0, fs);
12282 gen_store_fpr64(ctx, fp0, fd);
12283 tcg_temp_free_i64(fp0);
12284 gen_set_label(l1);
12285 }
a16336e4 12286 }
6ea83fed 12287 break;
bf4120ad 12288 case OPC_ADDR_PS:
e29c9628 12289 check_ps(ctx);
b6d96bed 12290 {
a7812ae4
PB
12291 TCGv_i64 fp0 = tcg_temp_new_i64();
12292 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12293
12294 gen_load_fpr64(ctx, fp0, ft);
12295 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12296 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12297 tcg_temp_free_i64(fp1);
b6d96bed 12298 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12299 tcg_temp_free_i64(fp0);
b6d96bed 12300 }
fbcc6828 12301 break;
bf4120ad 12302 case OPC_MULR_PS:
e29c9628 12303 check_ps(ctx);
b6d96bed 12304 {
a7812ae4
PB
12305 TCGv_i64 fp0 = tcg_temp_new_i64();
12306 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12307
12308 gen_load_fpr64(ctx, fp0, ft);
12309 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12310 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12311 tcg_temp_free_i64(fp1);
b6d96bed 12312 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12313 tcg_temp_free_i64(fp0);
b6d96bed 12314 }
57fa1fb3 12315 break;
bf4120ad 12316 case OPC_RECIP2_PS:
e29c9628 12317 check_ps(ctx);
b6d96bed 12318 {
a7812ae4
PB
12319 TCGv_i64 fp0 = tcg_temp_new_i64();
12320 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12321
12322 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12323 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12324 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12325 tcg_temp_free_i64(fp1);
b6d96bed 12326 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12327 tcg_temp_free_i64(fp0);
b6d96bed 12328 }
57fa1fb3 12329 break;
bf4120ad 12330 case OPC_RECIP1_PS:
e29c9628 12331 check_ps(ctx);
b6d96bed 12332 {
a7812ae4 12333 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12334
12335 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12336 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12337 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12338 tcg_temp_free_i64(fp0);
b6d96bed 12339 }
57fa1fb3 12340 break;
bf4120ad 12341 case OPC_RSQRT1_PS:
e29c9628 12342 check_ps(ctx);
b6d96bed 12343 {
a7812ae4 12344 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12345
12346 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12347 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12348 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12349 tcg_temp_free_i64(fp0);
b6d96bed 12350 }
57fa1fb3 12351 break;
bf4120ad 12352 case OPC_RSQRT2_PS:
e29c9628 12353 check_ps(ctx);
b6d96bed 12354 {
a7812ae4
PB
12355 TCGv_i64 fp0 = tcg_temp_new_i64();
12356 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12357
12358 gen_load_fpr64(ctx, fp0, fs);
12359 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12360 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12361 tcg_temp_free_i64(fp1);
b6d96bed 12362 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12363 tcg_temp_free_i64(fp0);
b6d96bed 12364 }
57fa1fb3 12365 break;
bf4120ad 12366 case OPC_CVT_S_PU:
5e755519 12367 check_cp1_64bitmode(ctx);
b6d96bed 12368 {
a7812ae4 12369 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12370
7f6613ce 12371 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12372 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12373 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12374 tcg_temp_free_i32(fp0);
b6d96bed 12375 }
dd016883 12376 break;
bf4120ad 12377 case OPC_CVT_PW_PS:
e29c9628 12378 check_ps(ctx);
b6d96bed 12379 {
a7812ae4 12380 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12381
12382 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12383 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 12384 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12385 tcg_temp_free_i64(fp0);
b6d96bed 12386 }
6ea83fed 12387 break;
bf4120ad 12388 case OPC_CVT_S_PL:
5e755519 12389 check_cp1_64bitmode(ctx);
b6d96bed 12390 {
a7812ae4 12391 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12392
7c979afd 12393 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12394 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 12395 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12396 tcg_temp_free_i32(fp0);
b6d96bed 12397 }
6ea83fed 12398 break;
bf4120ad 12399 case OPC_PLL_PS:
e29c9628 12400 check_ps(ctx);
b6d96bed 12401 {
a7812ae4
PB
12402 TCGv_i32 fp0 = tcg_temp_new_i32();
12403 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12404
7c979afd
LA
12405 gen_load_fpr32(ctx, fp0, fs);
12406 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 12407 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 12408 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
12409 tcg_temp_free_i32(fp0);
12410 tcg_temp_free_i32(fp1);
b6d96bed 12411 }
6ea83fed 12412 break;
bf4120ad 12413 case OPC_PLU_PS:
e29c9628 12414 check_ps(ctx);
b6d96bed 12415 {
a7812ae4
PB
12416 TCGv_i32 fp0 = tcg_temp_new_i32();
12417 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12418
7c979afd 12419 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 12420 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12421 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12422 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12423 tcg_temp_free_i32(fp0);
12424 tcg_temp_free_i32(fp1);
b6d96bed 12425 }
5a5012ec 12426 break;
bf4120ad 12427 case OPC_PUL_PS:
e29c9628 12428 check_ps(ctx);
b6d96bed 12429 {
a7812ae4
PB
12430 TCGv_i32 fp0 = tcg_temp_new_i32();
12431 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12432
7f6613ce 12433 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
12434 gen_load_fpr32(ctx, fp1, ft);
12435 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12436 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12437 tcg_temp_free_i32(fp0);
12438 tcg_temp_free_i32(fp1);
b6d96bed 12439 }
5a5012ec 12440 break;
bf4120ad 12441 case OPC_PUU_PS:
e29c9628 12442 check_ps(ctx);
b6d96bed 12443 {
a7812ae4
PB
12444 TCGv_i32 fp0 = tcg_temp_new_i32();
12445 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12446
7f6613ce
PJ
12447 gen_load_fpr32h(ctx, fp0, fs);
12448 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12449 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12450 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12451 tcg_temp_free_i32(fp0);
12452 tcg_temp_free_i32(fp1);
b6d96bed 12453 }
5a5012ec 12454 break;
bf4120ad
NF
12455 case OPC_CMP_F_PS:
12456 case OPC_CMP_UN_PS:
12457 case OPC_CMP_EQ_PS:
12458 case OPC_CMP_UEQ_PS:
12459 case OPC_CMP_OLT_PS:
12460 case OPC_CMP_ULT_PS:
12461 case OPC_CMP_OLE_PS:
12462 case OPC_CMP_ULE_PS:
12463 case OPC_CMP_SF_PS:
12464 case OPC_CMP_NGLE_PS:
12465 case OPC_CMP_SEQ_PS:
12466 case OPC_CMP_NGL_PS:
12467 case OPC_CMP_LT_PS:
12468 case OPC_CMP_NGE_PS:
12469 case OPC_CMP_LE_PS:
12470 case OPC_CMP_NGT_PS:
8153667c 12471 if (ctx->opcode & (1 << 6)) {
71375b59 12472 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 12473 } else {
71375b59 12474 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12475 }
6ea83fed 12476 break;
5a5012ec 12477 default:
9d68ac14 12478 MIPS_INVAL("farith");
9c708c7f 12479 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12480 return;
12481 }
6ea83fed 12482}
6af0bf9c 12483
5a5012ec 12484/* Coprocessor 3 (FPU) */
235785e8
AM
12485static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12486 int fd, int fs, int base, int index)
7a387fff 12487{
4e2474d6 12488 TCGv t0 = tcg_temp_new();
7a387fff 12489
93b12ccc 12490 if (base == 0) {
6c5c1e20 12491 gen_load_gpr(t0, index);
93b12ccc 12492 } else if (index == 0) {
6c5c1e20 12493 gen_load_gpr(t0, base);
93b12ccc 12494 } else {
05168674 12495 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12496 }
7480515f
AM
12497 /*
12498 * Don't do NOP if destination is zero: we must perform the actual
12499 * memory access.
12500 */
5a5012ec
TS
12501 switch (opc) {
12502 case OPC_LWXC1:
8c0ab41f 12503 check_cop1x(ctx);
b6d96bed 12504 {
a7812ae4 12505 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12506
5f68f5ae 12507 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12508 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12509 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12510 tcg_temp_free_i32(fp0);
b6d96bed 12511 }
5a5012ec
TS
12512 break;
12513 case OPC_LDXC1:
8c0ab41f
AJ
12514 check_cop1x(ctx);
12515 check_cp1_registers(ctx, fd);
b6d96bed 12516 {
a7812ae4 12517 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12518 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12519 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12520 tcg_temp_free_i64(fp0);
b6d96bed 12521 }
5a5012ec
TS
12522 break;
12523 case OPC_LUXC1:
8c0ab41f 12524 check_cp1_64bitmode(ctx);
6c5c1e20 12525 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12526 {
a7812ae4 12527 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12528
5f68f5ae 12529 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12530 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12531 tcg_temp_free_i64(fp0);
b6d96bed 12532 }
5a5012ec
TS
12533 break;
12534 case OPC_SWXC1:
8c0ab41f 12535 check_cop1x(ctx);
b6d96bed 12536 {
a7812ae4 12537 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12538 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12539 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12540 tcg_temp_free_i32(fp0);
b6d96bed 12541 }
5a5012ec
TS
12542 break;
12543 case OPC_SDXC1:
8c0ab41f
AJ
12544 check_cop1x(ctx);
12545 check_cp1_registers(ctx, fs);
b6d96bed 12546 {
a7812ae4 12547 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12548 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12549 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12550 tcg_temp_free_i64(fp0);
b6d96bed 12551 }
5a5012ec
TS
12552 break;
12553 case OPC_SUXC1:
8c0ab41f 12554 check_cp1_64bitmode(ctx);
6c5c1e20 12555 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12556 {
a7812ae4 12557 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12558 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12559 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12560 tcg_temp_free_i64(fp0);
b6d96bed 12561 }
5a5012ec 12562 break;
5a5012ec 12563 }
6c5c1e20 12564 tcg_temp_free(t0);
5a5012ec
TS
12565}
12566
235785e8
AM
12567static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12568 int fd, int fr, int fs, int ft)
5a5012ec 12569{
5a5012ec
TS
12570 switch (opc) {
12571 case OPC_ALNV_PS:
e29c9628 12572 check_ps(ctx);
a16336e4 12573 {
a7812ae4 12574 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12575 TCGv_i32 fp = tcg_temp_new_i32();
12576 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12577 TCGLabel *l1 = gen_new_label();
12578 TCGLabel *l2 = gen_new_label();
a16336e4 12579
6c5c1e20
TS
12580 gen_load_gpr(t0, fr);
12581 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12582
12583 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12584 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12585 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12586 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12587 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12588 tcg_gen_br(l2);
12589 gen_set_label(l1);
6c5c1e20
TS
12590 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12591 tcg_temp_free(t0);
a16336e4 12592#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12593 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12594 gen_load_fpr32h(ctx, fph, ft);
12595 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12596 gen_store_fpr32(ctx, fph, fd);
a16336e4 12597#else
7f6613ce 12598 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12599 gen_load_fpr32(ctx, fp, ft);
12600 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12601 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12602#endif
12603 gen_set_label(l2);
c905fdac
AJ
12604 tcg_temp_free_i32(fp);
12605 tcg_temp_free_i32(fph);
a16336e4 12606 }
5a5012ec
TS
12607 break;
12608 case OPC_MADD_S:
b8aa4598 12609 check_cop1x(ctx);
b6d96bed 12610 {
a7812ae4
PB
12611 TCGv_i32 fp0 = tcg_temp_new_i32();
12612 TCGv_i32 fp1 = tcg_temp_new_i32();
12613 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12614
7c979afd
LA
12615 gen_load_fpr32(ctx, fp0, fs);
12616 gen_load_fpr32(ctx, fp1, ft);
12617 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12618 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12619 tcg_temp_free_i32(fp0);
12620 tcg_temp_free_i32(fp1);
7c979afd 12621 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12622 tcg_temp_free_i32(fp2);
b6d96bed 12623 }
5a5012ec
TS
12624 break;
12625 case OPC_MADD_D:
b8aa4598
TS
12626 check_cop1x(ctx);
12627 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12628 {
a7812ae4
PB
12629 TCGv_i64 fp0 = tcg_temp_new_i64();
12630 TCGv_i64 fp1 = tcg_temp_new_i64();
12631 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12632
12633 gen_load_fpr64(ctx, fp0, fs);
12634 gen_load_fpr64(ctx, fp1, ft);
12635 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12636 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12637 tcg_temp_free_i64(fp0);
12638 tcg_temp_free_i64(fp1);
b6d96bed 12639 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12640 tcg_temp_free_i64(fp2);
b6d96bed 12641 }
5a5012ec
TS
12642 break;
12643 case OPC_MADD_PS:
e29c9628 12644 check_ps(ctx);
b6d96bed 12645 {
a7812ae4
PB
12646 TCGv_i64 fp0 = tcg_temp_new_i64();
12647 TCGv_i64 fp1 = tcg_temp_new_i64();
12648 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12649
12650 gen_load_fpr64(ctx, fp0, fs);
12651 gen_load_fpr64(ctx, fp1, ft);
12652 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12653 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12654 tcg_temp_free_i64(fp0);
12655 tcg_temp_free_i64(fp1);
b6d96bed 12656 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12657 tcg_temp_free_i64(fp2);
b6d96bed 12658 }
5a5012ec
TS
12659 break;
12660 case OPC_MSUB_S:
b8aa4598 12661 check_cop1x(ctx);
b6d96bed 12662 {
a7812ae4
PB
12663 TCGv_i32 fp0 = tcg_temp_new_i32();
12664 TCGv_i32 fp1 = tcg_temp_new_i32();
12665 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12666
7c979afd
LA
12667 gen_load_fpr32(ctx, fp0, fs);
12668 gen_load_fpr32(ctx, fp1, ft);
12669 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12670 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12671 tcg_temp_free_i32(fp0);
12672 tcg_temp_free_i32(fp1);
7c979afd 12673 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12674 tcg_temp_free_i32(fp2);
b6d96bed 12675 }
5a5012ec
TS
12676 break;
12677 case OPC_MSUB_D:
b8aa4598
TS
12678 check_cop1x(ctx);
12679 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12680 {
a7812ae4
PB
12681 TCGv_i64 fp0 = tcg_temp_new_i64();
12682 TCGv_i64 fp1 = tcg_temp_new_i64();
12683 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12684
12685 gen_load_fpr64(ctx, fp0, fs);
12686 gen_load_fpr64(ctx, fp1, ft);
12687 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12688 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12689 tcg_temp_free_i64(fp0);
12690 tcg_temp_free_i64(fp1);
b6d96bed 12691 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12692 tcg_temp_free_i64(fp2);
b6d96bed 12693 }
5a5012ec
TS
12694 break;
12695 case OPC_MSUB_PS:
e29c9628 12696 check_ps(ctx);
b6d96bed 12697 {
a7812ae4
PB
12698 TCGv_i64 fp0 = tcg_temp_new_i64();
12699 TCGv_i64 fp1 = tcg_temp_new_i64();
12700 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12701
12702 gen_load_fpr64(ctx, fp0, fs);
12703 gen_load_fpr64(ctx, fp1, ft);
12704 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12705 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12706 tcg_temp_free_i64(fp0);
12707 tcg_temp_free_i64(fp1);
b6d96bed 12708 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12709 tcg_temp_free_i64(fp2);
b6d96bed 12710 }
5a5012ec
TS
12711 break;
12712 case OPC_NMADD_S:
b8aa4598 12713 check_cop1x(ctx);
b6d96bed 12714 {
a7812ae4
PB
12715 TCGv_i32 fp0 = tcg_temp_new_i32();
12716 TCGv_i32 fp1 = tcg_temp_new_i32();
12717 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12718
7c979afd
LA
12719 gen_load_fpr32(ctx, fp0, fs);
12720 gen_load_fpr32(ctx, fp1, ft);
12721 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12722 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12723 tcg_temp_free_i32(fp0);
12724 tcg_temp_free_i32(fp1);
7c979afd 12725 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12726 tcg_temp_free_i32(fp2);
b6d96bed 12727 }
5a5012ec
TS
12728 break;
12729 case OPC_NMADD_D:
b8aa4598
TS
12730 check_cop1x(ctx);
12731 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12732 {
a7812ae4
PB
12733 TCGv_i64 fp0 = tcg_temp_new_i64();
12734 TCGv_i64 fp1 = tcg_temp_new_i64();
12735 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12736
12737 gen_load_fpr64(ctx, fp0, fs);
12738 gen_load_fpr64(ctx, fp1, ft);
12739 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12740 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12741 tcg_temp_free_i64(fp0);
12742 tcg_temp_free_i64(fp1);
b6d96bed 12743 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12744 tcg_temp_free_i64(fp2);
b6d96bed 12745 }
5a5012ec
TS
12746 break;
12747 case OPC_NMADD_PS:
e29c9628 12748 check_ps(ctx);
b6d96bed 12749 {
a7812ae4
PB
12750 TCGv_i64 fp0 = tcg_temp_new_i64();
12751 TCGv_i64 fp1 = tcg_temp_new_i64();
12752 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12753
12754 gen_load_fpr64(ctx, fp0, fs);
12755 gen_load_fpr64(ctx, fp1, ft);
12756 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12757 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12758 tcg_temp_free_i64(fp0);
12759 tcg_temp_free_i64(fp1);
b6d96bed 12760 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12761 tcg_temp_free_i64(fp2);
b6d96bed 12762 }
5a5012ec
TS
12763 break;
12764 case OPC_NMSUB_S:
b8aa4598 12765 check_cop1x(ctx);
b6d96bed 12766 {
a7812ae4
PB
12767 TCGv_i32 fp0 = tcg_temp_new_i32();
12768 TCGv_i32 fp1 = tcg_temp_new_i32();
12769 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12770
7c979afd
LA
12771 gen_load_fpr32(ctx, fp0, fs);
12772 gen_load_fpr32(ctx, fp1, ft);
12773 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12774 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12775 tcg_temp_free_i32(fp0);
12776 tcg_temp_free_i32(fp1);
7c979afd 12777 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12778 tcg_temp_free_i32(fp2);
b6d96bed 12779 }
5a5012ec
TS
12780 break;
12781 case OPC_NMSUB_D:
b8aa4598
TS
12782 check_cop1x(ctx);
12783 check_cp1_registers(ctx, fd | fs | ft | fr);
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_nmsub_d(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_NMSUB_PS:
e29c9628 12800 check_ps(ctx);
b6d96bed 12801 {
a7812ae4
PB
12802 TCGv_i64 fp0 = tcg_temp_new_i64();
12803 TCGv_i64 fp1 = tcg_temp_new_i64();
12804 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12805
12806 gen_load_fpr64(ctx, fp0, fs);
12807 gen_load_fpr64(ctx, fp1, ft);
12808 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12809 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12810 tcg_temp_free_i64(fp0);
12811 tcg_temp_free_i64(fp1);
b6d96bed 12812 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12813 tcg_temp_free_i64(fp2);
b6d96bed 12814 }
5a5012ec 12815 break;
923617a3 12816 default:
9d68ac14 12817 MIPS_INVAL("flt3_arith");
9c708c7f 12818 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
12819 return;
12820 }
7a387fff
TS
12821}
12822
b00c7218 12823static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12824{
12825 TCGv t0;
12826
b3167288 12827#if !defined(CONFIG_USER_ONLY)
7480515f
AM
12828 /*
12829 * The Linux kernel will emulate rdhwr if it's not supported natively.
12830 * Therefore only check the ISA in system mode.
12831 */
d75c135e 12832 check_insn(ctx, ISA_MIPS32R2);
b3167288 12833#endif
26ebe468
NF
12834 t0 = tcg_temp_new();
12835
12836 switch (rd) {
12837 case 0:
895c2d04 12838 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12839 gen_store_gpr(t0, rt);
12840 break;
12841 case 1:
895c2d04 12842 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12843 gen_store_gpr(t0, rt);
12844 break;
12845 case 2:
eeb3bba8 12846 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12847 gen_io_start();
12848 }
895c2d04 12849 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 12850 gen_store_gpr(t0, rt);
7480515f
AM
12851 /*
12852 * Break the TB to be able to take timer interrupts immediately
12853 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12854 * we break completely out of translated code.
12855 */
eeb3bba8
EC
12856 gen_save_pc(ctx->base.pc_next + 4);
12857 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12858 break;
12859 case 3:
895c2d04 12860 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12861 gen_store_gpr(t0, rt);
12862 break;
b00c7218
YK
12863 case 4:
12864 check_insn(ctx, ISA_MIPS32R6);
12865 if (sel != 0) {
7480515f
AM
12866 /*
12867 * Performance counter registers are not implemented other than
b00c7218
YK
12868 * control register 0.
12869 */
12870 generate_exception(ctx, EXCP_RI);
12871 }
12872 gen_helper_rdhwr_performance(t0, cpu_env);
12873 gen_store_gpr(t0, rt);
12874 break;
12875 case 5:
12876 check_insn(ctx, ISA_MIPS32R6);
12877 gen_helper_rdhwr_xnp(t0, cpu_env);
12878 gen_store_gpr(t0, rt);
12879 break;
26ebe468
NF
12880 case 29:
12881#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12882 tcg_gen_ld_tl(t0, cpu_env,
12883 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12884 gen_store_gpr(t0, rt);
12885 break;
12886#else
d279279e
PJ
12887 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12888 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12889 tcg_gen_ld_tl(t0, cpu_env,
12890 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12891 gen_store_gpr(t0, rt);
12892 } else {
9c708c7f 12893 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
12894 }
12895 break;
26ebe468
NF
12896#endif
12897 default: /* Invalid */
12898 MIPS_INVAL("rdhwr");
9c708c7f 12899 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
12900 break;
12901 }
12902 tcg_temp_free(t0);
12903}
12904
a5f53390
LA
12905static inline void clear_branch_hflags(DisasContext *ctx)
12906{
12907 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12908 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12909 save_cpu_state(ctx, 0);
12910 } else {
7480515f
AM
12911 /*
12912 * It is not safe to save ctx->hflags as hflags may be changed
12913 * in execution time by the instruction in delay / forbidden slot.
12914 */
a5f53390
LA
12915 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12916 }
12917}
12918
31837be3 12919static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12920{
12921 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12922 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12923 /* Branches completion */
a5f53390 12924 clear_branch_hflags(ctx);
eeb3bba8 12925 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12926 /* FIXME: Need to clear can_do_io. */
364d4831 12927 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12928 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12929 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12930 break;
c9602061
NF
12931 case MIPS_HFLAG_B:
12932 /* unconditional branch */
364d4831
NF
12933 if (proc_hflags & MIPS_HFLAG_BX) {
12934 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12935 }
c9602061
NF
12936 gen_goto_tb(ctx, 0, ctx->btarget);
12937 break;
12938 case MIPS_HFLAG_BL:
12939 /* blikely taken case */
c9602061
NF
12940 gen_goto_tb(ctx, 0, ctx->btarget);
12941 break;
12942 case MIPS_HFLAG_BC:
12943 /* Conditional branch */
c9602061 12944 {
42a268c2 12945 TCGLabel *l1 = gen_new_label();
c9602061
NF
12946
12947 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12948 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12949 gen_set_label(l1);
12950 gen_goto_tb(ctx, 0, ctx->btarget);
12951 }
12952 break;
12953 case MIPS_HFLAG_BR:
12954 /* unconditional branch to register */
d75c135e 12955 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12956 TCGv t0 = tcg_temp_new();
12957 TCGv_i32 t1 = tcg_temp_new_i32();
12958
12959 tcg_gen_andi_tl(t0, btarget, 0x1);
12960 tcg_gen_trunc_tl_i32(t1, t0);
12961 tcg_temp_free(t0);
12962 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12963 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12964 tcg_gen_or_i32(hflags, hflags, t1);
12965 tcg_temp_free_i32(t1);
12966
12967 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12968 } else {
12969 tcg_gen_mov_tl(cpu_PC, btarget);
12970 }
eeb3bba8 12971 if (ctx->base.singlestep_enabled) {
c9602061 12972 save_cpu_state(ctx, 0);
9c708c7f 12973 gen_helper_raise_exception_debug(cpu_env);
c9602061 12974 }
7f11636d 12975 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12976 break;
12977 default:
a5f53390
LA
12978 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12979 abort();
c9602061
NF
12980 }
12981 }
12982}
12983
6893f074
YK
12984/* Compact Branches */
12985static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12986 int rs, int rt, int32_t offset)
12987{
12988 int bcond_compute = 0;
12989 TCGv t0 = tcg_temp_new();
12990 TCGv t1 = tcg_temp_new();
65935f07 12991 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12992
12993 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12994#ifdef MIPS_DEBUG_DISAS
12995 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12996 "\n", ctx->base.pc_next);
6893f074 12997#endif
9c708c7f 12998 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12999 goto out;
13000 }
13001
13002 /* Load needed operands and calculate btarget */
13003 switch (opc) {
13004 /* compact branch */
13005 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13006 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13007 gen_load_gpr(t0, rs);
13008 gen_load_gpr(t1, rt);
13009 bcond_compute = 1;
eeb3bba8 13010 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13011 if (rs <= rt && rs == 0) {
13012 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 13013 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13014 }
13015 break;
13016 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13017 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13018 gen_load_gpr(t0, rs);
13019 gen_load_gpr(t1, rt);
13020 bcond_compute = 1;
eeb3bba8 13021 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13022 break;
13023 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13024 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13025 if (rs == 0 || rs == rt) {
13026 /* OPC_BLEZALC, OPC_BGEZALC */
13027 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 13028 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13029 }
13030 gen_load_gpr(t0, rs);
13031 gen_load_gpr(t1, rt);
13032 bcond_compute = 1;
eeb3bba8 13033 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13034 break;
13035 case OPC_BC:
13036 case OPC_BALC:
eeb3bba8 13037 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13038 break;
13039 case OPC_BEQZC:
13040 case OPC_BNEZC:
13041 if (rs != 0) {
13042 /* OPC_BEQZC, OPC_BNEZC */
13043 gen_load_gpr(t0, rs);
13044 bcond_compute = 1;
eeb3bba8 13045 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13046 } else {
13047 /* OPC_JIC, OPC_JIALC */
13048 TCGv tbase = tcg_temp_new();
13049 TCGv toffset = tcg_temp_new();
13050
13051 gen_load_gpr(tbase, rt);
13052 tcg_gen_movi_tl(toffset, offset);
13053 gen_op_addr_add(ctx, btarget, tbase, toffset);
13054 tcg_temp_free(tbase);
13055 tcg_temp_free(toffset);
13056 }
13057 break;
13058 default:
13059 MIPS_INVAL("Compact branch/jump");
9c708c7f 13060 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13061 goto out;
13062 }
13063
13064 if (bcond_compute == 0) {
13065 /* Uncoditional compact branch */
13066 switch (opc) {
13067 case OPC_JIALC:
eeb3bba8 13068 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13069 /* Fallthrough */
13070 case OPC_JIC:
13071 ctx->hflags |= MIPS_HFLAG_BR;
13072 break;
13073 case OPC_BALC:
eeb3bba8 13074 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13075 /* Fallthrough */
13076 case OPC_BC:
13077 ctx->hflags |= MIPS_HFLAG_B;
13078 break;
13079 default:
13080 MIPS_INVAL("Compact branch/jump");
9c708c7f 13081 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13082 goto out;
13083 }
13084
13085 /* Generating branch here as compact branches don't have delay slot */
13086 gen_branch(ctx, 4);
13087 } else {
13088 /* Conditional compact branch */
13089 TCGLabel *fs = gen_new_label();
13090 save_cpu_state(ctx, 0);
13091
13092 switch (opc) {
13093 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13094 if (rs == 0 && rt != 0) {
13095 /* OPC_BLEZALC */
13096 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13097 } else if (rs != 0 && rt != 0 && rs == rt) {
13098 /* OPC_BGEZALC */
13099 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13100 } else {
13101 /* OPC_BGEUC */
13102 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13103 }
13104 break;
13105 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13106 if (rs == 0 && rt != 0) {
13107 /* OPC_BGTZALC */
13108 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13109 } else if (rs != 0 && rt != 0 && rs == rt) {
13110 /* OPC_BLTZALC */
13111 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13112 } else {
13113 /* OPC_BLTUC */
13114 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13115 }
13116 break;
13117 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13118 if (rs == 0 && rt != 0) {
13119 /* OPC_BLEZC */
13120 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13121 } else if (rs != 0 && rt != 0 && rs == rt) {
13122 /* OPC_BGEZC */
13123 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13124 } else {
13125 /* OPC_BGEC */
13126 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13127 }
13128 break;
13129 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13130 if (rs == 0 && rt != 0) {
13131 /* OPC_BGTZC */
13132 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13133 } else if (rs != 0 && rt != 0 && rs == rt) {
13134 /* OPC_BLTZC */
13135 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13136 } else {
13137 /* OPC_BLTC */
13138 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13139 }
13140 break;
13141 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13142 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13143 if (rs >= rt) {
13144 /* OPC_BOVC, OPC_BNVC */
13145 TCGv t2 = tcg_temp_new();
13146 TCGv t3 = tcg_temp_new();
13147 TCGv t4 = tcg_temp_new();
13148 TCGv input_overflow = tcg_temp_new();
13149
13150 gen_load_gpr(t0, rs);
13151 gen_load_gpr(t1, rt);
13152 tcg_gen_ext32s_tl(t2, t0);
13153 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13154 tcg_gen_ext32s_tl(t3, t1);
13155 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13156 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13157
13158 tcg_gen_add_tl(t4, t2, t3);
13159 tcg_gen_ext32s_tl(t4, t4);
13160 tcg_gen_xor_tl(t2, t2, t3);
13161 tcg_gen_xor_tl(t3, t4, t3);
13162 tcg_gen_andc_tl(t2, t3, t2);
13163 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13164 tcg_gen_or_tl(t4, t4, input_overflow);
13165 if (opc == OPC_BOVC) {
13166 /* OPC_BOVC */
13167 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13168 } else {
13169 /* OPC_BNVC */
13170 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13171 }
13172 tcg_temp_free(input_overflow);
13173 tcg_temp_free(t4);
13174 tcg_temp_free(t3);
13175 tcg_temp_free(t2);
13176 } else if (rs < rt && rs == 0) {
13177 /* OPC_BEQZALC, OPC_BNEZALC */
13178 if (opc == OPC_BEQZALC) {
13179 /* OPC_BEQZALC */
13180 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13181 } else {
13182 /* OPC_BNEZALC */
13183 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13184 }
13185 } else {
13186 /* OPC_BEQC, OPC_BNEC */
13187 if (opc == OPC_BEQC) {
13188 /* OPC_BEQC */
13189 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13190 } else {
13191 /* OPC_BNEC */
13192 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13193 }
13194 }
13195 break;
13196 case OPC_BEQZC:
13197 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13198 break;
13199 case OPC_BNEZC:
13200 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13201 break;
13202 default:
13203 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13204 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13205 goto out;
13206 }
13207
13208 /* Generating branch here as compact branches don't have delay slot */
13209 gen_goto_tb(ctx, 1, ctx->btarget);
13210 gen_set_label(fs);
13211
13212 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13213 }
13214
13215out:
13216 tcg_temp_free(t0);
13217 tcg_temp_free(t1);
13218}
13219
7a387fff 13220/* ISA extensions (ASEs) */
6af0bf9c 13221/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13222
13223/* MIPS16 major opcodes */
13224enum {
13225 M16_OPC_ADDIUSP = 0x00,
13226 M16_OPC_ADDIUPC = 0x01,
13227 M16_OPC_B = 0x02,
13228 M16_OPC_JAL = 0x03,
13229 M16_OPC_BEQZ = 0x04,
13230 M16_OPC_BNEQZ = 0x05,
13231 M16_OPC_SHIFT = 0x06,
13232 M16_OPC_LD = 0x07,
13233 M16_OPC_RRIA = 0x08,
13234 M16_OPC_ADDIU8 = 0x09,
13235 M16_OPC_SLTI = 0x0a,
13236 M16_OPC_SLTIU = 0x0b,
13237 M16_OPC_I8 = 0x0c,
13238 M16_OPC_LI = 0x0d,
13239 M16_OPC_CMPI = 0x0e,
13240 M16_OPC_SD = 0x0f,
13241 M16_OPC_LB = 0x10,
13242 M16_OPC_LH = 0x11,
13243 M16_OPC_LWSP = 0x12,
13244 M16_OPC_LW = 0x13,
13245 M16_OPC_LBU = 0x14,
13246 M16_OPC_LHU = 0x15,
13247 M16_OPC_LWPC = 0x16,
13248 M16_OPC_LWU = 0x17,
13249 M16_OPC_SB = 0x18,
13250 M16_OPC_SH = 0x19,
13251 M16_OPC_SWSP = 0x1a,
13252 M16_OPC_SW = 0x1b,
13253 M16_OPC_RRR = 0x1c,
13254 M16_OPC_RR = 0x1d,
13255 M16_OPC_EXTEND = 0x1e,
13256 M16_OPC_I64 = 0x1f
13257};
13258
13259/* I8 funct field */
13260enum {
13261 I8_BTEQZ = 0x0,
13262 I8_BTNEZ = 0x1,
13263 I8_SWRASP = 0x2,
13264 I8_ADJSP = 0x3,
13265 I8_SVRS = 0x4,
13266 I8_MOV32R = 0x5,
13267 I8_MOVR32 = 0x7
13268};
13269
13270/* RRR f field */
13271enum {
13272 RRR_DADDU = 0x0,
13273 RRR_ADDU = 0x1,
13274 RRR_DSUBU = 0x2,
13275 RRR_SUBU = 0x3
13276};
13277
13278/* RR funct field */
13279enum {
13280 RR_JR = 0x00,
13281 RR_SDBBP = 0x01,
13282 RR_SLT = 0x02,
13283 RR_SLTU = 0x03,
13284 RR_SLLV = 0x04,
13285 RR_BREAK = 0x05,
13286 RR_SRLV = 0x06,
13287 RR_SRAV = 0x07,
13288 RR_DSRL = 0x08,
13289 RR_CMP = 0x0a,
13290 RR_NEG = 0x0b,
13291 RR_AND = 0x0c,
13292 RR_OR = 0x0d,
13293 RR_XOR = 0x0e,
13294 RR_NOT = 0x0f,
13295 RR_MFHI = 0x10,
13296 RR_CNVT = 0x11,
13297 RR_MFLO = 0x12,
13298 RR_DSRA = 0x13,
13299 RR_DSLLV = 0x14,
13300 RR_DSRLV = 0x16,
13301 RR_DSRAV = 0x17,
13302 RR_MULT = 0x18,
13303 RR_MULTU = 0x19,
13304 RR_DIV = 0x1a,
13305 RR_DIVU = 0x1b,
13306 RR_DMULT = 0x1c,
13307 RR_DMULTU = 0x1d,
13308 RR_DDIV = 0x1e,
13309 RR_DDIVU = 0x1f
13310};
13311
13312/* I64 funct field */
13313enum {
13314 I64_LDSP = 0x0,
13315 I64_SDSP = 0x1,
13316 I64_SDRASP = 0x2,
13317 I64_DADJSP = 0x3,
13318 I64_LDPC = 0x4,
364d4831 13319 I64_DADDIU5 = 0x5,
6ea219d0
NF
13320 I64_DADDIUPC = 0x6,
13321 I64_DADDIUSP = 0x7
13322};
13323
13324/* RR ry field for CNVT */
13325enum {
13326 RR_RY_CNVT_ZEB = 0x0,
13327 RR_RY_CNVT_ZEH = 0x1,
13328 RR_RY_CNVT_ZEW = 0x2,
13329 RR_RY_CNVT_SEB = 0x4,
13330 RR_RY_CNVT_SEH = 0x5,
13331 RR_RY_CNVT_SEW = 0x6,
13332};
13333
235785e8 13334static int xlat(int r)
364d4831
NF
13335{
13336 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13337
13338 return map[r];
13339}
13340
235785e8
AM
13341static void gen_mips16_save(DisasContext *ctx,
13342 int xsregs, int aregs,
13343 int do_ra, int do_s0, int do_s1,
13344 int framesize)
364d4831
NF
13345{
13346 TCGv t0 = tcg_temp_new();
13347 TCGv t1 = tcg_temp_new();
c48245f0 13348 TCGv t2 = tcg_temp_new();
364d4831
NF
13349 int args, astatic;
13350
13351 switch (aregs) {
13352 case 0:
13353 case 1:
13354 case 2:
13355 case 3:
13356 case 11:
13357 args = 0;
13358 break;
13359 case 4:
13360 case 5:
13361 case 6:
13362 case 7:
13363 args = 1;
13364 break;
13365 case 8:
13366 case 9:
13367 case 10:
13368 args = 2;
13369 break;
13370 case 12:
13371 case 13:
13372 args = 3;
13373 break;
13374 case 14:
13375 args = 4;
13376 break;
13377 default:
9c708c7f 13378 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13379 return;
13380 }
13381
13382 switch (args) {
13383 case 4:
13384 gen_base_offset_addr(ctx, t0, 29, 12);
13385 gen_load_gpr(t1, 7);
5f68f5ae 13386 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13387 /* Fall through */
13388 case 3:
13389 gen_base_offset_addr(ctx, t0, 29, 8);
13390 gen_load_gpr(t1, 6);
5f68f5ae 13391 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13392 /* Fall through */
13393 case 2:
13394 gen_base_offset_addr(ctx, t0, 29, 4);
13395 gen_load_gpr(t1, 5);
5f68f5ae 13396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13397 /* Fall through */
13398 case 1:
13399 gen_base_offset_addr(ctx, t0, 29, 0);
13400 gen_load_gpr(t1, 4);
5f68f5ae 13401 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13402 }
13403
13404 gen_load_gpr(t0, 29);
13405
5f68f5ae 13406#define DECR_AND_STORE(reg) do { \
c48245f0
MR
13407 tcg_gen_movi_tl(t2, -4); \
13408 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13409 gen_load_gpr(t1, reg); \
13410 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
13411 } while (0)
13412
13413 if (do_ra) {
13414 DECR_AND_STORE(31);
13415 }
13416
13417 switch (xsregs) {
13418 case 7:
13419 DECR_AND_STORE(30);
13420 /* Fall through */
13421 case 6:
13422 DECR_AND_STORE(23);
13423 /* Fall through */
13424 case 5:
13425 DECR_AND_STORE(22);
13426 /* Fall through */
13427 case 4:
13428 DECR_AND_STORE(21);
13429 /* Fall through */
13430 case 3:
13431 DECR_AND_STORE(20);
13432 /* Fall through */
13433 case 2:
13434 DECR_AND_STORE(19);
13435 /* Fall through */
13436 case 1:
13437 DECR_AND_STORE(18);
13438 }
13439
13440 if (do_s1) {
13441 DECR_AND_STORE(17);
13442 }
13443 if (do_s0) {
13444 DECR_AND_STORE(16);
13445 }
13446
13447 switch (aregs) {
13448 case 0:
13449 case 4:
13450 case 8:
13451 case 12:
13452 case 14:
13453 astatic = 0;
13454 break;
13455 case 1:
13456 case 5:
13457 case 9:
13458 case 13:
13459 astatic = 1;
13460 break;
13461 case 2:
13462 case 6:
13463 case 10:
13464 astatic = 2;
13465 break;
13466 case 3:
13467 case 7:
13468 astatic = 3;
13469 break;
13470 case 11:
13471 astatic = 4;
13472 break;
13473 default:
9c708c7f 13474 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13475 return;
13476 }
13477
13478 if (astatic > 0) {
13479 DECR_AND_STORE(7);
13480 if (astatic > 1) {
13481 DECR_AND_STORE(6);
13482 if (astatic > 2) {
13483 DECR_AND_STORE(5);
13484 if (astatic > 3) {
13485 DECR_AND_STORE(4);
13486 }
13487 }
13488 }
13489 }
13490#undef DECR_AND_STORE
13491
c48245f0
MR
13492 tcg_gen_movi_tl(t2, -framesize);
13493 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13494 tcg_temp_free(t0);
13495 tcg_temp_free(t1);
c48245f0 13496 tcg_temp_free(t2);
364d4831
NF
13497}
13498
235785e8
AM
13499static void gen_mips16_restore(DisasContext *ctx,
13500 int xsregs, int aregs,
13501 int do_ra, int do_s0, int do_s1,
13502 int framesize)
364d4831
NF
13503{
13504 int astatic;
13505 TCGv t0 = tcg_temp_new();
13506 TCGv t1 = tcg_temp_new();
c48245f0 13507 TCGv t2 = tcg_temp_new();
364d4831 13508
c48245f0
MR
13509 tcg_gen_movi_tl(t2, framesize);
13510 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13511
5f68f5ae 13512#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13513 tcg_gen_movi_tl(t2, -4); \
13514 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13515 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13516 gen_store_gpr(t1, reg); \
364d4831
NF
13517 } while (0)
13518
13519 if (do_ra) {
13520 DECR_AND_LOAD(31);
13521 }
13522
13523 switch (xsregs) {
13524 case 7:
13525 DECR_AND_LOAD(30);
13526 /* Fall through */
13527 case 6:
13528 DECR_AND_LOAD(23);
13529 /* Fall through */
13530 case 5:
13531 DECR_AND_LOAD(22);
13532 /* Fall through */
13533 case 4:
13534 DECR_AND_LOAD(21);
13535 /* Fall through */
13536 case 3:
13537 DECR_AND_LOAD(20);
13538 /* Fall through */
13539 case 2:
13540 DECR_AND_LOAD(19);
13541 /* Fall through */
13542 case 1:
13543 DECR_AND_LOAD(18);
13544 }
13545
13546 if (do_s1) {
13547 DECR_AND_LOAD(17);
13548 }
13549 if (do_s0) {
13550 DECR_AND_LOAD(16);
13551 }
13552
13553 switch (aregs) {
13554 case 0:
13555 case 4:
13556 case 8:
13557 case 12:
13558 case 14:
13559 astatic = 0;
13560 break;
13561 case 1:
13562 case 5:
13563 case 9:
13564 case 13:
13565 astatic = 1;
13566 break;
13567 case 2:
13568 case 6:
13569 case 10:
13570 astatic = 2;
13571 break;
13572 case 3:
13573 case 7:
13574 astatic = 3;
13575 break;
13576 case 11:
13577 astatic = 4;
13578 break;
13579 default:
9c708c7f 13580 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13581 return;
13582 }
13583
13584 if (astatic > 0) {
13585 DECR_AND_LOAD(7);
13586 if (astatic > 1) {
13587 DECR_AND_LOAD(6);
13588 if (astatic > 2) {
13589 DECR_AND_LOAD(5);
13590 if (astatic > 3) {
13591 DECR_AND_LOAD(4);
13592 }
13593 }
13594 }
13595 }
13596#undef DECR_AND_LOAD
13597
c48245f0
MR
13598 tcg_gen_movi_tl(t2, framesize);
13599 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13600 tcg_temp_free(t0);
13601 tcg_temp_free(t1);
c48245f0 13602 tcg_temp_free(t2);
364d4831
NF
13603}
13604
235785e8
AM
13605static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13606 int is_64_bit, int extended)
364d4831
NF
13607{
13608 TCGv t0;
13609
13610 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13611 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13612 return;
13613 }
13614
13615 t0 = tcg_temp_new();
13616
13617 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13618 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13619 if (!is_64_bit) {
13620 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13621 }
13622
13623 tcg_temp_free(t0);
13624}
13625
0d74a222
LA
13626static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13627 int16_t offset)
13628{
13629 TCGv_i32 t0 = tcg_const_i32(op);
13630 TCGv t1 = tcg_temp_new();
13631 gen_base_offset_addr(ctx, t1, base, offset);
13632 gen_helper_cache(cpu_env, t1, t0);
13633}
13634
364d4831 13635#if defined(TARGET_MIPS64)
235785e8
AM
13636static void decode_i64_mips16(DisasContext *ctx,
13637 int ry, int funct, int16_t offset,
13638 int extended)
364d4831
NF
13639{
13640 switch (funct) {
13641 case I64_LDSP:
d9224450 13642 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13643 check_mips_64(ctx);
13644 offset = extended ? offset : offset << 3;
d75c135e 13645 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13646 break;
13647 case I64_SDSP:
d9224450 13648 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13649 check_mips_64(ctx);
13650 offset = extended ? offset : offset << 3;
5c13fdfd 13651 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13652 break;
13653 case I64_SDRASP:
d9224450 13654 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13655 check_mips_64(ctx);
13656 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13657 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13658 break;
13659 case I64_DADJSP:
d9224450 13660 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13661 check_mips_64(ctx);
13662 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13663 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13664 break;
13665 case I64_LDPC:
d9224450
MR
13666 check_insn(ctx, ISA_MIPS3);
13667 check_mips_64(ctx);
364d4831 13668 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13669 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13670 } else {
13671 offset = extended ? offset : offset << 3;
d75c135e 13672 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13673 }
13674 break;
13675 case I64_DADDIU5:
d9224450 13676 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13677 check_mips_64(ctx);
13678 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13679 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13680 break;
13681 case I64_DADDIUPC:
d9224450 13682 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13683 check_mips_64(ctx);
13684 offset = extended ? offset : offset << 2;
13685 gen_addiupc(ctx, ry, offset, 1, extended);
13686 break;
13687 case I64_DADDIUSP:
d9224450 13688 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13689 check_mips_64(ctx);
13690 offset = extended ? offset : offset << 2;
d75c135e 13691 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13692 break;
13693 }
13694}
13695#endif
13696
235785e8 13697static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 13698{
eeb3bba8 13699 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13700 int op, rx, ry, funct, sa;
13701 int16_t imm, offset;
13702
13703 ctx->opcode = (ctx->opcode << 16) | extend;
13704 op = (ctx->opcode >> 11) & 0x1f;
13705 sa = (ctx->opcode >> 22) & 0x1f;
13706 funct = (ctx->opcode >> 8) & 0x7;
13707 rx = xlat((ctx->opcode >> 8) & 0x7);
13708 ry = xlat((ctx->opcode >> 5) & 0x7);
13709 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13710 | ((ctx->opcode >> 21) & 0x3f) << 5
13711 | (ctx->opcode & 0x1f));
13712
7480515f
AM
13713 /*
13714 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13715 * counterparts.
13716 */
364d4831
NF
13717 switch (op) {
13718 case M16_OPC_ADDIUSP:
d75c135e 13719 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13720 break;
13721 case M16_OPC_ADDIUPC:
13722 gen_addiupc(ctx, rx, imm, 0, 1);
13723 break;
13724 case M16_OPC_B:
b231c103 13725 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13726 /* No delay slot, so just process as a normal instruction */
13727 break;
13728 case M16_OPC_BEQZ:
b231c103 13729 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13730 /* No delay slot, so just process as a normal instruction */
13731 break;
13732 case M16_OPC_BNEQZ:
b231c103 13733 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13734 /* No delay slot, so just process as a normal instruction */
13735 break;
13736 case M16_OPC_SHIFT:
13737 switch (ctx->opcode & 0x3) {
13738 case 0x0:
d75c135e 13739 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13740 break;
13741 case 0x1:
13742#if defined(TARGET_MIPS64)
13743 check_mips_64(ctx);
d75c135e 13744 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13745#else
9c708c7f 13746 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13747#endif
13748 break;
13749 case 0x2:
d75c135e 13750 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13751 break;
13752 case 0x3:
d75c135e 13753 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13754 break;
13755 }
13756 break;
13757#if defined(TARGET_MIPS64)
13758 case M16_OPC_LD:
d9224450 13759 check_insn(ctx, ISA_MIPS3);
d75de749 13760 check_mips_64(ctx);
d75c135e 13761 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13762 break;
13763#endif
13764 case M16_OPC_RRIA:
13765 imm = ctx->opcode & 0xf;
13766 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13767 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13768 imm = (int16_t) (imm << 1) >> 1;
13769 if ((ctx->opcode >> 4) & 0x1) {
13770#if defined(TARGET_MIPS64)
13771 check_mips_64(ctx);
d75c135e 13772 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13773#else
9c708c7f 13774 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13775#endif
13776 } else {
d75c135e 13777 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13778 }
13779 break;
13780 case M16_OPC_ADDIU8:
d75c135e 13781 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13782 break;
13783 case M16_OPC_SLTI:
d75c135e 13784 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13785 break;
13786 case M16_OPC_SLTIU:
d75c135e 13787 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13788 break;
13789 case M16_OPC_I8:
13790 switch (funct) {
13791 case I8_BTEQZ:
b231c103 13792 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13793 break;
13794 case I8_BTNEZ:
b231c103 13795 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13796 break;
13797 case I8_SWRASP:
5c13fdfd 13798 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13799 break;
13800 case I8_ADJSP:
d75c135e 13801 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13802 break;
13803 case I8_SVRS:
d9224450 13804 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13805 {
13806 int xsregs = (ctx->opcode >> 24) & 0x7;
13807 int aregs = (ctx->opcode >> 16) & 0xf;
13808 int do_ra = (ctx->opcode >> 6) & 0x1;
13809 int do_s0 = (ctx->opcode >> 5) & 0x1;
13810 int do_s1 = (ctx->opcode >> 4) & 0x1;
13811 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13812 | (ctx->opcode & 0xf)) << 3;
13813
13814 if (ctx->opcode & (1 << 7)) {
13815 gen_mips16_save(ctx, xsregs, aregs,
13816 do_ra, do_s0, do_s1,
13817 framesize);
13818 } else {
13819 gen_mips16_restore(ctx, xsregs, aregs,
13820 do_ra, do_s0, do_s1,
13821 framesize);
13822 }
13823 }
13824 break;
13825 default:
9c708c7f 13826 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13827 break;
13828 }
13829 break;
13830 case M16_OPC_LI:
13831 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13832 break;
13833 case M16_OPC_CMPI:
13834 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13835 break;
13836#if defined(TARGET_MIPS64)
13837 case M16_OPC_SD:
d9224450
MR
13838 check_insn(ctx, ISA_MIPS3);
13839 check_mips_64(ctx);
5c13fdfd 13840 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13841 break;
13842#endif
13843 case M16_OPC_LB:
d75c135e 13844 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13845 break;
13846 case M16_OPC_LH:
d75c135e 13847 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13848 break;
13849 case M16_OPC_LWSP:
d75c135e 13850 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13851 break;
13852 case M16_OPC_LW:
d75c135e 13853 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13854 break;
13855 case M16_OPC_LBU:
d75c135e 13856 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13857 break;
13858 case M16_OPC_LHU:
d75c135e 13859 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13860 break;
13861 case M16_OPC_LWPC:
d75c135e 13862 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13863 break;
13864#if defined(TARGET_MIPS64)
13865 case M16_OPC_LWU:
d9224450
MR
13866 check_insn(ctx, ISA_MIPS3);
13867 check_mips_64(ctx);
d75c135e 13868 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13869 break;
13870#endif
13871 case M16_OPC_SB:
5c13fdfd 13872 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13873 break;
13874 case M16_OPC_SH:
5c13fdfd 13875 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13876 break;
13877 case M16_OPC_SWSP:
5c13fdfd 13878 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13879 break;
13880 case M16_OPC_SW:
5c13fdfd 13881 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13882 break;
13883#if defined(TARGET_MIPS64)
13884 case M16_OPC_I64:
d75c135e 13885 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13886 break;
13887#endif
13888 default:
9c708c7f 13889 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13890 break;
13891 }
13892
13893 return 4;
13894}
13895
3b3c1694
LA
13896static inline bool is_uhi(int sdbbp_code)
13897{
13898#ifdef CONFIG_USER_ONLY
13899 return false;
13900#else
13901 return semihosting_enabled() && sdbbp_code == 1;
13902#endif
13903}
13904
82ba4266
AB
13905#ifdef CONFIG_USER_ONLY
13906/* The above should dead-code away any calls to this..*/
13907static inline void gen_helper_do_semihosting(void *env)
13908{
13909 g_assert_not_reached();
13910}
13911#endif
13912
235785e8 13913static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13914{
13915 int rx, ry;
13916 int sa;
13917 int op, cnvt_op, op1, offset;
13918 int funct;
13919 int n_bytes;
13920
13921 op = (ctx->opcode >> 11) & 0x1f;
13922 sa = (ctx->opcode >> 2) & 0x7;
13923 sa = sa == 0 ? 8 : sa;
13924 rx = xlat((ctx->opcode >> 8) & 0x7);
13925 cnvt_op = (ctx->opcode >> 5) & 0x7;
13926 ry = xlat((ctx->opcode >> 5) & 0x7);
13927 op1 = offset = ctx->opcode & 0x1f;
13928
13929 n_bytes = 2;
13930
13931 switch (op) {
13932 case M16_OPC_ADDIUSP:
13933 {
13934 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13935
d75c135e 13936 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13937 }
13938 break;
13939 case M16_OPC_ADDIUPC:
13940 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13941 break;
13942 case M16_OPC_B:
13943 offset = (ctx->opcode & 0x7ff) << 1;
13944 offset = (int16_t)(offset << 4) >> 4;
b231c103 13945 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13946 /* No delay slot, so just process as a normal instruction */
13947 break;
13948 case M16_OPC_JAL:
eeb3bba8 13949 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13950 offset = (((ctx->opcode & 0x1f) << 21)
13951 | ((ctx->opcode >> 5) & 0x1f) << 16
13952 | offset) << 2;
b231c103
YK
13953 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13954 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13955 n_bytes = 4;
364d4831
NF
13956 break;
13957 case M16_OPC_BEQZ:
b231c103
YK
13958 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13959 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13960 /* No delay slot, so just process as a normal instruction */
13961 break;
13962 case M16_OPC_BNEQZ:
b231c103
YK
13963 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13964 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13965 /* No delay slot, so just process as a normal instruction */
13966 break;
13967 case M16_OPC_SHIFT:
13968 switch (ctx->opcode & 0x3) {
13969 case 0x0:
d75c135e 13970 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13971 break;
13972 case 0x1:
13973#if defined(TARGET_MIPS64)
d9224450 13974 check_insn(ctx, ISA_MIPS3);
364d4831 13975 check_mips_64(ctx);
d75c135e 13976 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13977#else
9c708c7f 13978 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13979#endif
13980 break;
13981 case 0x2:
d75c135e 13982 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13983 break;
13984 case 0x3:
d75c135e 13985 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13986 break;
13987 }
13988 break;
13989#if defined(TARGET_MIPS64)
13990 case M16_OPC_LD:
d9224450 13991 check_insn(ctx, ISA_MIPS3);
364d4831 13992 check_mips_64(ctx);
d75c135e 13993 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13994 break;
13995#endif
13996 case M16_OPC_RRIA:
13997 {
13998 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13999
14000 if ((ctx->opcode >> 4) & 1) {
14001#if defined(TARGET_MIPS64)
d9224450 14002 check_insn(ctx, ISA_MIPS3);
364d4831 14003 check_mips_64(ctx);
d75c135e 14004 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 14005#else
9c708c7f 14006 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14007#endif
14008 } else {
d75c135e 14009 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14010 }
14011 }
14012 break;
14013 case M16_OPC_ADDIU8:
14014 {
14015 int16_t imm = (int8_t) ctx->opcode;
14016
d75c135e 14017 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14018 }
14019 break;
14020 case M16_OPC_SLTI:
14021 {
14022 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14023 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14024 }
14025 break;
14026 case M16_OPC_SLTIU:
14027 {
14028 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14029 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14030 }
14031 break;
14032 case M16_OPC_I8:
14033 {
14034 int reg32;
14035
14036 funct = (ctx->opcode >> 8) & 0x7;
14037 switch (funct) {
14038 case I8_BTEQZ:
14039 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 14040 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14041 break;
14042 case I8_BTNEZ:
14043 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 14044 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14045 break;
14046 case I8_SWRASP:
5c13fdfd 14047 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
14048 break;
14049 case I8_ADJSP:
d75c135e 14050 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
14051 ((int8_t)ctx->opcode) << 3);
14052 break;
14053 case I8_SVRS:
d9224450 14054 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14055 {
14056 int do_ra = ctx->opcode & (1 << 6);
14057 int do_s0 = ctx->opcode & (1 << 5);
14058 int do_s1 = ctx->opcode & (1 << 4);
14059 int framesize = ctx->opcode & 0xf;
14060
14061 if (framesize == 0) {
14062 framesize = 128;
14063 } else {
14064 framesize = framesize << 3;
14065 }
14066
14067 if (ctx->opcode & (1 << 7)) {
14068 gen_mips16_save(ctx, 0, 0,
14069 do_ra, do_s0, do_s1, framesize);
14070 } else {
14071 gen_mips16_restore(ctx, 0, 0,
14072 do_ra, do_s0, do_s1, framesize);
14073 }
14074 }
14075 break;
14076 case I8_MOV32R:
14077 {
14078 int rz = xlat(ctx->opcode & 0x7);
14079
14080 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14081 ((ctx->opcode >> 5) & 0x7);
d75c135e 14082 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
14083 }
14084 break;
14085 case I8_MOVR32:
14086 reg32 = ctx->opcode & 0x1f;
d75c135e 14087 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
14088 break;
14089 default:
9c708c7f 14090 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14091 break;
14092 }
14093 }
14094 break;
14095 case M16_OPC_LI:
14096 {
14097 int16_t imm = (uint8_t) ctx->opcode;
14098
d75c135e 14099 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
14100 }
14101 break;
14102 case M16_OPC_CMPI:
14103 {
14104 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14105 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
14106 }
14107 break;
14108#if defined(TARGET_MIPS64)
14109 case M16_OPC_SD:
d9224450 14110 check_insn(ctx, ISA_MIPS3);
364d4831 14111 check_mips_64(ctx);
5c13fdfd 14112 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
14113 break;
14114#endif
14115 case M16_OPC_LB:
d75c135e 14116 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14117 break;
14118 case M16_OPC_LH:
d75c135e 14119 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
14120 break;
14121 case M16_OPC_LWSP:
d75c135e 14122 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14123 break;
14124 case M16_OPC_LW:
d75c135e 14125 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
14126 break;
14127 case M16_OPC_LBU:
d75c135e 14128 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14129 break;
14130 case M16_OPC_LHU:
d75c135e 14131 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
14132 break;
14133 case M16_OPC_LWPC:
d75c135e 14134 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 14135 break;
235785e8 14136#if defined(TARGET_MIPS64)
364d4831 14137 case M16_OPC_LWU:
d9224450 14138 check_insn(ctx, ISA_MIPS3);
364d4831 14139 check_mips_64(ctx);
d75c135e 14140 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
14141 break;
14142#endif
14143 case M16_OPC_SB:
5c13fdfd 14144 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14145 break;
14146 case M16_OPC_SH:
5c13fdfd 14147 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14148 break;
14149 case M16_OPC_SWSP:
5c13fdfd 14150 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14151 break;
14152 case M16_OPC_SW:
5c13fdfd 14153 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14154 break;
14155 case M16_OPC_RRR:
14156 {
14157 int rz = xlat((ctx->opcode >> 2) & 0x7);
14158 int mips32_op;
14159
14160 switch (ctx->opcode & 0x3) {
14161 case RRR_ADDU:
14162 mips32_op = OPC_ADDU;
14163 break;
14164 case RRR_SUBU:
14165 mips32_op = OPC_SUBU;
14166 break;
14167#if defined(TARGET_MIPS64)
14168 case RRR_DADDU:
14169 mips32_op = OPC_DADDU;
d9224450 14170 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14171 check_mips_64(ctx);
14172 break;
14173 case RRR_DSUBU:
14174 mips32_op = OPC_DSUBU;
d9224450 14175 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14176 check_mips_64(ctx);
14177 break;
14178#endif
14179 default:
9c708c7f 14180 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14181 goto done;
14182 }
14183
d75c135e 14184 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14185 done:
14186 ;
14187 }
14188 break;
14189 case M16_OPC_RR:
14190 switch (op1) {
14191 case RR_JR:
14192 {
14193 int nd = (ctx->opcode >> 7) & 0x1;
14194 int link = (ctx->opcode >> 6) & 0x1;
14195 int ra = (ctx->opcode >> 5) & 0x1;
14196
d9224450
MR
14197 if (nd) {
14198 check_insn(ctx, ISA_MIPS32);
14199 }
14200
364d4831 14201 if (link) {
b231c103 14202 op = OPC_JALR;
364d4831
NF
14203 } else {
14204 op = OPC_JR;
14205 }
14206
b231c103
YK
14207 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14208 (nd ? 0 : 2));
364d4831
NF
14209 }
14210 break;
14211 case RR_SDBBP:
3b3c1694
LA
14212 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14213 gen_helper_do_semihosting(cpu_env);
14214 } else {
7480515f
AM
14215 /*
14216 * XXX: not clear which exception should be raised
3b3c1694
LA
14217 * when in debug mode...
14218 */
14219 check_insn(ctx, ISA_MIPS32);
9c708c7f 14220 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14221 }
364d4831
NF
14222 break;
14223 case RR_SLT:
d75c135e 14224 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14225 break;
14226 case RR_SLTU:
d75c135e 14227 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14228 break;
14229 case RR_BREAK:
9c708c7f 14230 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14231 break;
14232 case RR_SLLV:
d75c135e 14233 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14234 break;
14235 case RR_SRLV:
d75c135e 14236 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14237 break;
14238 case RR_SRAV:
d75c135e 14239 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 14240 break;
235785e8 14241#if defined(TARGET_MIPS64)
364d4831 14242 case RR_DSRL:
d9224450 14243 check_insn(ctx, ISA_MIPS3);
364d4831 14244 check_mips_64(ctx);
d75c135e 14245 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14246 break;
14247#endif
14248 case RR_CMP:
d75c135e 14249 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14250 break;
14251 case RR_NEG:
d75c135e 14252 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14253 break;
14254 case RR_AND:
d75c135e 14255 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14256 break;
14257 case RR_OR:
d75c135e 14258 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14259 break;
14260 case RR_XOR:
d75c135e 14261 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14262 break;
14263 case RR_NOT:
d75c135e 14264 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14265 break;
14266 case RR_MFHI:
26135ead 14267 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14268 break;
14269 case RR_CNVT:
d9224450 14270 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14271 switch (cnvt_op) {
14272 case RR_RY_CNVT_ZEB:
14273 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14274 break;
14275 case RR_RY_CNVT_ZEH:
14276 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14277 break;
14278 case RR_RY_CNVT_SEB:
14279 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14280 break;
14281 case RR_RY_CNVT_SEH:
14282 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14283 break;
71375b59 14284#if defined(TARGET_MIPS64)
364d4831 14285 case RR_RY_CNVT_ZEW:
d9224450 14286 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14287 check_mips_64(ctx);
14288 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14289 break;
14290 case RR_RY_CNVT_SEW:
d9224450 14291 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14292 check_mips_64(ctx);
14293 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14294 break;
14295#endif
14296 default:
9c708c7f 14297 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14298 break;
14299 }
14300 break;
14301 case RR_MFLO:
26135ead 14302 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 14303 break;
235785e8 14304#if defined(TARGET_MIPS64)
364d4831 14305 case RR_DSRA:
d9224450 14306 check_insn(ctx, ISA_MIPS3);
364d4831 14307 check_mips_64(ctx);
d75c135e 14308 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14309 break;
14310 case RR_DSLLV:
d9224450 14311 check_insn(ctx, ISA_MIPS3);
364d4831 14312 check_mips_64(ctx);
d75c135e 14313 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14314 break;
14315 case RR_DSRLV:
d9224450 14316 check_insn(ctx, ISA_MIPS3);
364d4831 14317 check_mips_64(ctx);
d75c135e 14318 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14319 break;
14320 case RR_DSRAV:
d9224450 14321 check_insn(ctx, ISA_MIPS3);
364d4831 14322 check_mips_64(ctx);
d75c135e 14323 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14324 break;
14325#endif
14326 case RR_MULT:
26135ead 14327 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14328 break;
14329 case RR_MULTU:
26135ead 14330 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14331 break;
14332 case RR_DIV:
26135ead 14333 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14334 break;
14335 case RR_DIVU:
26135ead 14336 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 14337 break;
235785e8 14338#if defined(TARGET_MIPS64)
364d4831 14339 case RR_DMULT:
d9224450 14340 check_insn(ctx, ISA_MIPS3);
364d4831 14341 check_mips_64(ctx);
26135ead 14342 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14343 break;
14344 case RR_DMULTU:
d9224450 14345 check_insn(ctx, ISA_MIPS3);
364d4831 14346 check_mips_64(ctx);
26135ead 14347 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14348 break;
14349 case RR_DDIV:
d9224450 14350 check_insn(ctx, ISA_MIPS3);
364d4831 14351 check_mips_64(ctx);
26135ead 14352 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14353 break;
14354 case RR_DDIVU:
d9224450 14355 check_insn(ctx, ISA_MIPS3);
364d4831 14356 check_mips_64(ctx);
26135ead 14357 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14358 break;
14359#endif
14360 default:
9c708c7f 14361 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14362 break;
14363 }
14364 break;
14365 case M16_OPC_EXTEND:
240ce26a 14366 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14367 n_bytes = 4;
14368 break;
14369#if defined(TARGET_MIPS64)
14370 case M16_OPC_I64:
14371 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14372 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14373 break;
14374#endif
14375 default:
9c708c7f 14376 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14377 break;
14378 }
14379
14380 return n_bytes;
14381}
14382
211da992 14383/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 14384
211da992
CWR
14385/*
14386 * microMIPS32/microMIPS64 major opcodes
14387 *
14388 * 1. MIPS Architecture for Programmers Volume II-B:
14389 * The microMIPS32 Instruction Set (Revision 3.05)
14390 *
14391 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14392 *
14393 * 2. MIPS Architecture For Programmers Volume II-A:
14394 * The MIPS64 Instruction Set (Revision 3.51)
14395 */
6af0bf9c 14396
3c824109
NF
14397enum {
14398 POOL32A = 0x00,
14399 POOL16A = 0x01,
14400 LBU16 = 0x02,
14401 MOVE16 = 0x03,
14402 ADDI32 = 0x04,
3a1f4268
YK
14403 R6_LUI = 0x04,
14404 AUI = 0x04,
3c824109
NF
14405 LBU32 = 0x05,
14406 SB32 = 0x06,
14407 LB32 = 0x07,
14408
14409 POOL32B = 0x08,
14410 POOL16B = 0x09,
14411 LHU16 = 0x0a,
14412 ANDI16 = 0x0b,
14413 ADDIU32 = 0x0c,
14414 LHU32 = 0x0d,
14415 SH32 = 0x0e,
14416 LH32 = 0x0f,
14417
14418 POOL32I = 0x10,
14419 POOL16C = 0x11,
14420 LWSP16 = 0x12,
14421 POOL16D = 0x13,
14422 ORI32 = 0x14,
14423 POOL32F = 0x15,
211da992
CWR
14424 POOL32S = 0x16, /* MIPS64 */
14425 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
14426
14427 POOL32C = 0x18,
14428 LWGP16 = 0x19,
14429 LW16 = 0x1a,
14430 POOL16E = 0x1b,
14431 XORI32 = 0x1c,
14432 JALS32 = 0x1d,
3a1f4268
YK
14433 BOVC = 0x1d,
14434 BEQC = 0x1d,
14435 BEQZALC = 0x1d,
3c824109 14436 ADDIUPC = 0x1e,
3a1f4268
YK
14437 PCREL = 0x1e,
14438 BNVC = 0x1f,
14439 BNEC = 0x1f,
14440 BNEZALC = 0x1f,
3c824109 14441
3a1f4268
YK
14442 R6_BEQZC = 0x20,
14443 JIC = 0x20,
3c824109
NF
14444 POOL16F = 0x21,
14445 SB16 = 0x22,
14446 BEQZ16 = 0x23,
3a1f4268 14447 BEQZC16 = 0x23,
3c824109
NF
14448 SLTI32 = 0x24,
14449 BEQ32 = 0x25,
3a1f4268 14450 BC = 0x25,
3c824109
NF
14451 SWC132 = 0x26,
14452 LWC132 = 0x27,
14453
3a1f4268 14454 /* 0x29 is reserved */
3c824109 14455 RES_29 = 0x29,
3a1f4268
YK
14456 R6_BNEZC = 0x28,
14457 JIALC = 0x28,
3c824109
NF
14458 SH16 = 0x2a,
14459 BNEZ16 = 0x2b,
3a1f4268 14460 BNEZC16 = 0x2b,
3c824109
NF
14461 SLTIU32 = 0x2c,
14462 BNE32 = 0x2d,
3a1f4268 14463 BALC = 0x2d,
3c824109
NF
14464 SDC132 = 0x2e,
14465 LDC132 = 0x2f,
14466
3a1f4268 14467 /* 0x31 is reserved */
3c824109 14468 RES_31 = 0x31,
3a1f4268
YK
14469 BLEZALC = 0x30,
14470 BGEZALC = 0x30,
14471 BGEUC = 0x30,
3c824109
NF
14472 SWSP16 = 0x32,
14473 B16 = 0x33,
3a1f4268 14474 BC16 = 0x33,
3c824109
NF
14475 ANDI32 = 0x34,
14476 J32 = 0x35,
3a1f4268
YK
14477 BGTZC = 0x35,
14478 BLTZC = 0x35,
14479 BLTC = 0x35,
211da992
CWR
14480 SD32 = 0x36, /* MIPS64 */
14481 LD32 = 0x37, /* MIPS64 */
3c824109 14482
3a1f4268 14483 /* 0x39 is reserved */
3c824109 14484 RES_39 = 0x39,
3a1f4268
YK
14485 BGTZALC = 0x38,
14486 BLTZALC = 0x38,
14487 BLTUC = 0x38,
3c824109
NF
14488 SW16 = 0x3a,
14489 LI16 = 0x3b,
14490 JALX32 = 0x3c,
14491 JAL32 = 0x3d,
3a1f4268
YK
14492 BLEZC = 0x3d,
14493 BGEZC = 0x3d,
14494 BGEC = 0x3d,
3c824109
NF
14495 SW32 = 0x3e,
14496 LW32 = 0x3f
14497};
14498
3a1f4268
YK
14499/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14500enum {
14501 ADDIUPC_00 = 0x00,
c38a1d52
AR
14502 ADDIUPC_01 = 0x01,
14503 ADDIUPC_02 = 0x02,
14504 ADDIUPC_03 = 0x03,
14505 ADDIUPC_04 = 0x04,
14506 ADDIUPC_05 = 0x05,
14507 ADDIUPC_06 = 0x06,
3a1f4268
YK
14508 ADDIUPC_07 = 0x07,
14509 AUIPC = 0x1e,
14510 ALUIPC = 0x1f,
14511 LWPC_08 = 0x08,
c38a1d52
AR
14512 LWPC_09 = 0x09,
14513 LWPC_0A = 0x0A,
14514 LWPC_0B = 0x0B,
14515 LWPC_0C = 0x0C,
14516 LWPC_0D = 0x0D,
14517 LWPC_0E = 0x0E,
3a1f4268
YK
14518 LWPC_0F = 0x0F,
14519};
14520
3c824109
NF
14521/* POOL32A encoding of minor opcode field */
14522
14523enum {
7480515f
AM
14524 /*
14525 * These opcodes are distinguished only by bits 9..6; those bits are
14526 * what are recorded below.
14527 */
3c824109
NF
14528 SLL32 = 0x0,
14529 SRL32 = 0x1,
14530 SRA = 0x2,
14531 ROTR = 0x3,
3a1f4268
YK
14532 SELEQZ = 0x5,
14533 SELNEZ = 0x6,
b00c7218 14534 R6_RDHWR = 0x7,
3c824109
NF
14535
14536 SLLV = 0x0,
14537 SRLV = 0x1,
14538 SRAV = 0x2,
14539 ROTRV = 0x3,
14540 ADD = 0x4,
14541 ADDU32 = 0x5,
14542 SUB = 0x6,
14543 SUBU32 = 0x7,
14544 MUL = 0x8,
14545 AND = 0x9,
14546 OR32 = 0xa,
14547 NOR = 0xb,
14548 XOR32 = 0xc,
14549 SLT = 0xd,
14550 SLTU = 0xe,
14551
14552 MOVN = 0x0,
3a1f4268 14553 R6_MUL = 0x0,
3c824109 14554 MOVZ = 0x1,
3a1f4268
YK
14555 MUH = 0x1,
14556 MULU = 0x2,
14557 MUHU = 0x3,
3c824109 14558 LWXS = 0x4,
3a1f4268
YK
14559 R6_DIV = 0x4,
14560 MOD = 0x5,
14561 R6_DIVU = 0x6,
14562 MODU = 0x7,
3c824109
NF
14563
14564 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14565 BREAK32 = 0x07,
3c824109 14566 INS = 0x0c,
3a1f4268
YK
14567 LSA = 0x0f,
14568 ALIGN = 0x1f,
3c824109 14569 EXT = 0x2c,
bb238210
YK
14570 POOL32AXF = 0x3c,
14571 SIGRIE = 0x3f
3c824109
NF
14572};
14573
14574/* POOL32AXF encoding of minor opcode field extension */
14575
d132c79f
CWR
14576/*
14577 * 1. MIPS Architecture for Programmers Volume II-B:
14578 * The microMIPS32 Instruction Set (Revision 3.05)
14579 *
14580 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14581 *
14582 * 2. MIPS Architecture for Programmers VolumeIV-e:
14583 * The MIPS DSP Application-Specific Extension
14584 * to the microMIPS32 Architecture (Revision 2.34)
14585 *
14586 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14587 */
14588
3c824109
NF
14589enum {
14590 /* bits 11..6 */
14591 TEQ = 0x00,
14592 TGE = 0x08,
14593 TGEU = 0x10,
14594 TLT = 0x20,
14595 TLTU = 0x28,
14596 TNE = 0x30,
14597
14598 MFC0 = 0x03,
14599 MTC0 = 0x0b,
14600
d132c79f
CWR
14601 /* begin of microMIPS32 DSP */
14602
3c824109
NF
14603 /* bits 13..12 for 0x01 */
14604 MFHI_ACC = 0x0,
14605 MFLO_ACC = 0x1,
14606 MTHI_ACC = 0x2,
14607 MTLO_ACC = 0x3,
14608
14609 /* bits 13..12 for 0x2a */
14610 MADD_ACC = 0x0,
14611 MADDU_ACC = 0x1,
14612 MSUB_ACC = 0x2,
14613 MSUBU_ACC = 0x3,
14614
14615 /* bits 13..12 for 0x32 */
14616 MULT_ACC = 0x0,
6801038b 14617 MULTU_ACC = 0x1,
3c824109 14618
d132c79f
CWR
14619 /* end of microMIPS32 DSP */
14620
3c824109 14621 /* bits 15..12 for 0x2c */
3a1f4268 14622 BITSWAP = 0x0,
3c824109
NF
14623 SEB = 0x2,
14624 SEH = 0x3,
14625 CLO = 0x4,
14626 CLZ = 0x5,
14627 RDHWR = 0x6,
14628 WSBH = 0x7,
14629 MULT = 0x8,
14630 MULTU = 0x9,
14631 DIV = 0xa,
14632 DIVU = 0xb,
14633 MADD = 0xc,
14634 MADDU = 0xd,
14635 MSUB = 0xe,
14636 MSUBU = 0xf,
14637
14638 /* bits 15..12 for 0x34 */
14639 MFC2 = 0x4,
14640 MTC2 = 0x5,
14641 MFHC2 = 0x8,
14642 MTHC2 = 0x9,
14643 CFC2 = 0xc,
14644 CTC2 = 0xd,
14645
14646 /* bits 15..12 for 0x3c */
14647 JALR = 0x0,
14648 JR = 0x0, /* alias */
3a1f4268
YK
14649 JALRC = 0x0,
14650 JRC = 0x0,
3c824109 14651 JALR_HB = 0x1,
3a1f4268 14652 JALRC_HB = 0x1,
3c824109
NF
14653 JALRS = 0x4,
14654 JALRS_HB = 0x5,
14655
14656 /* bits 15..12 for 0x05 */
14657 RDPGPR = 0xe,
14658 WRPGPR = 0xf,
14659
14660 /* bits 15..12 for 0x0d */
14661 TLBP = 0x0,
14662 TLBR = 0x1,
14663 TLBWI = 0x2,
14664 TLBWR = 0x3,
e60ec063
YK
14665 TLBINV = 0x4,
14666 TLBINVF = 0x5,
3c824109
NF
14667 WAIT = 0x9,
14668 IRET = 0xd,
14669 DERET = 0xe,
14670 ERET = 0xf,
14671
14672 /* bits 15..12 for 0x15 */
14673 DMT = 0x0,
14674 DVPE = 0x1,
14675 EMT = 0x2,
14676 EVPE = 0x3,
14677
14678 /* bits 15..12 for 0x1d */
14679 DI = 0x4,
14680 EI = 0x5,
14681
14682 /* bits 15..12 for 0x2d */
14683 SYNC = 0x6,
14684 SYSCALL = 0x8,
14685 SDBBP = 0xd,
14686
14687 /* bits 15..12 for 0x35 */
14688 MFHI32 = 0x0,
14689 MFLO32 = 0x1,
14690 MTHI32 = 0x2,
14691 MTLO32 = 0x3,
14692};
14693
14694/* POOL32B encoding of minor opcode field (bits 15..12) */
14695
14696enum {
14697 LWC2 = 0x0,
14698 LWP = 0x1,
14699 LDP = 0x4,
14700 LWM32 = 0x5,
14701 CACHE = 0x6,
14702 LDM = 0x7,
14703 SWC2 = 0x8,
14704 SWP = 0x9,
14705 SDP = 0xc,
14706 SWM32 = 0xd,
14707 SDM = 0xf
14708};
14709
14710/* POOL32C encoding of minor opcode field (bits 15..12) */
14711
14712enum {
14713 LWL = 0x0,
14714 SWL = 0x8,
14715 LWR = 0x1,
14716 SWR = 0x9,
14717 PREF = 0x2,
8fffc646 14718 ST_EVA = 0xa,
3c824109
NF
14719 LL = 0x3,
14720 SC = 0xb,
14721 LDL = 0x4,
14722 SDL = 0xc,
14723 LDR = 0x5,
14724 SDR = 0xd,
8fffc646 14725 LD_EVA = 0x6,
3c824109
NF
14726 LWU = 0xe,
14727 LLD = 0x7,
14728 SCD = 0xf
14729};
14730
8fffc646
JH
14731/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14732
14733enum {
14734 LBUE = 0x0,
14735 LHUE = 0x1,
14736 LWLE = 0x2,
14737 LWRE = 0x3,
14738 LBE = 0x4,
14739 LHE = 0x5,
14740 LLE = 0x6,
14741 LWE = 0x7,
14742};
14743
14744/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14745
14746enum {
14747 SWLE = 0x0,
14748 SWRE = 0x1,
14749 PREFE = 0x2,
14750 CACHEE = 0x3,
14751 SBE = 0x4,
14752 SHE = 0x5,
14753 SCE = 0x6,
14754 SWE = 0x7,
14755};
14756
3c824109
NF
14757/* POOL32F encoding of minor opcode field (bits 5..0) */
14758
14759enum {
14760 /* These are the bit 7..6 values */
14761 ADD_FMT = 0x0,
3c824109
NF
14762
14763 SUB_FMT = 0x1,
3c824109
NF
14764
14765 MUL_FMT = 0x2,
14766
14767 DIV_FMT = 0x3,
14768
14769 /* These are the bit 8..6 values */
3a1f4268 14770 MOVN_FMT = 0x0,
3c824109
NF
14771 RSQRT2_FMT = 0x0,
14772 MOVF_FMT = 0x0,
3a1f4268
YK
14773 RINT_FMT = 0x0,
14774 SELNEZ_FMT = 0x0,
3c824109 14775
3a1f4268 14776 MOVZ_FMT = 0x1,
3c824109
NF
14777 LWXC1 = 0x1,
14778 MOVT_FMT = 0x1,
3a1f4268
YK
14779 CLASS_FMT = 0x1,
14780 SELEQZ_FMT = 0x1,
3c824109
NF
14781
14782 PLL_PS = 0x2,
14783 SWXC1 = 0x2,
3a1f4268 14784 SEL_FMT = 0x2,
3c824109
NF
14785
14786 PLU_PS = 0x3,
14787 LDXC1 = 0x3,
14788
3a1f4268 14789 MOVN_FMT_04 = 0x4,
3c824109
NF
14790 PUL_PS = 0x4,
14791 SDXC1 = 0x4,
14792 RECIP2_FMT = 0x4,
14793
3a1f4268 14794 MOVZ_FMT_05 = 0x05,
3c824109
NF
14795 PUU_PS = 0x5,
14796 LUXC1 = 0x5,
14797
14798 CVT_PS_S = 0x6,
14799 SUXC1 = 0x6,
14800 ADDR_PS = 0x6,
14801 PREFX = 0x6,
3a1f4268 14802 MADDF_FMT = 0x6,
3c824109
NF
14803
14804 MULR_PS = 0x7,
3a1f4268 14805 MSUBF_FMT = 0x7,
3c824109
NF
14806
14807 MADD_S = 0x01,
14808 MADD_D = 0x09,
14809 MADD_PS = 0x11,
14810 ALNV_PS = 0x19,
14811 MSUB_S = 0x21,
14812 MSUB_D = 0x29,
14813 MSUB_PS = 0x31,
14814
14815 NMADD_S = 0x02,
14816 NMADD_D = 0x0a,
14817 NMADD_PS = 0x12,
14818 NMSUB_S = 0x22,
14819 NMSUB_D = 0x2a,
14820 NMSUB_PS = 0x32,
14821
3a1f4268
YK
14822 MIN_FMT = 0x3,
14823 MAX_FMT = 0xb,
14824 MINA_FMT = 0x23,
14825 MAXA_FMT = 0x2b,
3c824109
NF
14826 POOL32FXF = 0x3b,
14827
14828 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14829 C_COND_FMT = 0x3c,
14830
14831 CMP_CONDN_S = 0x5,
14832 CMP_CONDN_D = 0x15
3c824109
NF
14833};
14834
14835/* POOL32Fxf encoding of minor opcode extension field */
14836
14837enum {
14838 CVT_L = 0x04,
14839 RSQRT_FMT = 0x08,
14840 FLOOR_L = 0x0c,
14841 CVT_PW_PS = 0x1c,
14842 CVT_W = 0x24,
14843 SQRT_FMT = 0x28,
14844 FLOOR_W = 0x2c,
14845 CVT_PS_PW = 0x3c,
14846 CFC1 = 0x40,
14847 RECIP_FMT = 0x48,
14848 CEIL_L = 0x4c,
14849 CTC1 = 0x60,
14850 CEIL_W = 0x6c,
14851 MFC1 = 0x80,
14852 CVT_S_PL = 0x84,
14853 TRUNC_L = 0x8c,
14854 MTC1 = 0xa0,
14855 CVT_S_PU = 0xa4,
14856 TRUNC_W = 0xac,
14857 MFHC1 = 0xc0,
14858 ROUND_L = 0xcc,
14859 MTHC1 = 0xe0,
14860 ROUND_W = 0xec,
14861
14862 MOV_FMT = 0x01,
14863 MOVF = 0x05,
14864 ABS_FMT = 0x0d,
14865 RSQRT1_FMT = 0x1d,
14866 MOVT = 0x25,
14867 NEG_FMT = 0x2d,
14868 CVT_D = 0x4d,
14869 RECIP1_FMT = 0x5d,
14870 CVT_S = 0x6d
14871};
14872
14873/* POOL32I encoding of minor opcode field (bits 25..21) */
14874
14875enum {
14876 BLTZ = 0x00,
14877 BLTZAL = 0x01,
14878 BGEZ = 0x02,
14879 BGEZAL = 0x03,
14880 BLEZ = 0x04,
14881 BNEZC = 0x05,
14882 BGTZ = 0x06,
14883 BEQZC = 0x07,
14884 TLTI = 0x08,
3a1f4268 14885 BC1EQZC = 0x08,
3c824109 14886 TGEI = 0x09,
3a1f4268 14887 BC1NEZC = 0x09,
3c824109 14888 TLTIU = 0x0a,
3a1f4268 14889 BC2EQZC = 0x0a,
3c824109 14890 TGEIU = 0x0b,
3a1f4268 14891 BC2NEZC = 0x0a,
3c824109 14892 TNEI = 0x0c,
3a1f4268 14893 R6_SYNCI = 0x0c,
3c824109
NF
14894 LUI = 0x0d,
14895 TEQI = 0x0e,
14896 SYNCI = 0x10,
14897 BLTZALS = 0x11,
14898 BGEZALS = 0x13,
14899 BC2F = 0x14,
14900 BC2T = 0x15,
14901 BPOSGE64 = 0x1a,
14902 BPOSGE32 = 0x1b,
14903 /* These overlap and are distinguished by bit16 of the instruction */
14904 BC1F = 0x1c,
14905 BC1T = 0x1d,
14906 BC1ANY2F = 0x1c,
14907 BC1ANY2T = 0x1d,
14908 BC1ANY4F = 0x1e,
14909 BC1ANY4T = 0x1f
14910};
14911
14912/* POOL16A encoding of minor opcode field */
14913
14914enum {
14915 ADDU16 = 0x0,
14916 SUBU16 = 0x1
14917};
14918
14919/* POOL16B encoding of minor opcode field */
14920
14921enum {
14922 SLL16 = 0x0,
14923 SRL16 = 0x1
14924};
14925
14926/* POOL16C encoding of minor opcode field */
14927
14928enum {
14929 NOT16 = 0x00,
14930 XOR16 = 0x04,
14931 AND16 = 0x08,
14932 OR16 = 0x0c,
14933 LWM16 = 0x10,
14934 SWM16 = 0x14,
14935 JR16 = 0x18,
14936 JRC16 = 0x1a,
14937 JALR16 = 0x1c,
14938 JALR16S = 0x1e,
14939 MFHI16 = 0x20,
14940 MFLO16 = 0x24,
14941 BREAK16 = 0x28,
14942 SDBBP16 = 0x2c,
14943 JRADDIUSP = 0x30
14944};
14945
3a1f4268
YK
14946/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14947
14948enum {
14949 R6_NOT16 = 0x00,
14950 R6_AND16 = 0x01,
14951 R6_LWM16 = 0x02,
14952 R6_JRC16 = 0x03,
14953 MOVEP = 0x04,
c38a1d52
AR
14954 MOVEP_05 = 0x05,
14955 MOVEP_06 = 0x06,
3a1f4268
YK
14956 MOVEP_07 = 0x07,
14957 R6_XOR16 = 0x08,
14958 R6_OR16 = 0x09,
14959 R6_SWM16 = 0x0a,
14960 JALRC16 = 0x0b,
14961 MOVEP_0C = 0x0c,
c38a1d52
AR
14962 MOVEP_0D = 0x0d,
14963 MOVEP_0E = 0x0e,
3a1f4268
YK
14964 MOVEP_0F = 0x0f,
14965 JRCADDIUSP = 0x13,
14966 R6_BREAK16 = 0x1b,
14967 R6_SDBBP16 = 0x3b
14968};
14969
3c824109
NF
14970/* POOL16D encoding of minor opcode field */
14971
14972enum {
14973 ADDIUS5 = 0x0,
14974 ADDIUSP = 0x1
14975};
14976
14977/* POOL16E encoding of minor opcode field */
14978
14979enum {
14980 ADDIUR2 = 0x0,
14981 ADDIUR1SP = 0x1
14982};
14983
235785e8 14984static int mmreg(int r)
3c824109
NF
14985{
14986 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14987
14988 return map[r];
14989}
14990
14991/* Used for 16-bit store instructions. */
235785e8 14992static int mmreg2(int r)
3c824109
NF
14993{
14994 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14995
14996 return map[r];
14997}
14998
14999#define uMIPS_RD(op) ((op >> 7) & 0x7)
15000#define uMIPS_RS(op) ((op >> 4) & 0x7)
15001#define uMIPS_RS2(op) uMIPS_RS(op)
15002#define uMIPS_RS1(op) ((op >> 1) & 0x7)
15003#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15004#define uMIPS_RS5(op) (op & 0x1f)
15005
15006/* Signed immediate */
15007#define SIMM(op, start, width) \
71375b59
AM
15008 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15009 << (32 - width)) \
15010 >> (32 - width))
3c824109 15011/* Zero-extended immediate */
71375b59 15012#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 15013
d75c135e 15014static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
15015{
15016 int rd = mmreg(uMIPS_RD(ctx->opcode));
15017
d75c135e 15018 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
15019}
15020
d75c135e 15021static void gen_addiur2(DisasContext *ctx)
3c824109
NF
15022{
15023 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15024 int rd = mmreg(uMIPS_RD(ctx->opcode));
15025 int rs = mmreg(uMIPS_RS(ctx->opcode));
15026
d75c135e 15027 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
15028}
15029
d75c135e 15030static void gen_addiusp(DisasContext *ctx)
3c824109
NF
15031{
15032 int encoded = ZIMM(ctx->opcode, 1, 9);
15033 int decoded;
15034
15035 if (encoded <= 1) {
15036 decoded = 256 + encoded;
15037 } else if (encoded <= 255) {
15038 decoded = encoded;
15039 } else if (encoded <= 509) {
15040 decoded = encoded - 512;
15041 } else {
15042 decoded = encoded - 768;
15043 }
15044
d75c135e 15045 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
15046}
15047
d75c135e 15048static void gen_addius5(DisasContext *ctx)
3c824109
NF
15049{
15050 int imm = SIMM(ctx->opcode, 1, 4);
15051 int rd = (ctx->opcode >> 5) & 0x1f;
15052
d75c135e 15053 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
15054}
15055
d75c135e 15056static void gen_andi16(DisasContext *ctx)
3c824109
NF
15057{
15058 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15059 31, 32, 63, 64, 255, 32768, 65535 };
15060 int rd = mmreg(uMIPS_RD(ctx->opcode));
15061 int rs = mmreg(uMIPS_RS(ctx->opcode));
15062 int encoded = ZIMM(ctx->opcode, 0, 4);
15063
d75c135e 15064 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
15065}
15066
235785e8
AM
15067static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15068 int base, int16_t offset)
3c824109
NF
15069{
15070 TCGv t0, t1;
15071 TCGv_i32 t2;
15072
15073 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 15074 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15075 return;
15076 }
15077
15078 t0 = tcg_temp_new();
15079
15080 gen_base_offset_addr(ctx, t0, base, offset);
15081
15082 t1 = tcg_const_tl(reglist);
15083 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 15084
3c824109
NF
15085 save_cpu_state(ctx, 1);
15086 switch (opc) {
15087 case LWM32:
895c2d04 15088 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
15089 break;
15090 case SWM32:
895c2d04 15091 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
15092 break;
15093#ifdef TARGET_MIPS64
15094 case LDM:
895c2d04 15095 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
15096 break;
15097 case SDM:
895c2d04 15098 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 15099 break;
6af0bf9c 15100#endif
3c824109 15101 }
3c824109 15102 tcg_temp_free(t0);
33087598 15103 tcg_temp_free(t1);
3c824109
NF
15104 tcg_temp_free_i32(t2);
15105}
6af0bf9c 15106
3c824109 15107
240ce26a 15108static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 15109{
3c824109
NF
15110 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15111 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 15112
3c824109
NF
15113 switch (((ctx->opcode) >> 4) & 0x3f) {
15114 case NOT16 + 0:
15115 case NOT16 + 1:
15116 case NOT16 + 2:
15117 case NOT16 + 3:
d75c135e 15118 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
15119 break;
15120 case XOR16 + 0:
15121 case XOR16 + 1:
15122 case XOR16 + 2:
15123 case XOR16 + 3:
d75c135e 15124 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
15125 break;
15126 case AND16 + 0:
15127 case AND16 + 1:
15128 case AND16 + 2:
15129 case AND16 + 3:
d75c135e 15130 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
15131 break;
15132 case OR16 + 0:
15133 case OR16 + 1:
15134 case OR16 + 2:
15135 case OR16 + 3:
d75c135e 15136 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
15137 break;
15138 case LWM16 + 0:
15139 case LWM16 + 1:
15140 case LWM16 + 2:
15141 case LWM16 + 3:
15142 {
15143 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15144 int offset = ZIMM(ctx->opcode, 0, 4);
15145
15146 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15147 29, offset << 2);
15148 }
15149 break;
15150 case SWM16 + 0:
15151 case SWM16 + 1:
15152 case SWM16 + 2:
15153 case SWM16 + 3:
15154 {
15155 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15156 int offset = ZIMM(ctx->opcode, 0, 4);
15157
15158 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15159 29, offset << 2);
15160 }
15161 break;
15162 case JR16 + 0:
15163 case JR16 + 1:
15164 {
15165 int reg = ctx->opcode & 0x1f;
15166
b231c103 15167 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15168 }
3c824109
NF
15169 break;
15170 case JRC16 + 0:
15171 case JRC16 + 1:
15172 {
15173 int reg = ctx->opcode & 0x1f;
b231c103 15174 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
15175 /*
15176 * Let normal delay slot handling in our caller take us
15177 * to the branch target.
15178 */
3c824109
NF
15179 }
15180 break;
15181 case JALR16 + 0:
15182 case JALR16 + 1:
b231c103
YK
15183 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15184 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15185 break;
3c824109
NF
15186 case JALR16S + 0:
15187 case JALR16S + 1:
b231c103
YK
15188 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15189 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15190 break;
15191 case MFHI16 + 0:
15192 case MFHI16 + 1:
26135ead 15193 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15194 break;
15195 case MFLO16 + 0:
15196 case MFLO16 + 1:
26135ead 15197 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15198 break;
15199 case BREAK16:
9c708c7f 15200 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15201 break;
15202 case SDBBP16:
3b3c1694
LA
15203 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15204 gen_helper_do_semihosting(cpu_env);
15205 } else {
7480515f
AM
15206 /*
15207 * XXX: not clear which exception should be raised
3b3c1694
LA
15208 * when in debug mode...
15209 */
15210 check_insn(ctx, ISA_MIPS32);
9c708c7f 15211 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15212 }
3c824109
NF
15213 break;
15214 case JRADDIUSP + 0:
15215 case JRADDIUSP + 1:
15216 {
15217 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15218 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15219 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
15220 /*
15221 * Let normal delay slot handling in our caller take us
15222 * to the branch target.
15223 */
3c824109
NF
15224 }
15225 break;
15226 default:
9c708c7f 15227 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15228 break;
15229 }
15230}
15231
ed7ce6c0
YK
15232static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15233 int enc_rs)
15234{
15235 int rd, rs, re, rt;
15236 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15237 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15238 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15239 rd = rd_enc[enc_dest];
15240 re = re_enc[enc_dest];
15241 rs = rs_rt_enc[enc_rs];
15242 rt = rs_rt_enc[enc_rt];
15243 if (rs) {
15244 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15245 } else {
15246 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15247 }
15248 if (rt) {
15249 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15250 } else {
15251 tcg_gen_movi_tl(cpu_gpr[re], 0);
15252 }
15253}
15254
15255static void gen_pool16c_r6_insn(DisasContext *ctx)
15256{
15257 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15258 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15259
15260 switch (ctx->opcode & 0xf) {
15261 case R6_NOT16:
15262 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15263 break;
15264 case R6_AND16:
15265 gen_logic(ctx, OPC_AND, rt, rt, rs);
15266 break;
15267 case R6_LWM16:
15268 {
15269 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15270 int offset = extract32(ctx->opcode, 4, 4);
15271 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15272 }
15273 break;
15274 case R6_JRC16: /* JRCADDIUSP */
15275 if ((ctx->opcode >> 4) & 1) {
15276 /* JRCADDIUSP */
15277 int imm = extract32(ctx->opcode, 5, 5);
15278 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15279 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15280 } else {
15281 /* JRC16 */
e1555d7d 15282 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15283 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15284 }
15285 break;
c38a1d52
AR
15286 case MOVEP:
15287 case MOVEP_05:
15288 case MOVEP_06:
15289 case MOVEP_07:
15290 case MOVEP_0C:
15291 case MOVEP_0D:
15292 case MOVEP_0E:
15293 case MOVEP_0F:
ed7ce6c0
YK
15294 {
15295 int enc_dest = uMIPS_RD(ctx->opcode);
15296 int enc_rt = uMIPS_RS2(ctx->opcode);
15297 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15298 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15299 }
15300 break;
15301 case R6_XOR16:
15302 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15303 break;
15304 case R6_OR16:
15305 gen_logic(ctx, OPC_OR, rt, rt, rs);
15306 break;
15307 case R6_SWM16:
15308 {
15309 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15310 int offset = extract32(ctx->opcode, 4, 4);
15311 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15312 }
15313 break;
15314 case JALRC16: /* BREAK16, SDBBP16 */
15315 switch (ctx->opcode & 0x3f) {
15316 case JALRC16:
15317 case JALRC16 + 0x20:
15318 /* JALRC16 */
15319 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15320 31, 0, 0);
15321 break;
15322 case R6_BREAK16:
15323 /* BREAK16 */
15324 generate_exception(ctx, EXCP_BREAK);
15325 break;
15326 case R6_SDBBP16:
15327 /* SDBBP16 */
060ebfef
LA
15328 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15329 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15330 } else {
060ebfef
LA
15331 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15332 generate_exception(ctx, EXCP_RI);
15333 } else {
15334 generate_exception(ctx, EXCP_DBp);
15335 }
ed7ce6c0
YK
15336 }
15337 break;
15338 }
15339 break;
15340 default:
15341 generate_exception(ctx, EXCP_RI);
15342 break;
15343 }
15344}
15345
235785e8 15346static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
15347{
15348 TCGv t0 = tcg_temp_new();
15349 TCGv t1 = tcg_temp_new();
15350
15351 gen_load_gpr(t0, base);
15352
15353 if (index != 0) {
15354 gen_load_gpr(t1, index);
15355 tcg_gen_shli_tl(t1, t1, 2);
15356 gen_op_addr_add(ctx, t0, t1, t0);
15357 }
15358
5f68f5ae 15359 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15360 gen_store_gpr(t1, rd);
15361
15362 tcg_temp_free(t0);
15363 tcg_temp_free(t1);
15364}
15365
235785e8
AM
15366static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15367 int base, int16_t offset)
3c824109 15368{
3c824109
NF
15369 TCGv t0, t1;
15370
36c6711b 15371 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15372 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15373 return;
15374 }
15375
3c824109
NF
15376 t0 = tcg_temp_new();
15377 t1 = tcg_temp_new();
8e9ade68 15378
3c824109
NF
15379 gen_base_offset_addr(ctx, t0, base, offset);
15380
15381 switch (opc) {
15382 case LWP:
36c6711b 15383 if (rd == base) {
9c708c7f 15384 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15385 return;
15386 }
5f68f5ae 15387 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15388 gen_store_gpr(t1, rd);
15389 tcg_gen_movi_tl(t1, 4);
15390 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15391 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 15392 gen_store_gpr(t1, rd + 1);
3c824109
NF
15393 break;
15394 case SWP:
3c824109 15395 gen_load_gpr(t1, rd);
5f68f5ae 15396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15397 tcg_gen_movi_tl(t1, 4);
15398 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15399 gen_load_gpr(t1, rd + 1);
5f68f5ae 15400 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15401 break;
15402#ifdef TARGET_MIPS64
15403 case LDP:
36c6711b 15404 if (rd == base) {
9c708c7f 15405 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15406 return;
15407 }
5f68f5ae 15408 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15409 gen_store_gpr(t1, rd);
15410 tcg_gen_movi_tl(t1, 8);
15411 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15412 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 15413 gen_store_gpr(t1, rd + 1);
3c824109
NF
15414 break;
15415 case SDP:
3c824109 15416 gen_load_gpr(t1, rd);
5f68f5ae 15417 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15418 tcg_gen_movi_tl(t1, 8);
15419 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 15420 gen_load_gpr(t1, rd + 1);
5f68f5ae 15421 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15422 break;
15423#endif
6af0bf9c 15424 }
3c824109
NF
15425 tcg_temp_free(t0);
15426 tcg_temp_free(t1);
15427}
618b0fe9 15428
d208ac0c
LA
15429static void gen_sync(int stype)
15430{
15431 TCGBar tcg_mo = TCG_BAR_SC;
15432
15433 switch (stype) {
15434 case 0x4: /* SYNC_WMB */
15435 tcg_mo |= TCG_MO_ST_ST;
15436 break;
15437 case 0x10: /* SYNC_MB */
15438 tcg_mo |= TCG_MO_ALL;
15439 break;
15440 case 0x11: /* SYNC_ACQUIRE */
15441 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15442 break;
15443 case 0x12: /* SYNC_RELEASE */
15444 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15445 break;
15446 case 0x13: /* SYNC_RMB */
15447 tcg_mo |= TCG_MO_LD_LD;
15448 break;
15449 default:
15450 tcg_mo |= TCG_MO_ALL;
15451 break;
15452 }
15453
15454 tcg_gen_mb(tcg_mo);
15455}
15456
235785e8 15457static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
15458{
15459 int extension = (ctx->opcode >> 6) & 0x3f;
15460 int minor = (ctx->opcode >> 12) & 0xf;
15461 uint32_t mips32_op;
15462
15463 switch (extension) {
15464 case TEQ:
15465 mips32_op = OPC_TEQ;
15466 goto do_trap;
15467 case TGE:
15468 mips32_op = OPC_TGE;
15469 goto do_trap;
15470 case TGEU:
15471 mips32_op = OPC_TGEU;
15472 goto do_trap;
15473 case TLT:
15474 mips32_op = OPC_TLT;
15475 goto do_trap;
15476 case TLTU:
15477 mips32_op = OPC_TLTU;
15478 goto do_trap;
15479 case TNE:
15480 mips32_op = OPC_TNE;
15481 do_trap:
15482 gen_trap(ctx, mips32_op, rs, rt, -1);
15483 break;
15484#ifndef CONFIG_USER_ONLY
15485 case MFC0:
15486 case MFC0 + 32:
2e15497c 15487 check_cp0_enabled(ctx);
3c824109
NF
15488 if (rt == 0) {
15489 /* Treat as NOP. */
15490 break;
15491 }
d75c135e 15492 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15493 break;
15494 case MTC0:
15495 case MTC0 + 32:
2e15497c 15496 check_cp0_enabled(ctx);
3c824109
NF
15497 {
15498 TCGv t0 = tcg_temp_new();
618b0fe9 15499
3c824109 15500 gen_load_gpr(t0, rt);
d75c135e 15501 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15502 tcg_temp_free(t0);
15503 }
15504 break;
15505#endif
a1fc6246
LA
15506 case 0x2a:
15507 switch (minor & 3) {
15508 case MADD_ACC:
15509 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15510 break;
15511 case MADDU_ACC:
15512 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15513 break;
15514 case MSUB_ACC:
15515 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15516 break;
15517 case MSUBU_ACC:
15518 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15519 break;
15520 default:
15521 goto pool32axf_invalid;
15522 }
15523 break;
15524 case 0x32:
15525 switch (minor & 3) {
15526 case MULT_ACC:
15527 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15528 break;
15529 case MULTU_ACC:
15530 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15531 break;
15532 default:
15533 goto pool32axf_invalid;
15534 }
15535 break;
3c824109
NF
15536 case 0x2c:
15537 switch (minor) {
e0332095
YK
15538 case BITSWAP:
15539 check_insn(ctx, ISA_MIPS32R6);
15540 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15541 break;
3c824109
NF
15542 case SEB:
15543 gen_bshfl(ctx, OPC_SEB, rs, rt);
15544 break;
15545 case SEH:
15546 gen_bshfl(ctx, OPC_SEH, rs, rt);
15547 break;
15548 case CLO:
15549 mips32_op = OPC_CLO;
15550 goto do_cl;
15551 case CLZ:
15552 mips32_op = OPC_CLZ;
15553 do_cl:
d75c135e 15554 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15555 gen_cl(ctx, mips32_op, rt, rs);
15556 break;
15557 case RDHWR:
b00c7218
YK
15558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15559 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15560 break;
15561 case WSBH:
15562 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15563 break;
15564 case MULT:
9e8f441a 15565 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15566 mips32_op = OPC_MULT;
26135ead 15567 goto do_mul;
3c824109 15568 case MULTU:
9e8f441a 15569 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15570 mips32_op = OPC_MULTU;
26135ead 15571 goto do_mul;
3c824109 15572 case DIV:
9e8f441a 15573 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15574 mips32_op = OPC_DIV;
26135ead 15575 goto do_div;
3c824109 15576 case DIVU:
9e8f441a 15577 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15578 mips32_op = OPC_DIVU;
26135ead
RS
15579 goto do_div;
15580 do_div:
15581 check_insn(ctx, ISA_MIPS32);
15582 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15583 break;
3c824109 15584 case MADD:
9e8f441a 15585 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15586 mips32_op = OPC_MADD;
26135ead 15587 goto do_mul;
3c824109 15588 case MADDU:
9e8f441a 15589 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15590 mips32_op = OPC_MADDU;
26135ead 15591 goto do_mul;
3c824109 15592 case MSUB:
9e8f441a 15593 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15594 mips32_op = OPC_MSUB;
26135ead 15595 goto do_mul;
3c824109 15596 case MSUBU:
9e8f441a 15597 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15598 mips32_op = OPC_MSUBU;
26135ead 15599 do_mul:
d75c135e 15600 check_insn(ctx, ISA_MIPS32);
a1fc6246 15601 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15602 break;
15603 default:
15604 goto pool32axf_invalid;
15605 }
15606 break;
15607 case 0x34:
15608 switch (minor) {
15609 case MFC2:
15610 case MTC2:
15611 case MFHC2:
15612 case MTHC2:
15613 case CFC2:
15614 case CTC2:
15615 generate_exception_err(ctx, EXCP_CpU, 2);
15616 break;
15617 default:
15618 goto pool32axf_invalid;
15619 }
15620 break;
15621 case 0x3c:
15622 switch (minor) {
65935f07
YK
15623 case JALR: /* JALRC */
15624 case JALR_HB: /* JALRC_HB */
15625 if (ctx->insn_flags & ISA_MIPS32R6) {
15626 /* JALRC, JALRC_HB */
15627 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15628 } else {
15629 /* JALR, JALR_HB */
15630 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15631 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15632 }
3c824109
NF
15633 break;
15634 case JALRS:
15635 case JALRS_HB:
9e8f441a 15636 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15637 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15638 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15639 break;
15640 default:
15641 goto pool32axf_invalid;
15642 }
15643 break;
15644 case 0x05:
15645 switch (minor) {
15646 case RDPGPR:
2e15497c 15647 check_cp0_enabled(ctx);
d75c135e 15648 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15649 gen_load_srsgpr(rs, rt);
3c824109
NF
15650 break;
15651 case WRPGPR:
2e15497c 15652 check_cp0_enabled(ctx);
d75c135e 15653 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15654 gen_store_srsgpr(rs, rt);
3c824109
NF
15655 break;
15656 default:
15657 goto pool32axf_invalid;
15658 }
15659 break;
15660#ifndef CONFIG_USER_ONLY
15661 case 0x0d:
15662 switch (minor) {
15663 case TLBP:
15664 mips32_op = OPC_TLBP;
15665 goto do_cp0;
15666 case TLBR:
15667 mips32_op = OPC_TLBR;
15668 goto do_cp0;
15669 case TLBWI:
15670 mips32_op = OPC_TLBWI;
15671 goto do_cp0;
15672 case TLBWR:
15673 mips32_op = OPC_TLBWR;
15674 goto do_cp0;
e60ec063
YK
15675 case TLBINV:
15676 mips32_op = OPC_TLBINV;
15677 goto do_cp0;
15678 case TLBINVF:
15679 mips32_op = OPC_TLBINVF;
15680 goto do_cp0;
3c824109
NF
15681 case WAIT:
15682 mips32_op = OPC_WAIT;
15683 goto do_cp0;
15684 case DERET:
15685 mips32_op = OPC_DERET;
15686 goto do_cp0;
15687 case ERET:
15688 mips32_op = OPC_ERET;
15689 do_cp0:
15690 gen_cp0(env, ctx, mips32_op, rt, rs);
15691 break;
15692 default:
15693 goto pool32axf_invalid;
15694 }
15695 break;
15696 case 0x1d:
15697 switch (minor) {
15698 case DI:
2e15497c 15699 check_cp0_enabled(ctx);
3c824109
NF
15700 {
15701 TCGv t0 = tcg_temp_new();
15702
15703 save_cpu_state(ctx, 1);
895c2d04 15704 gen_helper_di(t0, cpu_env);
3c824109 15705 gen_store_gpr(t0, rs);
71375b59
AM
15706 /*
15707 * Stop translation as we may have switched the execution
15708 * mode.
15709 */
eeb3bba8 15710 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15711 tcg_temp_free(t0);
15712 }
15713 break;
15714 case EI:
2e15497c 15715 check_cp0_enabled(ctx);
3c824109
NF
15716 {
15717 TCGv t0 = tcg_temp_new();
15718
15719 save_cpu_state(ctx, 1);
895c2d04 15720 gen_helper_ei(t0, cpu_env);
3c824109 15721 gen_store_gpr(t0, rs);
7480515f
AM
15722 /*
15723 * DISAS_STOP isn't sufficient, we need to ensure we break out
15724 * of translated code to check for pending interrupts.
15725 */
eeb3bba8
EC
15726 gen_save_pc(ctx->base.pc_next + 4);
15727 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15728 tcg_temp_free(t0);
15729 }
15730 break;
15731 default:
15732 goto pool32axf_invalid;
15733 }
15734 break;
15735#endif
15736 case 0x2d:
15737 switch (minor) {
15738 case SYNC:
d208ac0c 15739 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15740 break;
15741 case SYSCALL:
9c708c7f 15742 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15743 break;
15744 case SDBBP:
3b3c1694
LA
15745 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15746 gen_helper_do_semihosting(cpu_env);
15747 } else {
15748 check_insn(ctx, ISA_MIPS32);
e0332095 15749 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15750 generate_exception_end(ctx, EXCP_RI);
e0332095 15751 } else {
9c708c7f 15752 generate_exception_end(ctx, EXCP_DBp);
e0332095 15753 }
3b3c1694 15754 }
3c824109
NF
15755 break;
15756 default:
15757 goto pool32axf_invalid;
15758 }
15759 break;
a1fc6246 15760 case 0x01:
26135ead 15761 switch (minor & 3) {
a1fc6246 15762 case MFHI_ACC:
26135ead 15763 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15764 break;
a1fc6246 15765 case MFLO_ACC:
26135ead 15766 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15767 break;
a1fc6246 15768 case MTHI_ACC:
26135ead 15769 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15770 break;
a1fc6246 15771 case MTLO_ACC:
26135ead 15772 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15773 break;
15774 default:
15775 goto pool32axf_invalid;
15776 }
15777 break;
a1fc6246 15778 case 0x35:
9e8f441a 15779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15780 switch (minor) {
15781 case MFHI32:
15782 gen_HILO(ctx, OPC_MFHI, 0, rs);
15783 break;
15784 case MFLO32:
15785 gen_HILO(ctx, OPC_MFLO, 0, rs);
15786 break;
15787 case MTHI32:
15788 gen_HILO(ctx, OPC_MTHI, 0, rs);
15789 break;
15790 case MTLO32:
15791 gen_HILO(ctx, OPC_MTLO, 0, rs);
15792 break;
15793 default:
15794 goto pool32axf_invalid;
15795 }
15796 break;
3c824109
NF
15797 default:
15798 pool32axf_invalid:
15799 MIPS_INVAL("pool32axf");
9c708c7f 15800 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15801 break;
15802 }
15803}
15804
7480515f
AM
15805/*
15806 * Values for microMIPS fmt field. Variable-width, depending on which
15807 * formats the instruction supports.
15808 */
3c824109
NF
15809enum {
15810 FMT_SD_S = 0,
15811 FMT_SD_D = 1,
15812
15813 FMT_SDPS_S = 0,
15814 FMT_SDPS_D = 1,
15815 FMT_SDPS_PS = 2,
15816
15817 FMT_SWL_S = 0,
15818 FMT_SWL_W = 1,
15819 FMT_SWL_L = 2,
15820
15821 FMT_DWL_D = 0,
15822 FMT_DWL_W = 1,
15823 FMT_DWL_L = 2
15824};
15825
d75c135e 15826static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
15827{
15828 int extension = (ctx->opcode >> 6) & 0x3ff;
15829 uint32_t mips32_op;
15830
71375b59
AM
15831#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15832#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15833#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
15834
15835 switch (extension) {
15836 case FLOAT_1BIT_FMT(CFC1, 0):
15837 mips32_op = OPC_CFC1;
15838 goto do_cp1;
15839 case FLOAT_1BIT_FMT(CTC1, 0):
15840 mips32_op = OPC_CTC1;
15841 goto do_cp1;
15842 case FLOAT_1BIT_FMT(MFC1, 0):
15843 mips32_op = OPC_MFC1;
15844 goto do_cp1;
15845 case FLOAT_1BIT_FMT(MTC1, 0):
15846 mips32_op = OPC_MTC1;
15847 goto do_cp1;
15848 case FLOAT_1BIT_FMT(MFHC1, 0):
15849 mips32_op = OPC_MFHC1;
15850 goto do_cp1;
15851 case FLOAT_1BIT_FMT(MTHC1, 0):
15852 mips32_op = OPC_MTHC1;
15853 do_cp1:
15854 gen_cp1(ctx, mips32_op, rt, rs);
15855 break;
15856
15857 /* Reciprocal square root */
15858 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15859 mips32_op = OPC_RSQRT_S;
15860 goto do_unaryfp;
15861 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15862 mips32_op = OPC_RSQRT_D;
15863 goto do_unaryfp;
15864
15865 /* Square root */
15866 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15867 mips32_op = OPC_SQRT_S;
15868 goto do_unaryfp;
15869 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15870 mips32_op = OPC_SQRT_D;
15871 goto do_unaryfp;
15872
15873 /* Reciprocal */
15874 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15875 mips32_op = OPC_RECIP_S;
15876 goto do_unaryfp;
15877 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15878 mips32_op = OPC_RECIP_D;
15879 goto do_unaryfp;
15880
15881 /* Floor */
15882 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15883 mips32_op = OPC_FLOOR_L_S;
15884 goto do_unaryfp;
15885 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15886 mips32_op = OPC_FLOOR_L_D;
15887 goto do_unaryfp;
15888 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15889 mips32_op = OPC_FLOOR_W_S;
15890 goto do_unaryfp;
15891 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15892 mips32_op = OPC_FLOOR_W_D;
15893 goto do_unaryfp;
15894
15895 /* Ceiling */
15896 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15897 mips32_op = OPC_CEIL_L_S;
15898 goto do_unaryfp;
15899 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15900 mips32_op = OPC_CEIL_L_D;
15901 goto do_unaryfp;
15902 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15903 mips32_op = OPC_CEIL_W_S;
15904 goto do_unaryfp;
15905 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15906 mips32_op = OPC_CEIL_W_D;
15907 goto do_unaryfp;
15908
15909 /* Truncation */
15910 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15911 mips32_op = OPC_TRUNC_L_S;
15912 goto do_unaryfp;
15913 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15914 mips32_op = OPC_TRUNC_L_D;
15915 goto do_unaryfp;
15916 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15917 mips32_op = OPC_TRUNC_W_S;
15918 goto do_unaryfp;
15919 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15920 mips32_op = OPC_TRUNC_W_D;
15921 goto do_unaryfp;
15922
15923 /* Round */
15924 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15925 mips32_op = OPC_ROUND_L_S;
15926 goto do_unaryfp;
15927 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15928 mips32_op = OPC_ROUND_L_D;
15929 goto do_unaryfp;
15930 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15931 mips32_op = OPC_ROUND_W_S;
15932 goto do_unaryfp;
15933 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15934 mips32_op = OPC_ROUND_W_D;
15935 goto do_unaryfp;
15936
15937 /* Integer to floating-point conversion */
15938 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15939 mips32_op = OPC_CVT_L_S;
15940 goto do_unaryfp;
15941 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15942 mips32_op = OPC_CVT_L_D;
15943 goto do_unaryfp;
15944 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15945 mips32_op = OPC_CVT_W_S;
15946 goto do_unaryfp;
15947 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15948 mips32_op = OPC_CVT_W_D;
15949 goto do_unaryfp;
15950
15951 /* Paired-foo conversions */
15952 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15953 mips32_op = OPC_CVT_S_PL;
15954 goto do_unaryfp;
15955 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15956 mips32_op = OPC_CVT_S_PU;
15957 goto do_unaryfp;
15958 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15959 mips32_op = OPC_CVT_PW_PS;
15960 goto do_unaryfp;
15961 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15962 mips32_op = OPC_CVT_PS_PW;
15963 goto do_unaryfp;
15964
15965 /* Floating-point moves */
15966 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15967 mips32_op = OPC_MOV_S;
15968 goto do_unaryfp;
15969 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15970 mips32_op = OPC_MOV_D;
15971 goto do_unaryfp;
15972 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15973 mips32_op = OPC_MOV_PS;
15974 goto do_unaryfp;
15975
15976 /* Absolute value */
15977 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15978 mips32_op = OPC_ABS_S;
15979 goto do_unaryfp;
15980 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15981 mips32_op = OPC_ABS_D;
15982 goto do_unaryfp;
15983 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15984 mips32_op = OPC_ABS_PS;
15985 goto do_unaryfp;
15986
15987 /* Negation */
15988 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15989 mips32_op = OPC_NEG_S;
15990 goto do_unaryfp;
15991 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15992 mips32_op = OPC_NEG_D;
15993 goto do_unaryfp;
15994 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15995 mips32_op = OPC_NEG_PS;
15996 goto do_unaryfp;
15997
15998 /* Reciprocal square root step */
15999 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16000 mips32_op = OPC_RSQRT1_S;
16001 goto do_unaryfp;
16002 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16003 mips32_op = OPC_RSQRT1_D;
16004 goto do_unaryfp;
16005 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16006 mips32_op = OPC_RSQRT1_PS;
16007 goto do_unaryfp;
16008
16009 /* Reciprocal step */
16010 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16011 mips32_op = OPC_RECIP1_S;
16012 goto do_unaryfp;
16013 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16014 mips32_op = OPC_RECIP1_S;
16015 goto do_unaryfp;
16016 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16017 mips32_op = OPC_RECIP1_PS;
16018 goto do_unaryfp;
16019
16020 /* Conversions from double */
16021 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16022 mips32_op = OPC_CVT_D_S;
16023 goto do_unaryfp;
16024 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16025 mips32_op = OPC_CVT_D_W;
16026 goto do_unaryfp;
16027 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16028 mips32_op = OPC_CVT_D_L;
16029 goto do_unaryfp;
16030
16031 /* Conversions from single */
16032 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16033 mips32_op = OPC_CVT_S_D;
16034 goto do_unaryfp;
16035 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16036 mips32_op = OPC_CVT_S_W;
16037 goto do_unaryfp;
16038 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16039 mips32_op = OPC_CVT_S_L;
16040 do_unaryfp:
16041 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16042 break;
16043
16044 /* Conditional moves on floating-point codes */
16045 case COND_FLOAT_MOV(MOVT, 0):
16046 case COND_FLOAT_MOV(MOVT, 1):
16047 case COND_FLOAT_MOV(MOVT, 2):
16048 case COND_FLOAT_MOV(MOVT, 3):
16049 case COND_FLOAT_MOV(MOVT, 4):
16050 case COND_FLOAT_MOV(MOVT, 5):
16051 case COND_FLOAT_MOV(MOVT, 6):
16052 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 16053 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16054 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16055 break;
16056 case COND_FLOAT_MOV(MOVF, 0):
16057 case COND_FLOAT_MOV(MOVF, 1):
16058 case COND_FLOAT_MOV(MOVF, 2):
16059 case COND_FLOAT_MOV(MOVF, 3):
16060 case COND_FLOAT_MOV(MOVF, 4):
16061 case COND_FLOAT_MOV(MOVF, 5):
16062 case COND_FLOAT_MOV(MOVF, 6):
16063 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 16064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16065 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16066 break;
16067 default:
16068 MIPS_INVAL("pool32fxf");
9c708c7f 16069 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16070 break;
16071 }
16072}
16073
f60eeb0c 16074static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16075{
16076 int32_t offset;
16077 uint16_t insn;
16078 int rt, rs, rd, rr;
16079 int16_t imm;
8fffc646 16080 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
16081 uint32_t cond, fmt, cc;
16082
eeb3bba8 16083 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
16084 ctx->opcode = (ctx->opcode << 16) | insn;
16085
16086 rt = (ctx->opcode >> 21) & 0x1f;
16087 rs = (ctx->opcode >> 16) & 0x1f;
16088 rd = (ctx->opcode >> 11) & 0x1f;
16089 rr = (ctx->opcode >> 6) & 0x1f;
16090 imm = (int16_t) ctx->opcode;
16091
16092 op = (ctx->opcode >> 26) & 0x3f;
16093 switch (op) {
16094 case POOL32A:
16095 minor = ctx->opcode & 0x3f;
16096 switch (minor) {
16097 case 0x00:
16098 minor = (ctx->opcode >> 6) & 0xf;
16099 switch (minor) {
16100 case SLL32:
16101 mips32_op = OPC_SLL;
16102 goto do_shifti;
16103 case SRA:
16104 mips32_op = OPC_SRA;
16105 goto do_shifti;
16106 case SRL32:
16107 mips32_op = OPC_SRL;
16108 goto do_shifti;
16109 case ROTR:
16110 mips32_op = OPC_ROTR;
16111 do_shifti:
d75c135e 16112 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 16113 break;
e0332095
YK
16114 case SELEQZ:
16115 check_insn(ctx, ISA_MIPS32R6);
16116 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16117 break;
16118 case SELNEZ:
16119 check_insn(ctx, ISA_MIPS32R6);
16120 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16121 break;
b00c7218
YK
16122 case R6_RDHWR:
16123 check_insn(ctx, ISA_MIPS32R6);
16124 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16125 break;
3c824109
NF
16126 default:
16127 goto pool32a_invalid;
16128 }
16129 break;
16130 case 0x10:
16131 minor = (ctx->opcode >> 6) & 0xf;
16132 switch (minor) {
16133 /* Arithmetic */
16134 case ADD:
16135 mips32_op = OPC_ADD;
16136 goto do_arith;
16137 case ADDU32:
16138 mips32_op = OPC_ADDU;
16139 goto do_arith;
16140 case SUB:
16141 mips32_op = OPC_SUB;
16142 goto do_arith;
16143 case SUBU32:
16144 mips32_op = OPC_SUBU;
16145 goto do_arith;
16146 case MUL:
9e8f441a 16147 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16148 mips32_op = OPC_MUL;
16149 do_arith:
d75c135e 16150 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16151 break;
16152 /* Shifts */
16153 case SLLV:
16154 mips32_op = OPC_SLLV;
16155 goto do_shift;
16156 case SRLV:
16157 mips32_op = OPC_SRLV;
16158 goto do_shift;
16159 case SRAV:
16160 mips32_op = OPC_SRAV;
16161 goto do_shift;
16162 case ROTRV:
16163 mips32_op = OPC_ROTRV;
16164 do_shift:
d75c135e 16165 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16166 break;
16167 /* Logical operations */
16168 case AND:
16169 mips32_op = OPC_AND;
16170 goto do_logic;
16171 case OR32:
16172 mips32_op = OPC_OR;
16173 goto do_logic;
16174 case NOR:
16175 mips32_op = OPC_NOR;
16176 goto do_logic;
16177 case XOR32:
16178 mips32_op = OPC_XOR;
16179 do_logic:
d75c135e 16180 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16181 break;
16182 /* Set less than */
16183 case SLT:
16184 mips32_op = OPC_SLT;
16185 goto do_slt;
16186 case SLTU:
16187 mips32_op = OPC_SLTU;
16188 do_slt:
d75c135e 16189 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16190 break;
16191 default:
16192 goto pool32a_invalid;
16193 }
16194 break;
16195 case 0x18:
16196 minor = (ctx->opcode >> 6) & 0xf;
16197 switch (minor) {
16198 /* Conditional moves */
e0332095
YK
16199 case MOVN: /* MUL */
16200 if (ctx->insn_flags & ISA_MIPS32R6) {
16201 /* MUL */
16202 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16203 } else {
16204 /* MOVN */
16205 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16206 }
16207 break;
16208 case MOVZ: /* MUH */
16209 if (ctx->insn_flags & ISA_MIPS32R6) {
16210 /* MUH */
16211 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16212 } else {
16213 /* MOVZ */
16214 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16215 }
16216 break;
16217 case MULU:
16218 check_insn(ctx, ISA_MIPS32R6);
16219 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16220 break;
16221 case MUHU:
16222 check_insn(ctx, ISA_MIPS32R6);
16223 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16224 break;
16225 case LWXS: /* DIV */
16226 if (ctx->insn_flags & ISA_MIPS32R6) {
16227 /* DIV */
16228 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16229 } else {
16230 /* LWXS */
16231 gen_ldxs(ctx, rs, rt, rd);
16232 }
16233 break;
16234 case MOD:
16235 check_insn(ctx, ISA_MIPS32R6);
16236 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16237 break;
16238 case R6_DIVU:
16239 check_insn(ctx, ISA_MIPS32R6);
16240 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16241 break;
e0332095
YK
16242 case MODU:
16243 check_insn(ctx, ISA_MIPS32R6);
16244 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16245 break;
16246 default:
16247 goto pool32a_invalid;
16248 }
16249 break;
16250 case INS:
16251 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16252 return;
e0332095
YK
16253 case LSA:
16254 check_insn(ctx, ISA_MIPS32R6);
16255 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16256 extract32(ctx->opcode, 9, 2));
16257 break;
16258 case ALIGN:
16259 check_insn(ctx, ISA_MIPS32R6);
821f2008 16260 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16261 break;
3c824109
NF
16262 case EXT:
16263 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16264 return;
16265 case POOL32AXF:
240ce26a 16266 gen_pool32axf(env, ctx, rt, rs);
3c824109 16267 break;
dbd8af98 16268 case BREAK32:
9c708c7f 16269 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16270 break;
bb238210
YK
16271 case SIGRIE:
16272 check_insn(ctx, ISA_MIPS32R6);
16273 generate_exception_end(ctx, EXCP_RI);
16274 break;
3c824109
NF
16275 default:
16276 pool32a_invalid:
16277 MIPS_INVAL("pool32a");
9c708c7f 16278 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16279 break;
16280 }
16281 break;
16282 case POOL32B:
16283 minor = (ctx->opcode >> 12) & 0xf;
16284 switch (minor) {
16285 case CACHE:
2e15497c 16286 check_cp0_enabled(ctx);
0d74a222
LA
16287 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16288 gen_cache_operation(ctx, rt, rs, imm);
16289 }
3c824109
NF
16290 break;
16291 case LWC2:
16292 case SWC2:
16293 /* COP2: Not implemented. */
16294 generate_exception_err(ctx, EXCP_CpU, 2);
16295 break;
3c824109
NF
16296#ifdef TARGET_MIPS64
16297 case LDP:
16298 case SDP:
d9224450
MR
16299 check_insn(ctx, ISA_MIPS3);
16300 check_mips_64(ctx);
3c824109 16301#endif
146dd620 16302 /* fall through */
d9224450
MR
16303 case LWP:
16304 case SWP:
3c824109
NF
16305 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16306 break;
3c824109
NF
16307#ifdef TARGET_MIPS64
16308 case LDM:
16309 case SDM:
d9224450
MR
16310 check_insn(ctx, ISA_MIPS3);
16311 check_mips_64(ctx);
3c824109 16312#endif
146dd620 16313 /* fall through */
d9224450
MR
16314 case LWM32:
16315 case SWM32:
3c824109
NF
16316 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16317 break;
16318 default:
16319 MIPS_INVAL("pool32b");
9c708c7f 16320 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16321 break;
16322 }
16323 break;
16324 case POOL32F:
5ab5c041 16325 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16326 minor = ctx->opcode & 0x3f;
16327 check_cp1_enabled(ctx);
16328 switch (minor) {
16329 case ALNV_PS:
9e8f441a 16330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16331 mips32_op = OPC_ALNV_PS;
16332 goto do_madd;
16333 case MADD_S:
9e8f441a 16334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16335 mips32_op = OPC_MADD_S;
16336 goto do_madd;
16337 case MADD_D:
9e8f441a 16338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16339 mips32_op = OPC_MADD_D;
16340 goto do_madd;
16341 case MADD_PS:
9e8f441a 16342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16343 mips32_op = OPC_MADD_PS;
16344 goto do_madd;
16345 case MSUB_S:
9e8f441a 16346 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16347 mips32_op = OPC_MSUB_S;
16348 goto do_madd;
16349 case MSUB_D:
9e8f441a 16350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16351 mips32_op = OPC_MSUB_D;
16352 goto do_madd;
16353 case MSUB_PS:
9e8f441a 16354 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16355 mips32_op = OPC_MSUB_PS;
16356 goto do_madd;
16357 case NMADD_S:
9e8f441a 16358 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16359 mips32_op = OPC_NMADD_S;
16360 goto do_madd;
16361 case NMADD_D:
9e8f441a 16362 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16363 mips32_op = OPC_NMADD_D;
16364 goto do_madd;
16365 case NMADD_PS:
9e8f441a 16366 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16367 mips32_op = OPC_NMADD_PS;
16368 goto do_madd;
16369 case NMSUB_S:
9e8f441a 16370 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16371 mips32_op = OPC_NMSUB_S;
16372 goto do_madd;
16373 case NMSUB_D:
9e8f441a 16374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16375 mips32_op = OPC_NMSUB_D;
16376 goto do_madd;
16377 case NMSUB_PS:
9e8f441a 16378 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16379 mips32_op = OPC_NMSUB_PS;
16380 do_madd:
16381 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16382 break;
16383 case CABS_COND_FMT:
9e8f441a 16384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16385 cond = (ctx->opcode >> 6) & 0xf;
16386 cc = (ctx->opcode >> 13) & 0x7;
16387 fmt = (ctx->opcode >> 10) & 0x3;
16388 switch (fmt) {
16389 case 0x0:
16390 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16391 break;
16392 case 0x1:
16393 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16394 break;
16395 case 0x2:
16396 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16397 break;
16398 default:
16399 goto pool32f_invalid;
16400 }
16401 break;
16402 case C_COND_FMT:
9e8f441a 16403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16404 cond = (ctx->opcode >> 6) & 0xf;
16405 cc = (ctx->opcode >> 13) & 0x7;
16406 fmt = (ctx->opcode >> 10) & 0x3;
16407 switch (fmt) {
16408 case 0x0:
16409 gen_cmp_s(ctx, cond, rt, rs, cc);
16410 break;
16411 case 0x1:
16412 gen_cmp_d(ctx, cond, rt, rs, cc);
16413 break;
16414 case 0x2:
16415 gen_cmp_ps(ctx, cond, rt, rs, cc);
16416 break;
16417 default:
16418 goto pool32f_invalid;
16419 }
16420 break;
2a24a7ba
YK
16421 case CMP_CONDN_S:
16422 check_insn(ctx, ISA_MIPS32R6);
16423 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16424 break;
16425 case CMP_CONDN_D:
16426 check_insn(ctx, ISA_MIPS32R6);
16427 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16428 break;
3c824109 16429 case POOL32FXF:
d75c135e 16430 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
16431 break;
16432 case 0x00:
16433 /* PLL foo */
16434 switch ((ctx->opcode >> 6) & 0x7) {
16435 case PLL_PS:
16436 mips32_op = OPC_PLL_PS;
16437 goto do_ps;
16438 case PLU_PS:
16439 mips32_op = OPC_PLU_PS;
16440 goto do_ps;
16441 case PUL_PS:
16442 mips32_op = OPC_PUL_PS;
16443 goto do_ps;
16444 case PUU_PS:
16445 mips32_op = OPC_PUU_PS;
16446 goto do_ps;
16447 case CVT_PS_S:
9e8f441a 16448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16449 mips32_op = OPC_CVT_PS_S;
16450 do_ps:
16451 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16452 break;
16453 default:
16454 goto pool32f_invalid;
16455 }
16456 break;
2a24a7ba
YK
16457 case MIN_FMT:
16458 check_insn(ctx, ISA_MIPS32R6);
16459 switch ((ctx->opcode >> 9) & 0x3) {
16460 case FMT_SDPS_S:
16461 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16462 break;
16463 case FMT_SDPS_D:
16464 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16465 break;
16466 default:
16467 goto pool32f_invalid;
16468 }
16469 break;
3c824109
NF
16470 case 0x08:
16471 /* [LS][WDU]XC1 */
16472 switch ((ctx->opcode >> 6) & 0x7) {
16473 case LWXC1:
9e8f441a 16474 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16475 mips32_op = OPC_LWXC1;
16476 goto do_ldst_cp1;
16477 case SWXC1:
9e8f441a 16478 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16479 mips32_op = OPC_SWXC1;
16480 goto do_ldst_cp1;
16481 case LDXC1:
9e8f441a 16482 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16483 mips32_op = OPC_LDXC1;
16484 goto do_ldst_cp1;
16485 case SDXC1:
9e8f441a 16486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16487 mips32_op = OPC_SDXC1;
16488 goto do_ldst_cp1;
16489 case LUXC1:
9e8f441a 16490 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16491 mips32_op = OPC_LUXC1;
16492 goto do_ldst_cp1;
16493 case SUXC1:
9e8f441a 16494 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16495 mips32_op = OPC_SUXC1;
16496 do_ldst_cp1:
16497 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16498 break;
16499 default:
16500 goto pool32f_invalid;
16501 }
16502 break;
2a24a7ba
YK
16503 case MAX_FMT:
16504 check_insn(ctx, ISA_MIPS32R6);
16505 switch ((ctx->opcode >> 9) & 0x3) {
16506 case FMT_SDPS_S:
16507 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16508 break;
16509 case FMT_SDPS_D:
16510 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16511 break;
16512 default:
16513 goto pool32f_invalid;
16514 }
16515 break;
3c824109
NF
16516 case 0x18:
16517 /* 3D insns */
9e8f441a 16518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16519 fmt = (ctx->opcode >> 9) & 0x3;
16520 switch ((ctx->opcode >> 6) & 0x7) {
16521 case RSQRT2_FMT:
16522 switch (fmt) {
16523 case FMT_SDPS_S:
16524 mips32_op = OPC_RSQRT2_S;
16525 goto do_3d;
16526 case FMT_SDPS_D:
16527 mips32_op = OPC_RSQRT2_D;
16528 goto do_3d;
16529 case FMT_SDPS_PS:
16530 mips32_op = OPC_RSQRT2_PS;
16531 goto do_3d;
16532 default:
16533 goto pool32f_invalid;
16534 }
16535 break;
16536 case RECIP2_FMT:
16537 switch (fmt) {
16538 case FMT_SDPS_S:
16539 mips32_op = OPC_RECIP2_S;
16540 goto do_3d;
16541 case FMT_SDPS_D:
16542 mips32_op = OPC_RECIP2_D;
16543 goto do_3d;
16544 case FMT_SDPS_PS:
16545 mips32_op = OPC_RECIP2_PS;
16546 goto do_3d;
16547 default:
16548 goto pool32f_invalid;
16549 }
16550 break;
16551 case ADDR_PS:
16552 mips32_op = OPC_ADDR_PS;
16553 goto do_3d;
16554 case MULR_PS:
16555 mips32_op = OPC_MULR_PS;
16556 do_3d:
16557 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16558 break;
16559 default:
16560 goto pool32f_invalid;
16561 }
16562 break;
16563 case 0x20:
2a24a7ba 16564 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16565 cc = (ctx->opcode >> 13) & 0x7;
16566 fmt = (ctx->opcode >> 9) & 0x3;
16567 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16568 case MOVF_FMT: /* RINT_FMT */
16569 if (ctx->insn_flags & ISA_MIPS32R6) {
16570 /* RINT_FMT */
16571 switch (fmt) {
16572 case FMT_SDPS_S:
16573 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16574 break;
16575 case FMT_SDPS_D:
16576 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16577 break;
16578 default:
16579 goto pool32f_invalid;
16580 }
16581 } else {
16582 /* MOVF_FMT */
16583 switch (fmt) {
16584 case FMT_SDPS_S:
16585 gen_movcf_s(ctx, rs, rt, cc, 0);
16586 break;
16587 case FMT_SDPS_D:
16588 gen_movcf_d(ctx, rs, rt, cc, 0);
16589 break;
16590 case FMT_SDPS_PS:
16591 check_ps(ctx);
16592 gen_movcf_ps(ctx, rs, rt, cc, 0);
16593 break;
16594 default:
16595 goto pool32f_invalid;
16596 }
3c824109
NF
16597 }
16598 break;
2a24a7ba
YK
16599 case MOVT_FMT: /* CLASS_FMT */
16600 if (ctx->insn_flags & ISA_MIPS32R6) {
16601 /* CLASS_FMT */
16602 switch (fmt) {
16603 case FMT_SDPS_S:
16604 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16605 break;
16606 case FMT_SDPS_D:
16607 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16608 break;
16609 default:
16610 goto pool32f_invalid;
16611 }
16612 } else {
16613 /* MOVT_FMT */
16614 switch (fmt) {
16615 case FMT_SDPS_S:
16616 gen_movcf_s(ctx, rs, rt, cc, 1);
16617 break;
16618 case FMT_SDPS_D:
16619 gen_movcf_d(ctx, rs, rt, cc, 1);
16620 break;
16621 case FMT_SDPS_PS:
16622 check_ps(ctx);
16623 gen_movcf_ps(ctx, rs, rt, cc, 1);
16624 break;
16625 default:
16626 goto pool32f_invalid;
16627 }
3c824109
NF
16628 }
16629 break;
16630 case PREFX:
9e8f441a 16631 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16632 break;
16633 default:
16634 goto pool32f_invalid;
16635 }
16636 break;
16637#define FINSN_3ARG_SDPS(prfx) \
16638 switch ((ctx->opcode >> 8) & 0x3) { \
16639 case FMT_SDPS_S: \
16640 mips32_op = OPC_##prfx##_S; \
16641 goto do_fpop; \
16642 case FMT_SDPS_D: \
16643 mips32_op = OPC_##prfx##_D; \
16644 goto do_fpop; \
16645 case FMT_SDPS_PS: \
e29c9628 16646 check_ps(ctx); \
3c824109
NF
16647 mips32_op = OPC_##prfx##_PS; \
16648 goto do_fpop; \
16649 default: \
16650 goto pool32f_invalid; \
16651 }
2a24a7ba
YK
16652 case MINA_FMT:
16653 check_insn(ctx, ISA_MIPS32R6);
16654 switch ((ctx->opcode >> 9) & 0x3) {
16655 case FMT_SDPS_S:
16656 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16657 break;
16658 case FMT_SDPS_D:
16659 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16660 break;
16661 default:
16662 goto pool32f_invalid;
16663 }
16664 break;
16665 case MAXA_FMT:
16666 check_insn(ctx, ISA_MIPS32R6);
16667 switch ((ctx->opcode >> 9) & 0x3) {
16668 case FMT_SDPS_S:
16669 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16670 break;
16671 case FMT_SDPS_D:
16672 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16673 break;
16674 default:
16675 goto pool32f_invalid;
16676 }
16677 break;
3c824109
NF
16678 case 0x30:
16679 /* regular FP ops */
16680 switch ((ctx->opcode >> 6) & 0x3) {
16681 case ADD_FMT:
16682 FINSN_3ARG_SDPS(ADD);
16683 break;
16684 case SUB_FMT:
16685 FINSN_3ARG_SDPS(SUB);
16686 break;
16687 case MUL_FMT:
16688 FINSN_3ARG_SDPS(MUL);
16689 break;
16690 case DIV_FMT:
16691 fmt = (ctx->opcode >> 8) & 0x3;
16692 if (fmt == 1) {
16693 mips32_op = OPC_DIV_D;
16694 } else if (fmt == 0) {
16695 mips32_op = OPC_DIV_S;
16696 } else {
16697 goto pool32f_invalid;
16698 }
16699 goto do_fpop;
16700 default:
16701 goto pool32f_invalid;
16702 }
16703 break;
16704 case 0x38:
16705 /* cmovs */
2a24a7ba 16706 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16707 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16708 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16709 /* SELEQZ_FMT */
2a24a7ba
YK
16710 switch ((ctx->opcode >> 9) & 0x3) {
16711 case FMT_SDPS_S:
fdac60cd 16712 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16713 break;
16714 case FMT_SDPS_D:
fdac60cd 16715 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16716 break;
16717 default:
16718 goto pool32f_invalid;
16719 }
16720 } else {
16721 /* MOVN_FMT */
16722 FINSN_3ARG_SDPS(MOVN);
16723 }
16724 break;
16725 case MOVN_FMT_04:
16726 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16727 FINSN_3ARG_SDPS(MOVN);
16728 break;
fdac60cd 16729 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16730 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16731 /* SELNEZ_FMT */
2a24a7ba
YK
16732 switch ((ctx->opcode >> 9) & 0x3) {
16733 case FMT_SDPS_S:
fdac60cd 16734 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16735 break;
16736 case FMT_SDPS_D:
fdac60cd 16737 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16738 break;
16739 default:
16740 goto pool32f_invalid;
16741 }
16742 } else {
16743 /* MOVZ_FMT */
16744 FINSN_3ARG_SDPS(MOVZ);
16745 }
16746 break;
16747 case MOVZ_FMT_05:
16748 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16749 FINSN_3ARG_SDPS(MOVZ);
16750 break;
2a24a7ba
YK
16751 case SEL_FMT:
16752 check_insn(ctx, ISA_MIPS32R6);
16753 switch ((ctx->opcode >> 9) & 0x3) {
16754 case FMT_SDPS_S:
16755 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16756 break;
16757 case FMT_SDPS_D:
16758 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16759 break;
16760 default:
16761 goto pool32f_invalid;
16762 }
16763 break;
16764 case MADDF_FMT:
16765 check_insn(ctx, ISA_MIPS32R6);
16766 switch ((ctx->opcode >> 9) & 0x3) {
16767 case FMT_SDPS_S:
16768 mips32_op = OPC_MADDF_S;
16769 goto do_fpop;
16770 case FMT_SDPS_D:
16771 mips32_op = OPC_MADDF_D;
16772 goto do_fpop;
16773 default:
16774 goto pool32f_invalid;
16775 }
16776 break;
16777 case MSUBF_FMT:
16778 check_insn(ctx, ISA_MIPS32R6);
16779 switch ((ctx->opcode >> 9) & 0x3) {
16780 case FMT_SDPS_S:
16781 mips32_op = OPC_MSUBF_S;
16782 goto do_fpop;
16783 case FMT_SDPS_D:
16784 mips32_op = OPC_MSUBF_D;
16785 goto do_fpop;
16786 default:
16787 goto pool32f_invalid;
16788 }
16789 break;
3c824109
NF
16790 default:
16791 goto pool32f_invalid;
16792 }
16793 break;
16794 do_fpop:
16795 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16796 break;
16797 default:
16798 pool32f_invalid:
16799 MIPS_INVAL("pool32f");
9c708c7f 16800 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16801 break;
16802 }
16803 } else {
16804 generate_exception_err(ctx, EXCP_CpU, 1);
16805 }
16806 break;
16807 case POOL32I:
16808 minor = (ctx->opcode >> 21) & 0x1f;
16809 switch (minor) {
16810 case BLTZ:
9e8f441a 16811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16812 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16813 break;
3c824109 16814 case BLTZAL:
9e8f441a 16815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16816 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16817 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16818 break;
3c824109 16819 case BLTZALS:
9e8f441a 16820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16821 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16822 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16823 break;
3c824109 16824 case BGEZ:
9e8f441a 16825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16826 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16827 break;
3c824109 16828 case BGEZAL:
9e8f441a 16829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16830 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16831 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16832 break;
3c824109 16833 case BGEZALS:
9e8f441a 16834 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16835 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16836 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16837 break;
3c824109 16838 case BLEZ:
9e8f441a 16839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16840 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16841 break;
3c824109 16842 case BGTZ:
9e8f441a 16843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 16844 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16845 break;
16846
16847 /* Traps */
65935f07
YK
16848 case TLTI: /* BC1EQZC */
16849 if (ctx->insn_flags & ISA_MIPS32R6) {
16850 /* BC1EQZC */
16851 check_cp1_enabled(ctx);
16852 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16853 } else {
16854 /* TLTI */
16855 mips32_op = OPC_TLTI;
16856 goto do_trapi;
16857 }
16858 break;
16859 case TGEI: /* BC1NEZC */
16860 if (ctx->insn_flags & ISA_MIPS32R6) {
16861 /* BC1NEZC */
16862 check_cp1_enabled(ctx);
16863 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16864 } else {
16865 /* TGEI */
16866 mips32_op = OPC_TGEI;
16867 goto do_trapi;
16868 }
16869 break;
3c824109 16870 case TLTIU:
9e8f441a 16871 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16872 mips32_op = OPC_TLTIU;
16873 goto do_trapi;
16874 case TGEIU:
9e8f441a 16875 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16876 mips32_op = OPC_TGEIU;
16877 goto do_trapi;
3b4a5489
YK
16878 case TNEI: /* SYNCI */
16879 if (ctx->insn_flags & ISA_MIPS32R6) {
16880 /* SYNCI */
7480515f
AM
16881 /*
16882 * Break the TB to be able to sync copied instructions
16883 * immediately.
16884 */
eeb3bba8 16885 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16886 } else {
16887 /* TNEI */
16888 mips32_op = OPC_TNEI;
16889 goto do_trapi;
16890 }
16891 break;
3c824109 16892 case TEQI:
9e8f441a 16893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16894 mips32_op = OPC_TEQI;
16895 do_trapi:
16896 gen_trap(ctx, mips32_op, rs, -1, imm);
16897 break;
16898
16899 case BNEZC:
16900 case BEQZC:
9e8f441a 16901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16902 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16903 4, rs, 0, imm << 1, 0);
7480515f
AM
16904 /*
16905 * Compact branches don't have a delay slot, so just let
16906 * the normal delay slot handling take us to the branch
16907 * target.
16908 */
3c824109
NF
16909 break;
16910 case LUI:
9e8f441a 16911 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 16912 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16913 break;
16914 case SYNCI:
9e8f441a 16915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7480515f
AM
16916 /*
16917 * Break the TB to be able to sync copied instructions
16918 * immediately.
16919 */
eeb3bba8 16920 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16921 break;
16922 case BC2F:
16923 case BC2T:
9e8f441a 16924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16925 /* COP2: Not implemented. */
16926 generate_exception_err(ctx, EXCP_CpU, 2);
16927 break;
16928 case BC1F:
9e8f441a 16929 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16930 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16931 goto do_cp1branch;
16932 case BC1T:
9e8f441a 16933 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16934 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16935 goto do_cp1branch;
16936 case BC1ANY4F:
9e8f441a 16937 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16938 mips32_op = OPC_BC1FANY4;
16939 goto do_cp1mips3d;
16940 case BC1ANY4T:
9e8f441a 16941 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16942 mips32_op = OPC_BC1TANY4;
16943 do_cp1mips3d:
16944 check_cop1x(ctx);
d75c135e 16945 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16946 /* Fall through */
16947 do_cp1branch:
272f458d
MR
16948 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16949 check_cp1_enabled(ctx);
16950 gen_compute_branch1(ctx, mips32_op,
16951 (ctx->opcode >> 18) & 0x7, imm << 1);
16952 } else {
16953 generate_exception_err(ctx, EXCP_CpU, 1);
16954 }
3c824109
NF
16955 break;
16956 case BPOSGE64:
16957 case BPOSGE32:
16958 /* MIPS DSP: not implemented */
16959 /* Fall through */
16960 default:
16961 MIPS_INVAL("pool32i");
9c708c7f 16962 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16963 break;
16964 }
16965 break;
16966 case POOL32C:
16967 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
16968 offset = sextract32(ctx->opcode, 0,
16969 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
16970 switch (minor) {
16971 case LWL:
9e8f441a 16972 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16973 mips32_op = OPC_LWL;
5c13fdfd 16974 goto do_ld_lr;
3c824109 16975 case SWL:
9e8f441a 16976 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16977 mips32_op = OPC_SWL;
5c13fdfd 16978 goto do_st_lr;
3c824109 16979 case LWR:
9e8f441a 16980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16981 mips32_op = OPC_LWR;
5c13fdfd 16982 goto do_ld_lr;
3c824109 16983 case SWR:
9e8f441a 16984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16985 mips32_op = OPC_SWR;
5c13fdfd 16986 goto do_st_lr;
3c824109
NF
16987#if defined(TARGET_MIPS64)
16988 case LDL:
d9224450
MR
16989 check_insn(ctx, ISA_MIPS3);
16990 check_mips_64(ctx);
9e8f441a 16991 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16992 mips32_op = OPC_LDL;
5c13fdfd 16993 goto do_ld_lr;
3c824109 16994 case SDL:
d9224450
MR
16995 check_insn(ctx, ISA_MIPS3);
16996 check_mips_64(ctx);
9e8f441a 16997 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16998 mips32_op = OPC_SDL;
5c13fdfd 16999 goto do_st_lr;
3c824109 17000 case LDR:
d9224450
MR
17001 check_insn(ctx, ISA_MIPS3);
17002 check_mips_64(ctx);
9e8f441a 17003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17004 mips32_op = OPC_LDR;
5c13fdfd 17005 goto do_ld_lr;
3c824109 17006 case SDR:
d9224450
MR
17007 check_insn(ctx, ISA_MIPS3);
17008 check_mips_64(ctx);
9e8f441a 17009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17010 mips32_op = OPC_SDR;
5c13fdfd 17011 goto do_st_lr;
3c824109 17012 case LWU:
d9224450
MR
17013 check_insn(ctx, ISA_MIPS3);
17014 check_mips_64(ctx);
3c824109 17015 mips32_op = OPC_LWU;
5c13fdfd 17016 goto do_ld_lr;
3c824109 17017 case LLD:
d9224450
MR
17018 check_insn(ctx, ISA_MIPS3);
17019 check_mips_64(ctx);
3c824109 17020 mips32_op = OPC_LLD;
5c13fdfd 17021 goto do_ld_lr;
3c824109
NF
17022#endif
17023 case LL:
17024 mips32_op = OPC_LL;
5c13fdfd
AJ
17025 goto do_ld_lr;
17026 do_ld_lr:
3b4a5489 17027 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
17028 break;
17029 do_st_lr:
8fffc646 17030 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
17031 break;
17032 case SC:
33a07fa2 17033 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
17034 break;
17035#if defined(TARGET_MIPS64)
17036 case SCD:
d9224450
MR
17037 check_insn(ctx, ISA_MIPS3);
17038 check_mips_64(ctx);
33a07fa2 17039 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
17040 break;
17041#endif
8fffc646
JH
17042 case LD_EVA:
17043 if (!ctx->eva) {
17044 MIPS_INVAL("pool32c ld-eva");
17045 generate_exception_end(ctx, EXCP_RI);
17046 break;
17047 }
17048 check_cp0_enabled(ctx);
17049
17050 minor2 = (ctx->opcode >> 9) & 0x7;
17051 offset = sextract32(ctx->opcode, 0, 9);
17052 switch (minor2) {
17053 case LBUE:
17054 mips32_op = OPC_LBUE;
17055 goto do_ld_lr;
17056 case LHUE:
17057 mips32_op = OPC_LHUE;
17058 goto do_ld_lr;
17059 case LWLE:
17060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17061 mips32_op = OPC_LWLE;
17062 goto do_ld_lr;
17063 case LWRE:
17064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17065 mips32_op = OPC_LWRE;
17066 goto do_ld_lr;
17067 case LBE:
17068 mips32_op = OPC_LBE;
17069 goto do_ld_lr;
17070 case LHE:
17071 mips32_op = OPC_LHE;
17072 goto do_ld_lr;
17073 case LLE:
17074 mips32_op = OPC_LLE;
17075 goto do_ld_lr;
17076 case LWE:
17077 mips32_op = OPC_LWE;
17078 goto do_ld_lr;
17079 };
17080 break;
17081 case ST_EVA:
17082 if (!ctx->eva) {
17083 MIPS_INVAL("pool32c st-eva");
17084 generate_exception_end(ctx, EXCP_RI);
17085 break;
17086 }
17087 check_cp0_enabled(ctx);
17088
17089 minor2 = (ctx->opcode >> 9) & 0x7;
17090 offset = sextract32(ctx->opcode, 0, 9);
17091 switch (minor2) {
17092 case SWLE:
17093 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17094 mips32_op = OPC_SWLE;
17095 goto do_st_lr;
17096 case SWRE:
17097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17098 mips32_op = OPC_SWRE;
17099 goto do_st_lr;
17100 case PREFE:
17101 /* Treat as no-op */
17102 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17103 /* hint codes 24-31 are reserved and signal RI */
17104 generate_exception(ctx, EXCP_RI);
17105 }
17106 break;
17107 case CACHEE:
17108 /* Treat as no-op */
17109 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17110 gen_cache_operation(ctx, rt, rs, offset);
17111 }
17112 break;
17113 case SBE:
17114 mips32_op = OPC_SBE;
17115 goto do_st_lr;
17116 case SHE:
17117 mips32_op = OPC_SHE;
17118 goto do_st_lr;
17119 case SCE:
33a07fa2 17120 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
17121 break;
17122 case SWE:
17123 mips32_op = OPC_SWE;
17124 goto do_st_lr;
17125 };
17126 break;
3c824109
NF
17127 case PREF:
17128 /* Treat as no-op */
3b4a5489
YK
17129 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17130 /* hint codes 24-31 are reserved and signal RI */
17131 generate_exception(ctx, EXCP_RI);
17132 }
3c824109
NF
17133 break;
17134 default:
17135 MIPS_INVAL("pool32c");
9c708c7f 17136 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17137 break;
17138 }
17139 break;
ab39ee45
YK
17140 case ADDI32: /* AUI, LUI */
17141 if (ctx->insn_flags & ISA_MIPS32R6) {
17142 /* AUI, LUI */
17143 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17144 } else {
17145 /* ADDI32 */
17146 mips32_op = OPC_ADDI;
17147 goto do_addi;
17148 }
17149 break;
3c824109
NF
17150 case ADDIU32:
17151 mips32_op = OPC_ADDIU;
17152 do_addi:
d75c135e 17153 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17154 break;
17155
17156 /* Logical operations */
17157 case ORI32:
17158 mips32_op = OPC_ORI;
17159 goto do_logici;
17160 case XORI32:
17161 mips32_op = OPC_XORI;
17162 goto do_logici;
17163 case ANDI32:
17164 mips32_op = OPC_ANDI;
17165 do_logici:
d75c135e 17166 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17167 break;
17168
17169 /* Set less than immediate */
17170 case SLTI32:
17171 mips32_op = OPC_SLTI;
17172 goto do_slti;
17173 case SLTIU32:
17174 mips32_op = OPC_SLTIU;
17175 do_slti:
d75c135e 17176 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17177 break;
17178 case JALX32:
9e8f441a 17179 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17180 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17181 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17182 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17183 break;
65935f07
YK
17184 case JALS32: /* BOVC, BEQC, BEQZALC */
17185 if (ctx->insn_flags & ISA_MIPS32R6) {
17186 if (rs >= rt) {
17187 /* BOVC */
17188 mips32_op = OPC_BOVC;
17189 } else if (rs < rt && rs == 0) {
17190 /* BEQZALC */
17191 mips32_op = OPC_BEQZALC;
17192 } else {
17193 /* BEQC */
17194 mips32_op = OPC_BEQC;
17195 }
17196 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17197 } else {
17198 /* JALS32 */
17199 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17200 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17201 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17202 }
3c824109 17203 break;
65935f07
YK
17204 case BEQ32: /* BC */
17205 if (ctx->insn_flags & ISA_MIPS32R6) {
17206 /* BC */
17207 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17208 sextract32(ctx->opcode << 1, 0, 27));
17209 } else {
17210 /* BEQ32 */
17211 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17212 }
3c824109 17213 break;
65935f07
YK
17214 case BNE32: /* BALC */
17215 if (ctx->insn_flags & ISA_MIPS32R6) {
17216 /* BALC */
17217 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17218 sextract32(ctx->opcode << 1, 0, 27));
17219 } else {
17220 /* BNE32 */
17221 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17222 }
3c824109 17223 break;
65935f07
YK
17224 case J32: /* BGTZC, BLTZC, BLTC */
17225 if (ctx->insn_flags & ISA_MIPS32R6) {
17226 if (rs == 0 && rt != 0) {
17227 /* BGTZC */
17228 mips32_op = OPC_BGTZC;
17229 } else if (rs != 0 && rt != 0 && rs == rt) {
17230 /* BLTZC */
17231 mips32_op = OPC_BLTZC;
17232 } else {
17233 /* BLTC */
17234 mips32_op = OPC_BLTC;
17235 }
17236 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17237 } else {
17238 /* J32 */
17239 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17240 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17241 }
3c824109 17242 break;
65935f07
YK
17243 case JAL32: /* BLEZC, BGEZC, BGEC */
17244 if (ctx->insn_flags & ISA_MIPS32R6) {
17245 if (rs == 0 && rt != 0) {
17246 /* BLEZC */
17247 mips32_op = OPC_BLEZC;
17248 } else if (rs != 0 && rt != 0 && rs == rt) {
17249 /* BGEZC */
17250 mips32_op = OPC_BGEZC;
17251 } else {
17252 /* BGEC */
17253 mips32_op = OPC_BGEC;
17254 }
17255 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17256 } else {
17257 /* JAL32 */
17258 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17259 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17260 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17261 }
3c824109
NF
17262 break;
17263 /* Floating point (COP1) */
17264 case LWC132:
17265 mips32_op = OPC_LWC1;
17266 goto do_cop1;
17267 case LDC132:
17268 mips32_op = OPC_LDC1;
17269 goto do_cop1;
17270 case SWC132:
17271 mips32_op = OPC_SWC1;
17272 goto do_cop1;
17273 case SDC132:
17274 mips32_op = OPC_SDC1;
17275 do_cop1:
5ab5c041 17276 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17277 break;
ab39ee45
YK
17278 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17279 if (ctx->insn_flags & ISA_MIPS32R6) {
17280 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17281 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17282 case ADDIUPC_00:
17283 case ADDIUPC_01:
17284 case ADDIUPC_02:
17285 case ADDIUPC_03:
17286 case ADDIUPC_04:
17287 case ADDIUPC_05:
17288 case ADDIUPC_06:
17289 case ADDIUPC_07:
eeb3bba8 17290 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17291 break;
17292 case AUIPC:
eeb3bba8 17293 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17294 break;
17295 case ALUIPC:
eeb3bba8 17296 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17297 break;
c38a1d52
AR
17298 case LWPC_08:
17299 case LWPC_09:
17300 case LWPC_0A:
17301 case LWPC_0B:
17302 case LWPC_0C:
17303 case LWPC_0D:
17304 case LWPC_0E:
17305 case LWPC_0F:
eeb3bba8 17306 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17307 break;
17308 default:
17309 generate_exception(ctx, EXCP_RI);
17310 break;
17311 }
17312 } else {
17313 /* ADDIUPC */
3c824109 17314 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17315 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17316
17317 gen_addiupc(ctx, reg, offset, 0, 0);
17318 }
17319 break;
65935f07
YK
17320 case BNVC: /* BNEC, BNEZALC */
17321 check_insn(ctx, ISA_MIPS32R6);
17322 if (rs >= rt) {
17323 /* BNVC */
17324 mips32_op = OPC_BNVC;
17325 } else if (rs < rt && rs == 0) {
17326 /* BNEZALC */
17327 mips32_op = OPC_BNEZALC;
17328 } else {
17329 /* BNEC */
17330 mips32_op = OPC_BNEC;
17331 }
17332 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17333 break;
17334 case R6_BNEZC: /* JIALC */
17335 check_insn(ctx, ISA_MIPS32R6);
17336 if (rt != 0) {
17337 /* BNEZC */
17338 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17339 sextract32(ctx->opcode << 1, 0, 22));
17340 } else {
17341 /* JIALC */
17342 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17343 }
17344 break;
17345 case R6_BEQZC: /* JIC */
17346 check_insn(ctx, ISA_MIPS32R6);
17347 if (rt != 0) {
17348 /* BEQZC */
17349 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17350 sextract32(ctx->opcode << 1, 0, 22));
17351 } else {
17352 /* JIC */
17353 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17354 }
17355 break;
17356 case BLEZALC: /* BGEZALC, BGEUC */
17357 check_insn(ctx, ISA_MIPS32R6);
17358 if (rs == 0 && rt != 0) {
17359 /* BLEZALC */
17360 mips32_op = OPC_BLEZALC;
17361 } else if (rs != 0 && rt != 0 && rs == rt) {
17362 /* BGEZALC */
17363 mips32_op = OPC_BGEZALC;
17364 } else {
17365 /* BGEUC */
17366 mips32_op = OPC_BGEUC;
17367 }
17368 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17369 break;
17370 case BGTZALC: /* BLTZALC, BLTUC */
17371 check_insn(ctx, ISA_MIPS32R6);
17372 if (rs == 0 && rt != 0) {
17373 /* BGTZALC */
17374 mips32_op = OPC_BGTZALC;
17375 } else if (rs != 0 && rt != 0 && rs == rt) {
17376 /* BLTZALC */
17377 mips32_op = OPC_BLTZALC;
17378 } else {
17379 /* BLTUC */
17380 mips32_op = OPC_BLTUC;
17381 }
17382 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17383 break;
3c824109
NF
17384 /* Loads and stores */
17385 case LB32:
17386 mips32_op = OPC_LB;
5c13fdfd 17387 goto do_ld;
3c824109
NF
17388 case LBU32:
17389 mips32_op = OPC_LBU;
5c13fdfd 17390 goto do_ld;
3c824109
NF
17391 case LH32:
17392 mips32_op = OPC_LH;
5c13fdfd 17393 goto do_ld;
3c824109
NF
17394 case LHU32:
17395 mips32_op = OPC_LHU;
5c13fdfd 17396 goto do_ld;
3c824109
NF
17397 case LW32:
17398 mips32_op = OPC_LW;
5c13fdfd 17399 goto do_ld;
3c824109
NF
17400#ifdef TARGET_MIPS64
17401 case LD32:
d9224450
MR
17402 check_insn(ctx, ISA_MIPS3);
17403 check_mips_64(ctx);
3c824109 17404 mips32_op = OPC_LD;
5c13fdfd 17405 goto do_ld;
3c824109 17406 case SD32:
d9224450
MR
17407 check_insn(ctx, ISA_MIPS3);
17408 check_mips_64(ctx);
3c824109 17409 mips32_op = OPC_SD;
5c13fdfd 17410 goto do_st;
3c824109
NF
17411#endif
17412 case SB32:
17413 mips32_op = OPC_SB;
5c13fdfd 17414 goto do_st;
3c824109
NF
17415 case SH32:
17416 mips32_op = OPC_SH;
5c13fdfd 17417 goto do_st;
3c824109
NF
17418 case SW32:
17419 mips32_op = OPC_SW;
5c13fdfd
AJ
17420 goto do_st;
17421 do_ld:
d75c135e 17422 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
17423 break;
17424 do_st:
17425 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17426 break;
17427 default:
9c708c7f 17428 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17429 break;
17430 }
17431}
17432
235785e8 17433static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
17434{
17435 uint32_t op;
17436
17437 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
17438 if (ctx->base.pc_next & 0x1) {
17439 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 17440 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
17441 return 2;
17442 }
17443
17444 op = (ctx->opcode >> 10) & 0x3f;
17445 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
17446 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17447 switch (op & 0x7) { /* MSB-3..MSB-5 */
17448 case 0:
17449 /* POOL32A, POOL32B, POOL32I, POOL32C */
17450 case 4:
17451 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17452 case 5:
17453 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17454 case 6:
17455 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17456 case 7:
17457 /* LB32, LH32, LWC132, LDC132, LW32 */
17458 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 17459 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17460 return 2;
17461 }
17462 break;
b231c103
YK
17463 case 1:
17464 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17465 case 2:
17466 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17467 case 3:
17468 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17469 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 17470 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17471 return 2;
17472 }
17473 break;
3c824109
NF
17474 }
17475 }
b231c103 17476
3c824109
NF
17477 switch (op) {
17478 case POOL16A:
17479 {
17480 int rd = mmreg(uMIPS_RD(ctx->opcode));
17481 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17482 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17483 uint32_t opc = 0;
17484
17485 switch (ctx->opcode & 0x1) {
17486 case ADDU16:
17487 opc = OPC_ADDU;
17488 break;
17489 case SUBU16:
17490 opc = OPC_SUBU;
17491 break;
17492 }
ed7ce6c0 17493 if (ctx->insn_flags & ISA_MIPS32R6) {
7480515f
AM
17494 /*
17495 * In the Release 6, the register number location in
ed7ce6c0
YK
17496 * the instruction encoding has changed.
17497 */
17498 gen_arith(ctx, opc, rs1, rd, rs2);
17499 } else {
17500 gen_arith(ctx, opc, rd, rs1, rs2);
17501 }
3c824109
NF
17502 }
17503 break;
17504 case POOL16B:
17505 {
17506 int rd = mmreg(uMIPS_RD(ctx->opcode));
17507 int rs = mmreg(uMIPS_RS(ctx->opcode));
17508 int amount = (ctx->opcode >> 1) & 0x7;
17509 uint32_t opc = 0;
17510 amount = amount == 0 ? 8 : amount;
17511
17512 switch (ctx->opcode & 0x1) {
17513 case SLL16:
17514 opc = OPC_SLL;
17515 break;
17516 case SRL16:
17517 opc = OPC_SRL;
17518 break;
17519 }
17520
d75c135e 17521 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17522 }
17523 break;
17524 case POOL16C:
ed7ce6c0
YK
17525 if (ctx->insn_flags & ISA_MIPS32R6) {
17526 gen_pool16c_r6_insn(ctx);
17527 } else {
17528 gen_pool16c_insn(ctx);
17529 }
3c824109
NF
17530 break;
17531 case LWGP16:
17532 {
17533 int rd = mmreg(uMIPS_RD(ctx->opcode));
17534 int rb = 28; /* GP */
17535 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17536
d75c135e 17537 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17538 }
17539 break;
17540 case POOL16F:
9e8f441a 17541 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17542 if (ctx->opcode & 1) {
9c708c7f 17543 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17544 } else {
17545 /* MOVEP */
17546 int enc_dest = uMIPS_RD(ctx->opcode);
17547 int enc_rt = uMIPS_RS2(ctx->opcode);
17548 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17549 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17550 }
17551 break;
17552 case LBU16:
17553 {
17554 int rd = mmreg(uMIPS_RD(ctx->opcode));
17555 int rb = mmreg(uMIPS_RS(ctx->opcode));
17556 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17557 offset = (offset == 0xf ? -1 : offset);
17558
d75c135e 17559 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17560 }
17561 break;
17562 case LHU16:
17563 {
17564 int rd = mmreg(uMIPS_RD(ctx->opcode));
17565 int rb = mmreg(uMIPS_RS(ctx->opcode));
17566 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17567
d75c135e 17568 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17569 }
17570 break;
17571 case LWSP16:
17572 {
17573 int rd = (ctx->opcode >> 5) & 0x1f;
17574 int rb = 29; /* SP */
17575 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17576
d75c135e 17577 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17578 }
17579 break;
17580 case LW16:
17581 {
17582 int rd = mmreg(uMIPS_RD(ctx->opcode));
17583 int rb = mmreg(uMIPS_RS(ctx->opcode));
17584 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17585
d75c135e 17586 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17587 }
17588 break;
17589 case SB16:
17590 {
17591 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17592 int rb = mmreg(uMIPS_RS(ctx->opcode));
17593 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17594
5c13fdfd 17595 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17596 }
17597 break;
17598 case SH16:
17599 {
17600 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17601 int rb = mmreg(uMIPS_RS(ctx->opcode));
17602 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17603
5c13fdfd 17604 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17605 }
17606 break;
17607 case SWSP16:
17608 {
17609 int rd = (ctx->opcode >> 5) & 0x1f;
17610 int rb = 29; /* SP */
17611 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17612
5c13fdfd 17613 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17614 }
17615 break;
17616 case SW16:
17617 {
17618 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17619 int rb = mmreg(uMIPS_RS(ctx->opcode));
17620 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17621
5c13fdfd 17622 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17623 }
17624 break;
17625 case MOVE16:
17626 {
17627 int rd = uMIPS_RD5(ctx->opcode);
17628 int rs = uMIPS_RS5(ctx->opcode);
17629
7215d7e7 17630 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17631 }
17632 break;
17633 case ANDI16:
d75c135e 17634 gen_andi16(ctx);
3c824109
NF
17635 break;
17636 case POOL16D:
17637 switch (ctx->opcode & 0x1) {
17638 case ADDIUS5:
d75c135e 17639 gen_addius5(ctx);
3c824109
NF
17640 break;
17641 case ADDIUSP:
d75c135e 17642 gen_addiusp(ctx);
3c824109
NF
17643 break;
17644 }
17645 break;
17646 case POOL16E:
17647 switch (ctx->opcode & 0x1) {
17648 case ADDIUR2:
d75c135e 17649 gen_addiur2(ctx);
3c824109
NF
17650 break;
17651 case ADDIUR1SP:
d75c135e 17652 gen_addiur1sp(ctx);
3c824109
NF
17653 break;
17654 }
17655 break;
65935f07 17656 case B16: /* BC16 */
3c824109 17657 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17658 sextract32(ctx->opcode, 0, 10) << 1,
17659 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17660 break;
65935f07
YK
17661 case BNEZ16: /* BNEZC16 */
17662 case BEQZ16: /* BEQZC16 */
3c824109
NF
17663 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17664 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17665 0, sextract32(ctx->opcode, 0, 7) << 1,
17666 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17667
3c824109
NF
17668 break;
17669 case LI16:
17670 {
17671 int reg = mmreg(uMIPS_RD(ctx->opcode));
17672 int imm = ZIMM(ctx->opcode, 0, 7);
17673
17674 imm = (imm == 0x7f ? -1 : imm);
17675 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17676 }
17677 break;
3c824109 17678 case RES_29:
3c824109 17679 case RES_31:
3c824109 17680 case RES_39:
9c708c7f 17681 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17682 break;
17683 default:
f60eeb0c 17684 decode_micromips32_opc(env, ctx);
3c824109
NF
17685 return 4;
17686 }
17687
17688 return 2;
17689}
17690
261c95a0
YK
17691/*
17692 *
17693 * nanoMIPS opcodes
17694 *
17695 */
17696
17697/* MAJOR, P16, and P32 pools opcodes */
17698enum {
17699 NM_P_ADDIU = 0x00,
17700 NM_ADDIUPC = 0x01,
17701 NM_MOVE_BALC = 0x02,
17702 NM_P16_MV = 0x04,
17703 NM_LW16 = 0x05,
17704 NM_BC16 = 0x06,
17705 NM_P16_SR = 0x07,
17706
17707 NM_POOL32A = 0x08,
17708 NM_P_BAL = 0x0a,
17709 NM_P16_SHIFT = 0x0c,
17710 NM_LWSP16 = 0x0d,
17711 NM_BALC16 = 0x0e,
17712 NM_P16_4X4 = 0x0f,
17713
17714 NM_P_GP_W = 0x10,
17715 NM_P_GP_BH = 0x11,
17716 NM_P_J = 0x12,
17717 NM_P16C = 0x14,
17718 NM_LWGP16 = 0x15,
17719 NM_P16_LB = 0x17,
17720
17721 NM_P48I = 0x18,
17722 NM_P16_A1 = 0x1c,
17723 NM_LW4X4 = 0x1d,
17724 NM_P16_LH = 0x1f,
17725
17726 NM_P_U12 = 0x20,
17727 NM_P_LS_U12 = 0x21,
17728 NM_P_BR1 = 0x22,
17729 NM_P16_A2 = 0x24,
17730 NM_SW16 = 0x25,
17731 NM_BEQZC16 = 0x26,
17732
17733 NM_POOL32F = 0x28,
17734 NM_P_LS_S9 = 0x29,
17735 NM_P_BR2 = 0x2a,
17736
17737 NM_P16_ADDU = 0x2c,
17738 NM_SWSP16 = 0x2d,
17739 NM_BNEZC16 = 0x2e,
17740 NM_MOVEP = 0x2f,
17741
17742 NM_POOL32S = 0x30,
17743 NM_P_BRI = 0x32,
17744 NM_LI16 = 0x34,
17745 NM_SWGP16 = 0x35,
17746 NM_P16_BR = 0x36,
17747
17748 NM_P_LUI = 0x38,
17749 NM_ANDI16 = 0x3c,
17750 NM_SW4X4 = 0x3d,
17751 NM_MOVEPREV = 0x3f,
17752};
17753
17754/* POOL32A instruction pool */
17755enum {
17756 NM_POOL32A0 = 0x00,
17757 NM_SPECIAL2 = 0x01,
17758 NM_COP2_1 = 0x02,
17759 NM_UDI = 0x03,
17760 NM_POOL32A5 = 0x05,
17761 NM_POOL32A7 = 0x07,
17762};
17763
17764/* P.GP.W instruction pool */
17765enum {
17766 NM_ADDIUGP_W = 0x00,
17767 NM_LWGP = 0x02,
17768 NM_SWGP = 0x03,
17769};
17770
17771/* P48I instruction pool */
17772enum {
17773 NM_LI48 = 0x00,
17774 NM_ADDIU48 = 0x01,
17775 NM_ADDIUGP48 = 0x02,
17776 NM_ADDIUPC48 = 0x03,
17777 NM_LWPC48 = 0x0b,
17778 NM_SWPC48 = 0x0f,
17779};
17780
17781/* P.U12 instruction pool */
17782enum {
17783 NM_ORI = 0x00,
17784 NM_XORI = 0x01,
17785 NM_ANDI = 0x02,
17786 NM_P_SR = 0x03,
17787 NM_SLTI = 0x04,
17788 NM_SLTIU = 0x05,
17789 NM_SEQI = 0x06,
17790 NM_ADDIUNEG = 0x08,
17791 NM_P_SHIFT = 0x0c,
17792 NM_P_ROTX = 0x0d,
17793 NM_P_INS = 0x0e,
17794 NM_P_EXT = 0x0f,
17795};
17796
17797/* POOL32F instruction pool */
17798enum {
17799 NM_POOL32F_0 = 0x00,
17800 NM_POOL32F_3 = 0x03,
17801 NM_POOL32F_5 = 0x05,
17802};
17803
17804/* POOL32S instruction pool */
17805enum {
17806 NM_POOL32S_0 = 0x00,
17807 NM_POOL32S_4 = 0x04,
17808};
17809
17810/* P.LUI instruction pool */
17811enum {
17812 NM_LUI = 0x00,
17813 NM_ALUIPC = 0x01,
17814};
17815
17816/* P.GP.BH instruction pool */
17817enum {
17818 NM_LBGP = 0x00,
17819 NM_SBGP = 0x01,
17820 NM_LBUGP = 0x02,
17821 NM_ADDIUGP_B = 0x03,
17822 NM_P_GP_LH = 0x04,
17823 NM_P_GP_SH = 0x05,
17824 NM_P_GP_CP1 = 0x06,
17825};
17826
17827/* P.LS.U12 instruction pool */
17828enum {
17829 NM_LB = 0x00,
17830 NM_SB = 0x01,
17831 NM_LBU = 0x02,
17832 NM_P_PREFU12 = 0x03,
17833 NM_LH = 0x04,
17834 NM_SH = 0x05,
17835 NM_LHU = 0x06,
17836 NM_LWU = 0x07,
17837 NM_LW = 0x08,
17838 NM_SW = 0x09,
17839 NM_LWC1 = 0x0a,
17840 NM_SWC1 = 0x0b,
17841 NM_LDC1 = 0x0e,
17842 NM_SDC1 = 0x0f,
17843};
17844
17845/* P.LS.S9 instruction pool */
17846enum {
17847 NM_P_LS_S0 = 0x00,
17848 NM_P_LS_S1 = 0x01,
17849 NM_P_LS_E0 = 0x02,
17850 NM_P_LS_WM = 0x04,
17851 NM_P_LS_UAWM = 0x05,
17852};
17853
17854/* P.BAL instruction pool */
17855enum {
17856 NM_BC = 0x00,
17857 NM_BALC = 0x01,
17858};
17859
17860/* P.J instruction pool */
17861enum {
17862 NM_JALRC = 0x00,
17863 NM_JALRC_HB = 0x01,
17864 NM_P_BALRSC = 0x08,
17865};
17866
17867/* P.BR1 instruction pool */
17868enum {
17869 NM_BEQC = 0x00,
17870 NM_P_BR3A = 0x01,
17871 NM_BGEC = 0x02,
17872 NM_BGEUC = 0x03,
17873};
17874
17875/* P.BR2 instruction pool */
17876enum {
17877 NM_BNEC = 0x00,
17878 NM_BLTC = 0x02,
17879 NM_BLTUC = 0x03,
17880};
17881
17882/* P.BRI instruction pool */
17883enum {
17884 NM_BEQIC = 0x00,
17885 NM_BBEQZC = 0x01,
17886 NM_BGEIC = 0x02,
17887 NM_BGEIUC = 0x03,
17888 NM_BNEIC = 0x04,
17889 NM_BBNEZC = 0x05,
17890 NM_BLTIC = 0x06,
17891 NM_BLTIUC = 0x07,
17892};
17893
17894/* P16.SHIFT instruction pool */
17895enum {
17896 NM_SLL16 = 0x00,
17897 NM_SRL16 = 0x01,
17898};
17899
17900/* POOL16C instruction pool */
17901enum {
17902 NM_POOL16C_0 = 0x00,
17903 NM_LWXS16 = 0x01,
17904};
17905
17906/* P16.A1 instruction pool */
17907enum {
17908 NM_ADDIUR1SP = 0x01,
17909};
17910
17911/* P16.A2 instruction pool */
17912enum {
17913 NM_ADDIUR2 = 0x00,
17914 NM_P_ADDIURS5 = 0x01,
17915};
17916
17917/* P16.ADDU instruction pool */
17918enum {
17919 NM_ADDU16 = 0x00,
17920 NM_SUBU16 = 0x01,
17921};
17922
17923/* P16.SR instruction pool */
17924enum {
17925 NM_SAVE16 = 0x00,
17926 NM_RESTORE_JRC16 = 0x01,
17927};
17928
17929/* P16.4X4 instruction pool */
17930enum {
17931 NM_ADDU4X4 = 0x00,
17932 NM_MUL4X4 = 0x01,
17933};
17934
17935/* P16.LB instruction pool */
17936enum {
17937 NM_LB16 = 0x00,
17938 NM_SB16 = 0x01,
17939 NM_LBU16 = 0x02,
17940};
17941
17942/* P16.LH instruction pool */
17943enum {
17944 NM_LH16 = 0x00,
17945 NM_SH16 = 0x01,
17946 NM_LHU16 = 0x02,
17947};
17948
17949/* P.RI instruction pool */
17950enum {
17951 NM_SIGRIE = 0x00,
17952 NM_P_SYSCALL = 0x01,
17953 NM_BREAK = 0x02,
17954 NM_SDBBP = 0x03,
17955};
17956
17957/* POOL32A0 instruction pool */
17958enum {
17959 NM_P_TRAP = 0x00,
17960 NM_SEB = 0x01,
17961 NM_SLLV = 0x02,
17962 NM_MUL = 0x03,
17963 NM_MFC0 = 0x06,
17964 NM_MFHC0 = 0x07,
17965 NM_SEH = 0x09,
17966 NM_SRLV = 0x0a,
17967 NM_MUH = 0x0b,
17968 NM_MTC0 = 0x0e,
17969 NM_MTHC0 = 0x0f,
17970 NM_SRAV = 0x12,
17971 NM_MULU = 0x13,
17972 NM_ROTRV = 0x1a,
17973 NM_MUHU = 0x1b,
17974 NM_ADD = 0x22,
17975 NM_DIV = 0x23,
17976 NM_ADDU = 0x2a,
17977 NM_MOD = 0x2b,
17978 NM_SUB = 0x32,
17979 NM_DIVU = 0x33,
17980 NM_RDHWR = 0x38,
17981 NM_SUBU = 0x3a,
17982 NM_MODU = 0x3b,
17983 NM_P_CMOVE = 0x42,
17984 NM_FORK = 0x45,
17985 NM_MFTR = 0x46,
17986 NM_MFHTR = 0x47,
17987 NM_AND = 0x4a,
17988 NM_YIELD = 0x4d,
17989 NM_MTTR = 0x4e,
17990 NM_MTHTR = 0x4f,
17991 NM_OR = 0x52,
17992 NM_D_E_MT_VPE = 0x56,
17993 NM_NOR = 0x5a,
17994 NM_XOR = 0x62,
17995 NM_SLT = 0x6a,
17996 NM_P_SLTU = 0x72,
17997 NM_SOV = 0x7a,
17998};
17999
ba1e8117
AM
18000/* CRC32 instruction pool */
18001enum {
18002 NM_CRC32B = 0x00,
18003 NM_CRC32H = 0x01,
18004 NM_CRC32W = 0x02,
18005 NM_CRC32CB = 0x04,
18006 NM_CRC32CH = 0x05,
18007 NM_CRC32CW = 0x06,
18008};
18009
b3979b6f
SM
18010/* POOL32A5 instruction pool */
18011enum {
18012 NM_CMP_EQ_PH = 0x00,
18013 NM_CMP_LT_PH = 0x08,
18014 NM_CMP_LE_PH = 0x10,
18015 NM_CMPGU_EQ_QB = 0x18,
18016 NM_CMPGU_LT_QB = 0x20,
18017 NM_CMPGU_LE_QB = 0x28,
18018 NM_CMPGDU_EQ_QB = 0x30,
18019 NM_CMPGDU_LT_QB = 0x38,
18020 NM_CMPGDU_LE_QB = 0x40,
18021 NM_CMPU_EQ_QB = 0x48,
18022 NM_CMPU_LT_QB = 0x50,
18023 NM_CMPU_LE_QB = 0x58,
18024 NM_ADDQ_S_W = 0x60,
18025 NM_SUBQ_S_W = 0x68,
18026 NM_ADDSC = 0x70,
18027 NM_ADDWC = 0x78,
18028
18029 NM_ADDQ_S_PH = 0x01,
18030 NM_ADDQH_R_PH = 0x09,
18031 NM_ADDQH_R_W = 0x11,
18032 NM_ADDU_S_QB = 0x19,
18033 NM_ADDU_S_PH = 0x21,
18034 NM_ADDUH_R_QB = 0x29,
18035 NM_SHRAV_R_PH = 0x31,
18036 NM_SHRAV_R_QB = 0x39,
18037 NM_SUBQ_S_PH = 0x41,
18038 NM_SUBQH_R_PH = 0x49,
18039 NM_SUBQH_R_W = 0x51,
18040 NM_SUBU_S_QB = 0x59,
18041 NM_SUBU_S_PH = 0x61,
18042 NM_SUBUH_R_QB = 0x69,
18043 NM_SHLLV_S_PH = 0x71,
18044 NM_PRECR_SRA_R_PH_W = 0x79,
18045
18046 NM_MULEU_S_PH_QBL = 0x12,
18047 NM_MULEU_S_PH_QBR = 0x1a,
18048 NM_MULQ_RS_PH = 0x22,
18049 NM_MULQ_S_PH = 0x2a,
18050 NM_MULQ_RS_W = 0x32,
18051 NM_MULQ_S_W = 0x3a,
18052 NM_APPEND = 0x42,
18053 NM_MODSUB = 0x52,
18054 NM_SHRAV_R_W = 0x5a,
18055 NM_SHRLV_PH = 0x62,
18056 NM_SHRLV_QB = 0x6a,
18057 NM_SHLLV_QB = 0x72,
18058 NM_SHLLV_S_W = 0x7a,
18059
18060 NM_SHILO = 0x03,
18061
18062 NM_MULEQ_S_W_PHL = 0x04,
18063 NM_MULEQ_S_W_PHR = 0x0c,
18064
18065 NM_MUL_S_PH = 0x05,
18066 NM_PRECR_QB_PH = 0x0d,
18067 NM_PRECRQ_QB_PH = 0x15,
18068 NM_PRECRQ_PH_W = 0x1d,
18069 NM_PRECRQ_RS_PH_W = 0x25,
18070 NM_PRECRQU_S_QB_PH = 0x2d,
18071 NM_PACKRL_PH = 0x35,
18072 NM_PICK_QB = 0x3d,
18073 NM_PICK_PH = 0x45,
18074
18075 NM_SHRA_R_W = 0x5e,
18076 NM_SHRA_R_PH = 0x66,
18077 NM_SHLL_S_PH = 0x76,
18078 NM_SHLL_S_W = 0x7e,
18079
18080 NM_REPL_PH = 0x07
18081};
18082
261c95a0
YK
18083/* POOL32A7 instruction pool */
18084enum {
18085 NM_P_LSX = 0x00,
18086 NM_LSA = 0x01,
18087 NM_EXTW = 0x03,
18088 NM_POOL32AXF = 0x07,
18089};
18090
18091/* P.SR instruction pool */
18092enum {
18093 NM_PP_SR = 0x00,
18094 NM_P_SR_F = 0x01,
18095};
18096
18097/* P.SHIFT instruction pool */
18098enum {
18099 NM_P_SLL = 0x00,
18100 NM_SRL = 0x02,
18101 NM_SRA = 0x04,
18102 NM_ROTR = 0x06,
18103};
18104
18105/* P.ROTX instruction pool */
18106enum {
18107 NM_ROTX = 0x00,
18108};
18109
18110/* P.INS instruction pool */
18111enum {
18112 NM_INS = 0x00,
18113};
18114
18115/* P.EXT instruction pool */
18116enum {
18117 NM_EXT = 0x00,
18118};
18119
18120/* POOL32F_0 (fmt) instruction pool */
18121enum {
18122 NM_RINT_S = 0x04,
18123 NM_RINT_D = 0x44,
18124 NM_ADD_S = 0x06,
18125 NM_SELEQZ_S = 0x07,
18126 NM_SELEQZ_D = 0x47,
18127 NM_CLASS_S = 0x0c,
18128 NM_CLASS_D = 0x4c,
18129 NM_SUB_S = 0x0e,
18130 NM_SELNEZ_S = 0x0f,
18131 NM_SELNEZ_D = 0x4f,
18132 NM_MUL_S = 0x16,
18133 NM_SEL_S = 0x17,
18134 NM_SEL_D = 0x57,
18135 NM_DIV_S = 0x1e,
18136 NM_ADD_D = 0x26,
18137 NM_SUB_D = 0x2e,
18138 NM_MUL_D = 0x36,
18139 NM_MADDF_S = 0x37,
18140 NM_MADDF_D = 0x77,
18141 NM_DIV_D = 0x3e,
18142 NM_MSUBF_S = 0x3f,
18143 NM_MSUBF_D = 0x7f,
18144};
18145
18146/* POOL32F_3 instruction pool */
18147enum {
18148 NM_MIN_FMT = 0x00,
18149 NM_MAX_FMT = 0x01,
18150 NM_MINA_FMT = 0x04,
18151 NM_MAXA_FMT = 0x05,
18152 NM_POOL32FXF = 0x07,
18153};
18154
18155/* POOL32F_5 instruction pool */
18156enum {
18157 NM_CMP_CONDN_S = 0x00,
18158 NM_CMP_CONDN_D = 0x02,
18159};
18160
18161/* P.GP.LH instruction pool */
18162enum {
18163 NM_LHGP = 0x00,
18164 NM_LHUGP = 0x01,
18165};
18166
18167/* P.GP.SH instruction pool */
18168enum {
18169 NM_SHGP = 0x00,
18170};
18171
18172/* P.GP.CP1 instruction pool */
18173enum {
18174 NM_LWC1GP = 0x00,
18175 NM_SWC1GP = 0x01,
18176 NM_LDC1GP = 0x02,
18177 NM_SDC1GP = 0x03,
18178};
18179
18180/* P.LS.S0 instruction pool */
18181enum {
18182 NM_LBS9 = 0x00,
18183 NM_LHS9 = 0x04,
18184 NM_LWS9 = 0x08,
18185 NM_LDS9 = 0x0c,
18186
18187 NM_SBS9 = 0x01,
18188 NM_SHS9 = 0x05,
18189 NM_SWS9 = 0x09,
18190 NM_SDS9 = 0x0d,
18191
18192 NM_LBUS9 = 0x02,
18193 NM_LHUS9 = 0x06,
18194 NM_LWC1S9 = 0x0a,
18195 NM_LDC1S9 = 0x0e,
18196
18197 NM_P_PREFS9 = 0x03,
18198 NM_LWUS9 = 0x07,
18199 NM_SWC1S9 = 0x0b,
18200 NM_SDC1S9 = 0x0f,
18201};
18202
18203/* P.LS.S1 instruction pool */
18204enum {
18205 NM_ASET_ACLR = 0x02,
18206 NM_UALH = 0x04,
18207 NM_UASH = 0x05,
18208 NM_CACHE = 0x07,
18209 NM_P_LL = 0x0a,
18210 NM_P_SC = 0x0b,
18211};
18212
0d30b3bb
DN
18213/* P.LS.E0 instruction pool */
18214enum {
18215 NM_LBE = 0x00,
18216 NM_SBE = 0x01,
18217 NM_LBUE = 0x02,
18218 NM_P_PREFE = 0x03,
18219 NM_LHE = 0x04,
18220 NM_SHE = 0x05,
18221 NM_LHUE = 0x06,
18222 NM_CACHEE = 0x07,
18223 NM_LWE = 0x08,
18224 NM_SWE = 0x09,
18225 NM_P_LLE = 0x0a,
18226 NM_P_SCE = 0x0b,
18227};
18228
18229/* P.PREFE instruction pool */
18230enum {
18231 NM_SYNCIE = 0x00,
18232 NM_PREFE = 0x01,
18233};
18234
18235/* P.LLE instruction pool */
18236enum {
18237 NM_LLE = 0x00,
18238 NM_LLWPE = 0x01,
18239};
18240
18241/* P.SCE instruction pool */
18242enum {
18243 NM_SCE = 0x00,
18244 NM_SCWPE = 0x01,
18245};
18246
261c95a0
YK
18247/* P.LS.WM instruction pool */
18248enum {
18249 NM_LWM = 0x00,
18250 NM_SWM = 0x01,
18251};
18252
18253/* P.LS.UAWM instruction pool */
18254enum {
18255 NM_UALWM = 0x00,
18256 NM_UASWM = 0x01,
18257};
18258
18259/* P.BR3A instruction pool */
18260enum {
18261 NM_BC1EQZC = 0x00,
18262 NM_BC1NEZC = 0x01,
18263 NM_BC2EQZC = 0x02,
18264 NM_BC2NEZC = 0x03,
18265 NM_BPOSGE32C = 0x04,
18266};
18267
18268/* P16.RI instruction pool */
18269enum {
18270 NM_P16_SYSCALL = 0x01,
18271 NM_BREAK16 = 0x02,
18272 NM_SDBBP16 = 0x03,
18273};
18274
18275/* POOL16C_0 instruction pool */
18276enum {
18277 NM_POOL16C_00 = 0x00,
18278};
18279
18280/* P16.JRC instruction pool */
18281enum {
18282 NM_JRC = 0x00,
18283 NM_JALRC16 = 0x01,
18284};
18285
18286/* P.SYSCALL instruction pool */
18287enum {
18288 NM_SYSCALL = 0x00,
18289 NM_HYPCALL = 0x01,
18290};
18291
18292/* P.TRAP instruction pool */
18293enum {
18294 NM_TEQ = 0x00,
18295 NM_TNE = 0x01,
18296};
18297
18298/* P.CMOVE instruction pool */
18299enum {
18300 NM_MOVZ = 0x00,
18301 NM_MOVN = 0x01,
18302};
18303
18304/* POOL32Axf instruction pool */
18305enum {
b3979b6f
SM
18306 NM_POOL32AXF_1 = 0x01,
18307 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18308 NM_POOL32AXF_4 = 0x04,
18309 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18310 NM_POOL32AXF_7 = 0x07,
18311};
18312
18313/* POOL32Axf_1 instruction pool */
18314enum {
18315 NM_POOL32AXF_1_0 = 0x00,
18316 NM_POOL32AXF_1_1 = 0x01,
18317 NM_POOL32AXF_1_3 = 0x03,
18318 NM_POOL32AXF_1_4 = 0x04,
18319 NM_POOL32AXF_1_5 = 0x05,
18320 NM_POOL32AXF_1_7 = 0x07,
18321};
18322
18323/* POOL32Axf_2 instruction pool */
18324enum {
18325 NM_POOL32AXF_2_0_7 = 0x00,
18326 NM_POOL32AXF_2_8_15 = 0x01,
18327 NM_POOL32AXF_2_16_23 = 0x02,
18328 NM_POOL32AXF_2_24_31 = 0x03,
18329};
18330
18331/* POOL32Axf_7 instruction pool */
18332enum {
18333 NM_SHRA_R_QB = 0x0,
18334 NM_SHRL_PH = 0x1,
18335 NM_REPL_QB = 0x2,
18336};
18337
18338/* POOL32Axf_1_0 instruction pool */
18339enum {
18340 NM_MFHI = 0x0,
18341 NM_MFLO = 0x1,
18342 NM_MTHI = 0x2,
18343 NM_MTLO = 0x3,
18344};
18345
18346/* POOL32Axf_1_1 instruction pool */
18347enum {
18348 NM_MTHLIP = 0x0,
18349 NM_SHILOV = 0x1,
18350};
18351
18352/* POOL32Axf_1_3 instruction pool */
18353enum {
18354 NM_RDDSP = 0x0,
18355 NM_WRDSP = 0x1,
18356 NM_EXTP = 0x2,
18357 NM_EXTPDP = 0x3,
18358};
18359
18360/* POOL32Axf_1_4 instruction pool */
18361enum {
18362 NM_SHLL_QB = 0x0,
18363 NM_SHRL_QB = 0x1,
18364};
18365
18366/* POOL32Axf_1_5 instruction pool */
18367enum {
18368 NM_MAQ_S_W_PHR = 0x0,
18369 NM_MAQ_S_W_PHL = 0x1,
18370 NM_MAQ_SA_W_PHR = 0x2,
18371 NM_MAQ_SA_W_PHL = 0x3,
18372};
18373
18374/* POOL32Axf_1_7 instruction pool */
18375enum {
18376 NM_EXTR_W = 0x0,
18377 NM_EXTR_R_W = 0x1,
18378 NM_EXTR_RS_W = 0x2,
18379 NM_EXTR_S_H = 0x3,
18380};
18381
18382/* POOL32Axf_2_0_7 instruction pool */
18383enum {
18384 NM_DPA_W_PH = 0x0,
18385 NM_DPAQ_S_W_PH = 0x1,
18386 NM_DPS_W_PH = 0x2,
18387 NM_DPSQ_S_W_PH = 0x3,
18388 NM_BALIGN = 0x4,
18389 NM_MADD = 0x5,
18390 NM_MULT = 0x6,
18391 NM_EXTRV_W = 0x7,
18392};
18393
18394/* POOL32Axf_2_8_15 instruction pool */
18395enum {
18396 NM_DPAX_W_PH = 0x0,
18397 NM_DPAQ_SA_L_W = 0x1,
18398 NM_DPSX_W_PH = 0x2,
18399 NM_DPSQ_SA_L_W = 0x3,
18400 NM_MADDU = 0x5,
18401 NM_MULTU = 0x6,
18402 NM_EXTRV_R_W = 0x7,
18403};
18404
18405/* POOL32Axf_2_16_23 instruction pool */
18406enum {
18407 NM_DPAU_H_QBL = 0x0,
18408 NM_DPAQX_S_W_PH = 0x1,
18409 NM_DPSU_H_QBL = 0x2,
18410 NM_DPSQX_S_W_PH = 0x3,
18411 NM_EXTPV = 0x4,
18412 NM_MSUB = 0x5,
18413 NM_MULSA_W_PH = 0x6,
18414 NM_EXTRV_RS_W = 0x7,
18415};
18416
18417/* POOL32Axf_2_24_31 instruction pool */
18418enum {
18419 NM_DPAU_H_QBR = 0x0,
18420 NM_DPAQX_SA_W_PH = 0x1,
18421 NM_DPSU_H_QBR = 0x2,
18422 NM_DPSQX_SA_W_PH = 0x3,
18423 NM_EXTPDPV = 0x4,
18424 NM_MSUBU = 0x5,
18425 NM_MULSAQ_S_W_PH = 0x6,
18426 NM_EXTRV_S_H = 0x7,
261c95a0
YK
18427};
18428
18429/* POOL32Axf_{4, 5} instruction pool */
18430enum {
18431 NM_CLO = 0x25,
18432 NM_CLZ = 0x2d,
18433
18434 NM_TLBP = 0x01,
18435 NM_TLBR = 0x09,
18436 NM_TLBWI = 0x11,
18437 NM_TLBWR = 0x19,
18438 NM_TLBINV = 0x03,
18439 NM_TLBINVF = 0x0b,
18440 NM_DI = 0x23,
18441 NM_EI = 0x2b,
18442 NM_RDPGPR = 0x70,
18443 NM_WRPGPR = 0x78,
18444 NM_WAIT = 0x61,
18445 NM_DERET = 0x71,
18446 NM_ERETX = 0x79,
b3979b6f
SM
18447
18448 /* nanoMIPS DSP instructions */
18449 NM_ABSQ_S_QB = 0x00,
18450 NM_ABSQ_S_PH = 0x08,
18451 NM_ABSQ_S_W = 0x10,
18452 NM_PRECEQ_W_PHL = 0x28,
18453 NM_PRECEQ_W_PHR = 0x30,
18454 NM_PRECEQU_PH_QBL = 0x38,
18455 NM_PRECEQU_PH_QBR = 0x48,
18456 NM_PRECEU_PH_QBL = 0x58,
18457 NM_PRECEU_PH_QBR = 0x68,
18458 NM_PRECEQU_PH_QBLA = 0x39,
18459 NM_PRECEQU_PH_QBRA = 0x49,
18460 NM_PRECEU_PH_QBLA = 0x59,
18461 NM_PRECEU_PH_QBRA = 0x69,
18462 NM_REPLV_PH = 0x01,
18463 NM_REPLV_QB = 0x09,
18464 NM_BITREV = 0x18,
18465 NM_INSV = 0x20,
18466 NM_RADDU_W_QB = 0x78,
18467
18468 NM_BITSWAP = 0x05,
18469 NM_WSBH = 0x3d,
261c95a0
YK
18470};
18471
18472/* PP.SR instruction pool */
18473enum {
18474 NM_SAVE = 0x00,
18475 NM_RESTORE = 0x02,
18476 NM_RESTORE_JRC = 0x03,
18477};
18478
18479/* P.SR.F instruction pool */
18480enum {
18481 NM_SAVEF = 0x00,
18482 NM_RESTOREF = 0x01,
18483};
18484
18485/* P16.SYSCALL instruction pool */
18486enum {
18487 NM_SYSCALL16 = 0x00,
18488 NM_HYPCALL16 = 0x01,
18489};
18490
18491/* POOL16C_00 instruction pool */
18492enum {
18493 NM_NOT16 = 0x00,
18494 NM_XOR16 = 0x01,
18495 NM_AND16 = 0x02,
18496 NM_OR16 = 0x03,
18497};
18498
18499/* PP.LSX and PP.LSXS instruction pool */
18500enum {
18501 NM_LBX = 0x00,
18502 NM_LHX = 0x04,
18503 NM_LWX = 0x08,
18504 NM_LDX = 0x0c,
18505
18506 NM_SBX = 0x01,
18507 NM_SHX = 0x05,
18508 NM_SWX = 0x09,
18509 NM_SDX = 0x0d,
18510
18511 NM_LBUX = 0x02,
18512 NM_LHUX = 0x06,
18513 NM_LWC1X = 0x0a,
18514 NM_LDC1X = 0x0e,
18515
18516 NM_LWUX = 0x07,
18517 NM_SWC1X = 0x0b,
18518 NM_SDC1X = 0x0f,
18519
18520 NM_LHXS = 0x04,
18521 NM_LWXS = 0x08,
18522 NM_LDXS = 0x0c,
18523
18524 NM_SHXS = 0x05,
18525 NM_SWXS = 0x09,
18526 NM_SDXS = 0x0d,
18527
18528 NM_LHUXS = 0x06,
18529 NM_LWC1XS = 0x0a,
18530 NM_LDC1XS = 0x0e,
18531
18532 NM_LWUXS = 0x07,
18533 NM_SWC1XS = 0x0b,
18534 NM_SDC1XS = 0x0f,
18535};
18536
18537/* ERETx instruction pool */
18538enum {
18539 NM_ERET = 0x00,
18540 NM_ERETNC = 0x01,
18541};
18542
18543/* POOL32FxF_{0, 1} insturction pool */
18544enum {
18545 NM_CFC1 = 0x40,
18546 NM_CTC1 = 0x60,
18547 NM_MFC1 = 0x80,
18548 NM_MTC1 = 0xa0,
18549 NM_MFHC1 = 0xc0,
18550 NM_MTHC1 = 0xe0,
18551
18552 NM_CVT_S_PL = 0x84,
18553 NM_CVT_S_PU = 0xa4,
18554
18555 NM_CVT_L_S = 0x004,
18556 NM_CVT_L_D = 0x104,
18557 NM_CVT_W_S = 0x024,
18558 NM_CVT_W_D = 0x124,
18559
18560 NM_RSQRT_S = 0x008,
18561 NM_RSQRT_D = 0x108,
18562
18563 NM_SQRT_S = 0x028,
18564 NM_SQRT_D = 0x128,
18565
18566 NM_RECIP_S = 0x048,
18567 NM_RECIP_D = 0x148,
18568
18569 NM_FLOOR_L_S = 0x00c,
18570 NM_FLOOR_L_D = 0x10c,
18571
18572 NM_FLOOR_W_S = 0x02c,
18573 NM_FLOOR_W_D = 0x12c,
18574
18575 NM_CEIL_L_S = 0x04c,
18576 NM_CEIL_L_D = 0x14c,
18577 NM_CEIL_W_S = 0x06c,
18578 NM_CEIL_W_D = 0x16c,
18579 NM_TRUNC_L_S = 0x08c,
18580 NM_TRUNC_L_D = 0x18c,
18581 NM_TRUNC_W_S = 0x0ac,
18582 NM_TRUNC_W_D = 0x1ac,
18583 NM_ROUND_L_S = 0x0cc,
18584 NM_ROUND_L_D = 0x1cc,
18585 NM_ROUND_W_S = 0x0ec,
18586 NM_ROUND_W_D = 0x1ec,
18587
18588 NM_MOV_S = 0x01,
18589 NM_MOV_D = 0x81,
18590 NM_ABS_S = 0x0d,
18591 NM_ABS_D = 0x8d,
18592 NM_NEG_S = 0x2d,
18593 NM_NEG_D = 0xad,
18594 NM_CVT_D_S = 0x04d,
18595 NM_CVT_D_W = 0x0cd,
18596 NM_CVT_D_L = 0x14d,
18597 NM_CVT_S_D = 0x06d,
18598 NM_CVT_S_W = 0x0ed,
18599 NM_CVT_S_L = 0x16d,
18600};
18601
18602/* P.LL instruction pool */
18603enum {
18604 NM_LL = 0x00,
18605 NM_LLWP = 0x01,
18606};
18607
18608/* P.SC instruction pool */
18609enum {
18610 NM_SC = 0x00,
18611 NM_SCWP = 0x01,
18612};
18613
18614/* P.DVP instruction pool */
18615enum {
18616 NM_DVP = 0x00,
18617 NM_EVP = 0x01,
18618};
18619
c533c0f4
AM
18620
18621/*
18622 *
18623 * nanoMIPS decoding engine
18624 *
18625 */
18626
6bfa9f4c
AM
18627
18628/* extraction utilities */
18629
99e49abf
AM
18630#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18631#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18632#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
18633#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18634#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18635
ea4ca3c2
YK
18636/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18637static inline int decode_gpr_gpr3(int r)
18638{
18639 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18640
18641 return map[r & 0x7];
18642}
18643
8bdb7029
YK
18644/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18645static inline int decode_gpr_gpr3_src_store(int r)
18646{
18647 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18648
18649 return map[r & 0x7];
18650}
18651
ea4ca3c2
YK
18652/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18653static inline int decode_gpr_gpr4(int r)
18654{
18655 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18656 16, 17, 18, 19, 20, 21, 22, 23 };
18657
18658 return map[r & 0xf];
18659}
18660
8bdb7029
YK
18661/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18662static inline int decode_gpr_gpr4_zero(int r)
18663{
18664 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18665 16, 17, 18, 19, 20, 21, 22, 23 };
18666
18667 return map[r & 0xf];
18668}
18669
6bfa9f4c 18670
bf0718c5
SM
18671static void gen_adjust_sp(DisasContext *ctx, int u)
18672{
18673 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18674}
18675
18676static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18677 uint8_t gp, uint16_t u)
18678{
18679 int counter = 0;
18680 TCGv va = tcg_temp_new();
18681 TCGv t0 = tcg_temp_new();
18682
18683 while (counter != count) {
18684 bool use_gp = gp && (counter == count - 1);
18685 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18686 int this_offset = -((counter + 1) << 2);
18687 gen_base_offset_addr(ctx, va, 29, this_offset);
18688 gen_load_gpr(t0, this_rt);
18689 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18690 (MO_TEUL | ctx->default_tcg_memop_mask));
18691 counter++;
18692 }
18693
18694 /* adjust stack pointer */
18695 gen_adjust_sp(ctx, -u);
18696
18697 tcg_temp_free(t0);
18698 tcg_temp_free(va);
18699}
18700
18701static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18702 uint8_t gp, uint16_t u)
18703{
18704 int counter = 0;
18705 TCGv va = tcg_temp_new();
18706 TCGv t0 = tcg_temp_new();
18707
18708 while (counter != count) {
18709 bool use_gp = gp && (counter == count - 1);
18710 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18711 int this_offset = u - ((counter + 1) << 2);
18712 gen_base_offset_addr(ctx, va, 29, this_offset);
18713 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18714 ctx->default_tcg_memop_mask);
18715 tcg_gen_ext32s_tl(t0, t0);
18716 gen_store_gpr(t0, this_rt);
18717 counter++;
18718 }
18719
18720 /* adjust stack pointer */
18721 gen_adjust_sp(ctx, u);
18722
18723 tcg_temp_free(t0);
18724 tcg_temp_free(va);
18725}
18726
80845edf
YK
18727static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18728{
99e49abf
AM
18729 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18730 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
18731
18732 switch (extract32(ctx->opcode, 2, 2)) {
18733 case NM_NOT16:
18734 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18735 break;
18736 case NM_AND16:
18737 gen_logic(ctx, OPC_AND, rt, rt, rs);
18738 break;
18739 case NM_XOR16:
18740 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18741 break;
18742 case NM_OR16:
18743 gen_logic(ctx, OPC_OR, rt, rt, rs);
18744 break;
18745 }
18746}
18747
0a1a6ed7 18748static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18749{
18750 int rt = extract32(ctx->opcode, 21, 5);
18751 int rs = extract32(ctx->opcode, 16, 5);
18752 int rd = extract32(ctx->opcode, 11, 5);
18753
18754 switch (extract32(ctx->opcode, 3, 7)) {
18755 case NM_P_TRAP:
18756 switch (extract32(ctx->opcode, 10, 1)) {
18757 case NM_TEQ:
fb32f8c8 18758 check_nms(ctx);
e0cf0e65
YK
18759 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18760 break;
18761 case NM_TNE:
fb32f8c8 18762 check_nms(ctx);
e0cf0e65
YK
18763 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18764 break;
18765 }
18766 break;
18767 case NM_RDHWR:
fb32f8c8 18768 check_nms(ctx);
e0cf0e65
YK
18769 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18770 break;
18771 case NM_SEB:
fb32f8c8 18772 check_nms(ctx);
e0cf0e65
YK
18773 gen_bshfl(ctx, OPC_SEB, rs, rt);
18774 break;
18775 case NM_SEH:
18776 gen_bshfl(ctx, OPC_SEH, rs, rt);
18777 break;
18778 case NM_SLLV:
18779 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18780 break;
18781 case NM_SRLV:
18782 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18783 break;
18784 case NM_SRAV:
18785 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18786 break;
18787 case NM_ROTRV:
18788 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18789 break;
18790 case NM_ADD:
18791 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18792 break;
18793 case NM_ADDU:
18794 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18795 break;
18796 case NM_SUB:
fb32f8c8 18797 check_nms(ctx);
e0cf0e65
YK
18798 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18799 break;
18800 case NM_SUBU:
18801 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18802 break;
18803 case NM_P_CMOVE:
18804 switch (extract32(ctx->opcode, 10, 1)) {
18805 case NM_MOVZ:
18806 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18807 break;
18808 case NM_MOVN:
18809 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18810 break;
18811 }
18812 break;
18813 case NM_AND:
18814 gen_logic(ctx, OPC_AND, rd, rs, rt);
18815 break;
18816 case NM_OR:
18817 gen_logic(ctx, OPC_OR, rd, rs, rt);
18818 break;
18819 case NM_NOR:
18820 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18821 break;
18822 case NM_XOR:
18823 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18824 break;
18825 case NM_SLT:
18826 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18827 break;
18828 case NM_P_SLTU:
18829 if (rd == 0) {
18830 /* P_DVP */
18831#ifndef CONFIG_USER_ONLY
18832 TCGv t0 = tcg_temp_new();
18833 switch (extract32(ctx->opcode, 10, 1)) {
18834 case NM_DVP:
18835 if (ctx->vp) {
18836 check_cp0_enabled(ctx);
18837 gen_helper_dvp(t0, cpu_env);
18838 gen_store_gpr(t0, rt);
18839 }
18840 break;
18841 case NM_EVP:
18842 if (ctx->vp) {
18843 check_cp0_enabled(ctx);
18844 gen_helper_evp(t0, cpu_env);
18845 gen_store_gpr(t0, rt);
18846 }
18847 break;
18848 }
18849 tcg_temp_free(t0);
18850#endif
18851 } else {
18852 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18853 }
18854 break;
18855 case NM_SOV:
18856 {
18857 TCGv t0 = tcg_temp_new();
18858 TCGv t1 = tcg_temp_new();
18859 TCGv t2 = tcg_temp_new();
18860
18861 gen_load_gpr(t1, rs);
18862 gen_load_gpr(t2, rt);
18863 tcg_gen_add_tl(t0, t1, t2);
18864 tcg_gen_ext32s_tl(t0, t0);
18865 tcg_gen_xor_tl(t1, t1, t2);
18866 tcg_gen_xor_tl(t2, t0, t2);
18867 tcg_gen_andc_tl(t1, t2, t1);
18868
18869 /* operands of same sign, result different sign */
18870 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18871 gen_store_gpr(t0, rd);
18872
18873 tcg_temp_free(t0);
18874 tcg_temp_free(t1);
18875 tcg_temp_free(t2);
18876 }
18877 break;
18878 case NM_MUL:
18879 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18880 break;
18881 case NM_MUH:
18882 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18883 break;
18884 case NM_MULU:
18885 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18886 break;
18887 case NM_MUHU:
18888 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18889 break;
18890 case NM_DIV:
18891 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18892 break;
18893 case NM_MOD:
18894 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18895 break;
18896 case NM_DIVU:
18897 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18898 break;
18899 case NM_MODU:
18900 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18901 break;
18902#ifndef CONFIG_USER_ONLY
18903 case NM_MFC0:
18904 check_cp0_enabled(ctx);
18905 if (rt == 0) {
18906 /* Treat as NOP. */
18907 break;
18908 }
18909 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18910 break;
18911 case NM_MTC0:
18912 check_cp0_enabled(ctx);
18913 {
18914 TCGv t0 = tcg_temp_new();
18915
18916 gen_load_gpr(t0, rt);
18917 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18918 tcg_temp_free(t0);
18919 }
18920 break;
0a1a6ed7
SM
18921 case NM_D_E_MT_VPE:
18922 {
18923 uint8_t sc = extract32(ctx->opcode, 10, 1);
18924 TCGv t0 = tcg_temp_new();
18925
18926 switch (sc) {
18927 case 0:
18928 if (rs == 1) {
18929 /* DMT */
18930 check_cp0_mt(ctx);
18931 gen_helper_dmt(t0);
18932 gen_store_gpr(t0, rt);
18933 } else if (rs == 0) {
18934 /* DVPE */
18935 check_cp0_mt(ctx);
18936 gen_helper_dvpe(t0, cpu_env);
18937 gen_store_gpr(t0, rt);
18938 } else {
18939 generate_exception_end(ctx, EXCP_RI);
18940 }
18941 break;
18942 case 1:
18943 if (rs == 1) {
18944 /* EMT */
18945 check_cp0_mt(ctx);
18946 gen_helper_emt(t0);
18947 gen_store_gpr(t0, rt);
18948 } else if (rs == 0) {
18949 /* EVPE */
18950 check_cp0_mt(ctx);
18951 gen_helper_evpe(t0, cpu_env);
18952 gen_store_gpr(t0, rt);
18953 } else {
18954 generate_exception_end(ctx, EXCP_RI);
18955 }
18956 break;
18957 }
18958
18959 tcg_temp_free(t0);
18960 }
18961 break;
18962 case NM_FORK:
18963 check_mt(ctx);
18964 {
18965 TCGv t0 = tcg_temp_new();
18966 TCGv t1 = tcg_temp_new();
18967
18968 gen_load_gpr(t0, rt);
18969 gen_load_gpr(t1, rs);
18970 gen_helper_fork(t0, t1);
18971 tcg_temp_free(t0);
18972 tcg_temp_free(t1);
18973 }
18974 break;
18975 case NM_MFTR:
18976 case NM_MFHTR:
18977 check_cp0_enabled(ctx);
18978 if (rd == 0) {
18979 /* Treat as NOP. */
18980 return;
18981 }
18982 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18983 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18984 break;
18985 case NM_MTTR:
18986 case NM_MTHTR:
18987 check_cp0_enabled(ctx);
18988 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18989 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18990 break;
18991 case NM_YIELD:
18992 check_mt(ctx);
18993 {
18994 TCGv t0 = tcg_temp_new();
18995
18996 gen_load_gpr(t0, rs);
18997 gen_helper_yield(t0, cpu_env, t0);
18998 gen_store_gpr(t0, rt);
18999 tcg_temp_free(t0);
19000 }
19001 break;
e0cf0e65
YK
19002#endif
19003 default:
19004 generate_exception_end(ctx, EXCP_RI);
19005 break;
19006 }
19007}
19008
2ed42efa
SM
19009/* dsp */
19010static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19011 int ret, int v1, int v2)
19012{
19013 TCGv_i32 t0;
19014 TCGv v0_t;
19015 TCGv v1_t;
19016
19017 t0 = tcg_temp_new_i32();
19018
19019 v0_t = tcg_temp_new();
19020 v1_t = tcg_temp_new();
19021
19022 tcg_gen_movi_i32(t0, v2 >> 3);
19023
19024 gen_load_gpr(v0_t, ret);
19025 gen_load_gpr(v1_t, v1);
19026
19027 switch (opc) {
19028 case NM_MAQ_S_W_PHR:
19029 check_dsp(ctx);
19030 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19031 break;
19032 case NM_MAQ_S_W_PHL:
19033 check_dsp(ctx);
19034 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19035 break;
19036 case NM_MAQ_SA_W_PHR:
19037 check_dsp(ctx);
19038 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19039 break;
19040 case NM_MAQ_SA_W_PHL:
19041 check_dsp(ctx);
19042 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19043 break;
19044 default:
19045 generate_exception_end(ctx, EXCP_RI);
19046 break;
19047 }
19048
19049 tcg_temp_free_i32(t0);
19050
19051 tcg_temp_free(v0_t);
19052 tcg_temp_free(v1_t);
19053}
19054
19055
19056static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19057 int ret, int v1, int v2)
19058{
19059 int16_t imm;
19060 TCGv t0 = tcg_temp_new();
19061 TCGv t1 = tcg_temp_new();
19062 TCGv v0_t = tcg_temp_new();
19063
19064 gen_load_gpr(v0_t, v1);
19065
19066 switch (opc) {
19067 case NM_POOL32AXF_1_0:
19068 check_dsp(ctx);
19069 switch (extract32(ctx->opcode, 12, 2)) {
19070 case NM_MFHI:
19071 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19072 break;
19073 case NM_MFLO:
19074 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19075 break;
19076 case NM_MTHI:
19077 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19078 break;
19079 case NM_MTLO:
19080 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19081 break;
19082 }
19083 break;
19084 case NM_POOL32AXF_1_1:
19085 check_dsp(ctx);
19086 switch (extract32(ctx->opcode, 12, 2)) {
19087 case NM_MTHLIP:
19088 tcg_gen_movi_tl(t0, v2);
19089 gen_helper_mthlip(t0, v0_t, cpu_env);
19090 break;
19091 case NM_SHILOV:
19092 tcg_gen_movi_tl(t0, v2 >> 3);
19093 gen_helper_shilo(t0, v0_t, cpu_env);
19094 break;
19095 default:
19096 generate_exception_end(ctx, EXCP_RI);
19097 break;
19098 }
19099 break;
19100 case NM_POOL32AXF_1_3:
19101 check_dsp(ctx);
19102 imm = extract32(ctx->opcode, 14, 7);
19103 switch (extract32(ctx->opcode, 12, 2)) {
19104 case NM_RDDSP:
19105 tcg_gen_movi_tl(t0, imm);
19106 gen_helper_rddsp(t0, t0, cpu_env);
19107 gen_store_gpr(t0, ret);
19108 break;
19109 case NM_WRDSP:
19110 gen_load_gpr(t0, ret);
19111 tcg_gen_movi_tl(t1, imm);
19112 gen_helper_wrdsp(t0, t1, cpu_env);
19113 break;
19114 case NM_EXTP:
19115 tcg_gen_movi_tl(t0, v2 >> 3);
19116 tcg_gen_movi_tl(t1, v1);
19117 gen_helper_extp(t0, t0, t1, cpu_env);
19118 gen_store_gpr(t0, ret);
19119 break;
19120 case NM_EXTPDP:
19121 tcg_gen_movi_tl(t0, v2 >> 3);
19122 tcg_gen_movi_tl(t1, v1);
19123 gen_helper_extpdp(t0, t0, t1, cpu_env);
19124 gen_store_gpr(t0, ret);
19125 break;
19126 }
19127 break;
19128 case NM_POOL32AXF_1_4:
19129 check_dsp(ctx);
19130 tcg_gen_movi_tl(t0, v2 >> 2);
19131 switch (extract32(ctx->opcode, 12, 1)) {
19132 case NM_SHLL_QB:
19133 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19134 gen_store_gpr(t0, ret);
19135 break;
19136 case NM_SHRL_QB:
19137 gen_helper_shrl_qb(t0, t0, v0_t);
19138 gen_store_gpr(t0, ret);
19139 break;
19140 }
19141 break;
19142 case NM_POOL32AXF_1_5:
19143 opc = extract32(ctx->opcode, 12, 2);
19144 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19145 break;
19146 case NM_POOL32AXF_1_7:
19147 check_dsp(ctx);
19148 tcg_gen_movi_tl(t0, v2 >> 3);
19149 tcg_gen_movi_tl(t1, v1);
19150 switch (extract32(ctx->opcode, 12, 2)) {
19151 case NM_EXTR_W:
19152 gen_helper_extr_w(t0, t0, t1, cpu_env);
19153 gen_store_gpr(t0, ret);
19154 break;
19155 case NM_EXTR_R_W:
19156 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19157 gen_store_gpr(t0, ret);
19158 break;
19159 case NM_EXTR_RS_W:
19160 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19161 gen_store_gpr(t0, ret);
19162 break;
19163 case NM_EXTR_S_H:
19164 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19165 gen_store_gpr(t0, ret);
19166 break;
19167 }
19168 break;
19169 default:
19170 generate_exception_end(ctx, EXCP_RI);
19171 break;
19172 }
19173
19174 tcg_temp_free(t0);
19175 tcg_temp_free(t1);
19176 tcg_temp_free(v0_t);
19177}
19178
8b3698b2
SM
19179static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19180 TCGv v0, TCGv v1, int rd)
19181{
19182 TCGv_i32 t0;
19183
19184 t0 = tcg_temp_new_i32();
19185
19186 tcg_gen_movi_i32(t0, rd >> 3);
19187
19188 switch (opc) {
19189 case NM_POOL32AXF_2_0_7:
19190 switch (extract32(ctx->opcode, 9, 3)) {
19191 case NM_DPA_W_PH:
908f6be1 19192 check_dsp_r2(ctx);
8b3698b2
SM
19193 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19194 break;
19195 case NM_DPAQ_S_W_PH:
19196 check_dsp(ctx);
19197 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19198 break;
19199 case NM_DPS_W_PH:
908f6be1 19200 check_dsp_r2(ctx);
8b3698b2
SM
19201 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19202 break;
19203 case NM_DPSQ_S_W_PH:
19204 check_dsp(ctx);
19205 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19206 break;
19207 default:
19208 generate_exception_end(ctx, EXCP_RI);
19209 break;
19210 }
19211 break;
19212 case NM_POOL32AXF_2_8_15:
19213 switch (extract32(ctx->opcode, 9, 3)) {
19214 case NM_DPAX_W_PH:
908f6be1 19215 check_dsp_r2(ctx);
8b3698b2
SM
19216 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19217 break;
19218 case NM_DPAQ_SA_L_W:
19219 check_dsp(ctx);
19220 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19221 break;
19222 case NM_DPSX_W_PH:
908f6be1 19223 check_dsp_r2(ctx);
8b3698b2
SM
19224 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19225 break;
19226 case NM_DPSQ_SA_L_W:
19227 check_dsp(ctx);
19228 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19229 break;
19230 default:
19231 generate_exception_end(ctx, EXCP_RI);
19232 break;
19233 }
19234 break;
19235 case NM_POOL32AXF_2_16_23:
19236 switch (extract32(ctx->opcode, 9, 3)) {
19237 case NM_DPAU_H_QBL:
19238 check_dsp(ctx);
19239 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19240 break;
19241 case NM_DPAQX_S_W_PH:
908f6be1 19242 check_dsp_r2(ctx);
8b3698b2
SM
19243 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19244 break;
19245 case NM_DPSU_H_QBL:
19246 check_dsp(ctx);
19247 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19248 break;
19249 case NM_DPSQX_S_W_PH:
908f6be1 19250 check_dsp_r2(ctx);
8b3698b2
SM
19251 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19252 break;
19253 case NM_MULSA_W_PH:
908f6be1 19254 check_dsp_r2(ctx);
8b3698b2
SM
19255 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19256 break;
19257 default:
19258 generate_exception_end(ctx, EXCP_RI);
19259 break;
19260 }
19261 break;
19262 case NM_POOL32AXF_2_24_31:
19263 switch (extract32(ctx->opcode, 9, 3)) {
19264 case NM_DPAU_H_QBR:
19265 check_dsp(ctx);
19266 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19267 break;
19268 case NM_DPAQX_SA_W_PH:
908f6be1 19269 check_dsp_r2(ctx);
8b3698b2
SM
19270 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19271 break;
19272 case NM_DPSU_H_QBR:
19273 check_dsp(ctx);
19274 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19275 break;
19276 case NM_DPSQX_SA_W_PH:
908f6be1 19277 check_dsp_r2(ctx);
8b3698b2
SM
19278 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19279 break;
19280 case NM_MULSAQ_S_W_PH:
19281 check_dsp(ctx);
19282 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19283 break;
19284 default:
19285 generate_exception_end(ctx, EXCP_RI);
19286 break;
19287 }
19288 break;
19289 default:
19290 generate_exception_end(ctx, EXCP_RI);
19291 break;
19292 }
19293
19294 tcg_temp_free_i32(t0);
19295}
19296
19297static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19298 int rt, int rs, int rd)
19299{
19300 int ret = rt;
19301 TCGv t0 = tcg_temp_new();
19302 TCGv t1 = tcg_temp_new();
19303 TCGv v0_t = tcg_temp_new();
19304 TCGv v1_t = tcg_temp_new();
19305
19306 gen_load_gpr(v0_t, rt);
19307 gen_load_gpr(v1_t, rs);
19308
19309 switch (opc) {
19310 case NM_POOL32AXF_2_0_7:
19311 switch (extract32(ctx->opcode, 9, 3)) {
19312 case NM_DPA_W_PH:
19313 case NM_DPAQ_S_W_PH:
19314 case NM_DPS_W_PH:
19315 case NM_DPSQ_S_W_PH:
19316 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19317 break;
19318 case NM_BALIGN:
908f6be1 19319 check_dsp_r2(ctx);
8b3698b2
SM
19320 if (rt != 0) {
19321 gen_load_gpr(t0, rs);
19322 rd &= 3;
19323 if (rd != 0 && rd != 2) {
19324 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19325 tcg_gen_ext32u_tl(t0, t0);
19326 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19327 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19328 }
19329 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19330 }
19331 break;
19332 case NM_MADD:
19333 check_dsp(ctx);
19334 {
19335 int acc = extract32(ctx->opcode, 14, 2);
19336 TCGv_i64 t2 = tcg_temp_new_i64();
19337 TCGv_i64 t3 = tcg_temp_new_i64();
19338
19339 gen_load_gpr(t0, rt);
19340 gen_load_gpr(t1, rs);
19341 tcg_gen_ext_tl_i64(t2, t0);
19342 tcg_gen_ext_tl_i64(t3, t1);
19343 tcg_gen_mul_i64(t2, t2, t3);
19344 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19345 tcg_gen_add_i64(t2, t2, t3);
19346 tcg_temp_free_i64(t3);
19347 gen_move_low32(cpu_LO[acc], t2);
19348 gen_move_high32(cpu_HI[acc], t2);
19349 tcg_temp_free_i64(t2);
19350 }
19351 break;
19352 case NM_MULT:
19353 check_dsp(ctx);
19354 {
19355 int acc = extract32(ctx->opcode, 14, 2);
19356 TCGv_i32 t2 = tcg_temp_new_i32();
19357 TCGv_i32 t3 = tcg_temp_new_i32();
19358
19359 gen_load_gpr(t0, rs);
19360 gen_load_gpr(t1, rt);
19361 tcg_gen_trunc_tl_i32(t2, t0);
19362 tcg_gen_trunc_tl_i32(t3, t1);
19363 tcg_gen_muls2_i32(t2, t3, t2, t3);
19364 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19365 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19366 tcg_temp_free_i32(t2);
19367 tcg_temp_free_i32(t3);
19368 }
19369 break;
19370 case NM_EXTRV_W:
19371 check_dsp(ctx);
19372 gen_load_gpr(v1_t, rs);
19373 tcg_gen_movi_tl(t0, rd >> 3);
19374 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19375 gen_store_gpr(t0, ret);
19376 break;
19377 }
19378 break;
19379 case NM_POOL32AXF_2_8_15:
19380 switch (extract32(ctx->opcode, 9, 3)) {
19381 case NM_DPAX_W_PH:
19382 case NM_DPAQ_SA_L_W:
19383 case NM_DPSX_W_PH:
19384 case NM_DPSQ_SA_L_W:
19385 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19386 break;
19387 case NM_MADDU:
19388 check_dsp(ctx);
19389 {
19390 int acc = extract32(ctx->opcode, 14, 2);
19391 TCGv_i64 t2 = tcg_temp_new_i64();
19392 TCGv_i64 t3 = tcg_temp_new_i64();
19393
19394 gen_load_gpr(t0, rs);
19395 gen_load_gpr(t1, rt);
19396 tcg_gen_ext32u_tl(t0, t0);
19397 tcg_gen_ext32u_tl(t1, t1);
19398 tcg_gen_extu_tl_i64(t2, t0);
19399 tcg_gen_extu_tl_i64(t3, t1);
19400 tcg_gen_mul_i64(t2, t2, t3);
19401 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19402 tcg_gen_add_i64(t2, t2, t3);
19403 tcg_temp_free_i64(t3);
19404 gen_move_low32(cpu_LO[acc], t2);
19405 gen_move_high32(cpu_HI[acc], t2);
19406 tcg_temp_free_i64(t2);
19407 }
19408 break;
19409 case NM_MULTU:
19410 check_dsp(ctx);
19411 {
19412 int acc = extract32(ctx->opcode, 14, 2);
19413 TCGv_i32 t2 = tcg_temp_new_i32();
19414 TCGv_i32 t3 = tcg_temp_new_i32();
19415
19416 gen_load_gpr(t0, rs);
19417 gen_load_gpr(t1, rt);
19418 tcg_gen_trunc_tl_i32(t2, t0);
19419 tcg_gen_trunc_tl_i32(t3, t1);
19420 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19421 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19422 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19423 tcg_temp_free_i32(t2);
19424 tcg_temp_free_i32(t3);
19425 }
19426 break;
19427 case NM_EXTRV_R_W:
19428 check_dsp(ctx);
19429 tcg_gen_movi_tl(t0, rd >> 3);
19430 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19431 gen_store_gpr(t0, ret);
19432 break;
19433 default:
19434 generate_exception_end(ctx, EXCP_RI);
19435 break;
19436 }
19437 break;
19438 case NM_POOL32AXF_2_16_23:
19439 switch (extract32(ctx->opcode, 9, 3)) {
19440 case NM_DPAU_H_QBL:
19441 case NM_DPAQX_S_W_PH:
19442 case NM_DPSU_H_QBL:
19443 case NM_DPSQX_S_W_PH:
19444 case NM_MULSA_W_PH:
19445 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19446 break;
19447 case NM_EXTPV:
19448 check_dsp(ctx);
19449 tcg_gen_movi_tl(t0, rd >> 3);
19450 gen_helper_extp(t0, t0, v1_t, cpu_env);
19451 gen_store_gpr(t0, ret);
19452 break;
19453 case NM_MSUB:
19454 check_dsp(ctx);
19455 {
19456 int acc = extract32(ctx->opcode, 14, 2);
19457 TCGv_i64 t2 = tcg_temp_new_i64();
19458 TCGv_i64 t3 = tcg_temp_new_i64();
19459
19460 gen_load_gpr(t0, rs);
19461 gen_load_gpr(t1, rt);
19462 tcg_gen_ext_tl_i64(t2, t0);
19463 tcg_gen_ext_tl_i64(t3, t1);
19464 tcg_gen_mul_i64(t2, t2, t3);
19465 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19466 tcg_gen_sub_i64(t2, t3, t2);
19467 tcg_temp_free_i64(t3);
19468 gen_move_low32(cpu_LO[acc], t2);
19469 gen_move_high32(cpu_HI[acc], t2);
19470 tcg_temp_free_i64(t2);
19471 }
19472 break;
19473 case NM_EXTRV_RS_W:
19474 check_dsp(ctx);
19475 tcg_gen_movi_tl(t0, rd >> 3);
19476 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19477 gen_store_gpr(t0, ret);
19478 break;
19479 }
19480 break;
19481 case NM_POOL32AXF_2_24_31:
19482 switch (extract32(ctx->opcode, 9, 3)) {
19483 case NM_DPAU_H_QBR:
19484 case NM_DPAQX_SA_W_PH:
19485 case NM_DPSU_H_QBR:
19486 case NM_DPSQX_SA_W_PH:
19487 case NM_MULSAQ_S_W_PH:
19488 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19489 break;
19490 case NM_EXTPDPV:
19491 check_dsp(ctx);
19492 tcg_gen_movi_tl(t0, rd >> 3);
19493 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19494 gen_store_gpr(t0, ret);
19495 break;
19496 case NM_MSUBU:
19497 check_dsp(ctx);
19498 {
19499 int acc = extract32(ctx->opcode, 14, 2);
19500 TCGv_i64 t2 = tcg_temp_new_i64();
19501 TCGv_i64 t3 = tcg_temp_new_i64();
19502
19503 gen_load_gpr(t0, rs);
19504 gen_load_gpr(t1, rt);
19505 tcg_gen_ext32u_tl(t0, t0);
19506 tcg_gen_ext32u_tl(t1, t1);
19507 tcg_gen_extu_tl_i64(t2, t0);
19508 tcg_gen_extu_tl_i64(t3, t1);
19509 tcg_gen_mul_i64(t2, t2, t3);
19510 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19511 tcg_gen_sub_i64(t2, t3, t2);
19512 tcg_temp_free_i64(t3);
19513 gen_move_low32(cpu_LO[acc], t2);
19514 gen_move_high32(cpu_HI[acc], t2);
19515 tcg_temp_free_i64(t2);
19516 }
19517 break;
19518 case NM_EXTRV_S_H:
19519 check_dsp(ctx);
19520 tcg_gen_movi_tl(t0, rd >> 3);
19521 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19522 gen_store_gpr(t0, ret);
19523 break;
19524 }
19525 break;
19526 default:
19527 generate_exception_end(ctx, EXCP_RI);
19528 break;
19529 }
19530
19531 tcg_temp_free(t0);
19532 tcg_temp_free(t1);
19533
19534 tcg_temp_free(v0_t);
19535 tcg_temp_free(v1_t);
19536}
19537
4c75c985
SM
19538static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19539 int rt, int rs)
19540{
19541 int ret = rt;
19542 TCGv t0 = tcg_temp_new();
19543 TCGv v0_t = tcg_temp_new();
19544
19545 gen_load_gpr(v0_t, rs);
19546
19547 switch (opc) {
19548 case NM_ABSQ_S_QB:
908f6be1 19549 check_dsp_r2(ctx);
4c75c985
SM
19550 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19551 gen_store_gpr(v0_t, ret);
19552 break;
19553 case NM_ABSQ_S_PH:
19554 check_dsp(ctx);
19555 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19556 gen_store_gpr(v0_t, ret);
19557 break;
19558 case NM_ABSQ_S_W:
19559 check_dsp(ctx);
19560 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19561 gen_store_gpr(v0_t, ret);
19562 break;
19563 case NM_PRECEQ_W_PHL:
19564 check_dsp(ctx);
19565 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19566 tcg_gen_ext32s_tl(v0_t, v0_t);
19567 gen_store_gpr(v0_t, ret);
19568 break;
19569 case NM_PRECEQ_W_PHR:
19570 check_dsp(ctx);
19571 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19572 tcg_gen_shli_tl(v0_t, v0_t, 16);
19573 tcg_gen_ext32s_tl(v0_t, v0_t);
19574 gen_store_gpr(v0_t, ret);
19575 break;
19576 case NM_PRECEQU_PH_QBL:
19577 check_dsp(ctx);
19578 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19579 gen_store_gpr(v0_t, ret);
19580 break;
19581 case NM_PRECEQU_PH_QBR:
19582 check_dsp(ctx);
19583 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19584 gen_store_gpr(v0_t, ret);
19585 break;
19586 case NM_PRECEQU_PH_QBLA:
19587 check_dsp(ctx);
19588 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19589 gen_store_gpr(v0_t, ret);
19590 break;
19591 case NM_PRECEQU_PH_QBRA:
19592 check_dsp(ctx);
19593 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19594 gen_store_gpr(v0_t, ret);
19595 break;
19596 case NM_PRECEU_PH_QBL:
19597 check_dsp(ctx);
19598 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19599 gen_store_gpr(v0_t, ret);
19600 break;
19601 case NM_PRECEU_PH_QBR:
19602 check_dsp(ctx);
19603 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19604 gen_store_gpr(v0_t, ret);
19605 break;
19606 case NM_PRECEU_PH_QBLA:
19607 check_dsp(ctx);
19608 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19609 gen_store_gpr(v0_t, ret);
19610 break;
19611 case NM_PRECEU_PH_QBRA:
19612 check_dsp(ctx);
19613 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19614 gen_store_gpr(v0_t, ret);
19615 break;
19616 case NM_REPLV_PH:
19617 check_dsp(ctx);
19618 tcg_gen_ext16u_tl(v0_t, v0_t);
19619 tcg_gen_shli_tl(t0, v0_t, 16);
19620 tcg_gen_or_tl(v0_t, v0_t, t0);
19621 tcg_gen_ext32s_tl(v0_t, v0_t);
19622 gen_store_gpr(v0_t, ret);
19623 break;
19624 case NM_REPLV_QB:
19625 check_dsp(ctx);
19626 tcg_gen_ext8u_tl(v0_t, v0_t);
19627 tcg_gen_shli_tl(t0, v0_t, 8);
19628 tcg_gen_or_tl(v0_t, v0_t, t0);
19629 tcg_gen_shli_tl(t0, v0_t, 16);
19630 tcg_gen_or_tl(v0_t, v0_t, t0);
19631 tcg_gen_ext32s_tl(v0_t, v0_t);
19632 gen_store_gpr(v0_t, ret);
19633 break;
19634 case NM_BITREV:
19635 check_dsp(ctx);
19636 gen_helper_bitrev(v0_t, v0_t);
19637 gen_store_gpr(v0_t, ret);
19638 break;
19639 case NM_INSV:
19640 check_dsp(ctx);
19641 {
19642 TCGv tv0 = tcg_temp_new();
19643
19644 gen_load_gpr(tv0, rt);
19645 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19646 gen_store_gpr(v0_t, ret);
19647 tcg_temp_free(tv0);
19648 }
19649 break;
19650 case NM_RADDU_W_QB:
19651 check_dsp(ctx);
19652 gen_helper_raddu_w_qb(v0_t, v0_t);
19653 gen_store_gpr(v0_t, ret);
19654 break;
19655 case NM_BITSWAP:
19656 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19657 break;
19658 case NM_CLO:
fb32f8c8 19659 check_nms(ctx);
4c75c985
SM
19660 gen_cl(ctx, OPC_CLO, ret, rs);
19661 break;
19662 case NM_CLZ:
fb32f8c8 19663 check_nms(ctx);
4c75c985
SM
19664 gen_cl(ctx, OPC_CLZ, ret, rs);
19665 break;
19666 case NM_WSBH:
19667 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19668 break;
19669 default:
19670 generate_exception_end(ctx, EXCP_RI);
19671 break;
19672 }
19673
19674 tcg_temp_free(v0_t);
19675 tcg_temp_free(t0);
19676}
19677
0b591184
SM
19678static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19679 int rt, int rs, int rd)
19680{
19681 TCGv t0 = tcg_temp_new();
19682 TCGv rs_t = tcg_temp_new();
19683
19684 gen_load_gpr(rs_t, rs);
19685
19686 switch (opc) {
19687 case NM_SHRA_R_QB:
908f6be1 19688 check_dsp_r2(ctx);
0b591184
SM
19689 tcg_gen_movi_tl(t0, rd >> 2);
19690 switch (extract32(ctx->opcode, 12, 1)) {
19691 case 0:
19692 /* NM_SHRA_QB */
19693 gen_helper_shra_qb(t0, t0, rs_t);
19694 gen_store_gpr(t0, rt);
19695 break;
19696 case 1:
19697 /* NM_SHRA_R_QB */
19698 gen_helper_shra_r_qb(t0, t0, rs_t);
19699 gen_store_gpr(t0, rt);
19700 break;
19701 }
19702 break;
19703 case NM_SHRL_PH:
908f6be1 19704 check_dsp_r2(ctx);
0b591184
SM
19705 tcg_gen_movi_tl(t0, rd >> 1);
19706 gen_helper_shrl_ph(t0, t0, rs_t);
19707 gen_store_gpr(t0, rt);
19708 break;
19709 case NM_REPL_QB:
19710 check_dsp(ctx);
19711 {
19712 int16_t imm;
19713 target_long result;
19714 imm = extract32(ctx->opcode, 13, 8);
19715 result = (uint32_t)imm << 24 |
19716 (uint32_t)imm << 16 |
19717 (uint32_t)imm << 8 |
19718 (uint32_t)imm;
19719 result = (int32_t)result;
19720 tcg_gen_movi_tl(t0, result);
19721 gen_store_gpr(t0, rt);
19722 }
19723 break;
19724 default:
19725 generate_exception_end(ctx, EXCP_RI);
19726 break;
19727 }
19728 tcg_temp_free(t0);
19729 tcg_temp_free(rs_t);
19730}
19731
2ed42efa 19732
64224187
YK
19733static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19734{
64224187
YK
19735 int rt = extract32(ctx->opcode, 21, 5);
19736 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19737 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19738
19739 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19740 case NM_POOL32AXF_1:
19741 {
19742 int32_t op1 = extract32(ctx->opcode, 9, 3);
19743 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19744 }
19745 break;
19746 case NM_POOL32AXF_2:
8b3698b2
SM
19747 {
19748 int32_t op1 = extract32(ctx->opcode, 12, 2);
19749 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19750 }
2ed42efa 19751 break;
64224187 19752 case NM_POOL32AXF_4:
4c75c985
SM
19753 {
19754 int32_t op1 = extract32(ctx->opcode, 9, 7);
19755 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19756 }
2ed42efa 19757 break;
64224187
YK
19758 case NM_POOL32AXF_5:
19759 switch (extract32(ctx->opcode, 9, 7)) {
19760#ifndef CONFIG_USER_ONLY
19761 case NM_TLBP:
19762 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19763 break;
19764 case NM_TLBR:
19765 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19766 break;
19767 case NM_TLBWI:
19768 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19769 break;
19770 case NM_TLBWR:
19771 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19772 break;
19773 case NM_TLBINV:
19774 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19775 break;
19776 case NM_TLBINVF:
19777 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19778 break;
19779 case NM_DI:
19780 check_cp0_enabled(ctx);
19781 {
19782 TCGv t0 = tcg_temp_new();
19783
19784 save_cpu_state(ctx, 1);
19785 gen_helper_di(t0, cpu_env);
19786 gen_store_gpr(t0, rt);
19787 /* Stop translation as we may have switched the execution mode */
19788 ctx->base.is_jmp = DISAS_STOP;
19789 tcg_temp_free(t0);
19790 }
19791 break;
19792 case NM_EI:
19793 check_cp0_enabled(ctx);
19794 {
19795 TCGv t0 = tcg_temp_new();
19796
19797 save_cpu_state(ctx, 1);
19798 gen_helper_ei(t0, cpu_env);
19799 gen_store_gpr(t0, rt);
19800 /* Stop translation as we may have switched the execution mode */
19801 ctx->base.is_jmp = DISAS_STOP;
19802 tcg_temp_free(t0);
19803 }
19804 break;
19805 case NM_RDPGPR:
19806 gen_load_srsgpr(rs, rt);
19807 break;
19808 case NM_WRPGPR:
19809 gen_store_srsgpr(rs, rt);
19810 break;
19811 case NM_WAIT:
19812 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19813 break;
19814 case NM_DERET:
19815 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19816 break;
19817 case NM_ERETX:
19818 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19819 break;
19820#endif
19821 default:
19822 generate_exception_end(ctx, EXCP_RI);
19823 break;
19824 }
19825 break;
2ed42efa 19826 case NM_POOL32AXF_7:
0b591184
SM
19827 {
19828 int32_t op1 = extract32(ctx->opcode, 9, 3);
19829 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19830 }
2ed42efa 19831 break;
64224187
YK
19832 default:
19833 generate_exception_end(ctx, EXCP_RI);
19834 break;
19835 }
19836}
19837
11d0fc10
SM
19838/* Immediate Value Compact Branches */
19839static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19840 int rt, int32_t imm, int32_t offset)
19841{
19842 TCGCond cond;
19843 int bcond_compute = 0;
19844 TCGv t0 = tcg_temp_new();
19845 TCGv t1 = tcg_temp_new();
19846
19847 gen_load_gpr(t0, rt);
19848 tcg_gen_movi_tl(t1, imm);
19849 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19850
19851 /* Load needed operands and calculate btarget */
19852 switch (opc) {
19853 case NM_BEQIC:
19854 if (rt == 0 && imm == 0) {
19855 /* Unconditional branch */
19856 } else if (rt == 0 && imm != 0) {
19857 /* Treat as NOP */
19858 goto out;
19859 } else {
19860 bcond_compute = 1;
19861 cond = TCG_COND_EQ;
19862 }
19863 break;
19864 case NM_BBEQZC:
19865 case NM_BBNEZC:
fb32f8c8 19866 check_nms(ctx);
11d0fc10
SM
19867 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19868 generate_exception_end(ctx, EXCP_RI);
19869 goto out;
19870 } else if (rt == 0 && opc == NM_BBEQZC) {
19871 /* Unconditional branch */
19872 } else if (rt == 0 && opc == NM_BBNEZC) {
19873 /* Treat as NOP */
19874 goto out;
19875 } else {
19876 tcg_gen_shri_tl(t0, t0, imm);
19877 tcg_gen_andi_tl(t0, t0, 1);
19878 tcg_gen_movi_tl(t1, 0);
19879 bcond_compute = 1;
19880 if (opc == NM_BBEQZC) {
19881 cond = TCG_COND_EQ;
19882 } else {
19883 cond = TCG_COND_NE;
19884 }
19885 }
19886 break;
19887 case NM_BNEIC:
19888 if (rt == 0 && imm == 0) {
19889 /* Treat as NOP */
19890 goto out;
19891 } else if (rt == 0 && imm != 0) {
19892 /* Unconditional branch */
19893 } else {
19894 bcond_compute = 1;
19895 cond = TCG_COND_NE;
19896 }
19897 break;
19898 case NM_BGEIC:
19899 if (rt == 0 && imm == 0) {
19900 /* Unconditional branch */
19901 } else {
19902 bcond_compute = 1;
19903 cond = TCG_COND_GE;
19904 }
19905 break;
19906 case NM_BLTIC:
19907 bcond_compute = 1;
19908 cond = TCG_COND_LT;
19909 break;
19910 case NM_BGEIUC:
19911 if (rt == 0 && imm == 0) {
19912 /* Unconditional branch */
19913 } else {
19914 bcond_compute = 1;
19915 cond = TCG_COND_GEU;
19916 }
19917 break;
19918 case NM_BLTIUC:
19919 bcond_compute = 1;
19920 cond = TCG_COND_LTU;
19921 break;
19922 default:
19923 MIPS_INVAL("Immediate Value Compact branch");
19924 generate_exception_end(ctx, EXCP_RI);
19925 goto out;
19926 }
19927
697b7b6b
SM
19928 /* branch completion */
19929 clear_branch_hflags(ctx);
19930 ctx->base.is_jmp = DISAS_NORETURN;
19931
11d0fc10
SM
19932 if (bcond_compute == 0) {
19933 /* Uncoditional compact branch */
19934 gen_goto_tb(ctx, 0, ctx->btarget);
19935 } else {
19936 /* Conditional compact branch */
19937 TCGLabel *fs = gen_new_label();
19938
19939 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19940
19941 gen_goto_tb(ctx, 1, ctx->btarget);
19942 gen_set_label(fs);
19943
19944 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19945 }
19946
19947out:
19948 tcg_temp_free(t0);
19949 tcg_temp_free(t1);
19950}
19951
19952/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19953static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19954 int rt)
19955{
19956 TCGv t0 = tcg_temp_new();
19957 TCGv t1 = tcg_temp_new();
19958
19959 /* load rs */
19960 gen_load_gpr(t0, rs);
19961
19962 /* link */
19963 if (rt != 0) {
19964 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19965 }
19966
19967 /* calculate btarget */
19968 tcg_gen_shli_tl(t0, t0, 1);
19969 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19970 gen_op_addr_add(ctx, btarget, t1, t0);
19971
697b7b6b
SM
19972 /* branch completion */
19973 clear_branch_hflags(ctx);
19974 ctx->base.is_jmp = DISAS_NORETURN;
19975
11d0fc10
SM
19976 /* unconditional branch to register */
19977 tcg_gen_mov_tl(cpu_PC, btarget);
19978 tcg_gen_lookup_and_goto_ptr();
19979
19980 tcg_temp_free(t0);
19981 tcg_temp_free(t1);
19982}
19983
19984/* nanoMIPS Branches */
19985static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19986 int rs, int rt, int32_t offset)
19987{
19988 int bcond_compute = 0;
19989 TCGv t0 = tcg_temp_new();
19990 TCGv t1 = tcg_temp_new();
19991
19992 /* Load needed operands and calculate btarget */
19993 switch (opc) {
19994 /* compact branch */
19995 case OPC_BGEC:
19996 case OPC_BLTC:
19997 gen_load_gpr(t0, rs);
19998 gen_load_gpr(t1, rt);
19999 bcond_compute = 1;
20000 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20001 break;
20002 case OPC_BGEUC:
20003 case OPC_BLTUC:
20004 if (rs == 0 || rs == rt) {
20005 /* OPC_BLEZALC, OPC_BGEZALC */
20006 /* OPC_BGTZALC, OPC_BLTZALC */
20007 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20008 }
20009 gen_load_gpr(t0, rs);
20010 gen_load_gpr(t1, rt);
20011 bcond_compute = 1;
20012 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20013 break;
20014 case OPC_BC:
20015 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20016 break;
20017 case OPC_BEQZC:
20018 if (rs != 0) {
20019 /* OPC_BEQZC, OPC_BNEZC */
20020 gen_load_gpr(t0, rs);
20021 bcond_compute = 1;
20022 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20023 } else {
20024 /* OPC_JIC, OPC_JIALC */
20025 TCGv tbase = tcg_temp_new();
20026 TCGv toffset = tcg_temp_new();
20027
20028 gen_load_gpr(tbase, rt);
20029 tcg_gen_movi_tl(toffset, offset);
20030 gen_op_addr_add(ctx, btarget, tbase, toffset);
20031 tcg_temp_free(tbase);
20032 tcg_temp_free(toffset);
20033 }
20034 break;
20035 default:
20036 MIPS_INVAL("Compact branch/jump");
20037 generate_exception_end(ctx, EXCP_RI);
20038 goto out;
20039 }
20040
20041 if (bcond_compute == 0) {
20042 /* Uncoditional compact branch */
20043 switch (opc) {
20044 case OPC_BC:
20045 gen_goto_tb(ctx, 0, ctx->btarget);
20046 break;
20047 default:
20048 MIPS_INVAL("Compact branch/jump");
20049 generate_exception_end(ctx, EXCP_RI);
20050 goto out;
20051 }
20052 } else {
20053 /* Conditional compact branch */
20054 TCGLabel *fs = gen_new_label();
20055
20056 switch (opc) {
20057 case OPC_BGEUC:
20058 if (rs == 0 && rt != 0) {
20059 /* OPC_BLEZALC */
20060 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20061 } else if (rs != 0 && rt != 0 && rs == rt) {
20062 /* OPC_BGEZALC */
20063 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20064 } else {
20065 /* OPC_BGEUC */
20066 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20067 }
20068 break;
20069 case OPC_BLTUC:
20070 if (rs == 0 && rt != 0) {
20071 /* OPC_BGTZALC */
20072 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20073 } else if (rs != 0 && rt != 0 && rs == rt) {
20074 /* OPC_BLTZALC */
20075 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20076 } else {
20077 /* OPC_BLTUC */
20078 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20079 }
20080 break;
20081 case OPC_BGEC:
20082 if (rs == 0 && rt != 0) {
20083 /* OPC_BLEZC */
20084 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20085 } else if (rs != 0 && rt != 0 && rs == rt) {
20086 /* OPC_BGEZC */
20087 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20088 } else {
20089 /* OPC_BGEC */
20090 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20091 }
20092 break;
20093 case OPC_BLTC:
20094 if (rs == 0 && rt != 0) {
20095 /* OPC_BGTZC */
20096 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20097 } else if (rs != 0 && rt != 0 && rs == rt) {
20098 /* OPC_BLTZC */
20099 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20100 } else {
20101 /* OPC_BLTC */
20102 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20103 }
20104 break;
20105 case OPC_BEQZC:
20106 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20107 break;
20108 default:
20109 MIPS_INVAL("Compact conditional branch/jump");
20110 generate_exception_end(ctx, EXCP_RI);
20111 goto out;
20112 }
20113
697b7b6b
SM
20114 /* branch completion */
20115 clear_branch_hflags(ctx);
20116 ctx->base.is_jmp = DISAS_NORETURN;
20117
11d0fc10
SM
20118 /* Generating branch here as compact branches don't have delay slot */
20119 gen_goto_tb(ctx, 1, ctx->btarget);
20120 gen_set_label(fs);
20121
20122 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20123 }
20124
20125out:
20126 tcg_temp_free(t0);
20127 tcg_temp_free(t1);
20128}
20129
20130
20131/* nanoMIPS CP1 Branches */
20132static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20133 int32_t ft, int32_t offset)
20134{
20135 target_ulong btarget;
20136 TCGv_i64 t0 = tcg_temp_new_i64();
20137
20138 gen_load_fpr64(ctx, t0, ft);
20139 tcg_gen_andi_i64(t0, t0, 1);
20140
20141 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20142
20143 switch (op) {
20144 case NM_BC1EQZC:
20145 tcg_gen_xori_i64(t0, t0, 1);
20146 ctx->hflags |= MIPS_HFLAG_BC;
20147 break;
20148 case NM_BC1NEZC:
20149 /* t0 already set */
20150 ctx->hflags |= MIPS_HFLAG_BC;
20151 break;
20152 default:
20153 MIPS_INVAL("cp1 cond branch");
20154 generate_exception_end(ctx, EXCP_RI);
20155 goto out;
20156 }
20157
20158 tcg_gen_trunc_i64_tl(bcond, t0);
20159
20160 ctx->btarget = btarget;
20161
20162out:
20163 tcg_temp_free_i64(t0);
20164}
20165
eac52664
YK
20166
20167static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20168{
20169 TCGv t0, t1;
20170 t0 = tcg_temp_new();
20171 t1 = tcg_temp_new();
20172
20173 gen_load_gpr(t0, rs);
20174 gen_load_gpr(t1, rt);
20175
20176 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20177 /* PP.LSXS instructions require shifting */
20178 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20179 case NM_SHXS:
fb32f8c8 20180 check_nms(ctx);
45152d05 20181 /* fall through */
fb32f8c8 20182 case NM_LHXS:
eac52664
YK
20183 case NM_LHUXS:
20184 tcg_gen_shli_tl(t0, t0, 1);
20185 break;
eac52664 20186 case NM_SWXS:
fb32f8c8 20187 check_nms(ctx);
45152d05 20188 /* fall through */
fb32f8c8 20189 case NM_LWXS:
eac52664
YK
20190 case NM_LWC1XS:
20191 case NM_SWC1XS:
20192 tcg_gen_shli_tl(t0, t0, 2);
20193 break;
20194 case NM_LDC1XS:
20195 case NM_SDC1XS:
20196 tcg_gen_shli_tl(t0, t0, 3);
20197 break;
20198 }
20199 }
20200 gen_op_addr_add(ctx, t0, t0, t1);
20201
20202 switch (extract32(ctx->opcode, 7, 4)) {
20203 case NM_LBX:
20204 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20205 MO_SB);
20206 gen_store_gpr(t0, rd);
20207 break;
20208 case NM_LHX:
20209 /*case NM_LHXS:*/
20210 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20211 MO_TESW);
20212 gen_store_gpr(t0, rd);
20213 break;
20214 case NM_LWX:
20215 /*case NM_LWXS:*/
20216 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20217 MO_TESL);
20218 gen_store_gpr(t0, rd);
20219 break;
20220 case NM_LBUX:
20221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20222 MO_UB);
20223 gen_store_gpr(t0, rd);
20224 break;
20225 case NM_LHUX:
20226 /*case NM_LHUXS:*/
20227 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20228 MO_TEUW);
20229 gen_store_gpr(t0, rd);
20230 break;
20231 case NM_SBX:
fb32f8c8 20232 check_nms(ctx);
eac52664
YK
20233 gen_load_gpr(t1, rd);
20234 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20235 MO_8);
20236 break;
20237 case NM_SHX:
20238 /*case NM_SHXS:*/
fb32f8c8 20239 check_nms(ctx);
eac52664
YK
20240 gen_load_gpr(t1, rd);
20241 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20242 MO_TEUW);
20243 break;
20244 case NM_SWX:
20245 /*case NM_SWXS:*/
fb32f8c8 20246 check_nms(ctx);
eac52664
YK
20247 gen_load_gpr(t1, rd);
20248 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20249 MO_TEUL);
20250 break;
20251 case NM_LWC1X:
20252 /*case NM_LWC1XS:*/
20253 case NM_LDC1X:
20254 /*case NM_LDC1XS:*/
20255 case NM_SWC1X:
20256 /*case NM_SWC1XS:*/
20257 case NM_SDC1X:
20258 /*case NM_SDC1XS:*/
20259 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20260 check_cp1_enabled(ctx);
20261 switch (extract32(ctx->opcode, 7, 4)) {
20262 case NM_LWC1X:
20263 /*case NM_LWC1XS:*/
20264 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20265 break;
20266 case NM_LDC1X:
20267 /*case NM_LDC1XS:*/
20268 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20269 break;
20270 case NM_SWC1X:
20271 /*case NM_SWC1XS:*/
20272 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20273 break;
20274 case NM_SDC1X:
20275 /*case NM_SDC1XS:*/
20276 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20277 break;
20278 }
20279 } else {
20280 generate_exception_err(ctx, EXCP_CpU, 1);
20281 }
20282 break;
20283 default:
20284 generate_exception_end(ctx, EXCP_RI);
20285 break;
20286 }
20287
20288 tcg_temp_free(t0);
20289 tcg_temp_free(t1);
20290}
20291
579b8ea9
YK
20292static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20293{
20294 int rt, rs, rd;
20295
20296 rt = extract32(ctx->opcode, 21, 5);
20297 rs = extract32(ctx->opcode, 16, 5);
20298 rd = extract32(ctx->opcode, 11, 5);
20299
20300 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20301 generate_exception_end(ctx, EXCP_RI);
20302 return;
20303 }
20304 check_cp1_enabled(ctx);
20305 switch (extract32(ctx->opcode, 0, 3)) {
20306 case NM_POOL32F_0:
20307 switch (extract32(ctx->opcode, 3, 7)) {
20308 case NM_RINT_S:
20309 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20310 break;
20311 case NM_RINT_D:
20312 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20313 break;
20314 case NM_CLASS_S:
20315 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20316 break;
20317 case NM_CLASS_D:
20318 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20319 break;
20320 case NM_ADD_S:
20321 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20322 break;
20323 case NM_ADD_D:
20324 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20325 break;
20326 case NM_SUB_S:
20327 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20328 break;
20329 case NM_SUB_D:
20330 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20331 break;
20332 case NM_MUL_S:
20333 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20334 break;
20335 case NM_MUL_D:
20336 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20337 break;
20338 case NM_DIV_S:
20339 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20340 break;
20341 case NM_DIV_D:
20342 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20343 break;
20344 case NM_SELEQZ_S:
20345 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20346 break;
20347 case NM_SELEQZ_D:
20348 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20349 break;
20350 case NM_SELNEZ_S:
20351 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20352 break;
20353 case NM_SELNEZ_D:
20354 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20355 break;
20356 case NM_SEL_S:
20357 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20358 break;
20359 case NM_SEL_D:
20360 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20361 break;
20362 case NM_MADDF_S:
20363 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20364 break;
20365 case NM_MADDF_D:
20366 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20367 break;
20368 case NM_MSUBF_S:
20369 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20370 break;
20371 case NM_MSUBF_D:
20372 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20373 break;
20374 default:
20375 generate_exception_end(ctx, EXCP_RI);
20376 break;
20377 }
20378 break;
20379 case NM_POOL32F_3:
20380 switch (extract32(ctx->opcode, 3, 3)) {
20381 case NM_MIN_FMT:
20382 switch (extract32(ctx->opcode, 9, 1)) {
20383 case FMT_SDPS_S:
20384 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20385 break;
20386 case FMT_SDPS_D:
20387 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20388 break;
20389 }
20390 break;
20391 case NM_MAX_FMT:
20392 switch (extract32(ctx->opcode, 9, 1)) {
20393 case FMT_SDPS_S:
20394 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20395 break;
20396 case FMT_SDPS_D:
20397 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20398 break;
20399 }
20400 break;
20401 case NM_MINA_FMT:
20402 switch (extract32(ctx->opcode, 9, 1)) {
20403 case FMT_SDPS_S:
20404 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20405 break;
20406 case FMT_SDPS_D:
20407 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20408 break;
20409 }
20410 break;
20411 case NM_MAXA_FMT:
20412 switch (extract32(ctx->opcode, 9, 1)) {
20413 case FMT_SDPS_S:
20414 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20415 break;
20416 case FMT_SDPS_D:
20417 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20418 break;
20419 }
20420 break;
20421 case NM_POOL32FXF:
20422 switch (extract32(ctx->opcode, 6, 8)) {
20423 case NM_CFC1:
20424 gen_cp1(ctx, OPC_CFC1, rt, rs);
20425 break;
20426 case NM_CTC1:
20427 gen_cp1(ctx, OPC_CTC1, rt, rs);
20428 break;
20429 case NM_MFC1:
20430 gen_cp1(ctx, OPC_MFC1, rt, rs);
20431 break;
20432 case NM_MTC1:
20433 gen_cp1(ctx, OPC_MTC1, rt, rs);
20434 break;
20435 case NM_MFHC1:
20436 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20437 break;
20438 case NM_MTHC1:
20439 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20440 break;
20441 case NM_CVT_S_PL:
20442 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20443 break;
20444 case NM_CVT_S_PU:
20445 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20446 break;
20447 default:
20448 switch (extract32(ctx->opcode, 6, 9)) {
20449 case NM_CVT_L_S:
20450 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20451 break;
20452 case NM_CVT_L_D:
20453 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20454 break;
20455 case NM_CVT_W_S:
20456 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20457 break;
20458 case NM_CVT_W_D:
20459 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20460 break;
20461 case NM_RSQRT_S:
20462 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20463 break;
20464 case NM_RSQRT_D:
20465 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20466 break;
20467 case NM_SQRT_S:
20468 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20469 break;
20470 case NM_SQRT_D:
20471 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20472 break;
20473 case NM_RECIP_S:
20474 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20475 break;
20476 case NM_RECIP_D:
20477 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20478 break;
20479 case NM_FLOOR_L_S:
20480 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20481 break;
20482 case NM_FLOOR_L_D:
20483 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20484 break;
20485 case NM_FLOOR_W_S:
20486 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20487 break;
20488 case NM_FLOOR_W_D:
20489 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20490 break;
20491 case NM_CEIL_L_S:
20492 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20493 break;
20494 case NM_CEIL_L_D:
20495 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20496 break;
20497 case NM_CEIL_W_S:
20498 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20499 break;
20500 case NM_CEIL_W_D:
20501 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20502 break;
20503 case NM_TRUNC_L_S:
20504 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20505 break;
20506 case NM_TRUNC_L_D:
20507 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20508 break;
20509 case NM_TRUNC_W_S:
20510 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20511 break;
20512 case NM_TRUNC_W_D:
20513 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20514 break;
20515 case NM_ROUND_L_S:
20516 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20517 break;
20518 case NM_ROUND_L_D:
20519 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20520 break;
20521 case NM_ROUND_W_S:
20522 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20523 break;
20524 case NM_ROUND_W_D:
20525 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20526 break;
20527 case NM_MOV_S:
20528 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20529 break;
20530 case NM_MOV_D:
20531 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20532 break;
20533 case NM_ABS_S:
20534 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20535 break;
20536 case NM_ABS_D:
20537 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20538 break;
20539 case NM_NEG_S:
20540 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20541 break;
20542 case NM_NEG_D:
20543 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20544 break;
20545 case NM_CVT_D_S:
20546 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20547 break;
20548 case NM_CVT_D_W:
20549 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20550 break;
20551 case NM_CVT_D_L:
20552 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20553 break;
20554 case NM_CVT_S_D:
20555 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20556 break;
20557 case NM_CVT_S_W:
20558 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20559 break;
20560 case NM_CVT_S_L:
20561 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20562 break;
20563 default:
20564 generate_exception_end(ctx, EXCP_RI);
20565 break;
20566 }
20567 break;
20568 }
20569 break;
20570 }
20571 break;
20572 case NM_POOL32F_5:
20573 switch (extract32(ctx->opcode, 3, 3)) {
20574 case NM_CMP_CONDN_S:
20575 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20576 break;
20577 case NM_CMP_CONDN_D:
20578 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20579 break;
20580 default:
20581 generate_exception_end(ctx, EXCP_RI);
20582 break;
20583 }
20584 break;
20585 default:
20586 generate_exception_end(ctx, EXCP_RI);
20587 break;
20588 }
20589}
20590
3285a3e4
SM
20591static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20592 int rd, int rs, int rt)
20593{
20594 int ret = rd;
20595 TCGv t0 = tcg_temp_new();
20596 TCGv v1_t = tcg_temp_new();
20597 TCGv v2_t = tcg_temp_new();
20598
20599 gen_load_gpr(v1_t, rs);
20600 gen_load_gpr(v2_t, rt);
20601
20602 switch (opc) {
20603 case NM_CMP_EQ_PH:
20604 check_dsp(ctx);
20605 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20606 break;
20607 case NM_CMP_LT_PH:
20608 check_dsp(ctx);
20609 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20610 break;
20611 case NM_CMP_LE_PH:
20612 check_dsp(ctx);
20613 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20614 break;
20615 case NM_CMPU_EQ_QB:
20616 check_dsp(ctx);
20617 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20618 break;
20619 case NM_CMPU_LT_QB:
20620 check_dsp(ctx);
20621 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20622 break;
20623 case NM_CMPU_LE_QB:
20624 check_dsp(ctx);
20625 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20626 break;
20627 case NM_CMPGU_EQ_QB:
20628 check_dsp(ctx);
20629 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20630 gen_store_gpr(v1_t, ret);
20631 break;
20632 case NM_CMPGU_LT_QB:
20633 check_dsp(ctx);
20634 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20635 gen_store_gpr(v1_t, ret);
20636 break;
20637 case NM_CMPGU_LE_QB:
20638 check_dsp(ctx);
20639 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20640 gen_store_gpr(v1_t, ret);
20641 break;
20642 case NM_CMPGDU_EQ_QB:
908f6be1 20643 check_dsp_r2(ctx);
3285a3e4
SM
20644 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20645 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20646 gen_store_gpr(v1_t, ret);
20647 break;
20648 case NM_CMPGDU_LT_QB:
908f6be1 20649 check_dsp_r2(ctx);
3285a3e4
SM
20650 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20651 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20652 gen_store_gpr(v1_t, ret);
20653 break;
20654 case NM_CMPGDU_LE_QB:
908f6be1 20655 check_dsp_r2(ctx);
3285a3e4
SM
20656 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20657 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20658 gen_store_gpr(v1_t, ret);
20659 break;
20660 case NM_PACKRL_PH:
20661 check_dsp(ctx);
20662 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20663 gen_store_gpr(v1_t, ret);
20664 break;
20665 case NM_PICK_QB:
20666 check_dsp(ctx);
20667 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20668 gen_store_gpr(v1_t, ret);
20669 break;
20670 case NM_PICK_PH:
20671 check_dsp(ctx);
20672 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20673 gen_store_gpr(v1_t, ret);
20674 break;
20675 case NM_ADDQ_S_W:
20676 check_dsp(ctx);
20677 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20678 gen_store_gpr(v1_t, ret);
20679 break;
20680 case NM_SUBQ_S_W:
20681 check_dsp(ctx);
20682 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20683 gen_store_gpr(v1_t, ret);
20684 break;
20685 case NM_ADDSC:
20686 check_dsp(ctx);
20687 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20688 gen_store_gpr(v1_t, ret);
20689 break;
20690 case NM_ADDWC:
20691 check_dsp(ctx);
20692 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20693 gen_store_gpr(v1_t, ret);
20694 break;
20695 case NM_ADDQ_S_PH:
20696 check_dsp(ctx);
20697 switch (extract32(ctx->opcode, 10, 1)) {
20698 case 0:
20699 /* ADDQ_PH */
20700 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20701 gen_store_gpr(v1_t, ret);
20702 break;
20703 case 1:
20704 /* ADDQ_S_PH */
20705 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20706 gen_store_gpr(v1_t, ret);
20707 break;
20708 }
20709 break;
20710 case NM_ADDQH_R_PH:
908f6be1 20711 check_dsp_r2(ctx);
3285a3e4
SM
20712 switch (extract32(ctx->opcode, 10, 1)) {
20713 case 0:
20714 /* ADDQH_PH */
20715 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20716 gen_store_gpr(v1_t, ret);
20717 break;
20718 case 1:
20719 /* ADDQH_R_PH */
20720 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20721 gen_store_gpr(v1_t, ret);
20722 break;
20723 }
20724 break;
20725 case NM_ADDQH_R_W:
908f6be1 20726 check_dsp_r2(ctx);
3285a3e4
SM
20727 switch (extract32(ctx->opcode, 10, 1)) {
20728 case 0:
20729 /* ADDQH_W */
20730 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20731 gen_store_gpr(v1_t, ret);
20732 break;
20733 case 1:
20734 /* ADDQH_R_W */
20735 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20736 gen_store_gpr(v1_t, ret);
20737 break;
20738 }
20739 break;
20740 case NM_ADDU_S_QB:
20741 check_dsp(ctx);
20742 switch (extract32(ctx->opcode, 10, 1)) {
20743 case 0:
20744 /* ADDU_QB */
20745 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20746 gen_store_gpr(v1_t, ret);
20747 break;
20748 case 1:
20749 /* ADDU_S_QB */
20750 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20751 gen_store_gpr(v1_t, ret);
20752 break;
20753 }
20754 break;
20755 case NM_ADDU_S_PH:
908f6be1 20756 check_dsp_r2(ctx);
3285a3e4
SM
20757 switch (extract32(ctx->opcode, 10, 1)) {
20758 case 0:
20759 /* ADDU_PH */
20760 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20761 gen_store_gpr(v1_t, ret);
20762 break;
20763 case 1:
20764 /* ADDU_S_PH */
20765 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20766 gen_store_gpr(v1_t, ret);
20767 break;
20768 }
20769 break;
20770 case NM_ADDUH_R_QB:
908f6be1 20771 check_dsp_r2(ctx);
3285a3e4
SM
20772 switch (extract32(ctx->opcode, 10, 1)) {
20773 case 0:
20774 /* ADDUH_QB */
20775 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20776 gen_store_gpr(v1_t, ret);
20777 break;
20778 case 1:
20779 /* ADDUH_R_QB */
20780 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20781 gen_store_gpr(v1_t, ret);
20782 break;
20783 }
20784 break;
20785 case NM_SHRAV_R_PH:
20786 check_dsp(ctx);
20787 switch (extract32(ctx->opcode, 10, 1)) {
20788 case 0:
20789 /* SHRAV_PH */
20790 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20791 gen_store_gpr(v1_t, ret);
20792 break;
20793 case 1:
20794 /* SHRAV_R_PH */
20795 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20796 gen_store_gpr(v1_t, ret);
20797 break;
20798 }
20799 break;
20800 case NM_SHRAV_R_QB:
908f6be1 20801 check_dsp_r2(ctx);
3285a3e4
SM
20802 switch (extract32(ctx->opcode, 10, 1)) {
20803 case 0:
20804 /* SHRAV_QB */
20805 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20806 gen_store_gpr(v1_t, ret);
20807 break;
20808 case 1:
20809 /* SHRAV_R_QB */
20810 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20811 gen_store_gpr(v1_t, ret);
20812 break;
20813 }
20814 break;
20815 case NM_SUBQ_S_PH:
20816 check_dsp(ctx);
20817 switch (extract32(ctx->opcode, 10, 1)) {
20818 case 0:
20819 /* SUBQ_PH */
20820 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20821 gen_store_gpr(v1_t, ret);
20822 break;
20823 case 1:
20824 /* SUBQ_S_PH */
20825 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20826 gen_store_gpr(v1_t, ret);
20827 break;
20828 }
20829 break;
20830 case NM_SUBQH_R_PH:
908f6be1 20831 check_dsp_r2(ctx);
3285a3e4
SM
20832 switch (extract32(ctx->opcode, 10, 1)) {
20833 case 0:
20834 /* SUBQH_PH */
20835 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20836 gen_store_gpr(v1_t, ret);
20837 break;
20838 case 1:
20839 /* SUBQH_R_PH */
20840 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20841 gen_store_gpr(v1_t, ret);
20842 break;
20843 }
20844 break;
20845 case NM_SUBQH_R_W:
908f6be1 20846 check_dsp_r2(ctx);
3285a3e4
SM
20847 switch (extract32(ctx->opcode, 10, 1)) {
20848 case 0:
20849 /* SUBQH_W */
20850 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20851 gen_store_gpr(v1_t, ret);
20852 break;
20853 case 1:
20854 /* SUBQH_R_W */
20855 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20856 gen_store_gpr(v1_t, ret);
20857 break;
20858 }
20859 break;
20860 case NM_SUBU_S_QB:
20861 check_dsp(ctx);
20862 switch (extract32(ctx->opcode, 10, 1)) {
20863 case 0:
20864 /* SUBU_QB */
20865 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20866 gen_store_gpr(v1_t, ret);
20867 break;
20868 case 1:
20869 /* SUBU_S_QB */
20870 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20871 gen_store_gpr(v1_t, ret);
20872 break;
20873 }
20874 break;
20875 case NM_SUBU_S_PH:
908f6be1 20876 check_dsp_r2(ctx);
3285a3e4
SM
20877 switch (extract32(ctx->opcode, 10, 1)) {
20878 case 0:
20879 /* SUBU_PH */
20880 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20881 gen_store_gpr(v1_t, ret);
20882 break;
20883 case 1:
20884 /* SUBU_S_PH */
20885 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20886 gen_store_gpr(v1_t, ret);
20887 break;
20888 }
20889 break;
20890 case NM_SUBUH_R_QB:
908f6be1 20891 check_dsp_r2(ctx);
3285a3e4
SM
20892 switch (extract32(ctx->opcode, 10, 1)) {
20893 case 0:
20894 /* SUBUH_QB */
20895 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20896 gen_store_gpr(v1_t, ret);
20897 break;
20898 case 1:
20899 /* SUBUH_R_QB */
20900 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20901 gen_store_gpr(v1_t, ret);
20902 break;
20903 }
20904 break;
20905 case NM_SHLLV_S_PH:
20906 check_dsp(ctx);
20907 switch (extract32(ctx->opcode, 10, 1)) {
20908 case 0:
20909 /* SHLLV_PH */
20910 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20911 gen_store_gpr(v1_t, ret);
20912 break;
20913 case 1:
20914 /* SHLLV_S_PH */
20915 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20916 gen_store_gpr(v1_t, ret);
20917 break;
20918 }
20919 break;
20920 case NM_PRECR_SRA_R_PH_W:
908f6be1 20921 check_dsp_r2(ctx);
3285a3e4
SM
20922 switch (extract32(ctx->opcode, 10, 1)) {
20923 case 0:
20924 /* PRECR_SRA_PH_W */
20925 {
20926 TCGv_i32 sa_t = tcg_const_i32(rd);
20927 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20928 cpu_gpr[rt]);
20929 gen_store_gpr(v1_t, rt);
20930 tcg_temp_free_i32(sa_t);
20931 }
20932 break;
20933 case 1:
20934 /* PRECR_SRA_R_PH_W */
20935 {
20936 TCGv_i32 sa_t = tcg_const_i32(rd);
20937 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20938 cpu_gpr[rt]);
20939 gen_store_gpr(v1_t, rt);
20940 tcg_temp_free_i32(sa_t);
20941 }
20942 break;
20943 }
20944 break;
20945 case NM_MULEU_S_PH_QBL:
20946 check_dsp(ctx);
20947 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20948 gen_store_gpr(v1_t, ret);
20949 break;
20950 case NM_MULEU_S_PH_QBR:
20951 check_dsp(ctx);
20952 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20953 gen_store_gpr(v1_t, ret);
20954 break;
20955 case NM_MULQ_RS_PH:
20956 check_dsp(ctx);
20957 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20958 gen_store_gpr(v1_t, ret);
20959 break;
20960 case NM_MULQ_S_PH:
908f6be1 20961 check_dsp_r2(ctx);
3285a3e4
SM
20962 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20963 gen_store_gpr(v1_t, ret);
20964 break;
20965 case NM_MULQ_RS_W:
908f6be1 20966 check_dsp_r2(ctx);
3285a3e4
SM
20967 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20968 gen_store_gpr(v1_t, ret);
20969 break;
20970 case NM_MULQ_S_W:
908f6be1 20971 check_dsp_r2(ctx);
3285a3e4
SM
20972 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20973 gen_store_gpr(v1_t, ret);
20974 break;
20975 case NM_APPEND:
908f6be1 20976 check_dsp_r2(ctx);
3285a3e4
SM
20977 gen_load_gpr(t0, rs);
20978 if (rd != 0) {
20979 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20980 }
20981 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20982 break;
20983 case NM_MODSUB:
20984 check_dsp(ctx);
20985 gen_helper_modsub(v1_t, v1_t, v2_t);
20986 gen_store_gpr(v1_t, ret);
20987 break;
20988 case NM_SHRAV_R_W:
20989 check_dsp(ctx);
20990 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20991 gen_store_gpr(v1_t, ret);
20992 break;
20993 case NM_SHRLV_PH:
908f6be1 20994 check_dsp_r2(ctx);
3285a3e4
SM
20995 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20996 gen_store_gpr(v1_t, ret);
20997 break;
20998 case NM_SHRLV_QB:
20999 check_dsp(ctx);
21000 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21001 gen_store_gpr(v1_t, ret);
21002 break;
21003 case NM_SHLLV_QB:
21004 check_dsp(ctx);
21005 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21006 gen_store_gpr(v1_t, ret);
21007 break;
21008 case NM_SHLLV_S_W:
21009 check_dsp(ctx);
21010 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21011 gen_store_gpr(v1_t, ret);
21012 break;
21013 case NM_SHILO:
21014 check_dsp(ctx);
21015 {
21016 TCGv tv0 = tcg_temp_new();
21017 TCGv tv1 = tcg_temp_new();
21018 int16_t imm = extract32(ctx->opcode, 16, 7);
21019
21020 tcg_gen_movi_tl(tv0, rd >> 3);
21021 tcg_gen_movi_tl(tv1, imm);
21022 gen_helper_shilo(tv0, tv1, cpu_env);
21023 }
21024 break;
21025 case NM_MULEQ_S_W_PHL:
21026 check_dsp(ctx);
21027 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21028 gen_store_gpr(v1_t, ret);
21029 break;
21030 case NM_MULEQ_S_W_PHR:
21031 check_dsp(ctx);
21032 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21033 gen_store_gpr(v1_t, ret);
21034 break;
21035 case NM_MUL_S_PH:
908f6be1 21036 check_dsp_r2(ctx);
3285a3e4
SM
21037 switch (extract32(ctx->opcode, 10, 1)) {
21038 case 0:
21039 /* MUL_PH */
21040 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21041 gen_store_gpr(v1_t, ret);
21042 break;
21043 case 1:
21044 /* MUL_S_PH */
21045 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21046 gen_store_gpr(v1_t, ret);
21047 break;
21048 }
21049 break;
21050 case NM_PRECR_QB_PH:
908f6be1 21051 check_dsp_r2(ctx);
3285a3e4
SM
21052 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21053 gen_store_gpr(v1_t, ret);
21054 break;
21055 case NM_PRECRQ_QB_PH:
21056 check_dsp(ctx);
21057 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21058 gen_store_gpr(v1_t, ret);
21059 break;
21060 case NM_PRECRQ_PH_W:
21061 check_dsp(ctx);
21062 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21063 gen_store_gpr(v1_t, ret);
21064 break;
21065 case NM_PRECRQ_RS_PH_W:
21066 check_dsp(ctx);
21067 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21068 gen_store_gpr(v1_t, ret);
21069 break;
21070 case NM_PRECRQU_S_QB_PH:
21071 check_dsp(ctx);
21072 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21073 gen_store_gpr(v1_t, ret);
21074 break;
21075 case NM_SHRA_R_W:
21076 check_dsp(ctx);
21077 tcg_gen_movi_tl(t0, rd);
21078 gen_helper_shra_r_w(v1_t, t0, v1_t);
21079 gen_store_gpr(v1_t, rt);
21080 break;
21081 case NM_SHRA_R_PH:
21082 check_dsp(ctx);
21083 tcg_gen_movi_tl(t0, rd >> 1);
21084 switch (extract32(ctx->opcode, 10, 1)) {
21085 case 0:
21086 /* SHRA_PH */
21087 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 21088 gen_store_gpr(v1_t, rt);
d5ebcbaf 21089 break;
3285a3e4
SM
21090 case 1:
21091 /* SHRA_R_PH */
21092 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21093 gen_store_gpr(v1_t, rt);
21094 break;
21095 }
21096 break;
21097 case NM_SHLL_S_PH:
21098 check_dsp(ctx);
21099 tcg_gen_movi_tl(t0, rd >> 1);
21100 switch (extract32(ctx->opcode, 10, 2)) {
21101 case 0:
21102 /* SHLL_PH */
21103 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21104 gen_store_gpr(v1_t, rt);
21105 break;
21106 case 2:
21107 /* SHLL_S_PH */
21108 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21109 gen_store_gpr(v1_t, rt);
21110 break;
21111 default:
21112 generate_exception_end(ctx, EXCP_RI);
21113 break;
21114 }
21115 break;
21116 case NM_SHLL_S_W:
21117 check_dsp(ctx);
21118 tcg_gen_movi_tl(t0, rd);
21119 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21120 gen_store_gpr(v1_t, rt);
21121 break;
21122 case NM_REPL_PH:
21123 check_dsp(ctx);
21124 {
21125 int16_t imm;
21126 imm = sextract32(ctx->opcode, 11, 11);
21127 imm = (int16_t)(imm << 6) >> 6;
21128 if (rt != 0) {
21129 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21130 }
21131 }
21132 break;
21133 default:
21134 generate_exception_end(ctx, EXCP_RI);
21135 break;
21136 }
21137}
21138
c0280983
YK
21139static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21140{
21141 uint16_t insn;
21142 uint32_t op;
eac52664 21143 int rt, rs, rd;
c0280983
YK
21144 int offset;
21145 int imm;
21146
21147 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21148 ctx->opcode = (ctx->opcode << 16) | insn;
21149
21150 rt = extract32(ctx->opcode, 21, 5);
21151 rs = extract32(ctx->opcode, 16, 5);
eac52664 21152 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
21153
21154 op = extract32(ctx->opcode, 26, 6);
21155 switch (op) {
21156 case NM_P_ADDIU:
21157 if (rt == 0) {
21158 /* P.RI */
21159 switch (extract32(ctx->opcode, 19, 2)) {
21160 case NM_SIGRIE:
21161 default:
21162 generate_exception_end(ctx, EXCP_RI);
21163 break;
21164 case NM_P_SYSCALL:
21165 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21166 generate_exception_end(ctx, EXCP_SYSCALL);
21167 } else {
21168 generate_exception_end(ctx, EXCP_RI);
21169 }
21170 break;
21171 case NM_BREAK:
21172 generate_exception_end(ctx, EXCP_BREAK);
21173 break;
21174 case NM_SDBBP:
21175 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21176 gen_helper_do_semihosting(cpu_env);
21177 } else {
21178 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21179 generate_exception_end(ctx, EXCP_RI);
21180 } else {
21181 generate_exception_end(ctx, EXCP_DBp);
21182 }
21183 }
21184 break;
21185 }
21186 } else {
21187 /* NM_ADDIU */
21188 imm = extract32(ctx->opcode, 0, 16);
21189 if (rs != 0) {
21190 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21191 } else {
21192 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21193 }
21194 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21195 }
21196 break;
21197 case NM_ADDIUPC:
21198 if (rt != 0) {
21199 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21200 extract32(ctx->opcode, 1, 20) << 1;
21201 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21202 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21203 }
21204 break;
21205 case NM_POOL32A:
e0cf0e65
YK
21206 switch (ctx->opcode & 0x07) {
21207 case NM_POOL32A0:
0a1a6ed7 21208 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21209 break;
3285a3e4
SM
21210 case NM_POOL32A5:
21211 {
21212 int32_t op1 = extract32(ctx->opcode, 3, 7);
21213 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21214 }
21215 break;
e0cf0e65 21216 case NM_POOL32A7:
64224187 21217 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21218 case NM_P_LSX:
21219 gen_p_lsx(ctx, rd, rs, rt);
21220 break;
21221 case NM_LSA:
7480515f
AM
21222 /*
21223 * In nanoMIPS, the shift field directly encodes the shift
eac52664 21224 * amount, meaning that the supported shift values are in
7480515f
AM
21225 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21226 */
eac52664
YK
21227 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21228 extract32(ctx->opcode, 9, 2) - 1);
21229 break;
821f2008
JH
21230 case NM_EXTW:
21231 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21232 break;
64224187
YK
21233 case NM_POOL32AXF:
21234 gen_pool32axf_nanomips_insn(env, ctx);
21235 break;
21236 default:
21237 generate_exception_end(ctx, EXCP_RI);
21238 break;
21239 }
e0cf0e65
YK
21240 break;
21241 default:
21242 generate_exception_end(ctx, EXCP_RI);
21243 break;
21244 }
c0280983
YK
21245 break;
21246 case NM_P_GP_W:
21247 switch (ctx->opcode & 0x03) {
21248 case NM_ADDIUGP_W:
21249 if (rt != 0) {
21250 offset = extract32(ctx->opcode, 0, 21);
21251 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21252 }
21253 break;
21254 case NM_LWGP:
21255 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21256 break;
21257 case NM_SWGP:
21258 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21259 break;
21260 default:
21261 generate_exception_end(ctx, EXCP_RI);
21262 break;
21263 }
21264 break;
21265 case NM_P48I:
7ef009b2
YK
21266 {
21267 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21268 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21269 switch (extract32(ctx->opcode, 16, 5)) {
21270 case NM_LI48:
fb32f8c8 21271 check_nms(ctx);
7ef009b2
YK
21272 if (rt != 0) {
21273 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21274 }
21275 break;
21276 case NM_ADDIU48:
fb32f8c8 21277 check_nms(ctx);
7ef009b2
YK
21278 if (rt != 0) {
21279 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21280 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21281 }
21282 break;
21283 case NM_ADDIUGP48:
fb32f8c8 21284 check_nms(ctx);
7ef009b2
YK
21285 if (rt != 0) {
21286 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21287 }
21288 break;
21289 case NM_ADDIUPC48:
fb32f8c8 21290 check_nms(ctx);
7ef009b2
YK
21291 if (rt != 0) {
21292 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21293 addr_off);
21294
21295 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21296 }
21297 break;
21298 case NM_LWPC48:
fb32f8c8 21299 check_nms(ctx);
7ef009b2
YK
21300 if (rt != 0) {
21301 TCGv t0;
21302 t0 = tcg_temp_new();
21303
21304 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21305 addr_off);
21306
21307 tcg_gen_movi_tl(t0, addr);
21308 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21309 tcg_temp_free(t0);
21310 }
21311 break;
21312 case NM_SWPC48:
fb32f8c8 21313 check_nms(ctx);
7ef009b2
YK
21314 {
21315 TCGv t0, t1;
21316 t0 = tcg_temp_new();
21317 t1 = tcg_temp_new();
21318
21319 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21320 addr_off);
21321
21322 tcg_gen_movi_tl(t0, addr);
21323 gen_load_gpr(t1, rt);
21324
21325 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21326
21327 tcg_temp_free(t0);
21328 tcg_temp_free(t1);
21329 }
21330 break;
21331 default:
21332 generate_exception_end(ctx, EXCP_RI);
21333 break;
21334 }
21335 return 6;
21336 }
c0280983
YK
21337 case NM_P_U12:
21338 switch (extract32(ctx->opcode, 12, 4)) {
21339 case NM_ORI:
21340 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21341 break;
21342 case NM_XORI:
21343 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21344 break;
21345 case NM_ANDI:
21346 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21347 break;
21348 case NM_P_SR:
21349 switch (extract32(ctx->opcode, 20, 1)) {
21350 case NM_PP_SR:
21351 switch (ctx->opcode & 3) {
21352 case NM_SAVE:
21353 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21354 extract32(ctx->opcode, 2, 1),
21355 extract32(ctx->opcode, 3, 9) << 3);
21356 break;
21357 case NM_RESTORE:
21358 case NM_RESTORE_JRC:
21359 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21360 extract32(ctx->opcode, 2, 1),
21361 extract32(ctx->opcode, 3, 9) << 3);
21362 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21363 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21364 }
21365 break;
21366 default:
21367 generate_exception_end(ctx, EXCP_RI);
21368 break;
21369 }
21370 break;
21371 case NM_P_SR_F:
21372 generate_exception_end(ctx, EXCP_RI);
21373 break;
21374 }
21375 break;
21376 case NM_SLTI:
21377 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21378 break;
21379 case NM_SLTIU:
21380 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21381 break;
21382 case NM_SEQI:
21383 {
21384 TCGv t0 = tcg_temp_new();
21385
21386 imm = extract32(ctx->opcode, 0, 12);
21387 gen_load_gpr(t0, rs);
21388 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21389 gen_store_gpr(t0, rt);
21390
21391 tcg_temp_free(t0);
21392 }
21393 break;
21394 case NM_ADDIUNEG:
21395 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21396 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21397 break;
21398 case NM_P_SHIFT:
21399 {
21400 int shift = extract32(ctx->opcode, 0, 5);
21401 switch (extract32(ctx->opcode, 5, 4)) {
21402 case NM_P_SLL:
21403 if (rt == 0 && shift == 0) {
21404 /* NOP */
21405 } else if (rt == 0 && shift == 3) {
21406 /* EHB - treat as NOP */
21407 } else if (rt == 0 && shift == 5) {
21408 /* PAUSE - treat as NOP */
21409 } else if (rt == 0 && shift == 6) {
21410 /* SYNC */
21411 gen_sync(extract32(ctx->opcode, 16, 5));
21412 } else {
21413 /* SLL */
21414 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21415 extract32(ctx->opcode, 0, 5));
21416 }
21417 break;
21418 case NM_SRL:
21419 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21420 extract32(ctx->opcode, 0, 5));
21421 break;
21422 case NM_SRA:
21423 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21424 extract32(ctx->opcode, 0, 5));
21425 break;
21426 case NM_ROTR:
21427 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21428 extract32(ctx->opcode, 0, 5));
21429 break;
21430 }
21431 }
21432 break;
21433 case NM_P_ROTX:
fb32f8c8 21434 check_nms(ctx);
e222f506
MF
21435 if (rt != 0) {
21436 TCGv t0 = tcg_temp_new();
21437 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21438 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21439 << 1);
21440 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21441
21442 gen_load_gpr(t0, rs);
21443 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21444 tcg_temp_free(t0);
21445
21446 tcg_temp_free_i32(shift);
21447 tcg_temp_free_i32(shiftx);
21448 tcg_temp_free_i32(stripe);
21449 }
c0280983
YK
21450 break;
21451 case NM_P_INS:
21452 switch (((ctx->opcode >> 10) & 2) |
21453 (extract32(ctx->opcode, 5, 1))) {
21454 case NM_INS:
fb32f8c8 21455 check_nms(ctx);
c0280983
YK
21456 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21457 extract32(ctx->opcode, 6, 5));
21458 break;
21459 default:
21460 generate_exception_end(ctx, EXCP_RI);
21461 break;
21462 }
21463 break;
21464 case NM_P_EXT:
21465 switch (((ctx->opcode >> 10) & 2) |
21466 (extract32(ctx->opcode, 5, 1))) {
21467 case NM_EXT:
fb32f8c8 21468 check_nms(ctx);
c0280983
YK
21469 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21470 extract32(ctx->opcode, 6, 5));
21471 break;
21472 default:
21473 generate_exception_end(ctx, EXCP_RI);
21474 break;
21475 }
21476 break;
21477 default:
21478 generate_exception_end(ctx, EXCP_RI);
21479 break;
21480 }
21481 break;
21482 case NM_POOL32F:
579b8ea9 21483 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
21484 break;
21485 case NM_POOL32S:
21486 break;
21487 case NM_P_LUI:
21488 switch (extract32(ctx->opcode, 1, 1)) {
21489 case NM_LUI:
21490 if (rt != 0) {
21491 tcg_gen_movi_tl(cpu_gpr[rt],
21492 sextract32(ctx->opcode, 0, 1) << 31 |
21493 extract32(ctx->opcode, 2, 10) << 21 |
21494 extract32(ctx->opcode, 12, 9) << 12);
21495 }
21496 break;
21497 case NM_ALUIPC:
21498 if (rt != 0) {
21499 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21500 extract32(ctx->opcode, 2, 10) << 21 |
21501 extract32(ctx->opcode, 12, 9) << 12;
21502 target_long addr;
21503 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21504 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21505 }
21506 break;
21507 }
21508 break;
21509 case NM_P_GP_BH:
8f1d9b6d
YK
21510 {
21511 uint32_t u = extract32(ctx->opcode, 0, 18);
21512
21513 switch (extract32(ctx->opcode, 18, 3)) {
21514 case NM_LBGP:
21515 gen_ld(ctx, OPC_LB, rt, 28, u);
21516 break;
21517 case NM_SBGP:
21518 gen_st(ctx, OPC_SB, rt, 28, u);
21519 break;
21520 case NM_LBUGP:
21521 gen_ld(ctx, OPC_LBU, rt, 28, u);
21522 break;
21523 case NM_ADDIUGP_B:
21524 if (rt != 0) {
21525 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21526 }
21527 break;
21528 case NM_P_GP_LH:
21529 u &= ~1;
21530 switch (ctx->opcode & 1) {
21531 case NM_LHGP:
21532 gen_ld(ctx, OPC_LH, rt, 28, u);
21533 break;
21534 case NM_LHUGP:
21535 gen_ld(ctx, OPC_LHU, rt, 28, u);
21536 break;
21537 }
21538 break;
21539 case NM_P_GP_SH:
21540 u &= ~1;
21541 switch (ctx->opcode & 1) {
21542 case NM_SHGP:
21543 gen_st(ctx, OPC_SH, rt, 28, u);
21544 break;
21545 default:
21546 generate_exception_end(ctx, EXCP_RI);
21547 break;
21548 }
21549 break;
21550 case NM_P_GP_CP1:
21551 u &= ~0x3;
21552 switch (ctx->opcode & 0x3) {
21553 case NM_LWC1GP:
21554 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21555 break;
21556 case NM_LDC1GP:
21557 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21558 break;
21559 case NM_SWC1GP:
21560 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21561 break;
21562 case NM_SDC1GP:
21563 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21564 break;
21565 }
21566 break;
21567 default:
21568 generate_exception_end(ctx, EXCP_RI);
21569 break;
21570 }
21571 }
c0280983
YK
21572 break;
21573 case NM_P_LS_U12:
8f1d9b6d
YK
21574 {
21575 uint32_t u = extract32(ctx->opcode, 0, 12);
21576
21577 switch (extract32(ctx->opcode, 12, 4)) {
21578 case NM_P_PREFU12:
21579 if (rt == 31) {
21580 /* SYNCI */
7480515f
AM
21581 /*
21582 * Break the TB to be able to sync copied instructions
21583 * immediately.
21584 */
8f1d9b6d
YK
21585 ctx->base.is_jmp = DISAS_STOP;
21586 } else {
21587 /* PREF */
21588 /* Treat as NOP. */
21589 }
21590 break;
21591 case NM_LB:
21592 gen_ld(ctx, OPC_LB, rt, rs, u);
21593 break;
21594 case NM_LH:
21595 gen_ld(ctx, OPC_LH, rt, rs, u);
21596 break;
21597 case NM_LW:
21598 gen_ld(ctx, OPC_LW, rt, rs, u);
21599 break;
21600 case NM_LBU:
21601 gen_ld(ctx, OPC_LBU, rt, rs, u);
21602 break;
21603 case NM_LHU:
21604 gen_ld(ctx, OPC_LHU, rt, rs, u);
21605 break;
21606 case NM_SB:
21607 gen_st(ctx, OPC_SB, rt, rs, u);
21608 break;
21609 case NM_SH:
21610 gen_st(ctx, OPC_SH, rt, rs, u);
21611 break;
21612 case NM_SW:
21613 gen_st(ctx, OPC_SW, rt, rs, u);
21614 break;
21615 case NM_LWC1:
21616 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21617 break;
21618 case NM_LDC1:
21619 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21620 break;
21621 case NM_SWC1:
21622 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21623 break;
21624 case NM_SDC1:
21625 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21626 break;
21627 default:
21628 generate_exception_end(ctx, EXCP_RI);
21629 break;
21630 }
21631 }
c0280983
YK
21632 break;
21633 case NM_P_LS_S9:
8f1d9b6d
YK
21634 {
21635 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21636 extract32(ctx->opcode, 0, 8);
21637
21638 switch (extract32(ctx->opcode, 8, 3)) {
21639 case NM_P_LS_S0:
21640 switch (extract32(ctx->opcode, 11, 4)) {
21641 case NM_LBS9:
21642 gen_ld(ctx, OPC_LB, rt, rs, s);
21643 break;
21644 case NM_LHS9:
21645 gen_ld(ctx, OPC_LH, rt, rs, s);
21646 break;
21647 case NM_LWS9:
21648 gen_ld(ctx, OPC_LW, rt, rs, s);
21649 break;
21650 case NM_LBUS9:
21651 gen_ld(ctx, OPC_LBU, rt, rs, s);
21652 break;
21653 case NM_LHUS9:
21654 gen_ld(ctx, OPC_LHU, rt, rs, s);
21655 break;
21656 case NM_SBS9:
21657 gen_st(ctx, OPC_SB, rt, rs, s);
21658 break;
21659 case NM_SHS9:
21660 gen_st(ctx, OPC_SH, rt, rs, s);
21661 break;
21662 case NM_SWS9:
21663 gen_st(ctx, OPC_SW, rt, rs, s);
21664 break;
21665 case NM_LWC1S9:
21666 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21667 break;
21668 case NM_LDC1S9:
21669 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21670 break;
21671 case NM_SWC1S9:
21672 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21673 break;
21674 case NM_SDC1S9:
21675 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21676 break;
21677 case NM_P_PREFS9:
21678 if (rt == 31) {
21679 /* SYNCI */
7480515f
AM
21680 /*
21681 * Break the TB to be able to sync copied instructions
21682 * immediately.
21683 */
8f1d9b6d
YK
21684 ctx->base.is_jmp = DISAS_STOP;
21685 } else {
21686 /* PREF */
21687 /* Treat as NOP. */
21688 }
21689 break;
21690 default:
21691 generate_exception_end(ctx, EXCP_RI);
21692 break;
21693 }
21694 break;
21695 case NM_P_LS_S1:
21696 switch (extract32(ctx->opcode, 11, 4)) {
21697 case NM_UALH:
21698 case NM_UASH:
fb32f8c8 21699 check_nms(ctx);
8f1d9b6d
YK
21700 {
21701 TCGv t0 = tcg_temp_new();
21702 TCGv t1 = tcg_temp_new();
21703
21704 gen_base_offset_addr(ctx, t0, rs, s);
21705
21706 switch (extract32(ctx->opcode, 11, 4)) {
21707 case NM_UALH:
21708 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21709 MO_UNALN);
21710 gen_store_gpr(t0, rt);
21711 break;
21712 case NM_UASH:
21713 gen_load_gpr(t1, rt);
21714 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21715 MO_UNALN);
21716 break;
21717 }
21718 tcg_temp_free(t0);
21719 tcg_temp_free(t1);
21720 }
21721 break;
21722 case NM_P_LL:
21723 switch (ctx->opcode & 0x03) {
21724 case NM_LL:
21725 gen_ld(ctx, OPC_LL, rt, rs, s);
21726 break;
21727 case NM_LLWP:
0b16dcd1
AR
21728 check_xnp(ctx);
21729 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21730 break;
21731 }
21732 break;
21733 case NM_P_SC:
21734 switch (ctx->opcode & 0x03) {
21735 case NM_SC:
33a07fa2 21736 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
21737 break;
21738 case NM_SCWP:
0b16dcd1 21739 check_xnp(ctx);
8d5388c1
AM
21740 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21741 false);
8f1d9b6d
YK
21742 break;
21743 }
21744 break;
21745 case NM_CACHE:
21746 check_cp0_enabled(ctx);
21747 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21748 gen_cache_operation(ctx, rt, rs, s);
21749 }
21750 break;
21751 }
21752 break;
d046a9ea
DN
21753 case NM_P_LS_E0:
21754 switch (extract32(ctx->opcode, 11, 4)) {
21755 case NM_LBE:
21756 check_eva(ctx);
21757 check_cp0_enabled(ctx);
21758 gen_ld(ctx, OPC_LBE, rt, rs, s);
21759 break;
21760 case NM_SBE:
21761 check_eva(ctx);
21762 check_cp0_enabled(ctx);
21763 gen_st(ctx, OPC_SBE, rt, rs, s);
21764 break;
21765 case NM_LBUE:
21766 check_eva(ctx);
21767 check_cp0_enabled(ctx);
21768 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21769 break;
21770 case NM_P_PREFE:
21771 if (rt == 31) {
21772 /* case NM_SYNCIE */
21773 check_eva(ctx);
21774 check_cp0_enabled(ctx);
7480515f
AM
21775 /*
21776 * Break the TB to be able to sync copied instructions
21777 * immediately.
21778 */
d046a9ea
DN
21779 ctx->base.is_jmp = DISAS_STOP;
21780 } else {
21781 /* case NM_PREFE */
21782 check_eva(ctx);
21783 check_cp0_enabled(ctx);
21784 /* Treat as NOP. */
21785 }
21786 break;
21787 case NM_LHE:
21788 check_eva(ctx);
21789 check_cp0_enabled(ctx);
21790 gen_ld(ctx, OPC_LHE, rt, rs, s);
21791 break;
21792 case NM_SHE:
21793 check_eva(ctx);
21794 check_cp0_enabled(ctx);
21795 gen_st(ctx, OPC_SHE, rt, rs, s);
21796 break;
21797 case NM_LHUE:
21798 check_eva(ctx);
21799 check_cp0_enabled(ctx);
21800 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21801 break;
21802 case NM_CACHEE:
21803 check_nms_dl_il_sl_tl_l2c(ctx);
21804 gen_cache_operation(ctx, rt, rs, s);
21805 break;
21806 case NM_LWE:
21807 check_eva(ctx);
21808 check_cp0_enabled(ctx);
21809 gen_ld(ctx, OPC_LWE, rt, rs, s);
21810 break;
21811 case NM_SWE:
21812 check_eva(ctx);
21813 check_cp0_enabled(ctx);
21814 gen_st(ctx, OPC_SWE, rt, rs, s);
21815 break;
21816 case NM_P_LLE:
21817 switch (extract32(ctx->opcode, 2, 2)) {
21818 case NM_LLE:
21819 check_xnp(ctx);
21820 check_eva(ctx);
21821 check_cp0_enabled(ctx);
21822 gen_ld(ctx, OPC_LLE, rt, rs, s);
21823 break;
21824 case NM_LLWPE:
21825 check_xnp(ctx);
21826 check_eva(ctx);
21827 check_cp0_enabled(ctx);
21828 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21829 break;
d046a9ea
DN
21830 default:
21831 generate_exception_end(ctx, EXCP_RI);
21832 break;
21833 }
21834 break;
21835 case NM_P_SCE:
21836 switch (extract32(ctx->opcode, 2, 2)) {
21837 case NM_SCE:
21838 check_xnp(ctx);
21839 check_eva(ctx);
21840 check_cp0_enabled(ctx);
33a07fa2 21841 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
21842 break;
21843 case NM_SCWPE:
21844 check_xnp(ctx);
21845 check_eva(ctx);
21846 check_cp0_enabled(ctx);
8d5388c1
AM
21847 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21848 true);
2431a422 21849 break;
d046a9ea
DN
21850 default:
21851 generate_exception_end(ctx, EXCP_RI);
21852 break;
21853 }
21854 break;
21855 }
21856 break;
8f1d9b6d
YK
21857 case NM_P_LS_WM:
21858 case NM_P_LS_UAWM:
fb32f8c8 21859 check_nms(ctx);
8f1d9b6d
YK
21860 {
21861 int count = extract32(ctx->opcode, 12, 3);
21862 int counter = 0;
21863
21864 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21865 extract32(ctx->opcode, 0, 8);
21866 TCGv va = tcg_temp_new();
21867 TCGv t1 = tcg_temp_new();
14776ab5 21868 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
21869 NM_P_LS_UAWM ? MO_UNALN : 0;
21870
21871 count = (count == 0) ? 8 : count;
21872 while (counter != count) {
21873 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21874 int this_offset = offset + (counter << 2);
21875
21876 gen_base_offset_addr(ctx, va, rs, this_offset);
21877
21878 switch (extract32(ctx->opcode, 11, 1)) {
21879 case NM_LWM:
21880 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21881 memop | MO_TESL);
21882 gen_store_gpr(t1, this_rt);
21883 if ((this_rt == rs) &&
21884 (counter != (count - 1))) {
21885 /* UNPREDICTABLE */
21886 }
21887 break;
21888 case NM_SWM:
21889 this_rt = (rt == 0) ? 0 : this_rt;
21890 gen_load_gpr(t1, this_rt);
21891 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21892 memop | MO_TEUL);
21893 break;
21894 }
21895 counter++;
21896 }
21897 tcg_temp_free(va);
21898 tcg_temp_free(t1);
21899 }
21900 break;
21901 default:
21902 generate_exception_end(ctx, EXCP_RI);
21903 break;
21904 }
21905 }
c0280983
YK
21906 break;
21907 case NM_MOVE_BALC:
fb32f8c8 21908 check_nms(ctx);
11d0fc10
SM
21909 {
21910 TCGv t0 = tcg_temp_new();
21911 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21912 extract32(ctx->opcode, 1, 20) << 1;
21913 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21914 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21915 extract32(ctx->opcode, 21, 3));
21916 gen_load_gpr(t0, rt);
21917 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21918 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21919 tcg_temp_free(t0);
21920 }
c0280983
YK
21921 break;
21922 case NM_P_BAL:
11d0fc10
SM
21923 {
21924 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21925 extract32(ctx->opcode, 1, 24) << 1;
21926
21927 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21928 /* BC */
21929 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21930 } else {
21931 /* BALC */
21932 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21933 }
21934 }
c0280983
YK
21935 break;
21936 case NM_P_J:
11d0fc10
SM
21937 switch (extract32(ctx->opcode, 12, 4)) {
21938 case NM_JALRC:
21939 case NM_JALRC_HB:
21940 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21941 break;
21942 case NM_P_BALRSC:
21943 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21944 break;
21945 default:
21946 generate_exception_end(ctx, EXCP_RI);
21947 break;
21948 }
c0280983
YK
21949 break;
21950 case NM_P_BR1:
11d0fc10
SM
21951 {
21952 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21953 extract32(ctx->opcode, 1, 13) << 1;
21954 switch (extract32(ctx->opcode, 14, 2)) {
21955 case NM_BEQC:
fb32f8c8 21956 check_nms(ctx);
11d0fc10
SM
21957 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21958 break;
21959 case NM_P_BR3A:
21960 s = sextract32(ctx->opcode, 0, 1) << 14 |
21961 extract32(ctx->opcode, 1, 13) << 1;
21962 check_cp1_enabled(ctx);
21963 switch (extract32(ctx->opcode, 16, 5)) {
21964 case NM_BC1EQZC:
21965 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21966 break;
21967 case NM_BC1NEZC:
21968 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21969 break;
6d033ca7 21970 case NM_BPOSGE32C:
908f6be1 21971 check_dsp_r3(ctx);
6d033ca7
SM
21972 {
21973 int32_t imm = extract32(ctx->opcode, 1, 13) |
21974 extract32(ctx->opcode, 0, 1) << 13;
21975
21976 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21977 imm);
21978 }
21979 break;
11d0fc10
SM
21980 default:
21981 generate_exception_end(ctx, EXCP_RI);
21982 break;
21983 }
21984 break;
21985 case NM_BGEC:
21986 if (rs == rt) {
21987 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21988 } else {
21989 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21990 }
21991 break;
21992 case NM_BGEUC:
21993 if (rs == rt || rt == 0) {
21994 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21995 } else if (rs == 0) {
21996 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21997 } else {
21998 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21999 }
22000 break;
22001 }
22002 }
c0280983
YK
22003 break;
22004 case NM_P_BR2:
11d0fc10
SM
22005 {
22006 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22007 extract32(ctx->opcode, 1, 13) << 1;
22008 switch (extract32(ctx->opcode, 14, 2)) {
22009 case NM_BNEC:
fb32f8c8 22010 check_nms(ctx);
11d0fc10
SM
22011 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22012 break;
22013 case NM_BLTC:
22014 if (rs != 0 && rt != 0 && rs == rt) {
22015 /* NOP */
22016 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22017 } else {
22018 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22019 }
22020 break;
22021 case NM_BLTUC:
22022 if (rs == 0 || rs == rt) {
22023 /* NOP */
22024 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22025 } else {
22026 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22027 }
22028 break;
22029 default:
22030 generate_exception_end(ctx, EXCP_RI);
22031 break;
22032 }
22033 }
c0280983
YK
22034 break;
22035 case NM_P_BRI:
11d0fc10
SM
22036 {
22037 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22038 extract32(ctx->opcode, 1, 10) << 1;
22039 uint32_t u = extract32(ctx->opcode, 11, 7);
22040
22041 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22042 rt, u, s);
22043 }
c0280983
YK
22044 break;
22045 default:
22046 generate_exception_end(ctx, EXCP_RI);
22047 break;
22048 }
22049 return 4;
22050}
22051
c533c0f4
AM
22052static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22053{
ea4ca3c2 22054 uint32_t op;
99e49abf
AM
22055 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22056 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22057 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 22058 int offset;
ea4ca3c2
YK
22059 int imm;
22060
22061 /* make sure instructions are on a halfword boundary */
22062 if (ctx->base.pc_next & 0x1) {
22063 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22064 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22065 tcg_temp_free(tmp);
22066 generate_exception_end(ctx, EXCP_AdEL);
22067 return 2;
22068 }
22069
22070 op = extract32(ctx->opcode, 10, 6);
22071 switch (op) {
22072 case NM_P16_MV:
8869ad02
YK
22073 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22074 if (rt != 0) {
22075 /* MOVE */
22076 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22077 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22078 } else {
22079 /* P16.RI */
22080 switch (extract32(ctx->opcode, 3, 2)) {
22081 case NM_P16_SYSCALL:
22082 if (extract32(ctx->opcode, 2, 1) == 0) {
22083 generate_exception_end(ctx, EXCP_SYSCALL);
22084 } else {
22085 generate_exception_end(ctx, EXCP_RI);
22086 }
22087 break;
22088 case NM_BREAK16:
22089 generate_exception_end(ctx, EXCP_BREAK);
22090 break;
22091 case NM_SDBBP16:
22092 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22093 gen_helper_do_semihosting(cpu_env);
22094 } else {
22095 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22096 generate_exception_end(ctx, EXCP_RI);
22097 } else {
22098 generate_exception_end(ctx, EXCP_DBp);
22099 }
22100 }
22101 break;
22102 default:
22103 generate_exception_end(ctx, EXCP_RI);
22104 break;
22105 }
22106 }
ea4ca3c2
YK
22107 break;
22108 case NM_P16_SHIFT:
c46562fb
YK
22109 {
22110 int shift = extract32(ctx->opcode, 0, 3);
22111 uint32_t opc = 0;
22112 shift = (shift == 0) ? 8 : shift;
22113
22114 switch (extract32(ctx->opcode, 3, 1)) {
22115 case NM_SLL16:
22116 opc = OPC_SLL;
22117 break;
22118 case NM_SRL16:
22119 opc = OPC_SRL;
22120 break;
22121 }
22122 gen_shift_imm(ctx, opc, rt, rs, shift);
22123 }
ea4ca3c2
YK
22124 break;
22125 case NM_P16C:
8bdb7029
YK
22126 switch (ctx->opcode & 1) {
22127 case NM_POOL16C_0:
80845edf 22128 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
22129 break;
22130 case NM_LWXS16:
22131 gen_ldxs(ctx, rt, rs, rd);
22132 break;
22133 }
ea4ca3c2
YK
22134 break;
22135 case NM_P16_A1:
22136 switch (extract32(ctx->opcode, 6, 1)) {
22137 case NM_ADDIUR1SP:
22138 imm = extract32(ctx->opcode, 0, 6) << 2;
22139 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22140 break;
22141 default:
22142 generate_exception_end(ctx, EXCP_RI);
22143 break;
22144 }
22145 break;
22146 case NM_P16_A2:
22147 switch (extract32(ctx->opcode, 3, 1)) {
22148 case NM_ADDIUR2:
22149 imm = extract32(ctx->opcode, 0, 3) << 2;
22150 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22151 break;
22152 case NM_P_ADDIURS5:
22153 rt = extract32(ctx->opcode, 5, 5);
22154 if (rt != 0) {
22155 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22156 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22157 (extract32(ctx->opcode, 0, 3));
22158 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22159 }
22160 break;
22161 }
22162 break;
22163 case NM_P16_ADDU:
22164 switch (ctx->opcode & 0x1) {
22165 case NM_ADDU16:
22166 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22167 break;
22168 case NM_SUBU16:
22169 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22170 break;
22171 }
22172 break;
22173 case NM_P16_4X4:
22174 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22175 extract32(ctx->opcode, 5, 3);
22176 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22177 extract32(ctx->opcode, 0, 3);
22178 rt = decode_gpr_gpr4(rt);
22179 rs = decode_gpr_gpr4(rs);
22180 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22181 (extract32(ctx->opcode, 3, 1))) {
22182 case NM_ADDU4X4:
fb32f8c8 22183 check_nms(ctx);
ea4ca3c2
YK
22184 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22185 break;
22186 case NM_MUL4X4:
fb32f8c8 22187 check_nms(ctx);
ea4ca3c2
YK
22188 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22189 break;
22190 default:
22191 generate_exception_end(ctx, EXCP_RI);
22192 break;
22193 }
22194 break;
22195 case NM_LI16:
8869ad02
YK
22196 {
22197 int imm = extract32(ctx->opcode, 0, 7);
22198 imm = (imm == 0x7f ? -1 : imm);
22199 if (rt != 0) {
22200 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22201 }
22202 }
ea4ca3c2
YK
22203 break;
22204 case NM_ANDI16:
80845edf
YK
22205 {
22206 uint32_t u = extract32(ctx->opcode, 0, 4);
22207 u = (u == 12) ? 0xff :
22208 (u == 13) ? 0xffff : u;
22209 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22210 }
ea4ca3c2
YK
22211 break;
22212 case NM_P16_LB:
8bdb7029
YK
22213 offset = extract32(ctx->opcode, 0, 2);
22214 switch (extract32(ctx->opcode, 2, 2)) {
22215 case NM_LB16:
22216 gen_ld(ctx, OPC_LB, rt, rs, offset);
22217 break;
22218 case NM_SB16:
22219 rt = decode_gpr_gpr3_src_store(
99e49abf 22220 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22221 gen_st(ctx, OPC_SB, rt, rs, offset);
22222 break;
22223 case NM_LBU16:
22224 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22225 break;
22226 default:
22227 generate_exception_end(ctx, EXCP_RI);
22228 break;
22229 }
ea4ca3c2
YK
22230 break;
22231 case NM_P16_LH:
8bdb7029
YK
22232 offset = extract32(ctx->opcode, 1, 2) << 1;
22233 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22234 case NM_LH16:
22235 gen_ld(ctx, OPC_LH, rt, rs, offset);
22236 break;
22237 case NM_SH16:
22238 rt = decode_gpr_gpr3_src_store(
99e49abf 22239 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22240 gen_st(ctx, OPC_SH, rt, rs, offset);
22241 break;
22242 case NM_LHU16:
22243 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22244 break;
22245 default:
22246 generate_exception_end(ctx, EXCP_RI);
22247 break;
22248 }
ea4ca3c2
YK
22249 break;
22250 case NM_LW16:
8bdb7029
YK
22251 offset = extract32(ctx->opcode, 0, 4) << 2;
22252 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22253 break;
22254 case NM_LWSP16:
8bdb7029
YK
22255 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22256 offset = extract32(ctx->opcode, 0, 5) << 2;
22257 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22258 break;
22259 case NM_LW4X4:
fb32f8c8 22260 check_nms(ctx);
8bdb7029
YK
22261 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22262 extract32(ctx->opcode, 5, 3);
22263 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22264 extract32(ctx->opcode, 0, 3);
22265 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22266 (extract32(ctx->opcode, 8, 1) << 2);
22267 rt = decode_gpr_gpr4(rt);
22268 rs = decode_gpr_gpr4(rs);
22269 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22270 break;
22271 case NM_SW4X4:
fb32f8c8 22272 check_nms(ctx);
8bdb7029
YK
22273 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22274 extract32(ctx->opcode, 5, 3);
22275 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22276 extract32(ctx->opcode, 0, 3);
22277 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22278 (extract32(ctx->opcode, 8, 1) << 2);
22279 rt = decode_gpr_gpr4_zero(rt);
22280 rs = decode_gpr_gpr4(rs);
22281 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22282 break;
22283 case NM_LWGP16:
8bdb7029
YK
22284 offset = extract32(ctx->opcode, 0, 7) << 2;
22285 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22286 break;
22287 case NM_SWSP16:
8bdb7029
YK
22288 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22289 offset = extract32(ctx->opcode, 0, 5) << 2;
22290 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22291 break;
22292 case NM_SW16:
8bdb7029 22293 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
22294 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22295 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
22296 offset = extract32(ctx->opcode, 0, 4) << 2;
22297 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22298 break;
22299 case NM_SWGP16:
8bdb7029 22300 rt = decode_gpr_gpr3_src_store(
99e49abf 22301 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22302 offset = extract32(ctx->opcode, 0, 7) << 2;
22303 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22304 break;
22305 case NM_BC16:
764371d2
SM
22306 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22307 (sextract32(ctx->opcode, 0, 1) << 10) |
22308 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22309 break;
22310 case NM_BALC16:
764371d2
SM
22311 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22312 (sextract32(ctx->opcode, 0, 1) << 10) |
22313 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22314 break;
22315 case NM_BEQZC16:
764371d2
SM
22316 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22317 (sextract32(ctx->opcode, 0, 1) << 7) |
22318 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22319 break;
22320 case NM_BNEZC16:
764371d2
SM
22321 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22322 (sextract32(ctx->opcode, 0, 1) << 7) |
22323 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22324 break;
22325 case NM_P16_BR:
764371d2
SM
22326 switch (ctx->opcode & 0xf) {
22327 case 0:
22328 /* P16.JRC */
22329 switch (extract32(ctx->opcode, 4, 1)) {
22330 case NM_JRC:
22331 gen_compute_branch_nm(ctx, OPC_JR, 2,
22332 extract32(ctx->opcode, 5, 5), 0, 0);
22333 break;
22334 case NM_JALRC16:
22335 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22336 extract32(ctx->opcode, 5, 5), 31, 0);
22337 break;
22338 }
22339 break;
22340 default:
22341 {
22342 /* P16.BRI */
22343 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22344 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22345 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22346 extract32(ctx->opcode, 0, 4) << 1);
22347 }
22348 break;
22349 }
ea4ca3c2
YK
22350 break;
22351 case NM_P16_SR:
bf0718c5
SM
22352 {
22353 int count = extract32(ctx->opcode, 0, 4);
22354 int u = extract32(ctx->opcode, 4, 4) << 4;
22355
22356 rt = 30 + extract32(ctx->opcode, 9, 1);
22357 switch (extract32(ctx->opcode, 8, 1)) {
22358 case NM_SAVE16:
22359 gen_save(ctx, rt, count, 0, u);
22360 break;
22361 case NM_RESTORE_JRC16:
22362 gen_restore(ctx, rt, count, 0, u);
22363 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22364 break;
22365 }
22366 }
ea4ca3c2
YK
22367 break;
22368 case NM_MOVEP:
ea4ca3c2 22369 case NM_MOVEPREV:
fb32f8c8 22370 check_nms(ctx);
4d18232c
YK
22371 {
22372 static const int gpr2reg1[] = {4, 5, 6, 7};
22373 static const int gpr2reg2[] = {5, 6, 7, 8};
22374 int re;
22375 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22376 extract32(ctx->opcode, 8, 1);
22377 int r1 = gpr2reg1[rd2];
22378 int r2 = gpr2reg2[rd2];
22379 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22380 extract32(ctx->opcode, 0, 3);
22381 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22382 extract32(ctx->opcode, 5, 3);
22383 TCGv t0 = tcg_temp_new();
22384 TCGv t1 = tcg_temp_new();
22385 if (op == NM_MOVEP) {
22386 rd = r1;
22387 re = r2;
22388 rs = decode_gpr_gpr4_zero(r3);
22389 rt = decode_gpr_gpr4_zero(r4);
22390 } else {
22391 rd = decode_gpr_gpr4(r3);
22392 re = decode_gpr_gpr4(r4);
22393 rs = r1;
22394 rt = r2;
22395 }
22396 gen_load_gpr(t0, rs);
22397 gen_load_gpr(t1, rt);
22398 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22399 tcg_gen_mov_tl(cpu_gpr[re], t1);
22400 tcg_temp_free(t0);
22401 tcg_temp_free(t1);
22402 }
ea4ca3c2
YK
22403 break;
22404 default:
c0280983 22405 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
22406 }
22407
c533c0f4
AM
22408 return 2;
22409}
22410
22411
3c824109
NF
22412/* SmartMIPS extension to MIPS32 */
22413
22414#if defined(TARGET_MIPS64)
22415
22416/* MDMX extension to MIPS64 */
22417
22418#endif
22419
9b1a1d68 22420/* MIPSDSP functions. */
d75c135e 22421static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
22422 int rd, int base, int offset)
22423{
9b1a1d68
JL
22424 TCGv t0;
22425
9b1a1d68
JL
22426 check_dsp(ctx);
22427 t0 = tcg_temp_new();
22428
22429 if (base == 0) {
22430 gen_load_gpr(t0, offset);
22431 } else if (offset == 0) {
22432 gen_load_gpr(t0, base);
22433 } else {
22434 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22435 }
22436
9b1a1d68
JL
22437 switch (opc) {
22438 case OPC_LBUX:
5f68f5ae 22439 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 22440 gen_store_gpr(t0, rd);
9b1a1d68
JL
22441 break;
22442 case OPC_LHX:
5f68f5ae 22443 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 22444 gen_store_gpr(t0, rd);
9b1a1d68
JL
22445 break;
22446 case OPC_LWX:
5f68f5ae 22447 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 22448 gen_store_gpr(t0, rd);
9b1a1d68
JL
22449 break;
22450#if defined(TARGET_MIPS64)
22451 case OPC_LDX:
5f68f5ae 22452 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 22453 gen_store_gpr(t0, rd);
9b1a1d68
JL
22454 break;
22455#endif
22456 }
9b1a1d68
JL
22457 tcg_temp_free(t0);
22458}
22459
461c08df
JL
22460static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22461 int ret, int v1, int v2)
22462{
461c08df
JL
22463 TCGv v1_t;
22464 TCGv v2_t;
22465
22466 if (ret == 0) {
22467 /* Treat as NOP. */
461c08df
JL
22468 return;
22469 }
22470
22471 v1_t = tcg_temp_new();
22472 v2_t = tcg_temp_new();
22473
22474 gen_load_gpr(v1_t, v1);
22475 gen_load_gpr(v2_t, v2);
22476
22477 switch (op1) {
22478 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22479 case OPC_MULT_G_2E:
908f6be1 22480 check_dsp_r2(ctx);
461c08df
JL
22481 switch (op2) {
22482 case OPC_ADDUH_QB:
22483 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22484 break;
22485 case OPC_ADDUH_R_QB:
22486 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22487 break;
22488 case OPC_ADDQH_PH:
22489 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22490 break;
22491 case OPC_ADDQH_R_PH:
22492 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22493 break;
22494 case OPC_ADDQH_W:
22495 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22496 break;
22497 case OPC_ADDQH_R_W:
22498 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22499 break;
22500 case OPC_SUBUH_QB:
22501 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22502 break;
22503 case OPC_SUBUH_R_QB:
22504 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22505 break;
22506 case OPC_SUBQH_PH:
22507 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22508 break;
22509 case OPC_SUBQH_R_PH:
22510 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22511 break;
22512 case OPC_SUBQH_W:
22513 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22514 break;
22515 case OPC_SUBQH_R_W:
22516 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22517 break;
22518 }
22519 break;
22520 case OPC_ABSQ_S_PH_DSP:
22521 switch (op2) {
22522 case OPC_ABSQ_S_QB:
908f6be1 22523 check_dsp_r2(ctx);
461c08df
JL
22524 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22525 break;
22526 case OPC_ABSQ_S_PH:
22527 check_dsp(ctx);
22528 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22529 break;
22530 case OPC_ABSQ_S_W:
22531 check_dsp(ctx);
22532 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22533 break;
22534 case OPC_PRECEQ_W_PHL:
22535 check_dsp(ctx);
22536 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22537 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22538 break;
22539 case OPC_PRECEQ_W_PHR:
22540 check_dsp(ctx);
22541 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22542 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22543 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22544 break;
22545 case OPC_PRECEQU_PH_QBL:
22546 check_dsp(ctx);
22547 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22548 break;
22549 case OPC_PRECEQU_PH_QBR:
22550 check_dsp(ctx);
22551 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22552 break;
22553 case OPC_PRECEQU_PH_QBLA:
22554 check_dsp(ctx);
22555 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22556 break;
22557 case OPC_PRECEQU_PH_QBRA:
22558 check_dsp(ctx);
22559 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22560 break;
22561 case OPC_PRECEU_PH_QBL:
22562 check_dsp(ctx);
22563 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22564 break;
22565 case OPC_PRECEU_PH_QBR:
22566 check_dsp(ctx);
22567 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22568 break;
22569 case OPC_PRECEU_PH_QBLA:
22570 check_dsp(ctx);
22571 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22572 break;
22573 case OPC_PRECEU_PH_QBRA:
22574 check_dsp(ctx);
22575 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22576 break;
22577 }
22578 break;
22579 case OPC_ADDU_QB_DSP:
22580 switch (op2) {
22581 case OPC_ADDQ_PH:
22582 check_dsp(ctx);
22583 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22584 break;
22585 case OPC_ADDQ_S_PH:
22586 check_dsp(ctx);
22587 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22588 break;
22589 case OPC_ADDQ_S_W:
22590 check_dsp(ctx);
22591 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_ADDU_QB:
22594 check_dsp(ctx);
22595 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_ADDU_S_QB:
22598 check_dsp(ctx);
22599 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_ADDU_PH:
908f6be1 22602 check_dsp_r2(ctx);
461c08df
JL
22603 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22604 break;
22605 case OPC_ADDU_S_PH:
908f6be1 22606 check_dsp_r2(ctx);
461c08df
JL
22607 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22608 break;
22609 case OPC_SUBQ_PH:
22610 check_dsp(ctx);
22611 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22612 break;
22613 case OPC_SUBQ_S_PH:
22614 check_dsp(ctx);
22615 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22616 break;
22617 case OPC_SUBQ_S_W:
22618 check_dsp(ctx);
22619 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22620 break;
22621 case OPC_SUBU_QB:
22622 check_dsp(ctx);
22623 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22624 break;
22625 case OPC_SUBU_S_QB:
22626 check_dsp(ctx);
22627 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22628 break;
22629 case OPC_SUBU_PH:
908f6be1 22630 check_dsp_r2(ctx);
461c08df
JL
22631 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22632 break;
22633 case OPC_SUBU_S_PH:
908f6be1 22634 check_dsp_r2(ctx);
461c08df
JL
22635 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22636 break;
22637 case OPC_ADDSC:
22638 check_dsp(ctx);
22639 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22640 break;
22641 case OPC_ADDWC:
22642 check_dsp(ctx);
22643 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22644 break;
22645 case OPC_MODSUB:
22646 check_dsp(ctx);
22647 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22648 break;
22649 case OPC_RADDU_W_QB:
22650 check_dsp(ctx);
22651 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22652 break;
22653 }
22654 break;
22655 case OPC_CMPU_EQ_QB_DSP:
22656 switch (op2) {
22657 case OPC_PRECR_QB_PH:
908f6be1 22658 check_dsp_r2(ctx);
461c08df
JL
22659 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22660 break;
22661 case OPC_PRECRQ_QB_PH:
22662 check_dsp(ctx);
22663 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22664 break;
22665 case OPC_PRECR_SRA_PH_W:
908f6be1 22666 check_dsp_r2(ctx);
461c08df
JL
22667 {
22668 TCGv_i32 sa_t = tcg_const_i32(v2);
22669 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22670 cpu_gpr[ret]);
22671 tcg_temp_free_i32(sa_t);
22672 break;
22673 }
22674 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22675 check_dsp_r2(ctx);
461c08df
JL
22676 {
22677 TCGv_i32 sa_t = tcg_const_i32(v2);
22678 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22679 cpu_gpr[ret]);
22680 tcg_temp_free_i32(sa_t);
22681 break;
22682 }
22683 case OPC_PRECRQ_PH_W:
22684 check_dsp(ctx);
22685 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22686 break;
22687 case OPC_PRECRQ_RS_PH_W:
22688 check_dsp(ctx);
22689 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22690 break;
22691 case OPC_PRECRQU_S_QB_PH:
22692 check_dsp(ctx);
22693 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22694 break;
22695 }
22696 break;
22697#ifdef TARGET_MIPS64
22698 case OPC_ABSQ_S_QH_DSP:
22699 switch (op2) {
22700 case OPC_PRECEQ_L_PWL:
22701 check_dsp(ctx);
22702 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22703 break;
22704 case OPC_PRECEQ_L_PWR:
22705 check_dsp(ctx);
22706 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22707 break;
22708 case OPC_PRECEQ_PW_QHL:
22709 check_dsp(ctx);
22710 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22711 break;
22712 case OPC_PRECEQ_PW_QHR:
22713 check_dsp(ctx);
22714 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22715 break;
22716 case OPC_PRECEQ_PW_QHLA:
22717 check_dsp(ctx);
22718 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22719 break;
22720 case OPC_PRECEQ_PW_QHRA:
22721 check_dsp(ctx);
22722 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22723 break;
22724 case OPC_PRECEQU_QH_OBL:
22725 check_dsp(ctx);
22726 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22727 break;
22728 case OPC_PRECEQU_QH_OBR:
22729 check_dsp(ctx);
22730 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22731 break;
22732 case OPC_PRECEQU_QH_OBLA:
22733 check_dsp(ctx);
22734 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22735 break;
22736 case OPC_PRECEQU_QH_OBRA:
22737 check_dsp(ctx);
22738 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22739 break;
22740 case OPC_PRECEU_QH_OBL:
22741 check_dsp(ctx);
22742 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22743 break;
22744 case OPC_PRECEU_QH_OBR:
22745 check_dsp(ctx);
22746 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22747 break;
22748 case OPC_PRECEU_QH_OBLA:
22749 check_dsp(ctx);
22750 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22751 break;
22752 case OPC_PRECEU_QH_OBRA:
22753 check_dsp(ctx);
22754 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22755 break;
22756 case OPC_ABSQ_S_OB:
908f6be1 22757 check_dsp_r2(ctx);
461c08df
JL
22758 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22759 break;
22760 case OPC_ABSQ_S_PW:
22761 check_dsp(ctx);
22762 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22763 break;
22764 case OPC_ABSQ_S_QH:
22765 check_dsp(ctx);
22766 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22767 break;
22768 }
22769 break;
22770 case OPC_ADDU_OB_DSP:
22771 switch (op2) {
22772 case OPC_RADDU_L_OB:
22773 check_dsp(ctx);
22774 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22775 break;
22776 case OPC_SUBQ_PW:
22777 check_dsp(ctx);
22778 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22779 break;
22780 case OPC_SUBQ_S_PW:
22781 check_dsp(ctx);
22782 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22783 break;
22784 case OPC_SUBQ_QH:
22785 check_dsp(ctx);
22786 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22787 break;
22788 case OPC_SUBQ_S_QH:
22789 check_dsp(ctx);
22790 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22791 break;
22792 case OPC_SUBU_OB:
22793 check_dsp(ctx);
22794 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22795 break;
22796 case OPC_SUBU_S_OB:
22797 check_dsp(ctx);
22798 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22799 break;
22800 case OPC_SUBU_QH:
908f6be1 22801 check_dsp_r2(ctx);
461c08df
JL
22802 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22803 break;
22804 case OPC_SUBU_S_QH:
908f6be1 22805 check_dsp_r2(ctx);
461c08df
JL
22806 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22807 break;
22808 case OPC_SUBUH_OB:
908f6be1 22809 check_dsp_r2(ctx);
461c08df
JL
22810 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22811 break;
22812 case OPC_SUBUH_R_OB:
908f6be1 22813 check_dsp_r2(ctx);
461c08df
JL
22814 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22815 break;
22816 case OPC_ADDQ_PW:
22817 check_dsp(ctx);
22818 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22819 break;
22820 case OPC_ADDQ_S_PW:
22821 check_dsp(ctx);
22822 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22823 break;
22824 case OPC_ADDQ_QH:
22825 check_dsp(ctx);
22826 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22827 break;
22828 case OPC_ADDQ_S_QH:
22829 check_dsp(ctx);
22830 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22831 break;
22832 case OPC_ADDU_OB:
22833 check_dsp(ctx);
22834 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22835 break;
22836 case OPC_ADDU_S_OB:
22837 check_dsp(ctx);
22838 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22839 break;
22840 case OPC_ADDU_QH:
908f6be1 22841 check_dsp_r2(ctx);
461c08df
JL
22842 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22843 break;
22844 case OPC_ADDU_S_QH:
908f6be1 22845 check_dsp_r2(ctx);
461c08df
JL
22846 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22847 break;
22848 case OPC_ADDUH_OB:
908f6be1 22849 check_dsp_r2(ctx);
461c08df
JL
22850 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22851 break;
22852 case OPC_ADDUH_R_OB:
908f6be1 22853 check_dsp_r2(ctx);
461c08df
JL
22854 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22855 break;
22856 }
22857 break;
22858 case OPC_CMPU_EQ_OB_DSP:
22859 switch (op2) {
22860 case OPC_PRECR_OB_QH:
908f6be1 22861 check_dsp_r2(ctx);
461c08df
JL
22862 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22863 break;
22864 case OPC_PRECR_SRA_QH_PW:
908f6be1 22865 check_dsp_r2(ctx);
461c08df
JL
22866 {
22867 TCGv_i32 ret_t = tcg_const_i32(ret);
22868 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22869 tcg_temp_free_i32(ret_t);
22870 break;
22871 }
22872 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22873 check_dsp_r2(ctx);
461c08df
JL
22874 {
22875 TCGv_i32 sa_v = tcg_const_i32(ret);
22876 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22877 tcg_temp_free_i32(sa_v);
22878 break;
22879 }
22880 case OPC_PRECRQ_OB_QH:
22881 check_dsp(ctx);
22882 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22883 break;
22884 case OPC_PRECRQ_PW_L:
22885 check_dsp(ctx);
22886 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22887 break;
22888 case OPC_PRECRQ_QH_PW:
22889 check_dsp(ctx);
22890 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22891 break;
22892 case OPC_PRECRQ_RS_QH_PW:
22893 check_dsp(ctx);
22894 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22895 break;
22896 case OPC_PRECRQU_S_OB_QH:
22897 check_dsp(ctx);
22898 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22899 break;
22900 }
22901 break;
22902#endif
22903 }
22904
22905 tcg_temp_free(v1_t);
22906 tcg_temp_free(v2_t);
461c08df 22907}
9b1a1d68 22908
77c5fa8b
JL
22909static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22910 int ret, int v1, int v2)
22911{
22912 uint32_t op2;
77c5fa8b
JL
22913 TCGv t0;
22914 TCGv v1_t;
22915 TCGv v2_t;
22916
22917 if (ret == 0) {
22918 /* Treat as NOP. */
77c5fa8b
JL
22919 return;
22920 }
22921
22922 t0 = tcg_temp_new();
22923 v1_t = tcg_temp_new();
22924 v2_t = tcg_temp_new();
22925
22926 tcg_gen_movi_tl(t0, v1);
22927 gen_load_gpr(v1_t, v1);
22928 gen_load_gpr(v2_t, v2);
22929
22930 switch (opc) {
22931 case OPC_SHLL_QB_DSP:
22932 {
22933 op2 = MASK_SHLL_QB(ctx->opcode);
22934 switch (op2) {
22935 case OPC_SHLL_QB:
22936 check_dsp(ctx);
22937 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22938 break;
22939 case OPC_SHLLV_QB:
22940 check_dsp(ctx);
22941 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22942 break;
22943 case OPC_SHLL_PH:
22944 check_dsp(ctx);
22945 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22946 break;
22947 case OPC_SHLLV_PH:
22948 check_dsp(ctx);
22949 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22950 break;
22951 case OPC_SHLL_S_PH:
22952 check_dsp(ctx);
22953 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22954 break;
22955 case OPC_SHLLV_S_PH:
22956 check_dsp(ctx);
22957 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22958 break;
22959 case OPC_SHLL_S_W:
22960 check_dsp(ctx);
22961 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22962 break;
22963 case OPC_SHLLV_S_W:
22964 check_dsp(ctx);
22965 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22966 break;
22967 case OPC_SHRL_QB:
22968 check_dsp(ctx);
22969 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22970 break;
22971 case OPC_SHRLV_QB:
22972 check_dsp(ctx);
22973 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22974 break;
22975 case OPC_SHRL_PH:
908f6be1 22976 check_dsp_r2(ctx);
77c5fa8b
JL
22977 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22978 break;
22979 case OPC_SHRLV_PH:
908f6be1 22980 check_dsp_r2(ctx);
77c5fa8b
JL
22981 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22982 break;
22983 case OPC_SHRA_QB:
908f6be1 22984 check_dsp_r2(ctx);
77c5fa8b
JL
22985 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22986 break;
22987 case OPC_SHRA_R_QB:
908f6be1 22988 check_dsp_r2(ctx);
77c5fa8b
JL
22989 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22990 break;
22991 case OPC_SHRAV_QB:
908f6be1 22992 check_dsp_r2(ctx);
77c5fa8b
JL
22993 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22994 break;
22995 case OPC_SHRAV_R_QB:
908f6be1 22996 check_dsp_r2(ctx);
77c5fa8b
JL
22997 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22998 break;
22999 case OPC_SHRA_PH:
23000 check_dsp(ctx);
23001 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23002 break;
23003 case OPC_SHRA_R_PH:
23004 check_dsp(ctx);
23005 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23006 break;
23007 case OPC_SHRAV_PH:
23008 check_dsp(ctx);
23009 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23010 break;
23011 case OPC_SHRAV_R_PH:
23012 check_dsp(ctx);
23013 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23014 break;
23015 case OPC_SHRA_R_W:
23016 check_dsp(ctx);
23017 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23018 break;
23019 case OPC_SHRAV_R_W:
23020 check_dsp(ctx);
23021 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23022 break;
23023 default: /* Invalid */
23024 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 23025 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23026 break;
23027 }
23028 break;
23029 }
23030#ifdef TARGET_MIPS64
23031 case OPC_SHLL_OB_DSP:
23032 op2 = MASK_SHLL_OB(ctx->opcode);
23033 switch (op2) {
23034 case OPC_SHLL_PW:
23035 check_dsp(ctx);
23036 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23037 break;
23038 case OPC_SHLLV_PW:
23039 check_dsp(ctx);
23040 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23041 break;
23042 case OPC_SHLL_S_PW:
23043 check_dsp(ctx);
23044 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23045 break;
23046 case OPC_SHLLV_S_PW:
23047 check_dsp(ctx);
23048 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23049 break;
23050 case OPC_SHLL_OB:
23051 check_dsp(ctx);
23052 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23053 break;
23054 case OPC_SHLLV_OB:
23055 check_dsp(ctx);
23056 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23057 break;
23058 case OPC_SHLL_QH:
23059 check_dsp(ctx);
23060 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23061 break;
23062 case OPC_SHLLV_QH:
23063 check_dsp(ctx);
23064 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23065 break;
23066 case OPC_SHLL_S_QH:
23067 check_dsp(ctx);
23068 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23069 break;
23070 case OPC_SHLLV_S_QH:
23071 check_dsp(ctx);
23072 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23073 break;
23074 case OPC_SHRA_OB:
908f6be1 23075 check_dsp_r2(ctx);
77c5fa8b
JL
23076 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23077 break;
23078 case OPC_SHRAV_OB:
908f6be1 23079 check_dsp_r2(ctx);
77c5fa8b
JL
23080 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23081 break;
23082 case OPC_SHRA_R_OB:
908f6be1 23083 check_dsp_r2(ctx);
77c5fa8b
JL
23084 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23085 break;
23086 case OPC_SHRAV_R_OB:
908f6be1 23087 check_dsp_r2(ctx);
77c5fa8b
JL
23088 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23089 break;
23090 case OPC_SHRA_PW:
23091 check_dsp(ctx);
23092 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23093 break;
23094 case OPC_SHRAV_PW:
23095 check_dsp(ctx);
23096 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23097 break;
23098 case OPC_SHRA_R_PW:
23099 check_dsp(ctx);
23100 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23101 break;
23102 case OPC_SHRAV_R_PW:
23103 check_dsp(ctx);
23104 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23105 break;
23106 case OPC_SHRA_QH:
23107 check_dsp(ctx);
23108 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23109 break;
23110 case OPC_SHRAV_QH:
23111 check_dsp(ctx);
23112 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23113 break;
23114 case OPC_SHRA_R_QH:
23115 check_dsp(ctx);
23116 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23117 break;
23118 case OPC_SHRAV_R_QH:
23119 check_dsp(ctx);
23120 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23121 break;
23122 case OPC_SHRL_OB:
23123 check_dsp(ctx);
23124 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23125 break;
23126 case OPC_SHRLV_OB:
23127 check_dsp(ctx);
23128 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23129 break;
23130 case OPC_SHRL_QH:
908f6be1 23131 check_dsp_r2(ctx);
77c5fa8b
JL
23132 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23133 break;
23134 case OPC_SHRLV_QH:
908f6be1 23135 check_dsp_r2(ctx);
77c5fa8b
JL
23136 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23137 break;
23138 default: /* Invalid */
23139 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 23140 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23141 break;
23142 }
23143 break;
23144#endif
23145 }
23146
23147 tcg_temp_free(t0);
23148 tcg_temp_free(v1_t);
23149 tcg_temp_free(v2_t);
77c5fa8b
JL
23150}
23151
a22260ae
JL
23152static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23153 int ret, int v1, int v2, int check_ret)
23154{
a22260ae
JL
23155 TCGv_i32 t0;
23156 TCGv v1_t;
23157 TCGv v2_t;
23158
23159 if ((ret == 0) && (check_ret == 1)) {
23160 /* Treat as NOP. */
a22260ae
JL
23161 return;
23162 }
23163
23164 t0 = tcg_temp_new_i32();
23165 v1_t = tcg_temp_new();
23166 v2_t = tcg_temp_new();
23167
23168 tcg_gen_movi_i32(t0, ret);
23169 gen_load_gpr(v1_t, v1);
23170 gen_load_gpr(v2_t, v2);
23171
23172 switch (op1) {
7480515f
AM
23173 /*
23174 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23175 * the same mask and op1.
23176 */
a22260ae 23177 case OPC_MULT_G_2E:
908f6be1 23178 check_dsp_r2(ctx);
a22260ae
JL
23179 switch (op2) {
23180 case OPC_MUL_PH:
23181 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_MUL_S_PH:
23184 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23185 break;
23186 case OPC_MULQ_S_W:
23187 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23188 break;
23189 case OPC_MULQ_RS_W:
23190 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23191 break;
23192 }
23193 break;
23194 case OPC_DPA_W_PH_DSP:
23195 switch (op2) {
23196 case OPC_DPAU_H_QBL:
23197 check_dsp(ctx);
23198 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23199 break;
23200 case OPC_DPAU_H_QBR:
23201 check_dsp(ctx);
23202 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23203 break;
23204 case OPC_DPSU_H_QBL:
23205 check_dsp(ctx);
23206 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23207 break;
23208 case OPC_DPSU_H_QBR:
23209 check_dsp(ctx);
23210 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23211 break;
23212 case OPC_DPA_W_PH:
908f6be1 23213 check_dsp_r2(ctx);
a22260ae
JL
23214 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23215 break;
23216 case OPC_DPAX_W_PH:
908f6be1 23217 check_dsp_r2(ctx);
a22260ae
JL
23218 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23219 break;
23220 case OPC_DPAQ_S_W_PH:
23221 check_dsp(ctx);
23222 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23223 break;
23224 case OPC_DPAQX_S_W_PH:
908f6be1 23225 check_dsp_r2(ctx);
a22260ae
JL
23226 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23227 break;
23228 case OPC_DPAQX_SA_W_PH:
908f6be1 23229 check_dsp_r2(ctx);
a22260ae
JL
23230 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23231 break;
23232 case OPC_DPS_W_PH:
908f6be1 23233 check_dsp_r2(ctx);
a22260ae
JL
23234 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23235 break;
23236 case OPC_DPSX_W_PH:
908f6be1 23237 check_dsp_r2(ctx);
a22260ae
JL
23238 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23239 break;
23240 case OPC_DPSQ_S_W_PH:
23241 check_dsp(ctx);
23242 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23243 break;
23244 case OPC_DPSQX_S_W_PH:
908f6be1 23245 check_dsp_r2(ctx);
a22260ae
JL
23246 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23247 break;
23248 case OPC_DPSQX_SA_W_PH:
908f6be1 23249 check_dsp_r2(ctx);
a22260ae
JL
23250 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23251 break;
23252 case OPC_MULSAQ_S_W_PH:
23253 check_dsp(ctx);
23254 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23255 break;
23256 case OPC_DPAQ_SA_L_W:
23257 check_dsp(ctx);
23258 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23259 break;
23260 case OPC_DPSQ_SA_L_W:
23261 check_dsp(ctx);
23262 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23263 break;
23264 case OPC_MAQ_S_W_PHL:
23265 check_dsp(ctx);
23266 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23267 break;
23268 case OPC_MAQ_S_W_PHR:
23269 check_dsp(ctx);
23270 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23271 break;
23272 case OPC_MAQ_SA_W_PHL:
23273 check_dsp(ctx);
23274 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23275 break;
23276 case OPC_MAQ_SA_W_PHR:
23277 check_dsp(ctx);
23278 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23279 break;
23280 case OPC_MULSA_W_PH:
908f6be1 23281 check_dsp_r2(ctx);
a22260ae
JL
23282 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23283 break;
23284 }
23285 break;
23286#ifdef TARGET_MIPS64
23287 case OPC_DPAQ_W_QH_DSP:
23288 {
23289 int ac = ret & 0x03;
23290 tcg_gen_movi_i32(t0, ac);
23291
23292 switch (op2) {
23293 case OPC_DMADD:
23294 check_dsp(ctx);
23295 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23296 break;
23297 case OPC_DMADDU:
23298 check_dsp(ctx);
23299 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23300 break;
23301 case OPC_DMSUB:
23302 check_dsp(ctx);
23303 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23304 break;
23305 case OPC_DMSUBU:
23306 check_dsp(ctx);
23307 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23308 break;
23309 case OPC_DPA_W_QH:
908f6be1 23310 check_dsp_r2(ctx);
a22260ae
JL
23311 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23312 break;
23313 case OPC_DPAQ_S_W_QH:
23314 check_dsp(ctx);
23315 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23316 break;
23317 case OPC_DPAQ_SA_L_PW:
23318 check_dsp(ctx);
23319 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23320 break;
23321 case OPC_DPAU_H_OBL:
23322 check_dsp(ctx);
23323 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23324 break;
23325 case OPC_DPAU_H_OBR:
23326 check_dsp(ctx);
23327 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23328 break;
23329 case OPC_DPS_W_QH:
908f6be1 23330 check_dsp_r2(ctx);
a22260ae
JL
23331 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23332 break;
23333 case OPC_DPSQ_S_W_QH:
23334 check_dsp(ctx);
23335 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23336 break;
23337 case OPC_DPSQ_SA_L_PW:
23338 check_dsp(ctx);
23339 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23340 break;
23341 case OPC_DPSU_H_OBL:
23342 check_dsp(ctx);
23343 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23344 break;
23345 case OPC_DPSU_H_OBR:
23346 check_dsp(ctx);
23347 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23348 break;
23349 case OPC_MAQ_S_L_PWL:
23350 check_dsp(ctx);
23351 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23352 break;
23353 case OPC_MAQ_S_L_PWR:
23354 check_dsp(ctx);
23355 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23356 break;
23357 case OPC_MAQ_S_W_QHLL:
23358 check_dsp(ctx);
23359 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23360 break;
23361 case OPC_MAQ_SA_W_QHLL:
23362 check_dsp(ctx);
23363 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23364 break;
23365 case OPC_MAQ_S_W_QHLR:
23366 check_dsp(ctx);
23367 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23368 break;
23369 case OPC_MAQ_SA_W_QHLR:
23370 check_dsp(ctx);
23371 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23372 break;
23373 case OPC_MAQ_S_W_QHRL:
23374 check_dsp(ctx);
23375 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23376 break;
23377 case OPC_MAQ_SA_W_QHRL:
23378 check_dsp(ctx);
23379 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23380 break;
23381 case OPC_MAQ_S_W_QHRR:
23382 check_dsp(ctx);
23383 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23384 break;
23385 case OPC_MAQ_SA_W_QHRR:
23386 check_dsp(ctx);
23387 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23388 break;
23389 case OPC_MULSAQ_S_L_PW:
23390 check_dsp(ctx);
23391 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23392 break;
23393 case OPC_MULSAQ_S_W_QH:
23394 check_dsp(ctx);
23395 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23396 break;
23397 }
23398 }
23399 break;
23400#endif
23401 case OPC_ADDU_QB_DSP:
23402 switch (op2) {
23403 case OPC_MULEU_S_PH_QBL:
23404 check_dsp(ctx);
23405 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23406 break;
23407 case OPC_MULEU_S_PH_QBR:
23408 check_dsp(ctx);
23409 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23410 break;
23411 case OPC_MULQ_RS_PH:
23412 check_dsp(ctx);
23413 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23414 break;
23415 case OPC_MULEQ_S_W_PHL:
23416 check_dsp(ctx);
23417 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23418 break;
23419 case OPC_MULEQ_S_W_PHR:
23420 check_dsp(ctx);
23421 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23422 break;
23423 case OPC_MULQ_S_PH:
908f6be1 23424 check_dsp_r2(ctx);
a22260ae
JL
23425 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23426 break;
23427 }
23428 break;
23429#ifdef TARGET_MIPS64
23430 case OPC_ADDU_OB_DSP:
23431 switch (op2) {
23432 case OPC_MULEQ_S_PW_QHL:
23433 check_dsp(ctx);
23434 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23435 break;
23436 case OPC_MULEQ_S_PW_QHR:
23437 check_dsp(ctx);
23438 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_MULEU_S_QH_OBL:
23441 check_dsp(ctx);
23442 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_MULEU_S_QH_OBR:
23445 check_dsp(ctx);
23446 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_MULQ_RS_QH:
23449 check_dsp(ctx);
23450 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23451 break;
23452 }
23453 break;
23454#endif
23455 }
23456
23457 tcg_temp_free_i32(t0);
23458 tcg_temp_free(v1_t);
23459 tcg_temp_free(v2_t);
a22260ae
JL
23460}
23461
d75c135e 23462static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
23463 int ret, int val)
23464{
1cb6686c
JL
23465 int16_t imm;
23466 TCGv t0;
23467 TCGv val_t;
23468
23469 if (ret == 0) {
23470 /* Treat as NOP. */
1cb6686c
JL
23471 return;
23472 }
23473
23474 t0 = tcg_temp_new();
23475 val_t = tcg_temp_new();
23476 gen_load_gpr(val_t, val);
23477
23478 switch (op1) {
23479 case OPC_ABSQ_S_PH_DSP:
23480 switch (op2) {
23481 case OPC_BITREV:
23482 check_dsp(ctx);
23483 gen_helper_bitrev(cpu_gpr[ret], val_t);
23484 break;
23485 case OPC_REPL_QB:
23486 check_dsp(ctx);
23487 {
23488 target_long result;
23489 imm = (ctx->opcode >> 16) & 0xFF;
23490 result = (uint32_t)imm << 24 |
23491 (uint32_t)imm << 16 |
23492 (uint32_t)imm << 8 |
23493 (uint32_t)imm;
23494 result = (int32_t)result;
23495 tcg_gen_movi_tl(cpu_gpr[ret], result);
23496 }
23497 break;
23498 case OPC_REPLV_QB:
23499 check_dsp(ctx);
23500 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23501 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23502 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23503 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23504 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23505 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23506 break;
23507 case OPC_REPL_PH:
23508 check_dsp(ctx);
23509 {
23510 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23511 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23512 tcg_gen_movi_tl(cpu_gpr[ret], \
23513 (target_long)((int32_t)imm << 16 | \
c4aaba92 23514 (uint16_t)imm));
1cb6686c
JL
23515 }
23516 break;
23517 case OPC_REPLV_PH:
23518 check_dsp(ctx);
23519 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23520 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23521 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23522 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23523 break;
23524 }
23525 break;
23526#ifdef TARGET_MIPS64
23527 case OPC_ABSQ_S_QH_DSP:
23528 switch (op2) {
23529 case OPC_REPL_OB:
23530 check_dsp(ctx);
23531 {
23532 target_long temp;
23533
23534 imm = (ctx->opcode >> 16) & 0xFF;
23535 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23536 temp = (temp << 16) | temp;
23537 temp = (temp << 32) | temp;
23538 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23539 break;
23540 }
23541 case OPC_REPL_PW:
23542 check_dsp(ctx);
23543 {
23544 target_long temp;
23545
23546 imm = (ctx->opcode >> 16) & 0x03FF;
23547 imm = (int16_t)(imm << 6) >> 6;
23548 temp = ((target_long)imm << 32) \
23549 | ((target_long)imm & 0xFFFFFFFF);
23550 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23551 break;
23552 }
23553 case OPC_REPL_QH:
23554 check_dsp(ctx);
23555 {
23556 target_long temp;
23557
23558 imm = (ctx->opcode >> 16) & 0x03FF;
23559 imm = (int16_t)(imm << 6) >> 6;
23560
23561 temp = ((uint64_t)(uint16_t)imm << 48) |
23562 ((uint64_t)(uint16_t)imm << 32) |
23563 ((uint64_t)(uint16_t)imm << 16) |
23564 (uint64_t)(uint16_t)imm;
23565 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23566 break;
23567 }
23568 case OPC_REPLV_OB:
23569 check_dsp(ctx);
23570 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23571 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23572 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23573 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23574 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23575 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23576 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23577 break;
23578 case OPC_REPLV_PW:
23579 check_dsp(ctx);
23580 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23581 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23582 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23583 break;
23584 case OPC_REPLV_QH:
23585 check_dsp(ctx);
23586 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23587 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23588 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23589 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23590 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23591 break;
23592 }
23593 break;
23594#endif
23595 }
23596 tcg_temp_free(t0);
23597 tcg_temp_free(val_t);
1cb6686c
JL
23598}
23599
26690560
JL
23600static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23601 uint32_t op1, uint32_t op2,
23602 int ret, int v1, int v2, int check_ret)
23603{
26690560
JL
23604 TCGv t1;
23605 TCGv v1_t;
23606 TCGv v2_t;
23607
23608 if ((ret == 0) && (check_ret == 1)) {
23609 /* Treat as NOP. */
26690560
JL
23610 return;
23611 }
23612
26690560
JL
23613 t1 = tcg_temp_new();
23614 v1_t = tcg_temp_new();
23615 v2_t = tcg_temp_new();
23616
23617 gen_load_gpr(v1_t, v1);
23618 gen_load_gpr(v2_t, v2);
23619
23620 switch (op1) {
26690560
JL
23621 case OPC_CMPU_EQ_QB_DSP:
23622 switch (op2) {
23623 case OPC_CMPU_EQ_QB:
23624 check_dsp(ctx);
23625 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23626 break;
23627 case OPC_CMPU_LT_QB:
23628 check_dsp(ctx);
23629 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23630 break;
23631 case OPC_CMPU_LE_QB:
23632 check_dsp(ctx);
23633 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23634 break;
23635 case OPC_CMPGU_EQ_QB:
23636 check_dsp(ctx);
23637 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23638 break;
23639 case OPC_CMPGU_LT_QB:
23640 check_dsp(ctx);
23641 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23642 break;
23643 case OPC_CMPGU_LE_QB:
23644 check_dsp(ctx);
23645 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23646 break;
23647 case OPC_CMPGDU_EQ_QB:
908f6be1 23648 check_dsp_r2(ctx);
26690560
JL
23649 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23650 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23651 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23652 tcg_gen_shli_tl(t1, t1, 24);
23653 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23654 break;
23655 case OPC_CMPGDU_LT_QB:
908f6be1 23656 check_dsp_r2(ctx);
26690560
JL
23657 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23658 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23659 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23660 tcg_gen_shli_tl(t1, t1, 24);
23661 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23662 break;
23663 case OPC_CMPGDU_LE_QB:
908f6be1 23664 check_dsp_r2(ctx);
26690560
JL
23665 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23666 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23667 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23668 tcg_gen_shli_tl(t1, t1, 24);
23669 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23670 break;
23671 case OPC_CMP_EQ_PH:
23672 check_dsp(ctx);
23673 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23674 break;
23675 case OPC_CMP_LT_PH:
23676 check_dsp(ctx);
23677 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23678 break;
23679 case OPC_CMP_LE_PH:
23680 check_dsp(ctx);
23681 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23682 break;
23683 case OPC_PICK_QB:
23684 check_dsp(ctx);
23685 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23686 break;
23687 case OPC_PICK_PH:
23688 check_dsp(ctx);
23689 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23690 break;
23691 case OPC_PACKRL_PH:
23692 check_dsp(ctx);
23693 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23694 break;
23695 }
23696 break;
23697#ifdef TARGET_MIPS64
23698 case OPC_CMPU_EQ_OB_DSP:
23699 switch (op2) {
23700 case OPC_CMP_EQ_PW:
23701 check_dsp(ctx);
23702 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23703 break;
23704 case OPC_CMP_LT_PW:
23705 check_dsp(ctx);
23706 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23707 break;
23708 case OPC_CMP_LE_PW:
23709 check_dsp(ctx);
23710 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23711 break;
23712 case OPC_CMP_EQ_QH:
23713 check_dsp(ctx);
23714 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23715 break;
23716 case OPC_CMP_LT_QH:
23717 check_dsp(ctx);
23718 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23719 break;
23720 case OPC_CMP_LE_QH:
23721 check_dsp(ctx);
23722 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23723 break;
23724 case OPC_CMPGDU_EQ_OB:
908f6be1 23725 check_dsp_r2(ctx);
26690560
JL
23726 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23727 break;
23728 case OPC_CMPGDU_LT_OB:
908f6be1 23729 check_dsp_r2(ctx);
26690560
JL
23730 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23731 break;
23732 case OPC_CMPGDU_LE_OB:
908f6be1 23733 check_dsp_r2(ctx);
26690560
JL
23734 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23735 break;
23736 case OPC_CMPGU_EQ_OB:
23737 check_dsp(ctx);
23738 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23739 break;
23740 case OPC_CMPGU_LT_OB:
23741 check_dsp(ctx);
23742 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23743 break;
23744 case OPC_CMPGU_LE_OB:
23745 check_dsp(ctx);
23746 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23747 break;
23748 case OPC_CMPU_EQ_OB:
23749 check_dsp(ctx);
23750 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23751 break;
23752 case OPC_CMPU_LT_OB:
23753 check_dsp(ctx);
23754 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23755 break;
23756 case OPC_CMPU_LE_OB:
23757 check_dsp(ctx);
23758 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23759 break;
23760 case OPC_PACKRL_PW:
23761 check_dsp(ctx);
23762 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23763 break;
23764 case OPC_PICK_OB:
23765 check_dsp(ctx);
23766 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23767 break;
23768 case OPC_PICK_PW:
23769 check_dsp(ctx);
23770 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23771 break;
23772 case OPC_PICK_QH:
23773 check_dsp(ctx);
23774 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23775 break;
23776 }
23777 break;
df6126a7
AJ
23778#endif
23779 }
23780
23781 tcg_temp_free(t1);
23782 tcg_temp_free(v1_t);
23783 tcg_temp_free(v2_t);
df6126a7
AJ
23784}
23785
23786static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23787 uint32_t op1, int rt, int rs, int sa)
23788{
df6126a7
AJ
23789 TCGv t0;
23790
908f6be1 23791 check_dsp_r2(ctx);
df6126a7
AJ
23792
23793 if (rt == 0) {
23794 /* Treat as NOP. */
df6126a7
AJ
23795 return;
23796 }
23797
23798 t0 = tcg_temp_new();
23799 gen_load_gpr(t0, rs);
23800
23801 switch (op1) {
23802 case OPC_APPEND_DSP:
23803 switch (MASK_APPEND(ctx->opcode)) {
23804 case OPC_APPEND:
23805 if (sa != 0) {
23806 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23807 }
23808 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23809 break;
23810 case OPC_PREPEND:
23811 if (sa != 0) {
23812 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23813 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23814 tcg_gen_shli_tl(t0, t0, 32 - sa);
23815 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23816 }
23817 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23818 break;
23819 case OPC_BALIGN:
23820 sa &= 3;
23821 if (sa != 0 && sa != 2) {
23822 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23823 tcg_gen_ext32u_tl(t0, t0);
23824 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23825 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23826 }
23827 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23828 break;
23829 default: /* Invalid */
23830 MIPS_INVAL("MASK APPEND");
9c708c7f 23831 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
23832 break;
23833 }
23834 break;
23835#ifdef TARGET_MIPS64
26690560 23836 case OPC_DAPPEND_DSP:
df6126a7 23837 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23838 case OPC_DAPPEND:
df6126a7
AJ
23839 if (sa != 0) {
23840 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23841 }
26690560
JL
23842 break;
23843 case OPC_PREPENDD:
df6126a7
AJ
23844 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23845 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23846 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23847 break;
23848 case OPC_PREPENDW:
df6126a7
AJ
23849 if (sa != 0) {
23850 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23851 tcg_gen_shli_tl(t0, t0, 64 - sa);
23852 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23853 }
26690560
JL
23854 break;
23855 case OPC_DBALIGN:
df6126a7
AJ
23856 sa &= 7;
23857 if (sa != 0 && sa != 2 && sa != 4) {
23858 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23859 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23860 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23861 }
26690560
JL
23862 break;
23863 default: /* Invalid */
23864 MIPS_INVAL("MASK DAPPEND");
9c708c7f 23865 generate_exception_end(ctx, EXCP_RI);
26690560
JL
23866 break;
23867 }
23868 break;
23869#endif
23870 }
df6126a7 23871 tcg_temp_free(t0);
26690560
JL
23872}
23873
b53371ed
JL
23874static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23875 int ret, int v1, int v2, int check_ret)
23876
23877{
b53371ed
JL
23878 TCGv t0;
23879 TCGv t1;
23880 TCGv v1_t;
23881 TCGv v2_t;
23882 int16_t imm;
23883
23884 if ((ret == 0) && (check_ret == 1)) {
23885 /* Treat as NOP. */
b53371ed
JL
23886 return;
23887 }
23888
23889 t0 = tcg_temp_new();
23890 t1 = tcg_temp_new();
23891 v1_t = tcg_temp_new();
23892 v2_t = tcg_temp_new();
23893
23894 gen_load_gpr(v1_t, v1);
23895 gen_load_gpr(v2_t, v2);
23896
23897 switch (op1) {
23898 case OPC_EXTR_W_DSP:
23899 check_dsp(ctx);
23900 switch (op2) {
23901 case OPC_EXTR_W:
23902 tcg_gen_movi_tl(t0, v2);
23903 tcg_gen_movi_tl(t1, v1);
23904 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23905 break;
23906 case OPC_EXTR_R_W:
23907 tcg_gen_movi_tl(t0, v2);
23908 tcg_gen_movi_tl(t1, v1);
23909 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23910 break;
23911 case OPC_EXTR_RS_W:
23912 tcg_gen_movi_tl(t0, v2);
23913 tcg_gen_movi_tl(t1, v1);
23914 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23915 break;
23916 case OPC_EXTR_S_H:
23917 tcg_gen_movi_tl(t0, v2);
23918 tcg_gen_movi_tl(t1, v1);
23919 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23920 break;
23921 case OPC_EXTRV_S_H:
23922 tcg_gen_movi_tl(t0, v2);
23923 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23924 break;
23925 case OPC_EXTRV_W:
23926 tcg_gen_movi_tl(t0, v2);
23927 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23928 break;
23929 case OPC_EXTRV_R_W:
23930 tcg_gen_movi_tl(t0, v2);
23931 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23932 break;
23933 case OPC_EXTRV_RS_W:
23934 tcg_gen_movi_tl(t0, v2);
23935 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23936 break;
23937 case OPC_EXTP:
23938 tcg_gen_movi_tl(t0, v2);
23939 tcg_gen_movi_tl(t1, v1);
23940 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23941 break;
23942 case OPC_EXTPV:
23943 tcg_gen_movi_tl(t0, v2);
23944 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23945 break;
23946 case OPC_EXTPDP:
23947 tcg_gen_movi_tl(t0, v2);
23948 tcg_gen_movi_tl(t1, v1);
23949 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23950 break;
23951 case OPC_EXTPDPV:
23952 tcg_gen_movi_tl(t0, v2);
23953 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23954 break;
23955 case OPC_SHILO:
23956 imm = (ctx->opcode >> 20) & 0x3F;
23957 tcg_gen_movi_tl(t0, ret);
23958 tcg_gen_movi_tl(t1, imm);
23959 gen_helper_shilo(t0, t1, cpu_env);
23960 break;
23961 case OPC_SHILOV:
23962 tcg_gen_movi_tl(t0, ret);
23963 gen_helper_shilo(t0, v1_t, cpu_env);
23964 break;
23965 case OPC_MTHLIP:
23966 tcg_gen_movi_tl(t0, ret);
23967 gen_helper_mthlip(t0, v1_t, cpu_env);
23968 break;
23969 case OPC_WRDSP:
23970 imm = (ctx->opcode >> 11) & 0x3FF;
23971 tcg_gen_movi_tl(t0, imm);
23972 gen_helper_wrdsp(v1_t, t0, cpu_env);
23973 break;
23974 case OPC_RDDSP:
23975 imm = (ctx->opcode >> 16) & 0x03FF;
23976 tcg_gen_movi_tl(t0, imm);
23977 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23978 break;
23979 }
23980 break;
23981#ifdef TARGET_MIPS64
23982 case OPC_DEXTR_W_DSP:
23983 check_dsp(ctx);
23984 switch (op2) {
23985 case OPC_DMTHLIP:
23986 tcg_gen_movi_tl(t0, ret);
23987 gen_helper_dmthlip(v1_t, t0, cpu_env);
23988 break;
23989 case OPC_DSHILO:
23990 {
23991 int shift = (ctx->opcode >> 19) & 0x7F;
23992 int ac = (ctx->opcode >> 11) & 0x03;
23993 tcg_gen_movi_tl(t0, shift);
23994 tcg_gen_movi_tl(t1, ac);
23995 gen_helper_dshilo(t0, t1, cpu_env);
23996 break;
23997 }
23998 case OPC_DSHILOV:
23999 {
24000 int ac = (ctx->opcode >> 11) & 0x03;
24001 tcg_gen_movi_tl(t0, ac);
24002 gen_helper_dshilo(v1_t, t0, cpu_env);
24003 break;
24004 }
24005 case OPC_DEXTP:
24006 tcg_gen_movi_tl(t0, v2);
24007 tcg_gen_movi_tl(t1, v1);
24008
24009 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24010 break;
24011 case OPC_DEXTPV:
24012 tcg_gen_movi_tl(t0, v2);
24013 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24014 break;
24015 case OPC_DEXTPDP:
24016 tcg_gen_movi_tl(t0, v2);
24017 tcg_gen_movi_tl(t1, v1);
24018 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24019 break;
24020 case OPC_DEXTPDPV:
24021 tcg_gen_movi_tl(t0, v2);
24022 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24023 break;
24024 case OPC_DEXTR_L:
24025 tcg_gen_movi_tl(t0, v2);
24026 tcg_gen_movi_tl(t1, v1);
24027 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24028 break;
24029 case OPC_DEXTR_R_L:
24030 tcg_gen_movi_tl(t0, v2);
24031 tcg_gen_movi_tl(t1, v1);
24032 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24033 break;
24034 case OPC_DEXTR_RS_L:
24035 tcg_gen_movi_tl(t0, v2);
24036 tcg_gen_movi_tl(t1, v1);
24037 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24038 break;
24039 case OPC_DEXTR_W:
24040 tcg_gen_movi_tl(t0, v2);
24041 tcg_gen_movi_tl(t1, v1);
24042 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24043 break;
24044 case OPC_DEXTR_R_W:
24045 tcg_gen_movi_tl(t0, v2);
24046 tcg_gen_movi_tl(t1, v1);
24047 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24048 break;
24049 case OPC_DEXTR_RS_W:
24050 tcg_gen_movi_tl(t0, v2);
24051 tcg_gen_movi_tl(t1, v1);
24052 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24053 break;
24054 case OPC_DEXTR_S_H:
24055 tcg_gen_movi_tl(t0, v2);
24056 tcg_gen_movi_tl(t1, v1);
24057 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24058 break;
24059 case OPC_DEXTRV_S_H:
24060 tcg_gen_movi_tl(t0, v2);
24061 tcg_gen_movi_tl(t1, v1);
24062 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24063 break;
24064 case OPC_DEXTRV_L:
24065 tcg_gen_movi_tl(t0, v2);
24066 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24067 break;
24068 case OPC_DEXTRV_R_L:
24069 tcg_gen_movi_tl(t0, v2);
24070 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24071 break;
24072 case OPC_DEXTRV_RS_L:
24073 tcg_gen_movi_tl(t0, v2);
24074 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24075 break;
24076 case OPC_DEXTRV_W:
24077 tcg_gen_movi_tl(t0, v2);
24078 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24079 break;
24080 case OPC_DEXTRV_R_W:
24081 tcg_gen_movi_tl(t0, v2);
24082 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24083 break;
24084 case OPC_DEXTRV_RS_W:
24085 tcg_gen_movi_tl(t0, v2);
24086 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24087 break;
24088 }
24089 break;
24090#endif
24091 }
24092
24093 tcg_temp_free(t0);
24094 tcg_temp_free(t1);
24095 tcg_temp_free(v1_t);
24096 tcg_temp_free(v2_t);
b53371ed
JL
24097}
24098
9b1a1d68
JL
24099/* End MIPSDSP functions. */
24100
10dc65db
LA
24101static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24102{
4267d3e6 24103 int rs, rt, rd, sa;
b42ee5e1 24104 uint32_t op1, op2;
10dc65db
LA
24105
24106 rs = (ctx->opcode >> 21) & 0x1f;
24107 rt = (ctx->opcode >> 16) & 0x1f;
24108 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 24109 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24110
24111 op1 = MASK_SPECIAL(ctx->opcode);
24112 switch (op1) {
d4ea6acd 24113 case OPC_LSA:
1f1b4c00 24114 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24115 break;
c2e19f3c
AM
24116 case OPC_MULT:
24117 case OPC_MULTU:
24118 case OPC_DIV:
24119 case OPC_DIVU:
b42ee5e1
LA
24120 op2 = MASK_R6_MULDIV(ctx->opcode);
24121 switch (op2) {
24122 case R6_OPC_MUL:
24123 case R6_OPC_MUH:
24124 case R6_OPC_MULU:
24125 case R6_OPC_MUHU:
24126 case R6_OPC_DIV:
24127 case R6_OPC_MOD:
24128 case R6_OPC_DIVU:
24129 case R6_OPC_MODU:
24130 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24131 break;
24132 default:
24133 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24134 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24135 break;
24136 }
24137 break;
10dc65db
LA
24138 case OPC_SELEQZ:
24139 case OPC_SELNEZ:
24140 gen_cond_move(ctx, op1, rd, rs, rt);
24141 break;
4267d3e6
LA
24142 case R6_OPC_CLO:
24143 case R6_OPC_CLZ:
24144 if (rt == 0 && sa == 1) {
7480515f
AM
24145 /*
24146 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24147 * We need additionally to check other fields.
24148 */
4267d3e6
LA
24149 gen_cl(ctx, op1, rd, rs);
24150 } else {
9c708c7f 24151 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24152 }
24153 break;
24154 case R6_OPC_SDBBP:
3b3c1694
LA
24155 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24156 gen_helper_do_semihosting(cpu_env);
faf1f68b 24157 } else {
3b3c1694 24158 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 24159 generate_exception_end(ctx, EXCP_RI);
3b3c1694 24160 } else {
9c708c7f 24161 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24162 }
faf1f68b 24163 }
4267d3e6 24164 break;
b42ee5e1 24165#if defined(TARGET_MIPS64)
d4ea6acd
LA
24166 case OPC_DLSA:
24167 check_mips_64(ctx);
1f1b4c00 24168 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24169 break;
4267d3e6
LA
24170 case R6_OPC_DCLO:
24171 case R6_OPC_DCLZ:
24172 if (rt == 0 && sa == 1) {
7480515f
AM
24173 /*
24174 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24175 * We need additionally to check other fields.
24176 */
4267d3e6
LA
24177 check_mips_64(ctx);
24178 gen_cl(ctx, op1, rd, rs);
24179 } else {
9c708c7f 24180 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24181 }
24182 break;
c2e19f3c
AM
24183 case OPC_DMULT:
24184 case OPC_DMULTU:
24185 case OPC_DDIV:
24186 case OPC_DDIVU:
24187
b42ee5e1
LA
24188 op2 = MASK_R6_MULDIV(ctx->opcode);
24189 switch (op2) {
24190 case R6_OPC_DMUL:
24191 case R6_OPC_DMUH:
24192 case R6_OPC_DMULU:
24193 case R6_OPC_DMUHU:
24194 case R6_OPC_DDIV:
24195 case R6_OPC_DMOD:
24196 case R6_OPC_DDIVU:
24197 case R6_OPC_DMODU:
24198 check_mips_64(ctx);
24199 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24200 break;
24201 default:
24202 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24203 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24204 break;
24205 }
24206 break;
24207#endif
10dc65db
LA
24208 default: /* Invalid */
24209 MIPS_INVAL("special_r6");
9c708c7f 24210 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24211 break;
24212 }
24213}
24214
9dc324ce
FN
24215static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24216{
24217 int rs = extract32(ctx->opcode, 21, 5);
24218 int rt = extract32(ctx->opcode, 16, 5);
24219 int rd = extract32(ctx->opcode, 11, 5);
24220 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24221
24222 switch (op1) {
24223 case OPC_MOVN: /* Conditional move */
24224 case OPC_MOVZ:
24225 gen_cond_move(ctx, op1, rd, rs, rt);
24226 break;
24227 case OPC_MFHI: /* Move from HI/LO */
24228 case OPC_MFLO:
24229 gen_HILO(ctx, op1, 0, rd);
24230 break;
24231 case OPC_MTHI:
24232 case OPC_MTLO: /* Move to HI/LO */
24233 gen_HILO(ctx, op1, 0, rs);
24234 break;
24235 case OPC_MULT:
24236 case OPC_MULTU:
24237 gen_mul_txx9(ctx, op1, rd, rs, rt);
24238 break;
24239 case OPC_DIV:
24240 case OPC_DIVU:
24241 gen_muldiv(ctx, op1, 0, rs, rt);
24242 break;
24243#if defined(TARGET_MIPS64)
24244 case OPC_DMULT:
24245 case OPC_DMULTU:
24246 case OPC_DDIV:
24247 case OPC_DDIVU:
24248 check_insn_opc_user_only(ctx, INSN_R5900);
24249 gen_muldiv(ctx, op1, 0, rs, rt);
24250 break;
24251#endif
24252 case OPC_JR:
24253 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24254 break;
24255 default: /* Invalid */
24256 MIPS_INVAL("special_tx79");
24257 generate_exception_end(ctx, EXCP_RI);
24258 break;
24259 }
24260}
24261
10dc65db
LA
24262static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24263{
b42ee5e1 24264 int rs, rt, rd, sa;
10dc65db
LA
24265 uint32_t op1;
24266
24267 rs = (ctx->opcode >> 21) & 0x1f;
24268 rt = (ctx->opcode >> 16) & 0x1f;
24269 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24270 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24271
24272 op1 = MASK_SPECIAL(ctx->opcode);
24273 switch (op1) {
24274 case OPC_MOVN: /* Conditional move */
24275 case OPC_MOVZ:
24276 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
9dc324ce 24277 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24278 gen_cond_move(ctx, op1, rd, rs, rt);
24279 break;
24280 case OPC_MFHI: /* Move from HI/LO */
24281 case OPC_MFLO:
24282 gen_HILO(ctx, op1, rs & 3, rd);
24283 break;
24284 case OPC_MTHI:
24285 case OPC_MTLO: /* Move to HI/LO */
24286 gen_HILO(ctx, op1, rd & 3, rs);
24287 break;
24288 case OPC_MOVCI:
24289 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24290 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24291 check_cp1_enabled(ctx);
24292 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24293 (ctx->opcode >> 16) & 1);
24294 } else {
24295 generate_exception_err(ctx, EXCP_CpU, 1);
24296 }
24297 break;
b42ee5e1
LA
24298 case OPC_MULT:
24299 case OPC_MULTU:
24300 if (sa) {
24301 check_insn(ctx, INSN_VR54XX);
24302 op1 = MASK_MUL_VR54XX(ctx->opcode);
24303 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24304 } else {
24305 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24306 }
24307 break;
24308 case OPC_DIV:
24309 case OPC_DIVU:
24310 gen_muldiv(ctx, op1, 0, rs, rt);
24311 break;
24312#if defined(TARGET_MIPS64)
c2e19f3c
AM
24313 case OPC_DMULT:
24314 case OPC_DMULTU:
24315 case OPC_DDIV:
24316 case OPC_DDIVU:
b42ee5e1
LA
24317 check_insn(ctx, ISA_MIPS3);
24318 check_mips_64(ctx);
24319 gen_muldiv(ctx, op1, 0, rs, rt);
24320 break;
24321#endif
0aefa333 24322 case OPC_JR:
b231c103 24323 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24324 break;
4267d3e6
LA
24325 case OPC_SPIM:
24326#ifdef MIPS_STRICT_STANDARD
24327 MIPS_INVAL("SPIM");
9c708c7f 24328 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24329#else
24330 /* Implemented as RI exception for now. */
24331 MIPS_INVAL("spim (unofficial)");
9c708c7f 24332 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24333#endif
24334 break;
10dc65db
LA
24335 default: /* Invalid */
24336 MIPS_INVAL("special_legacy");
9c708c7f 24337 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24338 break;
24339 }
24340}
24341
099e5b4d 24342static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24343{
3c824109 24344 int rs, rt, rd, sa;
099e5b4d 24345 uint32_t op1;
3c824109 24346
3c824109
NF
24347 rs = (ctx->opcode >> 21) & 0x1f;
24348 rt = (ctx->opcode >> 16) & 0x1f;
24349 rd = (ctx->opcode >> 11) & 0x1f;
24350 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24351
24352 op1 = MASK_SPECIAL(ctx->opcode);
24353 switch (op1) {
24354 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24355 if (sa == 5 && rd == 0 &&
24356 rs == 0 && rt == 0) { /* PAUSE */
24357 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24358 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24359 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24360 break;
24361 }
24362 }
24363 /* Fallthrough */
099e5b4d
LA
24364 case OPC_SRA:
24365 gen_shift_imm(ctx, op1, rd, rt, sa);
24366 break;
24367 case OPC_SRL:
24368 switch ((ctx->opcode >> 21) & 0x1f) {
24369 case 1:
24370 /* rotr is decoded as srl on non-R2 CPUs */
24371 if (ctx->insn_flags & ISA_MIPS32R2) {
24372 op1 = OPC_ROTR;
ea63e2c3 24373 }
099e5b4d
LA
24374 /* Fallthrough */
24375 case 0:
24376 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24377 break;
099e5b4d 24378 default:
9c708c7f 24379 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24380 break;
099e5b4d
LA
24381 }
24382 break;
c2e19f3c
AM
24383 case OPC_ADD:
24384 case OPC_ADDU:
24385 case OPC_SUB:
24386 case OPC_SUBU:
099e5b4d
LA
24387 gen_arith(ctx, op1, rd, rs, rt);
24388 break;
24389 case OPC_SLLV: /* Shifts */
24390 case OPC_SRAV:
24391 gen_shift(ctx, op1, rd, rs, rt);
24392 break;
24393 case OPC_SRLV:
24394 switch ((ctx->opcode >> 6) & 0x1f) {
24395 case 1:
24396 /* rotrv is decoded as srlv on non-R2 CPUs */
24397 if (ctx->insn_flags & ISA_MIPS32R2) {
24398 op1 = OPC_ROTRV;
26135ead 24399 }
099e5b4d
LA
24400 /* Fallthrough */
24401 case 0:
24402 gen_shift(ctx, op1, rd, rs, rt);
26135ead 24403 break;
099e5b4d 24404 default:
9c708c7f 24405 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 24406 break;
099e5b4d
LA
24407 }
24408 break;
24409 case OPC_SLT: /* Set on less than */
24410 case OPC_SLTU:
24411 gen_slt(ctx, op1, rd, rs, rt);
24412 break;
24413 case OPC_AND: /* Logic*/
24414 case OPC_OR:
24415 case OPC_NOR:
24416 case OPC_XOR:
24417 gen_logic(ctx, op1, rd, rs, rt);
24418 break;
0aefa333 24419 case OPC_JALR:
b231c103 24420 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 24421 break;
c2e19f3c
AM
24422 case OPC_TGE: /* Traps */
24423 case OPC_TGEU:
24424 case OPC_TLT:
24425 case OPC_TLTU:
24426 case OPC_TEQ:
099e5b4d 24427 case OPC_TNE:
d9224450 24428 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
24429 gen_trap(ctx, op1, rs, rt, -1);
24430 break;
d4ea6acd 24431 case OPC_LSA: /* OPC_PMON */
f7685877
YK
24432 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24433 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
24434 decode_opc_special_r6(env, ctx);
24435 } else {
24436 /* Pmon entry point, also R4010 selsl */
b48cfdff 24437#ifdef MIPS_STRICT_STANDARD
d4ea6acd 24438 MIPS_INVAL("PMON / selsl");
9c708c7f 24439 generate_exception_end(ctx, EXCP_RI);
b48cfdff 24440#else
d4ea6acd 24441 gen_helper_0e0i(pmon, sa);
b48cfdff 24442#endif
d4ea6acd 24443 }
099e5b4d
LA
24444 break;
24445 case OPC_SYSCALL:
9c708c7f 24446 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
24447 break;
24448 case OPC_BREAK:
9c708c7f 24449 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 24450 break;
099e5b4d 24451 case OPC_SYNC:
d9224450 24452 check_insn(ctx, ISA_MIPS2);
d208ac0c 24453 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 24454 break;
4ad40f36 24455
d26bc211 24456#if defined(TARGET_MIPS64)
099e5b4d
LA
24457 /* MIPS64 specific opcodes */
24458 case OPC_DSLL:
24459 case OPC_DSRA:
24460 case OPC_DSLL32:
24461 case OPC_DSRA32:
24462 check_insn(ctx, ISA_MIPS3);
24463 check_mips_64(ctx);
24464 gen_shift_imm(ctx, op1, rd, rt, sa);
24465 break;
24466 case OPC_DSRL:
24467 switch ((ctx->opcode >> 21) & 0x1f) {
24468 case 1:
24469 /* drotr is decoded as dsrl on non-R2 CPUs */
24470 if (ctx->insn_flags & ISA_MIPS32R2) {
24471 op1 = OPC_DROTR;
ea63e2c3 24472 }
099e5b4d
LA
24473 /* Fallthrough */
24474 case 0:
d75c135e 24475 check_insn(ctx, ISA_MIPS3);
e189e748 24476 check_mips_64(ctx);
099e5b4d 24477 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24478 break;
099e5b4d 24479 default:
9c708c7f 24480 generate_exception_end(ctx, EXCP_RI);
460f00c4 24481 break;
099e5b4d
LA
24482 }
24483 break;
24484 case OPC_DSRL32:
24485 switch ((ctx->opcode >> 21) & 0x1f) {
24486 case 1:
24487 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24488 if (ctx->insn_flags & ISA_MIPS32R2) {
24489 op1 = OPC_DROTR32;
ea63e2c3 24490 }
099e5b4d
LA
24491 /* Fallthrough */
24492 case 0:
d75c135e 24493 check_insn(ctx, ISA_MIPS3);
e189e748 24494 check_mips_64(ctx);
099e5b4d 24495 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24496 break;
099e5b4d 24497 default:
9c708c7f 24498 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24499 break;
24500 }
24501 break;
c2e19f3c
AM
24502 case OPC_DADD:
24503 case OPC_DADDU:
24504 case OPC_DSUB:
24505 case OPC_DSUBU:
099e5b4d
LA
24506 check_insn(ctx, ISA_MIPS3);
24507 check_mips_64(ctx);
24508 gen_arith(ctx, op1, rd, rs, rt);
24509 break;
24510 case OPC_DSLLV:
24511 case OPC_DSRAV:
24512 check_insn(ctx, ISA_MIPS3);
24513 check_mips_64(ctx);
24514 gen_shift(ctx, op1, rd, rs, rt);
24515 break;
24516 case OPC_DSRLV:
24517 switch ((ctx->opcode >> 6) & 0x1f) {
24518 case 1:
24519 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24520 if (ctx->insn_flags & ISA_MIPS32R2) {
24521 op1 = OPC_DROTRV;
6af0bf9c 24522 }
099e5b4d
LA
24523 /* Fallthrough */
24524 case 0:
24525 check_insn(ctx, ISA_MIPS3);
e189e748 24526 check_mips_64(ctx);
099e5b4d 24527 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 24528 break;
099e5b4d 24529 default:
9c708c7f 24530 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24531 break;
24532 }
24533 break;
f7685877
YK
24534 case OPC_DLSA:
24535 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24536 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24537 decode_opc_special_r6(env, ctx);
24538 }
24539 break;
099e5b4d 24540#endif
10dc65db
LA
24541 default:
24542 if (ctx->insn_flags & ISA_MIPS32R6) {
24543 decode_opc_special_r6(env, ctx);
9dc324ce
FN
24544 } else if (ctx->insn_flags & INSN_R5900) {
24545 decode_opc_special_tx79(env, ctx);
10dc65db
LA
24546 } else {
24547 decode_opc_special_legacy(env, ctx);
24548 }
24549 }
24550}
24551
d67da337 24552
37b9aae2
MM
24553#if defined(TARGET_MIPS64)
24554
24555/*
24556 *
24557 * MMI (MultiMedia Interface) ASE instructions
24558 * ===========================================
24559 */
24560
24561/*
24562 * MMI instructions category: data communication
24563 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24564 *
24565 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24566 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24567 * PCPYUD PEXEH PEXTLW PPACW
24568 * PEXEW PEXTUB
24569 * PEXTUH
24570 * PEXTUW
24571 */
24572
d3434d9f
MM
24573/*
24574 * PCPYH rd, rt
24575 *
24576 * Parallel Copy Halfword
24577 *
24578 * 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
24579 * +-----------+---------+---------+---------+---------+-----------+
24580 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24581 * +-----------+---------+---------+---------+---------+-----------+
24582 */
24583static void gen_mmi_pcpyh(DisasContext *ctx)
24584{
24585 uint32_t pd, rt, rd;
24586 uint32_t opcode;
24587
24588 opcode = ctx->opcode;
24589
24590 pd = extract32(opcode, 21, 5);
24591 rt = extract32(opcode, 16, 5);
24592 rd = extract32(opcode, 11, 5);
24593
24594 if (unlikely(pd != 0)) {
24595 generate_exception_end(ctx, EXCP_RI);
24596 } else if (rd == 0) {
24597 /* nop */
24598 } else if (rt == 0) {
24599 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24600 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24601 } else {
24602 TCGv_i64 t0 = tcg_temp_new();
24603 TCGv_i64 t1 = tcg_temp_new();
24604 uint64_t mask = (1ULL << 16) - 1;
24605
24606 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24607 tcg_gen_movi_i64(t1, 0);
24608 tcg_gen_or_i64(t1, t0, t1);
24609 tcg_gen_shli_i64(t0, t0, 16);
24610 tcg_gen_or_i64(t1, t0, t1);
24611 tcg_gen_shli_i64(t0, t0, 16);
24612 tcg_gen_or_i64(t1, t0, t1);
24613 tcg_gen_shli_i64(t0, t0, 16);
24614 tcg_gen_or_i64(t1, t0, t1);
24615
24616 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24617
24618 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24619 tcg_gen_movi_i64(t1, 0);
24620 tcg_gen_or_i64(t1, t0, t1);
24621 tcg_gen_shli_i64(t0, t0, 16);
24622 tcg_gen_or_i64(t1, t0, t1);
24623 tcg_gen_shli_i64(t0, t0, 16);
24624 tcg_gen_or_i64(t1, t0, t1);
24625 tcg_gen_shli_i64(t0, t0, 16);
24626 tcg_gen_or_i64(t1, t0, t1);
24627
24628 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24629
24630 tcg_temp_free(t0);
24631 tcg_temp_free(t1);
24632 }
24633}
24634
b87eef31
MM
24635/*
24636 * PCPYLD rd, rs, rt
24637 *
24638 * Parallel Copy Lower Doubleword
24639 *
24640 * 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
24641 * +-----------+---------+---------+---------+---------+-----------+
24642 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24643 * +-----------+---------+---------+---------+---------+-----------+
24644 */
24645static void gen_mmi_pcpyld(DisasContext *ctx)
24646{
24647 uint32_t rs, rt, rd;
24648 uint32_t opcode;
24649
24650 opcode = ctx->opcode;
24651
24652 rs = extract32(opcode, 21, 5);
24653 rt = extract32(opcode, 16, 5);
24654 rd = extract32(opcode, 11, 5);
24655
24656 if (rd == 0) {
24657 /* nop */
24658 } else {
24659 if (rs == 0) {
24660 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24661 } else {
24662 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24663 }
24664 if (rt == 0) {
24665 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24666 } else {
24667 if (rd != rt) {
24668 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24669 }
24670 }
24671 }
24672}
24673
fd487f83
MM
24674/*
24675 * PCPYUD rd, rs, rt
24676 *
24677 * Parallel Copy Upper Doubleword
24678 *
24679 * 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
24680 * +-----------+---------+---------+---------+---------+-----------+
24681 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24682 * +-----------+---------+---------+---------+---------+-----------+
24683 */
24684static void gen_mmi_pcpyud(DisasContext *ctx)
24685{
24686 uint32_t rs, rt, rd;
24687 uint32_t opcode;
24688
24689 opcode = ctx->opcode;
24690
24691 rs = extract32(opcode, 21, 5);
24692 rt = extract32(opcode, 16, 5);
24693 rd = extract32(opcode, 11, 5);
24694
24695 if (rd == 0) {
24696 /* nop */
24697 } else {
24698 if (rs == 0) {
24699 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24700 } else {
24701 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24702 }
24703 if (rt == 0) {
24704 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24705 } else {
24706 if (rd != rt) {
24707 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24708 }
24709 }
24710 }
24711}
24712
37b9aae2
MM
24713#endif
24714
24715
b621f018
AM
24716#if !defined(TARGET_MIPS64)
24717
d67da337
AM
24718/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24719#define MXU_APTN1_A 0
24720#define MXU_APTN1_S 1
24721
b70bb918
CJ
24722/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24723#define MXU_APTN2_AA 0
24724#define MXU_APTN2_AS 1
24725#define MXU_APTN2_SA 2
24726#define MXU_APTN2_SS 3
24727
5bb29992
AM
24728/* MXU execute add/subtract 2-bit pattern 'eptn2' */
24729#define MXU_EPTN2_AA 0
24730#define MXU_EPTN2_AS 1
24731#define MXU_EPTN2_SA 2
24732#define MXU_EPTN2_SS 3
24733
a35723f4 24734/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
24735#define MXU_OPTN2_PTN0 0
24736#define MXU_OPTN2_PTN1 1
24737#define MXU_OPTN2_PTN2 2
24738#define MXU_OPTN2_PTN3 3
24739/* alternative naming scheme for 'optn2' */
a35723f4
CJ
24740#define MXU_OPTN2_WW 0
24741#define MXU_OPTN2_LW 1
24742#define MXU_OPTN2_HW 2
24743#define MXU_OPTN2_XW 3
24744
53f1131f
CJ
24745/* MXU operand getting pattern 'optn3' */
24746#define MXU_OPTN3_PTN0 0
24747#define MXU_OPTN3_PTN1 1
24748#define MXU_OPTN3_PTN2 2
24749#define MXU_OPTN3_PTN3 3
24750#define MXU_OPTN3_PTN4 4
24751#define MXU_OPTN3_PTN5 5
24752#define MXU_OPTN3_PTN6 6
24753#define MXU_OPTN3_PTN7 7
24754
d67da337 24755
96992d1a
CJ
24756/*
24757 * S32I2M XRa, rb - Register move from GRF to XRF
24758 */
24759static void gen_mxu_s32i2m(DisasContext *ctx)
24760{
24761 TCGv t0;
24762 uint32_t XRa, Rb;
24763
24764 t0 = tcg_temp_new();
24765
24766 XRa = extract32(ctx->opcode, 6, 5);
24767 Rb = extract32(ctx->opcode, 16, 5);
24768
24769 gen_load_gpr(t0, Rb);
24770 if (XRa <= 15) {
24771 gen_store_mxu_gpr(t0, XRa);
24772 } else if (XRa == 16) {
24773 gen_store_mxu_cr(t0);
24774 }
24775
24776 tcg_temp_free(t0);
24777}
24778
24779/*
24780 * S32M2I XRa, rb - Register move from XRF to GRF
24781 */
24782static void gen_mxu_s32m2i(DisasContext *ctx)
24783{
24784 TCGv t0;
24785 uint32_t XRa, Rb;
24786
24787 t0 = tcg_temp_new();
24788
24789 XRa = extract32(ctx->opcode, 6, 5);
24790 Rb = extract32(ctx->opcode, 16, 5);
24791
24792 if (XRa <= 15) {
24793 gen_load_mxu_gpr(t0, XRa);
24794 } else if (XRa == 16) {
24795 gen_load_mxu_cr(t0);
24796 }
24797
24798 gen_store_gpr(t0, Rb);
24799
24800 tcg_temp_free(t0);
24801}
24802
be57bcdb
CJ
24803/*
24804 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24805 */
24806static void gen_mxu_s8ldd(DisasContext *ctx)
24807{
24808 TCGv t0, t1;
be57bcdb
CJ
24809 uint32_t XRa, Rb, s8, optn3;
24810
24811 t0 = tcg_temp_new();
24812 t1 = tcg_temp_new();
24813
be57bcdb
CJ
24814 XRa = extract32(ctx->opcode, 6, 4);
24815 s8 = extract32(ctx->opcode, 10, 8);
24816 optn3 = extract32(ctx->opcode, 18, 3);
24817 Rb = extract32(ctx->opcode, 21, 5);
24818
be57bcdb
CJ
24819 gen_load_gpr(t0, Rb);
24820 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24821
24822 switch (optn3) {
24823 /* XRa[7:0] = tmp8 */
24824 case MXU_OPTN3_PTN0:
24825 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24826 gen_load_mxu_gpr(t0, XRa);
24827 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24828 break;
24829 /* XRa[15:8] = tmp8 */
24830 case MXU_OPTN3_PTN1:
24831 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24832 gen_load_mxu_gpr(t0, XRa);
24833 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24834 break;
24835 /* XRa[23:16] = tmp8 */
24836 case MXU_OPTN3_PTN2:
24837 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24838 gen_load_mxu_gpr(t0, XRa);
24839 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24840 break;
24841 /* XRa[31:24] = tmp8 */
24842 case MXU_OPTN3_PTN3:
24843 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24844 gen_load_mxu_gpr(t0, XRa);
24845 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24846 break;
24847 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24848 case MXU_OPTN3_PTN4:
24849 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24850 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24851 break;
24852 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24853 case MXU_OPTN3_PTN5:
24854 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24855 tcg_gen_shli_tl(t1, t1, 8);
24856 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24857 break;
24858 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24859 case MXU_OPTN3_PTN6:
24860 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24861 tcg_gen_mov_tl(t0, t1);
24862 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24863 tcg_gen_shli_tl(t1, t1, 16);
24864 tcg_gen_or_tl(t0, t0, t1);
24865 break;
24866 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24867 case MXU_OPTN3_PTN7:
24868 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24869 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24870 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24871 break;
24872 }
24873
24874 gen_store_mxu_gpr(t0, XRa);
24875
be57bcdb
CJ
24876 tcg_temp_free(t0);
24877 tcg_temp_free(t1);
24878}
24879
72c9bcf8
CJ
24880/*
24881 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24882 */
24883static void gen_mxu_d16mul(DisasContext *ctx)
24884{
24885 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
24886 uint32_t XRa, XRb, XRc, XRd, optn2;
24887
24888 t0 = tcg_temp_new();
24889 t1 = tcg_temp_new();
24890 t2 = tcg_temp_new();
24891 t3 = tcg_temp_new();
24892
72c9bcf8
CJ
24893 XRa = extract32(ctx->opcode, 6, 4);
24894 XRb = extract32(ctx->opcode, 10, 4);
24895 XRc = extract32(ctx->opcode, 14, 4);
24896 XRd = extract32(ctx->opcode, 18, 4);
24897 optn2 = extract32(ctx->opcode, 22, 2);
24898
72c9bcf8
CJ
24899 gen_load_mxu_gpr(t1, XRb);
24900 tcg_gen_sextract_tl(t0, t1, 0, 16);
24901 tcg_gen_sextract_tl(t1, t1, 16, 16);
24902 gen_load_mxu_gpr(t3, XRc);
24903 tcg_gen_sextract_tl(t2, t3, 0, 16);
24904 tcg_gen_sextract_tl(t3, t3, 16, 16);
24905
24906 switch (optn2) {
24907 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24908 tcg_gen_mul_tl(t3, t1, t3);
24909 tcg_gen_mul_tl(t2, t0, t2);
24910 break;
24911 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24912 tcg_gen_mul_tl(t3, t0, t3);
24913 tcg_gen_mul_tl(t2, t0, t2);
24914 break;
24915 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24916 tcg_gen_mul_tl(t3, t1, t3);
24917 tcg_gen_mul_tl(t2, t1, t2);
24918 break;
24919 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24920 tcg_gen_mul_tl(t3, t0, t3);
24921 tcg_gen_mul_tl(t2, t1, t2);
24922 break;
24923 }
24924 gen_store_mxu_gpr(t3, XRa);
24925 gen_store_mxu_gpr(t2, XRd);
24926
72c9bcf8
CJ
24927 tcg_temp_free(t0);
24928 tcg_temp_free(t1);
24929 tcg_temp_free(t2);
24930 tcg_temp_free(t3);
24931}
24932
e67915b4
CJ
24933/*
24934 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24935 * and accumulate
24936 */
24937static void gen_mxu_d16mac(DisasContext *ctx)
24938{
24939 TCGv t0, t1, t2, t3;
e67915b4
CJ
24940 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24941
24942 t0 = tcg_temp_new();
24943 t1 = tcg_temp_new();
24944 t2 = tcg_temp_new();
24945 t3 = tcg_temp_new();
24946
e67915b4
CJ
24947 XRa = extract32(ctx->opcode, 6, 4);
24948 XRb = extract32(ctx->opcode, 10, 4);
24949 XRc = extract32(ctx->opcode, 14, 4);
24950 XRd = extract32(ctx->opcode, 18, 4);
24951 optn2 = extract32(ctx->opcode, 22, 2);
24952 aptn2 = extract32(ctx->opcode, 24, 2);
24953
e67915b4
CJ
24954 gen_load_mxu_gpr(t1, XRb);
24955 tcg_gen_sextract_tl(t0, t1, 0, 16);
24956 tcg_gen_sextract_tl(t1, t1, 16, 16);
24957
24958 gen_load_mxu_gpr(t3, XRc);
24959 tcg_gen_sextract_tl(t2, t3, 0, 16);
24960 tcg_gen_sextract_tl(t3, t3, 16, 16);
24961
24962 switch (optn2) {
24963 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24964 tcg_gen_mul_tl(t3, t1, t3);
24965 tcg_gen_mul_tl(t2, t0, t2);
24966 break;
24967 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24968 tcg_gen_mul_tl(t3, t0, t3);
24969 tcg_gen_mul_tl(t2, t0, t2);
24970 break;
24971 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24972 tcg_gen_mul_tl(t3, t1, t3);
24973 tcg_gen_mul_tl(t2, t1, t2);
24974 break;
24975 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24976 tcg_gen_mul_tl(t3, t0, t3);
24977 tcg_gen_mul_tl(t2, t1, t2);
24978 break;
24979 }
24980 gen_load_mxu_gpr(t0, XRa);
24981 gen_load_mxu_gpr(t1, XRd);
24982
24983 switch (aptn2) {
24984 case MXU_APTN2_AA:
24985 tcg_gen_add_tl(t3, t0, t3);
24986 tcg_gen_add_tl(t2, t1, t2);
24987 break;
24988 case MXU_APTN2_AS:
24989 tcg_gen_add_tl(t3, t0, t3);
24990 tcg_gen_sub_tl(t2, t1, t2);
24991 break;
24992 case MXU_APTN2_SA:
24993 tcg_gen_sub_tl(t3, t0, t3);
24994 tcg_gen_add_tl(t2, t1, t2);
24995 break;
24996 case MXU_APTN2_SS:
24997 tcg_gen_sub_tl(t3, t0, t3);
24998 tcg_gen_sub_tl(t2, t1, t2);
24999 break;
25000 }
25001 gen_store_mxu_gpr(t3, XRa);
25002 gen_store_mxu_gpr(t2, XRd);
25003
e67915b4
CJ
25004 tcg_temp_free(t0);
25005 tcg_temp_free(t1);
25006 tcg_temp_free(t2);
25007 tcg_temp_free(t3);
25008}
25009
a9a4181b
CJ
25010/*
25011 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25012 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25013 */
25014static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25015{
25016 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
25017 uint32_t XRa, XRb, XRc, XRd, sel;
25018
25019 t0 = tcg_temp_new();
25020 t1 = tcg_temp_new();
25021 t2 = tcg_temp_new();
25022 t3 = tcg_temp_new();
25023 t4 = tcg_temp_new();
25024 t5 = tcg_temp_new();
25025 t6 = tcg_temp_new();
25026 t7 = tcg_temp_new();
25027
a9a4181b
CJ
25028 XRa = extract32(ctx->opcode, 6, 4);
25029 XRb = extract32(ctx->opcode, 10, 4);
25030 XRc = extract32(ctx->opcode, 14, 4);
25031 XRd = extract32(ctx->opcode, 18, 4);
25032 sel = extract32(ctx->opcode, 22, 2);
25033
a9a4181b
CJ
25034 gen_load_mxu_gpr(t3, XRb);
25035 gen_load_mxu_gpr(t7, XRc);
25036
25037 if (sel == 0x2) {
25038 /* Q8MULSU */
25039 tcg_gen_ext8s_tl(t0, t3);
25040 tcg_gen_shri_tl(t3, t3, 8);
25041 tcg_gen_ext8s_tl(t1, t3);
25042 tcg_gen_shri_tl(t3, t3, 8);
25043 tcg_gen_ext8s_tl(t2, t3);
25044 tcg_gen_shri_tl(t3, t3, 8);
25045 tcg_gen_ext8s_tl(t3, t3);
25046 } else {
25047 /* Q8MUL */
25048 tcg_gen_ext8u_tl(t0, t3);
25049 tcg_gen_shri_tl(t3, t3, 8);
25050 tcg_gen_ext8u_tl(t1, t3);
25051 tcg_gen_shri_tl(t3, t3, 8);
25052 tcg_gen_ext8u_tl(t2, t3);
25053 tcg_gen_shri_tl(t3, t3, 8);
25054 tcg_gen_ext8u_tl(t3, t3);
25055 }
25056
25057 tcg_gen_ext8u_tl(t4, t7);
25058 tcg_gen_shri_tl(t7, t7, 8);
25059 tcg_gen_ext8u_tl(t5, t7);
25060 tcg_gen_shri_tl(t7, t7, 8);
25061 tcg_gen_ext8u_tl(t6, t7);
25062 tcg_gen_shri_tl(t7, t7, 8);
25063 tcg_gen_ext8u_tl(t7, t7);
25064
25065 tcg_gen_mul_tl(t0, t0, t4);
25066 tcg_gen_mul_tl(t1, t1, t5);
25067 tcg_gen_mul_tl(t2, t2, t6);
25068 tcg_gen_mul_tl(t3, t3, t7);
25069
25070 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25071 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25072 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25073 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25074
25075 tcg_gen_shli_tl(t1, t1, 16);
25076 tcg_gen_shli_tl(t3, t3, 16);
25077
25078 tcg_gen_or_tl(t0, t0, t1);
25079 tcg_gen_or_tl(t1, t2, t3);
25080
25081 gen_store_mxu_gpr(t0, XRd);
25082 gen_store_mxu_gpr(t1, XRa);
25083
a9a4181b
CJ
25084 tcg_temp_free(t0);
25085 tcg_temp_free(t1);
25086 tcg_temp_free(t2);
25087 tcg_temp_free(t3);
25088 tcg_temp_free(t4);
25089 tcg_temp_free(t5);
25090 tcg_temp_free(t6);
25091 tcg_temp_free(t7);
25092}
25093
4ca83721
CJ
25094/*
25095 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25096 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25097 */
25098static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25099{
25100 TCGv t0, t1;
4ca83721
CJ
25101 uint32_t XRa, Rb, s12, sel;
25102
25103 t0 = tcg_temp_new();
25104 t1 = tcg_temp_new();
25105
4ca83721
CJ
25106 XRa = extract32(ctx->opcode, 6, 4);
25107 s12 = extract32(ctx->opcode, 10, 10);
25108 sel = extract32(ctx->opcode, 20, 1);
25109 Rb = extract32(ctx->opcode, 21, 5);
25110
4ca83721
CJ
25111 gen_load_gpr(t0, Rb);
25112
25113 tcg_gen_movi_tl(t1, s12);
25114 tcg_gen_shli_tl(t1, t1, 2);
25115 if (s12 & 0x200) {
25116 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25117 }
25118 tcg_gen_add_tl(t1, t0, t1);
25119 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25120
25121 if (sel == 1) {
25122 /* S32LDDR */
25123 tcg_gen_bswap32_tl(t1, t1);
25124 }
25125 gen_store_mxu_gpr(t1, XRa);
25126
4ca83721
CJ
25127 tcg_temp_free(t0);
25128 tcg_temp_free(t1);
25129}
25130
96992d1a 25131
b621f018
AM
25132/*
25133 * MXU instruction category: logic
25134 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25135 *
25136 * S32NOR S32AND S32OR S32XOR
25137 */
25138
25139/*
25140 * S32NOR XRa, XRb, XRc
25141 * Update XRa with the result of logical bitwise 'nor' operation
25142 * applied to the content of XRb and XRc.
25143 *
25144 * 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
25145 * +-----------+---------+-----+-------+-------+-------+-----------+
25146 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25147 * +-----------+---------+-----+-------+-------+-------+-----------+
25148 */
25149static void gen_mxu_S32NOR(DisasContext *ctx)
25150{
25151 uint32_t pad, XRc, XRb, XRa;
25152
25153 pad = extract32(ctx->opcode, 21, 5);
25154 XRc = extract32(ctx->opcode, 14, 4);
25155 XRb = extract32(ctx->opcode, 10, 4);
25156 XRa = extract32(ctx->opcode, 6, 4);
25157
25158 if (unlikely(pad != 0)) {
25159 /* opcode padding incorrect -> do nothing */
25160 } else if (unlikely(XRa == 0)) {
25161 /* destination is zero register -> do nothing */
25162 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25163 /* both operands zero registers -> just set destination to all 1s */
25164 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25165 } else if (unlikely(XRb == 0)) {
25166 /* XRb zero register -> just set destination to the negation of XRc */
25167 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25168 } else if (unlikely(XRc == 0)) {
25169 /* XRa zero register -> just set destination to the negation of XRb */
25170 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25171 } else if (unlikely(XRb == XRc)) {
25172 /* both operands same -> just set destination to the negation of XRb */
25173 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25174 } else {
25175 /* the most general case */
25176 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25177 }
25178}
25179
25180/*
25181 * S32AND XRa, XRb, XRc
25182 * Update XRa with the result of logical bitwise 'and' operation
25183 * applied to the content of XRb and XRc.
25184 *
25185 * 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
25186 * +-----------+---------+-----+-------+-------+-------+-----------+
25187 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25188 * +-----------+---------+-----+-------+-------+-------+-----------+
25189 */
25190static void gen_mxu_S32AND(DisasContext *ctx)
25191{
25192 uint32_t pad, XRc, XRb, XRa;
25193
25194 pad = extract32(ctx->opcode, 21, 5);
25195 XRc = extract32(ctx->opcode, 14, 4);
25196 XRb = extract32(ctx->opcode, 10, 4);
25197 XRa = extract32(ctx->opcode, 6, 4);
25198
25199 if (unlikely(pad != 0)) {
25200 /* opcode padding incorrect -> do nothing */
25201 } else if (unlikely(XRa == 0)) {
25202 /* destination is zero register -> do nothing */
25203 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25204 /* one of operands zero register -> just set destination to all 0s */
25205 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25206 } else if (unlikely(XRb == XRc)) {
25207 /* both operands same -> just set destination to one of them */
25208 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25209 } else {
25210 /* the most general case */
25211 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25212 }
25213}
25214
25215/*
25216 * S32OR XRa, XRb, XRc
25217 * Update XRa with the result of logical bitwise 'or' operation
25218 * applied to the content of XRb and XRc.
25219 *
25220 * 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
25221 * +-----------+---------+-----+-------+-------+-------+-----------+
25222 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25223 * +-----------+---------+-----+-------+-------+-------+-----------+
25224 */
25225static void gen_mxu_S32OR(DisasContext *ctx)
25226{
25227 uint32_t pad, XRc, XRb, XRa;
25228
25229 pad = extract32(ctx->opcode, 21, 5);
25230 XRc = extract32(ctx->opcode, 14, 4);
25231 XRb = extract32(ctx->opcode, 10, 4);
25232 XRa = extract32(ctx->opcode, 6, 4);
25233
25234 if (unlikely(pad != 0)) {
25235 /* opcode padding incorrect -> do nothing */
25236 } else if (unlikely(XRa == 0)) {
25237 /* destination is zero register -> do nothing */
25238 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25239 /* both operands zero registers -> just set destination to all 0s */
25240 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25241 } else if (unlikely(XRb == 0)) {
25242 /* XRb zero register -> just set destination to the content of XRc */
25243 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25244 } else if (unlikely(XRc == 0)) {
25245 /* XRc zero register -> just set destination to the content of XRb */
25246 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25247 } else if (unlikely(XRb == XRc)) {
25248 /* both operands same -> just set destination to one of them */
25249 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25250 } else {
25251 /* the most general case */
25252 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25253 }
25254}
25255
25256/*
25257 * S32XOR XRa, XRb, XRc
25258 * Update XRa with the result of logical bitwise 'xor' operation
25259 * applied to the content of XRb and XRc.
25260 *
25261 * 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
25262 * +-----------+---------+-----+-------+-------+-------+-----------+
25263 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25264 * +-----------+---------+-----+-------+-------+-------+-----------+
25265 */
25266static void gen_mxu_S32XOR(DisasContext *ctx)
25267{
25268 uint32_t pad, XRc, XRb, XRa;
25269
25270 pad = extract32(ctx->opcode, 21, 5);
25271 XRc = extract32(ctx->opcode, 14, 4);
25272 XRb = extract32(ctx->opcode, 10, 4);
25273 XRa = extract32(ctx->opcode, 6, 4);
25274
25275 if (unlikely(pad != 0)) {
25276 /* opcode padding incorrect -> do nothing */
25277 } else if (unlikely(XRa == 0)) {
25278 /* destination is zero register -> do nothing */
25279 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25280 /* both operands zero registers -> just set destination to all 0s */
25281 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25282 } else if (unlikely(XRb == 0)) {
25283 /* XRb zero register -> just set destination to the content of XRc */
25284 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25285 } else if (unlikely(XRc == 0)) {
25286 /* XRc zero register -> just set destination to the content of XRb */
25287 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25288 } else if (unlikely(XRb == XRc)) {
25289 /* both operands same -> just set destination to all 0s */
25290 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25291 } else {
25292 /* the most general case */
25293 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25294 }
25295}
25296
25297
bb84cbf3
AM
25298/*
25299 * MXU instruction category max/min
25300 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25301 *
25302 * S32MAX D16MAX Q8MAX
25303 * S32MIN D16MIN Q8MIN
25304 */
25305
25306/*
25307 * S32MAX XRa, XRb, XRc
25308 * Update XRa with the maximum of signed 32-bit integers contained
25309 * in XRb and XRc.
25310 *
25311 * S32MIN XRa, XRb, XRc
25312 * Update XRa with the minimum of signed 32-bit integers contained
25313 * in XRb and XRc.
25314 *
25315 * 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
25316 * +-----------+---------+-----+-------+-------+-------+-----------+
25317 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25318 * +-----------+---------+-----+-------+-------+-------+-----------+
25319 */
25320static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25321{
25322 uint32_t pad, opc, XRc, XRb, XRa;
25323
25324 pad = extract32(ctx->opcode, 21, 5);
25325 opc = extract32(ctx->opcode, 18, 3);
25326 XRc = extract32(ctx->opcode, 14, 4);
25327 XRb = extract32(ctx->opcode, 10, 4);
25328 XRa = extract32(ctx->opcode, 6, 4);
25329
25330 if (unlikely(pad != 0)) {
25331 /* opcode padding incorrect -> do nothing */
25332 } else if (unlikely(XRa == 0)) {
25333 /* destination is zero register -> do nothing */
25334 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25335 /* both operands zero registers -> just set destination to zero */
25336 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25337 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25338 /* exactly one operand is zero register - find which one is not...*/
25339 uint32_t XRx = XRb ? XRb : XRc;
25340 /* ...and do max/min operation with one operand 0 */
25341 if (opc == OPC_MXU_S32MAX) {
25342 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25343 } else {
25344 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25345 }
25346 } else if (unlikely(XRb == XRc)) {
25347 /* both operands same -> just set destination to one of them */
25348 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25349 } else {
25350 /* the most general case */
25351 if (opc == OPC_MXU_S32MAX) {
25352 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25353 mxu_gpr[XRc - 1]);
25354 } else {
25355 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25356 mxu_gpr[XRc - 1]);
25357 }
25358 }
25359}
25360
25361/*
25362 * D16MAX
25363 * Update XRa with the 16-bit-wise maximums of signed integers
25364 * contained in XRb and XRc.
25365 *
25366 * D16MIN
25367 * Update XRa with the 16-bit-wise minimums of signed integers
25368 * contained in XRb and XRc.
25369 *
25370 * 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
25371 * +-----------+---------+-----+-------+-------+-------+-----------+
25372 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25373 * +-----------+---------+-----+-------+-------+-------+-----------+
25374 */
25375static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25376{
25377 uint32_t pad, opc, XRc, XRb, XRa;
25378
25379 pad = extract32(ctx->opcode, 21, 5);
25380 opc = extract32(ctx->opcode, 18, 3);
25381 XRc = extract32(ctx->opcode, 14, 4);
25382 XRb = extract32(ctx->opcode, 10, 4);
25383 XRa = extract32(ctx->opcode, 6, 4);
25384
25385 if (unlikely(pad != 0)) {
25386 /* opcode padding incorrect -> do nothing */
25387 } else if (unlikely(XRc == 0)) {
25388 /* destination is zero register -> do nothing */
25389 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25390 /* both operands zero registers -> just set destination to zero */
25391 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25392 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25393 /* exactly one operand is zero register - find which one is not...*/
25394 uint32_t XRx = XRb ? XRb : XRc;
25395 /* ...and do half-word-wise max/min with one operand 0 */
25396 TCGv_i32 t0 = tcg_temp_new();
25397 TCGv_i32 t1 = tcg_const_i32(0);
25398
25399 /* the left half-word first */
25400 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25401 if (opc == OPC_MXU_D16MAX) {
25402 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25403 } else {
25404 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25405 }
25406
25407 /* the right half-word */
25408 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25409 /* move half-words to the leftmost position */
25410 tcg_gen_shli_i32(t0, t0, 16);
25411 /* t0 will be max/min of t0 and t1 */
25412 if (opc == OPC_MXU_D16MAX) {
25413 tcg_gen_smax_i32(t0, t0, t1);
25414 } else {
25415 tcg_gen_smin_i32(t0, t0, t1);
25416 }
25417 /* return resulting half-words to its original position */
25418 tcg_gen_shri_i32(t0, t0, 16);
25419 /* finaly update the destination */
25420 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25421
25422 tcg_temp_free(t1);
25423 tcg_temp_free(t0);
25424 } else if (unlikely(XRb == XRc)) {
25425 /* both operands same -> just set destination to one of them */
25426 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25427 } else {
25428 /* the most general case */
25429 TCGv_i32 t0 = tcg_temp_new();
25430 TCGv_i32 t1 = tcg_temp_new();
25431
25432 /* the left half-word first */
25433 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25434 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25435 if (opc == OPC_MXU_D16MAX) {
25436 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25437 } else {
25438 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25439 }
25440
25441 /* the right half-word */
25442 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25443 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25444 /* move half-words to the leftmost position */
25445 tcg_gen_shli_i32(t0, t0, 16);
25446 tcg_gen_shli_i32(t1, t1, 16);
25447 /* t0 will be max/min of t0 and t1 */
25448 if (opc == OPC_MXU_D16MAX) {
25449 tcg_gen_smax_i32(t0, t0, t1);
25450 } else {
25451 tcg_gen_smin_i32(t0, t0, t1);
25452 }
25453 /* return resulting half-words to its original position */
25454 tcg_gen_shri_i32(t0, t0, 16);
25455 /* finaly update the destination */
25456 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25457
25458 tcg_temp_free(t1);
25459 tcg_temp_free(t0);
25460 }
25461}
25462
25463/*
25464 * Q8MAX
25465 * Update XRa with the 8-bit-wise maximums of signed integers
25466 * contained in XRb and XRc.
25467 *
25468 * Q8MIN
25469 * Update XRa with the 8-bit-wise minimums of signed integers
25470 * contained in XRb and XRc.
25471 *
25472 * 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
25473 * +-----------+---------+-----+-------+-------+-------+-----------+
25474 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25475 * +-----------+---------+-----+-------+-------+-------+-----------+
25476 */
25477static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25478{
25479 uint32_t pad, opc, XRc, XRb, XRa;
25480
25481 pad = extract32(ctx->opcode, 21, 5);
25482 opc = extract32(ctx->opcode, 18, 3);
25483 XRc = extract32(ctx->opcode, 14, 4);
25484 XRb = extract32(ctx->opcode, 10, 4);
25485 XRa = extract32(ctx->opcode, 6, 4);
25486
25487 if (unlikely(pad != 0)) {
25488 /* opcode padding incorrect -> do nothing */
25489 } else if (unlikely(XRa == 0)) {
25490 /* destination is zero register -> do nothing */
25491 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25492 /* both operands zero registers -> just set destination to zero */
25493 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25494 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25495 /* exactly one operand is zero register - make it be the first...*/
25496 uint32_t XRx = XRb ? XRb : XRc;
25497 /* ...and do byte-wise max/min with one operand 0 */
25498 TCGv_i32 t0 = tcg_temp_new();
25499 TCGv_i32 t1 = tcg_const_i32(0);
25500 int32_t i;
25501
25502 /* the leftmost byte (byte 3) first */
25503 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25504 if (opc == OPC_MXU_Q8MAX) {
25505 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25506 } else {
25507 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25508 }
25509
25510 /* bytes 2, 1, 0 */
25511 for (i = 2; i >= 0; i--) {
25512 /* extract the byte */
25513 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25514 /* move the byte to the leftmost position */
25515 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25516 /* t0 will be max/min of t0 and t1 */
25517 if (opc == OPC_MXU_Q8MAX) {
25518 tcg_gen_smax_i32(t0, t0, t1);
25519 } else {
25520 tcg_gen_smin_i32(t0, t0, t1);
25521 }
25522 /* return resulting byte to its original position */
25523 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25524 /* finaly update the destination */
25525 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25526 }
25527
25528 tcg_temp_free(t1);
25529 tcg_temp_free(t0);
25530 } else if (unlikely(XRb == XRc)) {
25531 /* both operands same -> just set destination to one of them */
25532 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25533 } else {
25534 /* the most general case */
25535 TCGv_i32 t0 = tcg_temp_new();
25536 TCGv_i32 t1 = tcg_temp_new();
25537 int32_t i;
25538
25539 /* the leftmost bytes (bytes 3) first */
25540 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25541 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25542 if (opc == OPC_MXU_Q8MAX) {
25543 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25544 } else {
25545 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25546 }
25547
25548 /* bytes 2, 1, 0 */
25549 for (i = 2; i >= 0; i--) {
25550 /* extract corresponding bytes */
25551 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25552 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25553 /* move the bytes to the leftmost position */
25554 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25555 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25556 /* t0 will be max/min of t0 and t1 */
25557 if (opc == OPC_MXU_Q8MAX) {
25558 tcg_gen_smax_i32(t0, t0, t1);
25559 } else {
25560 tcg_gen_smin_i32(t0, t0, t1);
25561 }
25562 /* return resulting byte to its original position */
25563 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25564 /* finaly update the destination */
25565 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25566 }
25567
25568 tcg_temp_free(t1);
25569 tcg_temp_free(t0);
25570 }
25571}
25572
25573
79f5fee7
AM
25574/*
25575 * MXU instruction category: align
25576 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25577 *
25578 * S32ALN S32ALNI
25579 */
25580
25581/*
25582 * S32ALNI XRc, XRb, XRa, optn3
25583 * Arrange bytes from XRb and XRc according to one of five sets of
25584 * rules determined by optn3, and place the result in XRa.
25585 *
25586 * 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
25587 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25588 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25589 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25590 *
25591 */
25592static void gen_mxu_S32ALNI(DisasContext *ctx)
25593{
25594 uint32_t optn3, pad, XRc, XRb, XRa;
25595
25596 optn3 = extract32(ctx->opcode, 23, 3);
25597 pad = extract32(ctx->opcode, 21, 2);
25598 XRc = extract32(ctx->opcode, 14, 4);
25599 XRb = extract32(ctx->opcode, 10, 4);
25600 XRa = extract32(ctx->opcode, 6, 4);
25601
25602 if (unlikely(pad != 0)) {
25603 /* opcode padding incorrect -> do nothing */
25604 } else if (unlikely(XRa == 0)) {
25605 /* destination is zero register -> do nothing */
25606 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25607 /* both operands zero registers -> just set destination to all 0s */
25608 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25609 } else if (unlikely(XRb == 0)) {
25610 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25611 switch (optn3) {
25612 case MXU_OPTN3_PTN0:
25613 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25614 break;
25615 case MXU_OPTN3_PTN1:
25616 case MXU_OPTN3_PTN2:
25617 case MXU_OPTN3_PTN3:
25618 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25619 8 * (4 - optn3));
25620 break;
25621 case MXU_OPTN3_PTN4:
25622 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25623 break;
25624 }
25625 } else if (unlikely(XRc == 0)) {
25626 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25627 switch (optn3) {
25628 case MXU_OPTN3_PTN0:
25629 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25630 break;
25631 case MXU_OPTN3_PTN1:
25632 case MXU_OPTN3_PTN2:
25633 case MXU_OPTN3_PTN3:
25634 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25635 break;
25636 case MXU_OPTN3_PTN4:
25637 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25638 break;
25639 }
25640 } else if (unlikely(XRb == XRc)) {
25641 /* both operands same -> just rotation or moving from any of them */
25642 switch (optn3) {
25643 case MXU_OPTN3_PTN0:
25644 case MXU_OPTN3_PTN4:
25645 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25646 break;
25647 case MXU_OPTN3_PTN1:
25648 case MXU_OPTN3_PTN2:
25649 case MXU_OPTN3_PTN3:
25650 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25651 break;
25652 }
25653 } else {
25654 /* the most general case */
25655 switch (optn3) {
25656 case MXU_OPTN3_PTN0:
25657 {
25658 /* */
25659 /* XRb XRc */
25660 /* +---------------+ */
25661 /* | A B C D | E F G H */
25662 /* +-------+-------+ */
25663 /* | */
25664 /* XRa */
25665 /* */
25666
25667 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25668 }
25669 break;
25670 case MXU_OPTN3_PTN1:
25671 {
25672 /* */
25673 /* XRb XRc */
25674 /* +-------------------+ */
25675 /* A | B C D E | F G H */
25676 /* +---------+---------+ */
25677 /* | */
25678 /* XRa */
25679 /* */
25680
25681 TCGv_i32 t0 = tcg_temp_new();
25682 TCGv_i32 t1 = tcg_temp_new();
25683
25684 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25685 tcg_gen_shli_i32(t0, t0, 8);
25686
25687 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25688 tcg_gen_shri_i32(t1, t1, 24);
25689
25690 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25691
25692 tcg_temp_free(t1);
25693 tcg_temp_free(t0);
25694 }
25695 break;
25696 case MXU_OPTN3_PTN2:
25697 {
25698 /* */
25699 /* XRb XRc */
25700 /* +-------------------+ */
25701 /* A B | C D E F | G H */
25702 /* +---------+---------+ */
25703 /* | */
25704 /* XRa */
25705 /* */
25706
25707 TCGv_i32 t0 = tcg_temp_new();
25708 TCGv_i32 t1 = tcg_temp_new();
25709
25710 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25711 tcg_gen_shli_i32(t0, t0, 16);
25712
25713 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25714 tcg_gen_shri_i32(t1, t1, 16);
25715
25716 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25717
25718 tcg_temp_free(t1);
25719 tcg_temp_free(t0);
25720 }
25721 break;
25722 case MXU_OPTN3_PTN3:
25723 {
25724 /* */
25725 /* XRb XRc */
25726 /* +-------------------+ */
25727 /* A B C | D E F G | H */
25728 /* +---------+---------+ */
25729 /* | */
25730 /* XRa */
25731 /* */
25732
25733 TCGv_i32 t0 = tcg_temp_new();
25734 TCGv_i32 t1 = tcg_temp_new();
25735
25736 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25737 tcg_gen_shli_i32(t0, t0, 24);
25738
25739 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25740 tcg_gen_shri_i32(t1, t1, 8);
25741
25742 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25743
25744 tcg_temp_free(t1);
25745 tcg_temp_free(t0);
25746 }
25747 break;
25748 case MXU_OPTN3_PTN4:
25749 {
25750 /* */
25751 /* XRb XRc */
25752 /* +---------------+ */
25753 /* A B C D | E F G H | */
25754 /* +-------+-------+ */
25755 /* | */
25756 /* XRa */
25757 /* */
25758
25759 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25760 }
25761 break;
25762 }
25763 }
25764}
25765
25766
96992d1a
CJ
25767/*
25768 * Decoding engine for MXU
25769 * =======================
25770 */
25771
03f40088
AM
25772/*
25773 *
25774 * Decode MXU pool00
25775 *
25776 * 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
25777 * +-----------+---------+-----+-------+-------+-------+-----------+
25778 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25779 * +-----------+---------+-----+-------+-------+-------+-----------+
25780 *
25781 */
25782static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25783{
25784 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25785
25786 switch (opcode) {
25787 case OPC_MXU_S32MAX:
03f40088 25788 case OPC_MXU_S32MIN:
bb84cbf3 25789 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
25790 break;
25791 case OPC_MXU_D16MAX:
03f40088 25792 case OPC_MXU_D16MIN:
bb84cbf3 25793 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
25794 break;
25795 case OPC_MXU_Q8MAX:
03f40088 25796 case OPC_MXU_Q8MIN:
bb84cbf3 25797 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
25798 break;
25799 case OPC_MXU_Q8SLT:
25800 /* TODO: Implement emulation of Q8SLT instruction. */
25801 MIPS_INVAL("OPC_MXU_Q8SLT");
25802 generate_exception_end(ctx, EXCP_RI);
25803 break;
25804 case OPC_MXU_Q8SLTU:
25805 /* TODO: Implement emulation of Q8SLTU instruction. */
25806 MIPS_INVAL("OPC_MXU_Q8SLTU");
25807 generate_exception_end(ctx, EXCP_RI);
25808 break;
25809 default:
25810 MIPS_INVAL("decode_opc_mxu");
25811 generate_exception_end(ctx, EXCP_RI);
25812 break;
25813 }
25814}
25815
25816/*
25817 *
25818 * Decode MXU pool01
25819 *
25820 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25821 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25822 * +-----------+---------+-----+-------+-------+-------+-----------+
25823 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25824 * +-----------+---------+-----+-------+-------+-------+-----------+
25825 *
25826 * Q8ADD:
25827 * 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
25828 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25829 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25830 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25831 *
25832 */
25833static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25834{
25835 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25836
25837 switch (opcode) {
25838 case OPC_MXU_S32SLT:
25839 /* TODO: Implement emulation of S32SLT instruction. */
25840 MIPS_INVAL("OPC_MXU_S32SLT");
25841 generate_exception_end(ctx, EXCP_RI);
25842 break;
25843 case OPC_MXU_D16SLT:
25844 /* TODO: Implement emulation of D16SLT instruction. */
25845 MIPS_INVAL("OPC_MXU_D16SLT");
25846 generate_exception_end(ctx, EXCP_RI);
25847 break;
25848 case OPC_MXU_D16AVG:
25849 /* TODO: Implement emulation of D16AVG instruction. */
25850 MIPS_INVAL("OPC_MXU_D16AVG");
25851 generate_exception_end(ctx, EXCP_RI);
25852 break;
25853 case OPC_MXU_D16AVGR:
25854 /* TODO: Implement emulation of D16AVGR instruction. */
25855 MIPS_INVAL("OPC_MXU_D16AVGR");
25856 generate_exception_end(ctx, EXCP_RI);
25857 break;
25858 case OPC_MXU_Q8AVG:
25859 /* TODO: Implement emulation of Q8AVG instruction. */
25860 MIPS_INVAL("OPC_MXU_Q8AVG");
25861 generate_exception_end(ctx, EXCP_RI);
25862 break;
25863 case OPC_MXU_Q8AVGR:
25864 /* TODO: Implement emulation of Q8AVGR instruction. */
25865 MIPS_INVAL("OPC_MXU_Q8AVGR");
25866 generate_exception_end(ctx, EXCP_RI);
25867 break;
25868 case OPC_MXU_Q8ADD:
25869 /* TODO: Implement emulation of Q8ADD instruction. */
25870 MIPS_INVAL("OPC_MXU_Q8ADD");
25871 generate_exception_end(ctx, EXCP_RI);
25872 break;
25873 default:
25874 MIPS_INVAL("decode_opc_mxu");
25875 generate_exception_end(ctx, EXCP_RI);
25876 break;
25877 }
25878}
25879
25880/*
25881 *
25882 * Decode MXU pool02
25883 *
25884 * 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
25885 * +-----------+---------+-----+-------+-------+-------+-----------+
25886 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25887 * +-----------+---------+-----+-------+-------+-------+-----------+
25888 *
25889 */
25890static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25891{
25892 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25893
25894 switch (opcode) {
25895 case OPC_MXU_S32CPS:
25896 /* TODO: Implement emulation of S32CPS instruction. */
25897 MIPS_INVAL("OPC_MXU_S32CPS");
25898 generate_exception_end(ctx, EXCP_RI);
25899 break;
25900 case OPC_MXU_D16CPS:
25901 /* TODO: Implement emulation of D16CPS instruction. */
25902 MIPS_INVAL("OPC_MXU_D16CPS");
25903 generate_exception_end(ctx, EXCP_RI);
25904 break;
25905 case OPC_MXU_Q8ABD:
25906 /* TODO: Implement emulation of Q8ABD instruction. */
25907 MIPS_INVAL("OPC_MXU_Q8ABD");
25908 generate_exception_end(ctx, EXCP_RI);
25909 break;
25910 case OPC_MXU_Q16SAT:
25911 /* TODO: Implement emulation of Q16SAT instruction. */
25912 MIPS_INVAL("OPC_MXU_Q16SAT");
25913 generate_exception_end(ctx, EXCP_RI);
25914 break;
25915 default:
25916 MIPS_INVAL("decode_opc_mxu");
25917 generate_exception_end(ctx, EXCP_RI);
25918 break;
25919 }
25920}
25921
25922/*
25923 *
25924 * Decode MXU pool03
25925 *
25926 * D16MULF:
25927 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25928 * +-----------+---+---+-------+-------+-------+-------+-----------+
25929 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25930 * +-----------+---+---+-------+-------+-------+-------+-----------+
25931 *
25932 * D16MULE:
25933 * 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
25934 * +-----------+---+---+-------+-------+-------+-------+-----------+
25935 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25936 * +-----------+---+---+-------+-------+-------+-------+-----------+
25937 *
25938 */
25939static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25940{
25941 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25942
25943 switch (opcode) {
25944 case OPC_MXU_D16MULF:
25945 /* TODO: Implement emulation of D16MULF instruction. */
25946 MIPS_INVAL("OPC_MXU_D16MULF");
25947 generate_exception_end(ctx, EXCP_RI);
25948 break;
25949 case OPC_MXU_D16MULE:
25950 /* TODO: Implement emulation of D16MULE instruction. */
25951 MIPS_INVAL("OPC_MXU_D16MULE");
25952 generate_exception_end(ctx, EXCP_RI);
25953 break;
25954 default:
25955 MIPS_INVAL("decode_opc_mxu");
25956 generate_exception_end(ctx, EXCP_RI);
25957 break;
25958 }
25959}
25960
25961/*
25962 *
25963 * Decode MXU pool04
25964 *
25965 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25966 * +-----------+---------+-+-------------------+-------+-----------+
25967 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25968 * +-----------+---------+-+-------------------+-------+-----------+
25969 *
25970 */
25971static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25972{
25973 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25974
25975 switch (opcode) {
25976 case OPC_MXU_S32LDD:
03f40088 25977 case OPC_MXU_S32LDDR:
4ca83721 25978 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
25979 break;
25980 default:
25981 MIPS_INVAL("decode_opc_mxu");
25982 generate_exception_end(ctx, EXCP_RI);
25983 break;
25984 }
25985}
25986
25987/*
25988 *
25989 * Decode MXU pool05
25990 *
25991 * 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
25992 * +-----------+---------+-+-------------------+-------+-----------+
25993 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25994 * +-----------+---------+-+-------------------+-------+-----------+
25995 *
25996 */
25997static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25998{
25999 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26000
26001 switch (opcode) {
26002 case OPC_MXU_S32STD:
26003 /* TODO: Implement emulation of S32STD instruction. */
26004 MIPS_INVAL("OPC_MXU_S32STD");
26005 generate_exception_end(ctx, EXCP_RI);
26006 break;
26007 case OPC_MXU_S32STDR:
26008 /* TODO: Implement emulation of S32STDR instruction. */
26009 MIPS_INVAL("OPC_MXU_S32STDR");
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 pool06
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 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26026 * +-----------+---------+---------+---+-------+-------+-----------+
26027 *
26028 */
26029static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26030{
26031 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26032
26033 switch (opcode) {
26034 case OPC_MXU_S32LDDV:
26035 /* TODO: Implement emulation of S32LDDV instruction. */
26036 MIPS_INVAL("OPC_MXU_S32LDDV");
26037 generate_exception_end(ctx, EXCP_RI);
26038 break;
26039 case OPC_MXU_S32LDDVR:
26040 /* TODO: Implement emulation of S32LDDVR instruction. */
26041 MIPS_INVAL("OPC_MXU_S32LDDVR");
26042 generate_exception_end(ctx, EXCP_RI);
26043 break;
26044 default:
26045 MIPS_INVAL("decode_opc_mxu");
26046 generate_exception_end(ctx, EXCP_RI);
26047 break;
26048 }
26049}
26050
26051/*
26052 *
26053 * Decode MXU pool07
26054 *
26055 * 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
26056 * +-----------+---------+---------+---+-------+-------+-----------+
26057 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26058 * +-----------+---------+---------+---+-------+-------+-----------+
26059 *
26060 */
26061static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26062{
26063 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26064
26065 switch (opcode) {
26066 case OPC_MXU_S32STDV:
26067 /* TODO: Implement emulation of S32TDV instruction. */
26068 MIPS_INVAL("OPC_MXU_S32TDV");
26069 generate_exception_end(ctx, EXCP_RI);
26070 break;
26071 case OPC_MXU_S32STDVR:
26072 /* TODO: Implement emulation of S32TDVR instruction. */
26073 MIPS_INVAL("OPC_MXU_S32TDVR");
26074 generate_exception_end(ctx, EXCP_RI);
26075 break;
26076 default:
26077 MIPS_INVAL("decode_opc_mxu");
26078 generate_exception_end(ctx, EXCP_RI);
26079 break;
26080 }
26081}
26082
26083/*
26084 *
26085 * Decode MXU pool08
26086 *
26087 * 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
26088 * +-----------+---------+-+-------------------+-------+-----------+
26089 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26090 * +-----------+---------+-+-------------------+-------+-----------+
26091 *
7480515f 26092 */
03f40088
AM
26093static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26094{
26095 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26096
26097 switch (opcode) {
26098 case OPC_MXU_S32LDI:
26099 /* TODO: Implement emulation of S32LDI instruction. */
26100 MIPS_INVAL("OPC_MXU_S32LDI");
26101 generate_exception_end(ctx, EXCP_RI);
26102 break;
26103 case OPC_MXU_S32LDIR:
26104 /* TODO: Implement emulation of S32LDIR instruction. */
26105 MIPS_INVAL("OPC_MXU_S32LDIR");
26106 generate_exception_end(ctx, EXCP_RI);
26107 break;
26108 default:
26109 MIPS_INVAL("decode_opc_mxu");
26110 generate_exception_end(ctx, EXCP_RI);
26111 break;
26112 }
26113}
26114
26115/*
26116 *
26117 * Decode MXU pool09
26118 *
26119 * 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
26120 * +-----------+---------+-+-------------------+-------+-----------+
26121 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26122 * +-----------+---------+-+-------------------+-------+-----------+
26123 *
26124 */
26125static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26126{
26127 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26128
26129 switch (opcode) {
26130 case OPC_MXU_S32SDI:
26131 /* TODO: Implement emulation of S32SDI instruction. */
26132 MIPS_INVAL("OPC_MXU_S32SDI");
26133 generate_exception_end(ctx, EXCP_RI);
26134 break;
26135 case OPC_MXU_S32SDIR:
26136 /* TODO: Implement emulation of S32SDIR instruction. */
26137 MIPS_INVAL("OPC_MXU_S32SDIR");
26138 generate_exception_end(ctx, EXCP_RI);
26139 break;
26140 default:
26141 MIPS_INVAL("decode_opc_mxu");
26142 generate_exception_end(ctx, EXCP_RI);
26143 break;
26144 }
26145}
26146
26147/*
26148 *
26149 * Decode MXU pool10
26150 *
26151 * 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
26152 * +-----------+---------+---------+---+-------+-------+-----------+
26153 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26154 * +-----------+---------+---------+---+-------+-------+-----------+
26155 *
26156 */
26157static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26158{
26159 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26160
26161 switch (opcode) {
26162 case OPC_MXU_S32LDIV:
26163 /* TODO: Implement emulation of S32LDIV instruction. */
26164 MIPS_INVAL("OPC_MXU_S32LDIV");
26165 generate_exception_end(ctx, EXCP_RI);
26166 break;
26167 case OPC_MXU_S32LDIVR:
26168 /* TODO: Implement emulation of S32LDIVR instruction. */
26169 MIPS_INVAL("OPC_MXU_S32LDIVR");
26170 generate_exception_end(ctx, EXCP_RI);
26171 break;
26172 default:
26173 MIPS_INVAL("decode_opc_mxu");
26174 generate_exception_end(ctx, EXCP_RI);
26175 break;
26176 }
26177}
26178
26179/*
26180 *
26181 * Decode MXU pool11
26182 *
26183 * 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
26184 * +-----------+---------+---------+---+-------+-------+-----------+
26185 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26186 * +-----------+---------+---------+---+-------+-------+-----------+
26187 *
26188 */
26189static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26190{
26191 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26192
26193 switch (opcode) {
26194 case OPC_MXU_S32SDIV:
26195 /* TODO: Implement emulation of S32SDIV instruction. */
26196 MIPS_INVAL("OPC_MXU_S32SDIV");
26197 generate_exception_end(ctx, EXCP_RI);
26198 break;
26199 case OPC_MXU_S32SDIVR:
26200 /* TODO: Implement emulation of S32SDIVR instruction. */
26201 MIPS_INVAL("OPC_MXU_S32SDIVR");
26202 generate_exception_end(ctx, EXCP_RI);
26203 break;
26204 default:
26205 MIPS_INVAL("decode_opc_mxu");
26206 generate_exception_end(ctx, EXCP_RI);
26207 break;
26208 }
26209}
26210
26211/*
26212 *
26213 * Decode MXU pool12
26214 *
26215 * 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
26216 * +-----------+---+---+-------+-------+-------+-------+-----------+
26217 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26218 * +-----------+---+---+-------+-------+-------+-------+-----------+
26219 *
26220 */
26221static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26222{
26223 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26224
26225 switch (opcode) {
26226 case OPC_MXU_D32ACC:
26227 /* TODO: Implement emulation of D32ACC instruction. */
26228 MIPS_INVAL("OPC_MXU_D32ACC");
26229 generate_exception_end(ctx, EXCP_RI);
26230 break;
26231 case OPC_MXU_D32ACCM:
26232 /* TODO: Implement emulation of D32ACCM instruction. */
26233 MIPS_INVAL("OPC_MXU_D32ACCM");
26234 generate_exception_end(ctx, EXCP_RI);
26235 break;
26236 case OPC_MXU_D32ASUM:
26237 /* TODO: Implement emulation of D32ASUM instruction. */
26238 MIPS_INVAL("OPC_MXU_D32ASUM");
26239 generate_exception_end(ctx, EXCP_RI);
26240 break;
26241 default:
26242 MIPS_INVAL("decode_opc_mxu");
26243 generate_exception_end(ctx, EXCP_RI);
26244 break;
26245 }
26246}
26247
26248/*
26249 *
26250 * Decode MXU pool13
26251 *
26252 * 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
26253 * +-----------+---+---+-------+-------+-------+-------+-----------+
26254 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26255 * +-----------+---+---+-------+-------+-------+-------+-----------+
26256 *
26257 */
26258static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26259{
26260 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26261
26262 switch (opcode) {
26263 case OPC_MXU_Q16ACC:
26264 /* TODO: Implement emulation of Q16ACC instruction. */
26265 MIPS_INVAL("OPC_MXU_Q16ACC");
26266 generate_exception_end(ctx, EXCP_RI);
26267 break;
26268 case OPC_MXU_Q16ACCM:
26269 /* TODO: Implement emulation of Q16ACCM instruction. */
26270 MIPS_INVAL("OPC_MXU_Q16ACCM");
26271 generate_exception_end(ctx, EXCP_RI);
26272 break;
26273 case OPC_MXU_Q16ASUM:
26274 /* TODO: Implement emulation of Q16ASUM instruction. */
26275 MIPS_INVAL("OPC_MXU_Q16ASUM");
26276 generate_exception_end(ctx, EXCP_RI);
26277 break;
26278 default:
26279 MIPS_INVAL("decode_opc_mxu");
26280 generate_exception_end(ctx, EXCP_RI);
26281 break;
26282 }
26283}
26284
26285/*
26286 *
26287 * Decode MXU pool14
26288 *
26289 * Q8ADDE, Q8ACCE:
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 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26293 * +-----------+---+---+-------+-------+-------+-------+-----------+
26294 *
26295 * D8SUM, D8SUMC:
26296 * 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
26297 * +-----------+---+---+-------+-------+-------+-------+-----------+
26298 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26299 * +-----------+---+---+-------+-------+-------+-------+-----------+
26300 *
26301 */
26302static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26303{
26304 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26305
26306 switch (opcode) {
26307 case OPC_MXU_Q8ADDE:
26308 /* TODO: Implement emulation of Q8ADDE instruction. */
26309 MIPS_INVAL("OPC_MXU_Q8ADDE");
26310 generate_exception_end(ctx, EXCP_RI);
26311 break;
26312 case OPC_MXU_D8SUM:
26313 /* TODO: Implement emulation of D8SUM instruction. */
26314 MIPS_INVAL("OPC_MXU_D8SUM");
26315 generate_exception_end(ctx, EXCP_RI);
26316 break;
26317 case OPC_MXU_D8SUMC:
26318 /* TODO: Implement emulation of D8SUMC instruction. */
26319 MIPS_INVAL("OPC_MXU_D8SUMC");
26320 generate_exception_end(ctx, EXCP_RI);
26321 break;
26322 default:
26323 MIPS_INVAL("decode_opc_mxu");
26324 generate_exception_end(ctx, EXCP_RI);
26325 break;
26326 }
26327}
26328
26329/*
26330 *
26331 * Decode MXU pool15
26332 *
26333 * S32MUL, S32MULU, S32EXTRV:
26334 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26335 * +-----------+---------+---------+---+-------+-------+-----------+
26336 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26337 * +-----------+---------+---------+---+-------+-------+-----------+
26338 *
26339 * S32EXTR:
26340 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26341 * +-----------+---------+---------+---+-------+-------+-----------+
26342 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26343 * +-----------+---------+---------+---+-------+-------+-----------+
26344 *
26345 */
26346static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26347{
26348 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26349
26350 switch (opcode) {
26351 case OPC_MXU_S32MUL:
26352 /* TODO: Implement emulation of S32MUL instruction. */
26353 MIPS_INVAL("OPC_MXU_S32MUL");
26354 generate_exception_end(ctx, EXCP_RI);
26355 break;
26356 case OPC_MXU_S32MULU:
26357 /* TODO: Implement emulation of S32MULU instruction. */
26358 MIPS_INVAL("OPC_MXU_S32MULU");
26359 generate_exception_end(ctx, EXCP_RI);
26360 break;
26361 case OPC_MXU_S32EXTR:
26362 /* TODO: Implement emulation of S32EXTR instruction. */
26363 MIPS_INVAL("OPC_MXU_S32EXTR");
26364 generate_exception_end(ctx, EXCP_RI);
26365 break;
26366 case OPC_MXU_S32EXTRV:
26367 /* TODO: Implement emulation of S32EXTRV instruction. */
26368 MIPS_INVAL("OPC_MXU_S32EXTRV");
26369 generate_exception_end(ctx, EXCP_RI);
26370 break;
26371 default:
26372 MIPS_INVAL("decode_opc_mxu");
26373 generate_exception_end(ctx, EXCP_RI);
26374 break;
26375 }
26376}
26377
26378/*
26379 *
26380 * Decode MXU pool16
26381 *
26382 * D32SARW:
26383 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26384 * +-----------+---------+-----+-------+-------+-------+-----------+
26385 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26386 * +-----------+---------+-----+-------+-------+-------+-----------+
26387 *
26388 * S32ALN:
26389 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26390 * +-----------+---------+-----+-------+-------+-------+-----------+
26391 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26392 * +-----------+---------+-----+-------+-------+-------+-----------+
26393 *
26394 * S32ALNI:
26395 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26396 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26397 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26398 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26399 *
03f40088
AM
26400 * S32LUI:
26401 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26402 * +-----------+-----+---+-----+-------+---------------+-----------+
26403 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26404 * +-----------+-----+---+-----+-------+---------------+-----------+
26405 *
b621f018
AM
26406 * S32NOR, S32AND, S32OR, S32XOR:
26407 * 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
26408 * +-----------+---------+-----+-------+-------+-------+-----------+
26409 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26410 * +-----------+---------+-----+-------+-------+-------+-----------+
26411 *
03f40088
AM
26412 */
26413static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26414{
26415 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26416
26417 switch (opcode) {
26418 case OPC_MXU_D32SARW:
26419 /* TODO: Implement emulation of D32SARW instruction. */
26420 MIPS_INVAL("OPC_MXU_D32SARW");
26421 generate_exception_end(ctx, EXCP_RI);
26422 break;
26423 case OPC_MXU_S32ALN:
26424 /* TODO: Implement emulation of S32ALN instruction. */
26425 MIPS_INVAL("OPC_MXU_S32ALN");
26426 generate_exception_end(ctx, EXCP_RI);
26427 break;
26428 case OPC_MXU_S32ALNI:
79f5fee7 26429 gen_mxu_S32ALNI(ctx);
03f40088 26430 break;
b621f018
AM
26431 case OPC_MXU_S32LUI:
26432 /* TODO: Implement emulation of S32LUI instruction. */
26433 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
26434 generate_exception_end(ctx, EXCP_RI);
26435 break;
b621f018
AM
26436 case OPC_MXU_S32NOR:
26437 gen_mxu_S32NOR(ctx);
26438 break;
03f40088 26439 case OPC_MXU_S32AND:
b621f018 26440 gen_mxu_S32AND(ctx);
03f40088
AM
26441 break;
26442 case OPC_MXU_S32OR:
b621f018 26443 gen_mxu_S32OR(ctx);
03f40088
AM
26444 break;
26445 case OPC_MXU_S32XOR:
b621f018 26446 gen_mxu_S32XOR(ctx);
03f40088
AM
26447 break;
26448 default:
26449 MIPS_INVAL("decode_opc_mxu");
26450 generate_exception_end(ctx, EXCP_RI);
26451 break;
26452 }
26453}
26454
26455/*
26456 *
26457 * Decode MXU pool17
26458 *
26459 * 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
26460 * +-----------+---------+---------+---+---------+-----+-----------+
26461 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26462 * +-----------+---------+---------+---+---------+-----+-----------+
26463 *
26464 */
26465static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26466{
26467 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26468
26469 switch (opcode) {
26470 case OPC_MXU_LXW:
26471 /* TODO: Implement emulation of LXW instruction. */
26472 MIPS_INVAL("OPC_MXU_LXW");
26473 generate_exception_end(ctx, EXCP_RI);
26474 break;
26475 case OPC_MXU_LXH:
26476 /* TODO: Implement emulation of LXH instruction. */
26477 MIPS_INVAL("OPC_MXU_LXH");
26478 generate_exception_end(ctx, EXCP_RI);
26479 break;
26480 case OPC_MXU_LXHU:
26481 /* TODO: Implement emulation of LXHU instruction. */
26482 MIPS_INVAL("OPC_MXU_LXHU");
26483 generate_exception_end(ctx, EXCP_RI);
26484 break;
26485 case OPC_MXU_LXB:
26486 /* TODO: Implement emulation of LXB instruction. */
26487 MIPS_INVAL("OPC_MXU_LXB");
26488 generate_exception_end(ctx, EXCP_RI);
26489 break;
26490 case OPC_MXU_LXBU:
26491 /* TODO: Implement emulation of LXBU instruction. */
26492 MIPS_INVAL("OPC_MXU_LXBU");
26493 generate_exception_end(ctx, EXCP_RI);
26494 break;
26495 default:
26496 MIPS_INVAL("decode_opc_mxu");
26497 generate_exception_end(ctx, EXCP_RI);
26498 break;
26499 }
26500}
26501/*
26502 *
26503 * Decode MXU pool18
26504 *
26505 * 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 26506 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26507 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
26508 * +-----------+---------+-----+-------+-------+-------+-----------+
26509 *
26510 */
c233bf07 26511static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26512{
26513 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26514
26515 switch (opcode) {
26516 case OPC_MXU_D32SLLV:
26517 /* TODO: Implement emulation of D32SLLV instruction. */
26518 MIPS_INVAL("OPC_MXU_D32SLLV");
26519 generate_exception_end(ctx, EXCP_RI);
26520 break;
26521 case OPC_MXU_D32SLRV:
26522 /* TODO: Implement emulation of D32SLRV instruction. */
26523 MIPS_INVAL("OPC_MXU_D32SLRV");
26524 generate_exception_end(ctx, EXCP_RI);
26525 break;
26526 case OPC_MXU_D32SARV:
26527 /* TODO: Implement emulation of D32SARV instruction. */
26528 MIPS_INVAL("OPC_MXU_D32SARV");
26529 generate_exception_end(ctx, EXCP_RI);
26530 break;
26531 case OPC_MXU_Q16SLLV:
26532 /* TODO: Implement emulation of Q16SLLV instruction. */
26533 MIPS_INVAL("OPC_MXU_Q16SLLV");
26534 generate_exception_end(ctx, EXCP_RI);
26535 break;
26536 case OPC_MXU_Q16SLRV:
26537 /* TODO: Implement emulation of Q16SLRV instruction. */
26538 MIPS_INVAL("OPC_MXU_Q16SLRV");
26539 generate_exception_end(ctx, EXCP_RI);
26540 break;
26541 case OPC_MXU_Q16SARV:
26542 /* TODO: Implement emulation of Q16SARV instruction. */
26543 MIPS_INVAL("OPC_MXU_Q16SARV");
26544 generate_exception_end(ctx, EXCP_RI);
26545 break;
26546 default:
26547 MIPS_INVAL("decode_opc_mxu");
26548 generate_exception_end(ctx, EXCP_RI);
26549 break;
26550 }
26551}
26552
26553/*
26554 *
c233bf07 26555 * Decode MXU pool19
03f40088
AM
26556 *
26557 * 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
26558 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26559 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
26560 * +-----------+---+---+-------+-------+-------+-------+-----------+
26561 *
26562 */
c233bf07 26563static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26564{
26565 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26566
26567 switch (opcode) {
26568 case OPC_MXU_Q8MUL:
03f40088 26569 case OPC_MXU_Q8MULSU:
a9a4181b 26570 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
26571 break;
26572 default:
26573 MIPS_INVAL("decode_opc_mxu");
26574 generate_exception_end(ctx, EXCP_RI);
26575 break;
26576 }
26577}
26578
26579/*
26580 *
c233bf07 26581 * Decode MXU pool20
03f40088
AM
26582 *
26583 * 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
26584 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26585 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
26586 * +-----------+---------+-----+-------+-------+-------+-----------+
26587 *
26588 */
c233bf07 26589static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26590{
26591 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26592
26593 switch (opcode) {
26594 case OPC_MXU_Q8MOVZ:
26595 /* TODO: Implement emulation of Q8MOVZ instruction. */
26596 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26597 generate_exception_end(ctx, EXCP_RI);
26598 break;
26599 case OPC_MXU_Q8MOVN:
26600 /* TODO: Implement emulation of Q8MOVN instruction. */
26601 MIPS_INVAL("OPC_MXU_Q8MOVN");
26602 generate_exception_end(ctx, EXCP_RI);
26603 break;
26604 case OPC_MXU_D16MOVZ:
26605 /* TODO: Implement emulation of D16MOVZ instruction. */
26606 MIPS_INVAL("OPC_MXU_D16MOVZ");
26607 generate_exception_end(ctx, EXCP_RI);
26608 break;
26609 case OPC_MXU_D16MOVN:
26610 /* TODO: Implement emulation of D16MOVN instruction. */
26611 MIPS_INVAL("OPC_MXU_D16MOVN");
26612 generate_exception_end(ctx, EXCP_RI);
26613 break;
26614 case OPC_MXU_S32MOVZ:
26615 /* TODO: Implement emulation of S32MOVZ instruction. */
26616 MIPS_INVAL("OPC_MXU_S32MOVZ");
26617 generate_exception_end(ctx, EXCP_RI);
26618 break;
26619 case OPC_MXU_S32MOVN:
26620 /* TODO: Implement emulation of S32MOVN instruction. */
26621 MIPS_INVAL("OPC_MXU_S32MOVN");
26622 generate_exception_end(ctx, EXCP_RI);
26623 break;
26624 default:
26625 MIPS_INVAL("decode_opc_mxu");
26626 generate_exception_end(ctx, EXCP_RI);
26627 break;
26628 }
26629}
26630
26631/*
26632 *
c233bf07 26633 * Decode MXU pool21
03f40088
AM
26634 *
26635 * 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
26636 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26637 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
26638 * +-----------+---+---+-------+-------+-------+-------+-----------+
26639 *
26640 */
c233bf07 26641static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26642{
26643 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26644
26645 switch (opcode) {
26646 case OPC_MXU_Q8MAC:
26647 /* TODO: Implement emulation of Q8MAC instruction. */
26648 MIPS_INVAL("OPC_MXU_Q8MAC");
26649 generate_exception_end(ctx, EXCP_RI);
26650 break;
26651 case OPC_MXU_Q8MACSU:
26652 /* TODO: Implement emulation of Q8MACSU instruction. */
26653 MIPS_INVAL("OPC_MXU_Q8MACSU");
26654 generate_exception_end(ctx, EXCP_RI);
26655 break;
26656 default:
26657 MIPS_INVAL("decode_opc_mxu");
26658 generate_exception_end(ctx, EXCP_RI);
26659 break;
26660 }
26661}
26662
26663
26664/*
26665 * Main MXU decoding function
26666 *
26667 * 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
26668 * +-----------+---------------------------------------+-----------+
26669 * | SPECIAL2 | |x x x x x x|
26670 * +-----------+---------------------------------------+-----------+
26671 *
26672 */
0a348b9a
AM
26673static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26674{
11d56f61
CJ
26675 /*
26676 * TODO: Investigate necessity of including handling of
26677 * CLZ, CLO, SDBB in this function, as they belong to
26678 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26679 */
03f40088
AM
26680 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26681
87860df5
AM
26682 if (opcode == OPC__MXU_MUL) {
26683 uint32_t rs, rt, rd, op1;
26684
26685 rs = extract32(ctx->opcode, 21, 5);
26686 rt = extract32(ctx->opcode, 16, 5);
26687 rd = extract32(ctx->opcode, 11, 5);
26688 op1 = MASK_SPECIAL2(ctx->opcode);
26689
26690 gen_arith(ctx, op1, rd, rs, rt);
26691
26692 return;
26693 }
26694
26695 if (opcode == OPC_MXU_S32M2I) {
26696 gen_mxu_s32m2i(ctx);
26697 return;
26698 }
26699
26700 if (opcode == OPC_MXU_S32I2M) {
26701 gen_mxu_s32i2m(ctx);
26702 return;
26703 }
26704
e5bf8a08
AM
26705 {
26706 TCGv t_mxu_cr = tcg_temp_new();
26707 TCGLabel *l_exit = gen_new_label();
26708
26709 gen_load_mxu_cr(t_mxu_cr);
26710 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26711 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26712
26713 switch (opcode) {
26714 case OPC_MXU_S32MADD:
26715 /* TODO: Implement emulation of S32MADD instruction. */
26716 MIPS_INVAL("OPC_MXU_S32MADD");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_S32MADDU:
26720 /* TODO: Implement emulation of S32MADDU instruction. */
26721 MIPS_INVAL("OPC_MXU_S32MADDU");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 case OPC_MXU__POOL00:
26725 decode_opc_mxu__pool00(env, ctx);
26726 break;
26727 case OPC_MXU_S32MSUB:
26728 /* TODO: Implement emulation of S32MSUB instruction. */
26729 MIPS_INVAL("OPC_MXU_S32MSUB");
26730 generate_exception_end(ctx, EXCP_RI);
26731 break;
26732 case OPC_MXU_S32MSUBU:
26733 /* TODO: Implement emulation of S32MSUBU instruction. */
26734 MIPS_INVAL("OPC_MXU_S32MSUBU");
26735 generate_exception_end(ctx, EXCP_RI);
26736 break;
26737 case OPC_MXU__POOL01:
26738 decode_opc_mxu__pool01(env, ctx);
26739 break;
26740 case OPC_MXU__POOL02:
26741 decode_opc_mxu__pool02(env, ctx);
26742 break;
26743 case OPC_MXU_D16MUL:
26744 gen_mxu_d16mul(ctx);
26745 break;
26746 case OPC_MXU__POOL03:
26747 decode_opc_mxu__pool03(env, ctx);
26748 break;
26749 case OPC_MXU_D16MAC:
26750 gen_mxu_d16mac(ctx);
26751 break;
26752 case OPC_MXU_D16MACF:
26753 /* TODO: Implement emulation of D16MACF instruction. */
26754 MIPS_INVAL("OPC_MXU_D16MACF");
26755 generate_exception_end(ctx, EXCP_RI);
26756 break;
26757 case OPC_MXU_D16MADL:
26758 /* TODO: Implement emulation of D16MADL instruction. */
26759 MIPS_INVAL("OPC_MXU_D16MADL");
26760 generate_exception_end(ctx, EXCP_RI);
26761 break;
26762 case OPC_MXU_S16MAD:
26763 /* TODO: Implement emulation of S16MAD instruction. */
26764 MIPS_INVAL("OPC_MXU_S16MAD");
26765 generate_exception_end(ctx, EXCP_RI);
26766 break;
26767 case OPC_MXU_Q16ADD:
26768 /* TODO: Implement emulation of Q16ADD instruction. */
26769 MIPS_INVAL("OPC_MXU_Q16ADD");
26770 generate_exception_end(ctx, EXCP_RI);
26771 break;
26772 case OPC_MXU_D16MACE:
26773 /* TODO: Implement emulation of D16MACE instruction. */
26774 MIPS_INVAL("OPC_MXU_D16MACE");
26775 generate_exception_end(ctx, EXCP_RI);
26776 break;
26777 case OPC_MXU__POOL04:
26778 decode_opc_mxu__pool04(env, ctx);
26779 break;
26780 case OPC_MXU__POOL05:
26781 decode_opc_mxu__pool05(env, ctx);
26782 break;
26783 case OPC_MXU__POOL06:
26784 decode_opc_mxu__pool06(env, ctx);
26785 break;
26786 case OPC_MXU__POOL07:
26787 decode_opc_mxu__pool07(env, ctx);
26788 break;
26789 case OPC_MXU__POOL08:
26790 decode_opc_mxu__pool08(env, ctx);
26791 break;
26792 case OPC_MXU__POOL09:
26793 decode_opc_mxu__pool09(env, ctx);
26794 break;
26795 case OPC_MXU__POOL10:
26796 decode_opc_mxu__pool10(env, ctx);
26797 break;
26798 case OPC_MXU__POOL11:
26799 decode_opc_mxu__pool11(env, ctx);
26800 break;
26801 case OPC_MXU_D32ADD:
26802 /* TODO: Implement emulation of D32ADD instruction. */
26803 MIPS_INVAL("OPC_MXU_D32ADD");
26804 generate_exception_end(ctx, EXCP_RI);
26805 break;
26806 case OPC_MXU__POOL12:
26807 decode_opc_mxu__pool12(env, ctx);
26808 break;
26809 case OPC_MXU__POOL13:
26810 decode_opc_mxu__pool13(env, ctx);
26811 break;
26812 case OPC_MXU__POOL14:
26813 decode_opc_mxu__pool14(env, ctx);
26814 break;
26815 case OPC_MXU_Q8ACCE:
26816 /* TODO: Implement emulation of Q8ACCE instruction. */
26817 MIPS_INVAL("OPC_MXU_Q8ACCE");
26818 generate_exception_end(ctx, EXCP_RI);
26819 break;
26820 case OPC_MXU_S8LDD:
26821 gen_mxu_s8ldd(ctx);
26822 break;
26823 case OPC_MXU_S8STD:
26824 /* TODO: Implement emulation of S8STD instruction. */
26825 MIPS_INVAL("OPC_MXU_S8STD");
26826 generate_exception_end(ctx, EXCP_RI);
26827 break;
26828 case OPC_MXU_S8LDI:
26829 /* TODO: Implement emulation of S8LDI instruction. */
26830 MIPS_INVAL("OPC_MXU_S8LDI");
26831 generate_exception_end(ctx, EXCP_RI);
26832 break;
26833 case OPC_MXU_S8SDI:
26834 /* TODO: Implement emulation of S8SDI instruction. */
26835 MIPS_INVAL("OPC_MXU_S8SDI");
26836 generate_exception_end(ctx, EXCP_RI);
26837 break;
26838 case OPC_MXU__POOL15:
26839 decode_opc_mxu__pool15(env, ctx);
26840 break;
26841 case OPC_MXU__POOL16:
26842 decode_opc_mxu__pool16(env, ctx);
26843 break;
c233bf07
AM
26844 case OPC_MXU__POOL17:
26845 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
26846 break;
26847 case OPC_MXU_S16LDD:
26848 /* TODO: Implement emulation of S16LDD instruction. */
26849 MIPS_INVAL("OPC_MXU_S16LDD");
26850 generate_exception_end(ctx, EXCP_RI);
26851 break;
26852 case OPC_MXU_S16STD:
26853 /* TODO: Implement emulation of S16STD instruction. */
26854 MIPS_INVAL("OPC_MXU_S16STD");
26855 generate_exception_end(ctx, EXCP_RI);
26856 break;
26857 case OPC_MXU_S16LDI:
26858 /* TODO: Implement emulation of S16LDI instruction. */
26859 MIPS_INVAL("OPC_MXU_S16LDI");
26860 generate_exception_end(ctx, EXCP_RI);
26861 break;
26862 case OPC_MXU_S16SDI:
26863 /* TODO: Implement emulation of S16SDI instruction. */
26864 MIPS_INVAL("OPC_MXU_S16SDI");
26865 generate_exception_end(ctx, EXCP_RI);
26866 break;
26867 case OPC_MXU_D32SLL:
26868 /* TODO: Implement emulation of D32SLL instruction. */
26869 MIPS_INVAL("OPC_MXU_D32SLL");
26870 generate_exception_end(ctx, EXCP_RI);
26871 break;
26872 case OPC_MXU_D32SLR:
26873 /* TODO: Implement emulation of D32SLR instruction. */
26874 MIPS_INVAL("OPC_MXU_D32SLR");
26875 generate_exception_end(ctx, EXCP_RI);
26876 break;
26877 case OPC_MXU_D32SARL:
26878 /* TODO: Implement emulation of D32SARL instruction. */
26879 MIPS_INVAL("OPC_MXU_D32SARL");
26880 generate_exception_end(ctx, EXCP_RI);
26881 break;
26882 case OPC_MXU_D32SAR:
26883 /* TODO: Implement emulation of D32SAR instruction. */
26884 MIPS_INVAL("OPC_MXU_D32SAR");
26885 generate_exception_end(ctx, EXCP_RI);
26886 break;
26887 case OPC_MXU_Q16SLL:
26888 /* TODO: Implement emulation of Q16SLL instruction. */
26889 MIPS_INVAL("OPC_MXU_Q16SLL");
26890 generate_exception_end(ctx, EXCP_RI);
26891 break;
26892 case OPC_MXU_Q16SLR:
26893 /* TODO: Implement emulation of Q16SLR instruction. */
26894 MIPS_INVAL("OPC_MXU_Q16SLR");
26895 generate_exception_end(ctx, EXCP_RI);
26896 break;
c233bf07
AM
26897 case OPC_MXU__POOL18:
26898 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
26899 break;
26900 case OPC_MXU_Q16SAR:
26901 /* TODO: Implement emulation of Q16SAR instruction. */
26902 MIPS_INVAL("OPC_MXU_Q16SAR");
26903 generate_exception_end(ctx, EXCP_RI);
26904 break;
e5bf8a08
AM
26905 case OPC_MXU__POOL19:
26906 decode_opc_mxu__pool19(env, ctx);
26907 break;
26908 case OPC_MXU__POOL20:
26909 decode_opc_mxu__pool20(env, ctx);
26910 break;
c233bf07
AM
26911 case OPC_MXU__POOL21:
26912 decode_opc_mxu__pool21(env, ctx);
26913 break;
e5bf8a08
AM
26914 case OPC_MXU_Q16SCOP:
26915 /* TODO: Implement emulation of Q16SCOP instruction. */
26916 MIPS_INVAL("OPC_MXU_Q16SCOP");
26917 generate_exception_end(ctx, EXCP_RI);
26918 break;
26919 case OPC_MXU_Q8MADL:
26920 /* TODO: Implement emulation of Q8MADL instruction. */
26921 MIPS_INVAL("OPC_MXU_Q8MADL");
26922 generate_exception_end(ctx, EXCP_RI);
26923 break;
26924 case OPC_MXU_S32SFL:
26925 /* TODO: Implement emulation of S32SFL instruction. */
26926 MIPS_INVAL("OPC_MXU_S32SFL");
26927 generate_exception_end(ctx, EXCP_RI);
26928 break;
26929 case OPC_MXU_Q8SAD:
26930 /* TODO: Implement emulation of Q8SAD instruction. */
26931 MIPS_INVAL("OPC_MXU_Q8SAD");
26932 generate_exception_end(ctx, EXCP_RI);
26933 break;
26934 default:
26935 MIPS_INVAL("decode_opc_mxu");
26936 generate_exception_end(ctx, EXCP_RI);
26937 }
26938
26939 gen_set_label(l_exit);
26940 tcg_temp_free(t_mxu_cr);
03f40088 26941 }
0a348b9a
AM
26942}
26943
b621f018
AM
26944#endif /* !defined(TARGET_MIPS64) */
26945
03f40088 26946
10dc65db 26947static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
26948{
26949 int rs, rt, rd;
26950 uint32_t op1;
6c5c1e20 26951
4267d3e6
LA
26952 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26953
099e5b4d
LA
26954 rs = (ctx->opcode >> 21) & 0x1f;
26955 rt = (ctx->opcode >> 16) & 0x1f;
26956 rd = (ctx->opcode >> 11) & 0x1f;
26957
26958 op1 = MASK_SPECIAL2(ctx->opcode);
26959 switch (op1) {
c2e19f3c
AM
26960 case OPC_MADD: /* Multiply and add/sub */
26961 case OPC_MADDU:
26962 case OPC_MSUB:
26963 case OPC_MSUBU:
099e5b4d
LA
26964 check_insn(ctx, ISA_MIPS32);
26965 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26966 break;
26967 case OPC_MUL:
099e5b4d
LA
26968 gen_arith(ctx, op1, rd, rs, rt);
26969 break;
fac5a073
LA
26970 case OPC_DIV_G_2F:
26971 case OPC_DIVU_G_2F:
26972 case OPC_MULT_G_2F:
26973 case OPC_MULTU_G_2F:
26974 case OPC_MOD_G_2F:
26975 case OPC_MODU_G_2F:
26976 check_insn(ctx, INSN_LOONGSON2F);
26977 gen_loongson_integer(ctx, op1, rd, rs, rt);
26978 break;
099e5b4d
LA
26979 case OPC_CLO:
26980 case OPC_CLZ:
26981 check_insn(ctx, ISA_MIPS32);
26982 gen_cl(ctx, op1, rd, rs);
26983 break;
26984 case OPC_SDBBP:
3b3c1694
LA
26985 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26986 gen_helper_do_semihosting(cpu_env);
26987 } else {
7480515f
AM
26988 /*
26989 * XXX: not clear which exception should be raised
3b3c1694
LA
26990 * when in debug mode...
26991 */
26992 check_insn(ctx, ISA_MIPS32);
9c708c7f 26993 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 26994 }
099e5b4d 26995 break;
9b1a1d68 26996#if defined(TARGET_MIPS64)
099e5b4d
LA
26997 case OPC_DCLO:
26998 case OPC_DCLZ:
26999 check_insn(ctx, ISA_MIPS64);
27000 check_mips_64(ctx);
27001 gen_cl(ctx, op1, rd, rs);
27002 break;
4267d3e6
LA
27003 case OPC_DMULT_G_2F:
27004 case OPC_DMULTU_G_2F:
27005 case OPC_DDIV_G_2F:
27006 case OPC_DDIVU_G_2F:
27007 case OPC_DMOD_G_2F:
27008 case OPC_DMODU_G_2F:
27009 check_insn(ctx, INSN_LOONGSON2F);
27010 gen_loongson_integer(ctx, op1, rd, rs, rt);
27011 break;
10dc65db 27012#endif
4267d3e6
LA
27013 default: /* Invalid */
27014 MIPS_INVAL("special2_legacy");
9c708c7f 27015 generate_exception_end(ctx, EXCP_RI);
4267d3e6 27016 break;
10dc65db
LA
27017 }
27018}
27019
27020static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27021{
15eacb9b
YK
27022 int rs, rt, rd, sa;
27023 uint32_t op1, op2;
10dc65db
LA
27024 int16_t imm;
27025
27026 rs = (ctx->opcode >> 21) & 0x1f;
27027 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
27028 rd = (ctx->opcode >> 11) & 0x1f;
27029 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
27030 imm = (int16_t)ctx->opcode >> 7;
27031
27032 op1 = MASK_SPECIAL3(ctx->opcode);
27033 switch (op1) {
bf7910c6
LA
27034 case R6_OPC_PREF:
27035 if (rt >= 24) {
27036 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 27037 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
27038 }
27039 /* Treat as NOP. */
27040 break;
27041 case R6_OPC_CACHE:
40d48212 27042 check_cp0_enabled(ctx);
0d74a222
LA
27043 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27044 gen_cache_operation(ctx, rt, rs, imm);
27045 }
bf7910c6 27046 break;
10dc65db 27047 case R6_OPC_SC:
33a07fa2 27048 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
27049 break;
27050 case R6_OPC_LL:
27051 gen_ld(ctx, op1, rt, rs, imm);
27052 break;
15eacb9b
YK
27053 case OPC_BSHFL:
27054 {
27055 if (rd == 0) {
27056 /* Treat as NOP. */
27057 break;
27058 }
15eacb9b
YK
27059 op2 = MASK_BSHFL(ctx->opcode);
27060 switch (op2) {
c2e19f3c 27061 case OPC_ALIGN:
373ecd38
AM
27062 case OPC_ALIGN_1:
27063 case OPC_ALIGN_2:
27064 case OPC_ALIGN_3:
821f2008 27065 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
27066 break;
27067 case OPC_BITSWAP:
1f1b4c00 27068 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27069 break;
27070 }
15eacb9b
YK
27071 }
27072 break;
bf7910c6
LA
27073#if defined(TARGET_MIPS64)
27074 case R6_OPC_SCD:
33a07fa2 27075 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
27076 break;
27077 case R6_OPC_LLD:
27078 gen_ld(ctx, op1, rt, rs, imm);
27079 break;
15eacb9b
YK
27080 case OPC_DBSHFL:
27081 check_mips_64(ctx);
27082 {
27083 if (rd == 0) {
27084 /* Treat as NOP. */
27085 break;
27086 }
15eacb9b
YK
27087 op2 = MASK_DBSHFL(ctx->opcode);
27088 switch (op2) {
c2e19f3c 27089 case OPC_DALIGN:
373ecd38
AM
27090 case OPC_DALIGN_1:
27091 case OPC_DALIGN_2:
27092 case OPC_DALIGN_3:
27093 case OPC_DALIGN_4:
27094 case OPC_DALIGN_5:
27095 case OPC_DALIGN_6:
27096 case OPC_DALIGN_7:
821f2008 27097 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
27098 break;
27099 case OPC_DBITSWAP:
1f1b4c00 27100 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27101 break;
27102 }
1f1b4c00 27103
15eacb9b
YK
27104 }
27105 break;
bf7910c6 27106#endif
10dc65db
LA
27107 default: /* Invalid */
27108 MIPS_INVAL("special3_r6");
9c708c7f 27109 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
27110 break;
27111 }
27112}
27113
27114static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27115{
fac5a073 27116 int rs, rt, rd;
099e5b4d 27117 uint32_t op1, op2;
099e5b4d
LA
27118
27119 rs = (ctx->opcode >> 21) & 0x1f;
27120 rt = (ctx->opcode >> 16) & 0x1f;
27121 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
27122
27123 op1 = MASK_SPECIAL3(ctx->opcode);
27124 switch (op1) {
c2e19f3c
AM
27125 case OPC_DIV_G_2E:
27126 case OPC_DIVU_G_2E:
27127 case OPC_MOD_G_2E:
27128 case OPC_MODU_G_2E:
27129 case OPC_MULT_G_2E:
27130 case OPC_MULTU_G_2E:
7480515f
AM
27131 /*
27132 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27133 * the same mask and op1.
27134 */
908f6be1 27135 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 27136 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 27137 switch (op2) {
099e5b4d
LA
27138 case OPC_ADDUH_QB:
27139 case OPC_ADDUH_R_QB:
27140 case OPC_ADDQH_PH:
27141 case OPC_ADDQH_R_PH:
27142 case OPC_ADDQH_W:
27143 case OPC_ADDQH_R_W:
27144 case OPC_SUBUH_QB:
27145 case OPC_SUBUH_R_QB:
27146 case OPC_SUBQH_PH:
27147 case OPC_SUBQH_R_PH:
27148 case OPC_SUBQH_W:
27149 case OPC_SUBQH_R_W:
461c08df
JL
27150 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27151 break;
099e5b4d
LA
27152 case OPC_MUL_PH:
27153 case OPC_MUL_S_PH:
27154 case OPC_MULQ_S_W:
27155 case OPC_MULQ_RS_W:
27156 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27157 break;
461c08df 27158 default:
099e5b4d 27159 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 27160 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
27161 break;
27162 }
099e5b4d
LA
27163 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27164 gen_loongson_integer(ctx, op1, rd, rs, rt);
27165 } else {
9c708c7f 27166 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27167 }
27168 break;
27169 case OPC_LX_DSP:
27170 op2 = MASK_LX(ctx->opcode);
27171 switch (op2) {
27172#if defined(TARGET_MIPS64)
27173 case OPC_LDX:
27174#endif
27175 case OPC_LBUX:
27176 case OPC_LHX:
27177 case OPC_LWX:
27178 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27179 break;
27180 default: /* Invalid */
27181 MIPS_INVAL("MASK LX");
9c708c7f 27182 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27183 break;
27184 }
27185 break;
27186 case OPC_ABSQ_S_PH_DSP:
27187 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27188 switch (op2) {
27189 case OPC_ABSQ_S_QB:
27190 case OPC_ABSQ_S_PH:
27191 case OPC_ABSQ_S_W:
27192 case OPC_PRECEQ_W_PHL:
27193 case OPC_PRECEQ_W_PHR:
27194 case OPC_PRECEQU_PH_QBL:
27195 case OPC_PRECEQU_PH_QBR:
27196 case OPC_PRECEQU_PH_QBLA:
27197 case OPC_PRECEQU_PH_QBRA:
27198 case OPC_PRECEU_PH_QBL:
27199 case OPC_PRECEU_PH_QBR:
27200 case OPC_PRECEU_PH_QBLA:
27201 case OPC_PRECEU_PH_QBRA:
27202 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27203 break;
27204 case OPC_BITREV:
27205 case OPC_REPL_QB:
27206 case OPC_REPLV_QB:
27207 case OPC_REPL_PH:
27208 case OPC_REPLV_PH:
27209 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27210 break;
27211 default:
27212 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 27213 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27214 break;
27215 }
27216 break;
27217 case OPC_ADDU_QB_DSP:
27218 op2 = MASK_ADDU_QB(ctx->opcode);
27219 switch (op2) {
27220 case OPC_ADDQ_PH:
27221 case OPC_ADDQ_S_PH:
27222 case OPC_ADDQ_S_W:
27223 case OPC_ADDU_QB:
27224 case OPC_ADDU_S_QB:
27225 case OPC_ADDU_PH:
27226 case OPC_ADDU_S_PH:
27227 case OPC_SUBQ_PH:
27228 case OPC_SUBQ_S_PH:
27229 case OPC_SUBQ_S_W:
27230 case OPC_SUBU_QB:
27231 case OPC_SUBU_S_QB:
27232 case OPC_SUBU_PH:
27233 case OPC_SUBU_S_PH:
27234 case OPC_ADDSC:
27235 case OPC_ADDWC:
27236 case OPC_MODSUB:
27237 case OPC_RADDU_W_QB:
27238 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27239 break;
27240 case OPC_MULEU_S_PH_QBL:
27241 case OPC_MULEU_S_PH_QBR:
27242 case OPC_MULQ_RS_PH:
27243 case OPC_MULEQ_S_W_PHL:
27244 case OPC_MULEQ_S_W_PHR:
27245 case OPC_MULQ_S_PH:
27246 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27247 break;
27248 default: /* Invalid */
27249 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 27250 generate_exception_end(ctx, EXCP_RI);
461c08df 27251 break;
461c08df 27252
099e5b4d
LA
27253 }
27254 break;
27255 case OPC_CMPU_EQ_QB_DSP:
27256 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27257 switch (op2) {
27258 case OPC_PRECR_SRA_PH_W:
27259 case OPC_PRECR_SRA_R_PH_W:
27260 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 27261 break;
099e5b4d
LA
27262 case OPC_PRECR_QB_PH:
27263 case OPC_PRECRQ_QB_PH:
27264 case OPC_PRECRQ_PH_W:
27265 case OPC_PRECRQ_RS_PH_W:
27266 case OPC_PRECRQU_S_QB_PH:
27267 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 27268 break;
099e5b4d
LA
27269 case OPC_CMPU_EQ_QB:
27270 case OPC_CMPU_LT_QB:
27271 case OPC_CMPU_LE_QB:
27272 case OPC_CMP_EQ_PH:
27273 case OPC_CMP_LT_PH:
27274 case OPC_CMP_LE_PH:
27275 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 27276 break;
099e5b4d
LA
27277 case OPC_CMPGU_EQ_QB:
27278 case OPC_CMPGU_LT_QB:
27279 case OPC_CMPGU_LE_QB:
27280 case OPC_CMPGDU_EQ_QB:
27281 case OPC_CMPGDU_LT_QB:
27282 case OPC_CMPGDU_LE_QB:
27283 case OPC_PICK_QB:
27284 case OPC_PICK_PH:
27285 case OPC_PACKRL_PH:
27286 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27287 break;
27288 default: /* Invalid */
27289 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 27290 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27291 break;
27292 }
27293 break;
27294 case OPC_SHLL_QB_DSP:
27295 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27296 break;
27297 case OPC_DPA_W_PH_DSP:
27298 op2 = MASK_DPA_W_PH(ctx->opcode);
27299 switch (op2) {
27300 case OPC_DPAU_H_QBL:
27301 case OPC_DPAU_H_QBR:
27302 case OPC_DPSU_H_QBL:
27303 case OPC_DPSU_H_QBR:
27304 case OPC_DPA_W_PH:
27305 case OPC_DPAX_W_PH:
27306 case OPC_DPAQ_S_W_PH:
27307 case OPC_DPAQX_S_W_PH:
27308 case OPC_DPAQX_SA_W_PH:
27309 case OPC_DPS_W_PH:
27310 case OPC_DPSX_W_PH:
27311 case OPC_DPSQ_S_W_PH:
27312 case OPC_DPSQX_S_W_PH:
27313 case OPC_DPSQX_SA_W_PH:
27314 case OPC_MULSAQ_S_W_PH:
27315 case OPC_DPAQ_SA_L_W:
27316 case OPC_DPSQ_SA_L_W:
27317 case OPC_MAQ_S_W_PHL:
27318 case OPC_MAQ_S_W_PHR:
27319 case OPC_MAQ_SA_W_PHL:
27320 case OPC_MAQ_SA_W_PHR:
27321 case OPC_MULSA_W_PH:
27322 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27323 break;
27324 default: /* Invalid */
27325 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 27326 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27327 break;
27328 }
27329 break;
27330 case OPC_INSV_DSP:
27331 op2 = MASK_INSV(ctx->opcode);
27332 switch (op2) {
27333 case OPC_INSV:
27334 check_dsp(ctx);
27335 {
27336 TCGv t0, t1;
27337
27338 if (rt == 0) {
099e5b4d
LA
27339 break;
27340 }
27341
27342 t0 = tcg_temp_new();
27343 t1 = tcg_temp_new();
27344
27345 gen_load_gpr(t0, rt);
27346 gen_load_gpr(t1, rs);
27347
27348 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27349
27350 tcg_temp_free(t0);
27351 tcg_temp_free(t1);
a22260ae
JL
27352 break;
27353 }
099e5b4d
LA
27354 default: /* Invalid */
27355 MIPS_INVAL("MASK INSV");
9c708c7f 27356 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27357 break;
27358 }
27359 break;
27360 case OPC_APPEND_DSP:
27361 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27362 break;
27363 case OPC_EXTR_W_DSP:
27364 op2 = MASK_EXTR_W(ctx->opcode);
27365 switch (op2) {
27366 case OPC_EXTR_W:
27367 case OPC_EXTR_R_W:
27368 case OPC_EXTR_RS_W:
27369 case OPC_EXTR_S_H:
27370 case OPC_EXTRV_S_H:
27371 case OPC_EXTRV_W:
27372 case OPC_EXTRV_R_W:
27373 case OPC_EXTRV_RS_W:
27374 case OPC_EXTP:
27375 case OPC_EXTPV:
27376 case OPC_EXTPDP:
27377 case OPC_EXTPDPV:
27378 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27379 break;
27380 case OPC_RDDSP:
27381 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27382 break;
27383 case OPC_SHILO:
27384 case OPC_SHILOV:
27385 case OPC_MTHLIP:
27386 case OPC_WRDSP:
27387 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27388 break;
27389 default: /* Invalid */
27390 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27391 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27392 break;
27393 }
27394 break;
099e5b4d 27395#if defined(TARGET_MIPS64)
c2e19f3c
AM
27396 case OPC_DDIV_G_2E:
27397 case OPC_DDIVU_G_2E:
27398 case OPC_DMULT_G_2E:
27399 case OPC_DMULTU_G_2E:
27400 case OPC_DMOD_G_2E:
27401 case OPC_DMODU_G_2E:
fac5a073
LA
27402 check_insn(ctx, INSN_LOONGSON2E);
27403 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 27404 break;
099e5b4d
LA
27405 case OPC_ABSQ_S_QH_DSP:
27406 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27407 switch (op2) {
27408 case OPC_PRECEQ_L_PWL:
27409 case OPC_PRECEQ_L_PWR:
27410 case OPC_PRECEQ_PW_QHL:
27411 case OPC_PRECEQ_PW_QHR:
27412 case OPC_PRECEQ_PW_QHLA:
27413 case OPC_PRECEQ_PW_QHRA:
27414 case OPC_PRECEQU_QH_OBL:
27415 case OPC_PRECEQU_QH_OBR:
27416 case OPC_PRECEQU_QH_OBLA:
27417 case OPC_PRECEQU_QH_OBRA:
27418 case OPC_PRECEU_QH_OBL:
27419 case OPC_PRECEU_QH_OBR:
27420 case OPC_PRECEU_QH_OBLA:
27421 case OPC_PRECEU_QH_OBRA:
27422 case OPC_ABSQ_S_OB:
27423 case OPC_ABSQ_S_PW:
27424 case OPC_ABSQ_S_QH:
27425 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27426 break;
27427 case OPC_REPL_OB:
27428 case OPC_REPL_PW:
27429 case OPC_REPL_QH:
27430 case OPC_REPLV_OB:
27431 case OPC_REPLV_PW:
27432 case OPC_REPLV_QH:
27433 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27434 break;
27435 default: /* Invalid */
27436 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 27437 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27438 break;
27439 }
27440 break;
27441 case OPC_ADDU_OB_DSP:
27442 op2 = MASK_ADDU_OB(ctx->opcode);
27443 switch (op2) {
27444 case OPC_RADDU_L_OB:
27445 case OPC_SUBQ_PW:
27446 case OPC_SUBQ_S_PW:
27447 case OPC_SUBQ_QH:
27448 case OPC_SUBQ_S_QH:
27449 case OPC_SUBU_OB:
27450 case OPC_SUBU_S_OB:
27451 case OPC_SUBU_QH:
27452 case OPC_SUBU_S_QH:
27453 case OPC_SUBUH_OB:
27454 case OPC_SUBUH_R_OB:
27455 case OPC_ADDQ_PW:
27456 case OPC_ADDQ_S_PW:
27457 case OPC_ADDQ_QH:
27458 case OPC_ADDQ_S_QH:
27459 case OPC_ADDU_OB:
27460 case OPC_ADDU_S_OB:
27461 case OPC_ADDU_QH:
27462 case OPC_ADDU_S_QH:
27463 case OPC_ADDUH_OB:
27464 case OPC_ADDUH_R_OB:
27465 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 27466 break;
099e5b4d
LA
27467 case OPC_MULEQ_S_PW_QHL:
27468 case OPC_MULEQ_S_PW_QHR:
27469 case OPC_MULEU_S_QH_OBL:
27470 case OPC_MULEU_S_QH_OBR:
27471 case OPC_MULQ_RS_QH:
27472 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27473 break;
099e5b4d
LA
27474 default: /* Invalid */
27475 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 27476 generate_exception_end(ctx, EXCP_RI);
26690560 27477 break;
099e5b4d
LA
27478 }
27479 break;
27480 case OPC_CMPU_EQ_OB_DSP:
27481 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27482 switch (op2) {
27483 case OPC_PRECR_SRA_QH_PW:
27484 case OPC_PRECR_SRA_R_QH_PW:
27485 /* Return value is rt. */
27486 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 27487 break;
099e5b4d
LA
27488 case OPC_PRECR_OB_QH:
27489 case OPC_PRECRQ_OB_QH:
27490 case OPC_PRECRQ_PW_L:
27491 case OPC_PRECRQ_QH_PW:
27492 case OPC_PRECRQ_RS_QH_PW:
27493 case OPC_PRECRQU_S_OB_QH:
27494 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 27495 break;
099e5b4d
LA
27496 case OPC_CMPU_EQ_OB:
27497 case OPC_CMPU_LT_OB:
27498 case OPC_CMPU_LE_OB:
27499 case OPC_CMP_EQ_QH:
27500 case OPC_CMP_LT_QH:
27501 case OPC_CMP_LE_QH:
27502 case OPC_CMP_EQ_PW:
27503 case OPC_CMP_LT_PW:
27504 case OPC_CMP_LE_PW:
27505 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 27506 break;
099e5b4d
LA
27507 case OPC_CMPGDU_EQ_OB:
27508 case OPC_CMPGDU_LT_OB:
27509 case OPC_CMPGDU_LE_OB:
27510 case OPC_CMPGU_EQ_OB:
27511 case OPC_CMPGU_LT_OB:
27512 case OPC_CMPGU_LE_OB:
27513 case OPC_PACKRL_PW:
27514 case OPC_PICK_OB:
27515 case OPC_PICK_PW:
27516 case OPC_PICK_QH:
27517 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 27518 break;
099e5b4d
LA
27519 default: /* Invalid */
27520 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 27521 generate_exception_end(ctx, EXCP_RI);
161f85e6 27522 break;
099e5b4d
LA
27523 }
27524 break;
27525 case OPC_DAPPEND_DSP:
27526 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27527 break;
27528 case OPC_DEXTR_W_DSP:
27529 op2 = MASK_DEXTR_W(ctx->opcode);
27530 switch (op2) {
27531 case OPC_DEXTP:
27532 case OPC_DEXTPDP:
27533 case OPC_DEXTPDPV:
27534 case OPC_DEXTPV:
27535 case OPC_DEXTR_L:
27536 case OPC_DEXTR_R_L:
27537 case OPC_DEXTR_RS_L:
27538 case OPC_DEXTR_W:
27539 case OPC_DEXTR_R_W:
27540 case OPC_DEXTR_RS_W:
27541 case OPC_DEXTR_S_H:
27542 case OPC_DEXTRV_L:
27543 case OPC_DEXTRV_R_L:
27544 case OPC_DEXTRV_RS_L:
27545 case OPC_DEXTRV_S_H:
27546 case OPC_DEXTRV_W:
27547 case OPC_DEXTRV_R_W:
27548 case OPC_DEXTRV_RS_W:
27549 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 27550 break;
099e5b4d
LA
27551 case OPC_DMTHLIP:
27552 case OPC_DSHILO:
27553 case OPC_DSHILOV:
27554 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 27555 break;
099e5b4d
LA
27556 default: /* Invalid */
27557 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27558 generate_exception_end(ctx, EXCP_RI);
461c08df 27559 break;
099e5b4d
LA
27560 }
27561 break;
27562 case OPC_DPAQ_W_QH_DSP:
27563 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27564 switch (op2) {
27565 case OPC_DPAU_H_OBL:
27566 case OPC_DPAU_H_OBR:
27567 case OPC_DPSU_H_OBL:
27568 case OPC_DPSU_H_OBR:
27569 case OPC_DPA_W_QH:
27570 case OPC_DPAQ_S_W_QH:
27571 case OPC_DPS_W_QH:
27572 case OPC_DPSQ_S_W_QH:
27573 case OPC_MULSAQ_S_W_QH:
27574 case OPC_DPAQ_SA_L_PW:
27575 case OPC_DPSQ_SA_L_PW:
27576 case OPC_MULSAQ_S_L_PW:
27577 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27578 break;
27579 case OPC_MAQ_S_W_QHLL:
27580 case OPC_MAQ_S_W_QHLR:
27581 case OPC_MAQ_S_W_QHRL:
27582 case OPC_MAQ_S_W_QHRR:
27583 case OPC_MAQ_SA_W_QHLL:
27584 case OPC_MAQ_SA_W_QHLR:
27585 case OPC_MAQ_SA_W_QHRL:
27586 case OPC_MAQ_SA_W_QHRR:
27587 case OPC_MAQ_S_L_PWL:
27588 case OPC_MAQ_S_L_PWR:
27589 case OPC_DMADD:
27590 case OPC_DMADDU:
27591 case OPC_DMSUB:
27592 case OPC_DMSUBU:
27593 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 27594 break;
099e5b4d
LA
27595 default: /* Invalid */
27596 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 27597 generate_exception_end(ctx, EXCP_RI);
b53371ed 27598 break;
099e5b4d
LA
27599 }
27600 break;
27601 case OPC_DINSV_DSP:
27602 op2 = MASK_INSV(ctx->opcode);
27603 switch (op2) {
27604 case OPC_DINSV:
27605 {
27606 TCGv t0, t1;
27607
27608 if (rt == 0) {
a22260ae
JL
27609 break;
27610 }
099e5b4d 27611 check_dsp(ctx);
1cb6686c 27612
099e5b4d
LA
27613 t0 = tcg_temp_new();
27614 t1 = tcg_temp_new();
1cb6686c 27615
099e5b4d
LA
27616 gen_load_gpr(t0, rt);
27617 gen_load_gpr(t1, rs);
1cb6686c 27618
099e5b4d 27619 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 27620
099e5b4d
LA
27621 tcg_temp_free(t0);
27622 tcg_temp_free(t1);
77c5fa8b 27623 break;
099e5b4d 27624 }
7a387fff 27625 default: /* Invalid */
099e5b4d 27626 MIPS_INVAL("MASK DINSV");
9c708c7f 27627 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
27628 break;
27629 }
27630 break;
099e5b4d
LA
27631 case OPC_SHLL_OB_DSP:
27632 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27633 break;
27634#endif
fac5a073
LA
27635 default: /* Invalid */
27636 MIPS_INVAL("special3_legacy");
9c708c7f 27637 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
27638 break;
27639 }
27640}
27641
37b9aae2
MM
27642
27643#if defined(TARGET_MIPS64)
27644
874b2879 27645static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 27646{
c8341e00 27647 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
27648
27649 switch (opc) {
baa609db
AM
27650 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27651 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27652 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27653 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27654 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27655 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27656 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27657 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27658 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27659 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27660 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27661 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27662 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27663 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27664 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27665 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27666 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27667 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27668 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27669 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27670 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27671 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27672 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27673 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27674 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27675 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
27676 break;
27677 default:
27678 MIPS_INVAL("TX79 MMI class MMI0");
27679 generate_exception_end(ctx, EXCP_RI);
27680 break;
27681 }
27682}
27683
874b2879 27684static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 27685{
c8341e00 27686 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
27687
27688 switch (opc) {
baa609db
AM
27689 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27690 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27691 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27692 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27693 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27694 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27695 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27696 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27697 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27698 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27699 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27700 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27701 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27702 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27703 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27704 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27705 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27706 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27707 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
27708 break;
27709 default:
27710 MIPS_INVAL("TX79 MMI class MMI1");
27711 generate_exception_end(ctx, EXCP_RI);
27712 break;
27713 }
27714}
27715
874b2879 27716static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 27717{
c8341e00 27718 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
27719
27720 switch (opc) {
baa609db
AM
27721 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27722 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27723 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27724 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27725 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27726 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27727 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27728 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27729 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
baa609db
AM
27730 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27731 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27732 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27733 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27734 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27735 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27736 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27737 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27738 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27739 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27740 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27741 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27742 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3 27743 break;
b87eef31
MM
27744 case MMI_OPC_2_PCPYLD:
27745 gen_mmi_pcpyld(ctx);
27746 break;
6c1e48d3
FN
27747 default:
27748 MIPS_INVAL("TX79 MMI class MMI2");
27749 generate_exception_end(ctx, EXCP_RI);
27750 break;
27751 }
27752}
27753
874b2879 27754static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 27755{
c8341e00 27756 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
27757
27758 switch (opc) {
baa609db
AM
27759 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27760 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27761 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27762 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27763 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27764 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27765 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
baa609db
AM
27766 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27767 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27768 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
baa609db
AM
27769 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27770 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc 27771 break;
d3434d9f
MM
27772 case MMI_OPC_3_PCPYH:
27773 gen_mmi_pcpyh(ctx);
27774 break;
fd487f83
MM
27775 case MMI_OPC_3_PCPYUD:
27776 gen_mmi_pcpyud(ctx);
27777 break;
ec1944fc
FN
27778 default:
27779 MIPS_INVAL("TX79 MMI class MMI3");
27780 generate_exception_end(ctx, EXCP_RI);
27781 break;
27782 }
27783}
27784
874b2879 27785static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 27786{
c8341e00 27787 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
27788 int rs = extract32(ctx->opcode, 21, 5);
27789 int rt = extract32(ctx->opcode, 16, 5);
27790 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
27791
27792 switch (opc) {
baa609db 27793 case MMI_OPC_CLASS_MMI0:
874b2879 27794 decode_mmi0(env, ctx);
88eafe0b 27795 break;
baa609db 27796 case MMI_OPC_CLASS_MMI1:
874b2879 27797 decode_mmi1(env, ctx);
7a803ca2 27798 break;
baa609db 27799 case MMI_OPC_CLASS_MMI2:
874b2879 27800 decode_mmi2(env, ctx);
6c1e48d3 27801 break;
baa609db 27802 case MMI_OPC_CLASS_MMI3:
874b2879 27803 decode_mmi3(env, ctx);
ec1944fc 27804 break;
baa609db
AM
27805 case MMI_OPC_MULT1:
27806 case MMI_OPC_MULTU1:
3b948f05
PMD
27807 case MMI_OPC_MADD:
27808 case MMI_OPC_MADDU:
a95c4c26
FN
27809 case MMI_OPC_MADD1:
27810 case MMI_OPC_MADDU1:
06de726b
FN
27811 gen_mul_txx9(ctx, opc, rd, rs, rt);
27812 break;
baa609db
AM
27813 case MMI_OPC_DIV1:
27814 case MMI_OPC_DIVU1:
c42171c3 27815 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 27816 break;
baa609db
AM
27817 case MMI_OPC_MTLO1:
27818 case MMI_OPC_MTHI1:
86efbfb6 27819 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 27820 break;
baa609db
AM
27821 case MMI_OPC_MFLO1:
27822 case MMI_OPC_MFHI1:
86efbfb6 27823 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 27824 break;
baa609db 27825 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
27826 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27827 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27828 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27829 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27830 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27831 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27832 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27833 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27834 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
27835 break;
27836 default:
27837 MIPS_INVAL("TX79 MMI class");
27838 generate_exception_end(ctx, EXCP_RI);
27839 break;
27840 }
27841}
27842
874b2879 27843static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 27844{
baa609db 27845 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
27846}
27847
874b2879 27848static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 27849{
baa609db 27850 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
27851}
27852
27853/*
27854 * The TX79-specific instruction Store Quadword
27855 *
27856 * +--------+-------+-------+------------------------+
27857 * | 011111 | base | rt | offset | SQ
27858 * +--------+-------+-------+------------------------+
27859 * 6 5 5 16
27860 *
27861 * has the same opcode as the Read Hardware Register instruction
27862 *
27863 * +--------+-------+-------+-------+-------+--------+
27864 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27865 * +--------+-------+-------+-------+-------+--------+
27866 * 6 5 5 5 5 6
27867 *
27868 * that is required, trapped and emulated by the Linux kernel. However, all
27869 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27870 * offset is odd. Therefore all valid SQ instructions can execute normally.
27871 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27872 * between SQ and RDHWR, as the Linux kernel does.
27873 */
874b2879 27874static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
27875{
27876 int base = extract32(ctx->opcode, 21, 5);
27877 int rt = extract32(ctx->opcode, 16, 5);
27878 int offset = extract32(ctx->opcode, 0, 16);
27879
27880#ifdef CONFIG_USER_ONLY
27881 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27882 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27883
27884 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27885 int rd = extract32(ctx->opcode, 11, 5);
27886
27887 gen_rdhwr(ctx, rt, rd, 0);
27888 return;
27889 }
27890#endif
27891
874b2879 27892 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
27893}
27894
37b9aae2
MM
27895#endif
27896
fac5a073
LA
27897static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27898{
27899 int rs, rt, rd, sa;
27900 uint32_t op1, op2;
76964147 27901 int16_t imm;
fac5a073
LA
27902
27903 rs = (ctx->opcode >> 21) & 0x1f;
27904 rt = (ctx->opcode >> 16) & 0x1f;
27905 rd = (ctx->opcode >> 11) & 0x1f;
27906 sa = (ctx->opcode >> 6) & 0x1f;
76964147 27907 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
27908
27909 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
27910
27911 /*
27912 * EVA loads and stores overlap Loongson 2E instructions decoded by
27913 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27914 * EVA is absent.
27915 */
27916 if (ctx->eva) {
27917 switch (op1) {
c2e19f3c
AM
27918 case OPC_LWLE:
27919 case OPC_LWRE:
76964147
JH
27920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27921 /* fall through */
c2e19f3c
AM
27922 case OPC_LBUE:
27923 case OPC_LHUE:
27924 case OPC_LBE:
27925 case OPC_LHE:
27926 case OPC_LLE:
27927 case OPC_LWE:
76964147
JH
27928 check_cp0_enabled(ctx);
27929 gen_ld(ctx, op1, rt, rs, imm);
27930 return;
c2e19f3c
AM
27931 case OPC_SWLE:
27932 case OPC_SWRE:
76964147
JH
27933 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27934 /* fall through */
c2e19f3c
AM
27935 case OPC_SBE:
27936 case OPC_SHE:
76964147
JH
27937 case OPC_SWE:
27938 check_cp0_enabled(ctx);
27939 gen_st(ctx, op1, rt, rs, imm);
27940 return;
27941 case OPC_SCE:
27942 check_cp0_enabled(ctx);
33a07fa2 27943 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
27944 return;
27945 case OPC_CACHEE:
27946 check_cp0_enabled(ctx);
27947 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27948 gen_cache_operation(ctx, rt, rs, imm);
27949 }
27950 /* Treat as NOP. */
27951 return;
27952 case OPC_PREFE:
27953 check_cp0_enabled(ctx);
27954 /* Treat as NOP. */
27955 return;
27956 }
27957 }
27958
fac5a073
LA
27959 switch (op1) {
27960 case OPC_EXT:
27961 case OPC_INS:
27962 check_insn(ctx, ISA_MIPS32R2);
27963 gen_bitops(ctx, op1, rt, rs, sa, rd);
27964 break;
27965 case OPC_BSHFL:
fac5a073 27966 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 27967 switch (op2) {
c2e19f3c 27968 case OPC_ALIGN:
373ecd38
AM
27969 case OPC_ALIGN_1:
27970 case OPC_ALIGN_2:
27971 case OPC_ALIGN_3:
15eacb9b
YK
27972 case OPC_BITSWAP:
27973 check_insn(ctx, ISA_MIPS32R6);
27974 decode_opc_special3_r6(env, ctx);
27975 break;
27976 default:
27977 check_insn(ctx, ISA_MIPS32R2);
27978 gen_bshfl(ctx, op2, rt, rd);
27979 break;
27980 }
fac5a073
LA
27981 break;
27982#if defined(TARGET_MIPS64)
c2e19f3c
AM
27983 case OPC_DEXTM:
27984 case OPC_DEXTU:
27985 case OPC_DEXT:
27986 case OPC_DINSM:
27987 case OPC_DINSU:
27988 case OPC_DINS:
fac5a073
LA
27989 check_insn(ctx, ISA_MIPS64R2);
27990 check_mips_64(ctx);
27991 gen_bitops(ctx, op1, rt, rs, sa, rd);
27992 break;
27993 case OPC_DBSHFL:
fac5a073 27994 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 27995 switch (op2) {
c2e19f3c 27996 case OPC_DALIGN:
373ecd38
AM
27997 case OPC_DALIGN_1:
27998 case OPC_DALIGN_2:
27999 case OPC_DALIGN_3:
28000 case OPC_DALIGN_4:
28001 case OPC_DALIGN_5:
28002 case OPC_DALIGN_6:
28003 case OPC_DALIGN_7:
15eacb9b
YK
28004 case OPC_DBITSWAP:
28005 check_insn(ctx, ISA_MIPS32R6);
28006 decode_opc_special3_r6(env, ctx);
28007 break;
28008 default:
28009 check_insn(ctx, ISA_MIPS64R2);
28010 check_mips_64(ctx);
28011 op2 = MASK_DBSHFL(ctx->opcode);
28012 gen_bshfl(ctx, op2, rt, rd);
28013 break;
28014 }
fac5a073
LA
28015 break;
28016#endif
28017 case OPC_RDHWR:
b00c7218 28018 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
28019 break;
28020 case OPC_FORK:
9affc1c5 28021 check_mt(ctx);
fac5a073
LA
28022 {
28023 TCGv t0 = tcg_temp_new();
28024 TCGv t1 = tcg_temp_new();
28025
28026 gen_load_gpr(t0, rt);
28027 gen_load_gpr(t1, rs);
28028 gen_helper_fork(t0, t1);
28029 tcg_temp_free(t0);
28030 tcg_temp_free(t1);
28031 }
28032 break;
28033 case OPC_YIELD:
9affc1c5 28034 check_mt(ctx);
fac5a073
LA
28035 {
28036 TCGv t0 = tcg_temp_new();
28037
fac5a073
LA
28038 gen_load_gpr(t0, rs);
28039 gen_helper_yield(t0, cpu_env, t0);
28040 gen_store_gpr(t0, rd);
28041 tcg_temp_free(t0);
28042 }
28043 break;
10dc65db
LA
28044 default:
28045 if (ctx->insn_flags & ISA_MIPS32R6) {
28046 decode_opc_special3_r6(env, ctx);
28047 } else {
28048 decode_opc_special3_legacy(env, ctx);
28049 }
099e5b4d
LA
28050 }
28051}
28052
863f264d
YK
28053/* MIPS SIMD Architecture (MSA) */
28054static inline int check_msa_access(DisasContext *ctx)
28055{
28056 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28057 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 28058 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28059 return 0;
28060 }
28061
28062 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28063 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 28064 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
28065 return 0;
28066 } else {
9c708c7f 28067 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28068 return 0;
28069 }
28070 }
28071 return 1;
28072}
28073
5692c6e1
YK
28074static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28075{
28076 /* generates tcg ops to check if any element is 0 */
28077 /* Note this function only works with MSA_WRLEN = 128 */
28078 uint64_t eval_zero_or_big = 0;
28079 uint64_t eval_big = 0;
28080 TCGv_i64 t0 = tcg_temp_new_i64();
28081 TCGv_i64 t1 = tcg_temp_new_i64();
28082 switch (df) {
28083 case DF_BYTE:
28084 eval_zero_or_big = 0x0101010101010101ULL;
28085 eval_big = 0x8080808080808080ULL;
28086 break;
28087 case DF_HALF:
28088 eval_zero_or_big = 0x0001000100010001ULL;
28089 eval_big = 0x8000800080008000ULL;
28090 break;
28091 case DF_WORD:
28092 eval_zero_or_big = 0x0000000100000001ULL;
28093 eval_big = 0x8000000080000000ULL;
28094 break;
28095 case DF_DOUBLE:
28096 eval_zero_or_big = 0x0000000000000001ULL;
28097 eval_big = 0x8000000000000000ULL;
28098 break;
28099 }
235785e8
AM
28100 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28101 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
5692c6e1 28102 tcg_gen_andi_i64(t0, t0, eval_big);
235785e8
AM
28103 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28104 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28105 tcg_gen_andi_i64(t1, t1, eval_big);
28106 tcg_gen_or_i64(t0, t0, t1);
28107 /* if all bits are zero then all elements are not zero */
28108 /* if some bit is non-zero then some element is zero */
28109 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28110 tcg_gen_trunc_i64_tl(tresult, t0);
28111 tcg_temp_free_i64(t0);
28112 tcg_temp_free_i64(t1);
28113}
28114
28115static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28116{
28117 uint8_t df = (ctx->opcode >> 21) & 0x3;
28118 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28119 int64_t s16 = (int16_t)ctx->opcode;
28120
28121 check_msa_access(ctx);
28122
075a1fe7 28123 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 28124 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
28125 return;
28126 }
28127 switch (op1) {
28128 case OPC_BZ_V:
28129 case OPC_BNZ_V:
28130 {
28131 TCGv_i64 t0 = tcg_temp_new_i64();
235785e8 28132 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28133 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28134 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28135 tcg_gen_trunc_i64_tl(bcond, t0);
28136 tcg_temp_free_i64(t0);
28137 }
28138 break;
28139 case OPC_BZ_B:
28140 case OPC_BZ_H:
28141 case OPC_BZ_W:
28142 case OPC_BZ_D:
28143 gen_check_zero_element(bcond, df, wt);
28144 break;
28145 case OPC_BNZ_B:
28146 case OPC_BNZ_H:
28147 case OPC_BNZ_W:
28148 case OPC_BNZ_D:
28149 gen_check_zero_element(bcond, df, wt);
28150 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28151 break;
28152 }
28153
eeb3bba8 28154 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
28155
28156 ctx->hflags |= MIPS_HFLAG_BC;
28157 ctx->hflags |= MIPS_HFLAG_BDS32;
28158}
28159
4c789546
YK
28160static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28161{
28162#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28163 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28164 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28165 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28166
28167 TCGv_i32 twd = tcg_const_i32(wd);
28168 TCGv_i32 tws = tcg_const_i32(ws);
28169 TCGv_i32 ti8 = tcg_const_i32(i8);
28170
28171 switch (MASK_MSA_I8(ctx->opcode)) {
28172 case OPC_ANDI_B:
28173 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28174 break;
28175 case OPC_ORI_B:
28176 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28177 break;
28178 case OPC_NORI_B:
28179 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28180 break;
28181 case OPC_XORI_B:
28182 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28183 break;
28184 case OPC_BMNZI_B:
28185 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28186 break;
28187 case OPC_BMZI_B:
28188 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28189 break;
28190 case OPC_BSELI_B:
28191 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28192 break;
28193 case OPC_SHF_B:
28194 case OPC_SHF_H:
28195 case OPC_SHF_W:
28196 {
28197 uint8_t df = (ctx->opcode >> 24) & 0x3;
28198 if (df == DF_DOUBLE) {
9c708c7f 28199 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28200 } else {
28201 TCGv_i32 tdf = tcg_const_i32(df);
28202 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28203 tcg_temp_free_i32(tdf);
28204 }
28205 }
28206 break;
28207 default:
28208 MIPS_INVAL("MSA instruction");
9c708c7f 28209 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28210 break;
28211 }
28212
28213 tcg_temp_free_i32(twd);
28214 tcg_temp_free_i32(tws);
28215 tcg_temp_free_i32(ti8);
28216}
28217
80e71591
YK
28218static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28219{
28220#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28221 uint8_t df = (ctx->opcode >> 21) & 0x3;
28222 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28223 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28224 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28225 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28226
28227 TCGv_i32 tdf = tcg_const_i32(df);
28228 TCGv_i32 twd = tcg_const_i32(wd);
28229 TCGv_i32 tws = tcg_const_i32(ws);
28230 TCGv_i32 timm = tcg_temp_new_i32();
28231 tcg_gen_movi_i32(timm, u5);
28232
28233 switch (MASK_MSA_I5(ctx->opcode)) {
28234 case OPC_ADDVI_df:
28235 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28236 break;
28237 case OPC_SUBVI_df:
28238 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28239 break;
28240 case OPC_MAXI_S_df:
28241 tcg_gen_movi_i32(timm, s5);
28242 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28243 break;
28244 case OPC_MAXI_U_df:
28245 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28246 break;
28247 case OPC_MINI_S_df:
28248 tcg_gen_movi_i32(timm, s5);
28249 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28250 break;
28251 case OPC_MINI_U_df:
28252 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28253 break;
28254 case OPC_CEQI_df:
28255 tcg_gen_movi_i32(timm, s5);
28256 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28257 break;
28258 case OPC_CLTI_S_df:
28259 tcg_gen_movi_i32(timm, s5);
28260 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28261 break;
28262 case OPC_CLTI_U_df:
28263 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28264 break;
28265 case OPC_CLEI_S_df:
28266 tcg_gen_movi_i32(timm, s5);
28267 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28268 break;
28269 case OPC_CLEI_U_df:
28270 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28271 break;
28272 case OPC_LDI_df:
28273 {
28274 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28275 tcg_gen_movi_i32(timm, s10);
28276 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28277 }
28278 break;
28279 default:
28280 MIPS_INVAL("MSA instruction");
9c708c7f 28281 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
28282 break;
28283 }
28284
28285 tcg_temp_free_i32(tdf);
28286 tcg_temp_free_i32(twd);
28287 tcg_temp_free_i32(tws);
28288 tcg_temp_free_i32(timm);
28289}
28290
d4cf28de
YK
28291static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28292{
28293#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28294 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28295 uint32_t df = 0, m = 0;
28296 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28297 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28298
28299 TCGv_i32 tdf;
28300 TCGv_i32 tm;
28301 TCGv_i32 twd;
28302 TCGv_i32 tws;
28303
28304 if ((dfm & 0x40) == 0x00) {
28305 m = dfm & 0x3f;
28306 df = DF_DOUBLE;
28307 } else if ((dfm & 0x60) == 0x40) {
28308 m = dfm & 0x1f;
28309 df = DF_WORD;
28310 } else if ((dfm & 0x70) == 0x60) {
28311 m = dfm & 0x0f;
28312 df = DF_HALF;
28313 } else if ((dfm & 0x78) == 0x70) {
28314 m = dfm & 0x7;
28315 df = DF_BYTE;
28316 } else {
9c708c7f 28317 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28318 return;
28319 }
28320
28321 tdf = tcg_const_i32(df);
28322 tm = tcg_const_i32(m);
28323 twd = tcg_const_i32(wd);
28324 tws = tcg_const_i32(ws);
28325
28326 switch (MASK_MSA_BIT(ctx->opcode)) {
28327 case OPC_SLLI_df:
28328 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28329 break;
28330 case OPC_SRAI_df:
28331 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28332 break;
28333 case OPC_SRLI_df:
28334 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28335 break;
28336 case OPC_BCLRI_df:
28337 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28338 break;
28339 case OPC_BSETI_df:
28340 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28341 break;
28342 case OPC_BNEGI_df:
28343 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28344 break;
28345 case OPC_BINSLI_df:
28346 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28347 break;
28348 case OPC_BINSRI_df:
28349 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28350 break;
28351 case OPC_SAT_S_df:
28352 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28353 break;
28354 case OPC_SAT_U_df:
28355 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28356 break;
28357 case OPC_SRARI_df:
28358 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28359 break;
28360 case OPC_SRLRI_df:
28361 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28362 break;
28363 default:
28364 MIPS_INVAL("MSA instruction");
9c708c7f 28365 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28366 break;
28367 }
28368
28369 tcg_temp_free_i32(tdf);
28370 tcg_temp_free_i32(tm);
28371 tcg_temp_free_i32(twd);
28372 tcg_temp_free_i32(tws);
28373}
28374
28f99f08
YK
28375static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28376{
28377#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28378 uint8_t df = (ctx->opcode >> 21) & 0x3;
28379 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28380 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28381 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28382
28383 TCGv_i32 tdf = tcg_const_i32(df);
28384 TCGv_i32 twd = tcg_const_i32(wd);
28385 TCGv_i32 tws = tcg_const_i32(ws);
28386 TCGv_i32 twt = tcg_const_i32(wt);
28387
28388 switch (MASK_MSA_3R(ctx->opcode)) {
2e3eddb0
AM
28389 case OPC_BINSL_df:
28390 switch (df) {
28391 case DF_BYTE:
28392 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28393 break;
28394 case DF_HALF:
28395 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28396 break;
28397 case DF_WORD:
28398 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28399 break;
28400 case DF_DOUBLE:
28401 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28402 break;
28403 }
28404 break;
28405 case OPC_BINSR_df:
28406 switch (df) {
28407 case DF_BYTE:
28408 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28409 break;
28410 case DF_HALF:
28411 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28412 break;
28413 case DF_WORD:
28414 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28415 break;
28416 case DF_DOUBLE:
28417 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28418 break;
28419 }
28420 break;
28f99f08
YK
28421 case OPC_SLL_df:
28422 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28423 break;
28424 case OPC_ADDV_df:
28425 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28426 break;
28427 case OPC_CEQ_df:
28428 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28429 break;
28430 case OPC_ADD_A_df:
28431 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28432 break;
28433 case OPC_SUBS_S_df:
28434 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28435 break;
28436 case OPC_MULV_df:
28437 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28438 break;
28439 case OPC_SLD_df:
28440 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28441 break;
28442 case OPC_VSHF_df:
28443 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28444 break;
28445 case OPC_SRA_df:
28446 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28447 break;
28448 case OPC_SUBV_df:
28449 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28450 break;
28451 case OPC_ADDS_A_df:
28452 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28453 break;
28454 case OPC_SUBS_U_df:
28455 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28456 break;
28457 case OPC_MADDV_df:
28458 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28459 break;
28460 case OPC_SPLAT_df:
28461 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28462 break;
28463 case OPC_SRAR_df:
28464 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28465 break;
28466 case OPC_SRL_df:
28467 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28468 break;
28469 case OPC_MAX_S_df:
28470 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28471 break;
28472 case OPC_CLT_S_df:
28473 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28474 break;
28475 case OPC_ADDS_S_df:
28476 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28477 break;
28478 case OPC_SUBSUS_U_df:
28479 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28480 break;
28481 case OPC_MSUBV_df:
28482 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28483 break;
28484 case OPC_PCKEV_df:
28485 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28486 break;
28487 case OPC_SRLR_df:
28488 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28489 break;
28490 case OPC_BCLR_df:
28491 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28492 break;
28493 case OPC_MAX_U_df:
28494 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28495 break;
28496 case OPC_CLT_U_df:
28497 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28498 break;
28499 case OPC_ADDS_U_df:
28500 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28501 break;
28502 case OPC_SUBSUU_S_df:
28503 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28504 break;
28505 case OPC_PCKOD_df:
28506 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28507 break;
28508 case OPC_BSET_df:
28509 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28510 break;
28511 case OPC_MIN_S_df:
28512 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28513 break;
28514 case OPC_CLE_S_df:
28515 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28516 break;
28517 case OPC_AVE_S_df:
28518 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28519 break;
28520 case OPC_ASUB_S_df:
28521 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28522 break;
28523 case OPC_DIV_S_df:
28524 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28525 break;
28526 case OPC_ILVL_df:
28527 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28528 break;
28529 case OPC_BNEG_df:
28530 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28531 break;
28532 case OPC_MIN_U_df:
28533 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28534 break;
28535 case OPC_CLE_U_df:
28536 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28537 break;
28538 case OPC_AVE_U_df:
28539 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28540 break;
28541 case OPC_ASUB_U_df:
28542 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28543 break;
28544 case OPC_DIV_U_df:
28545 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28546 break;
28547 case OPC_ILVR_df:
28548 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28549 break;
28f99f08
YK
28550 case OPC_MAX_A_df:
28551 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28552 break;
28553 case OPC_AVER_S_df:
28554 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28555 break;
28556 case OPC_MOD_S_df:
28557 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28558 break;
28559 case OPC_ILVEV_df:
28560 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28561 break;
28f99f08
YK
28562 case OPC_MIN_A_df:
28563 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28564 break;
28565 case OPC_AVER_U_df:
28566 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28567 break;
28568 case OPC_MOD_U_df:
28569 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28570 break;
28571 case OPC_ILVOD_df:
28572 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28573 break;
28574
28575 case OPC_DOTP_S_df:
28576 case OPC_DOTP_U_df:
28577 case OPC_DPADD_S_df:
28578 case OPC_DPADD_U_df:
28579 case OPC_DPSUB_S_df:
28580 case OPC_HADD_S_df:
28581 case OPC_DPSUB_U_df:
28582 case OPC_HADD_U_df:
28583 case OPC_HSUB_S_df:
28584 case OPC_HSUB_U_df:
28585 if (df == DF_BYTE) {
9c708c7f
PD
28586 generate_exception_end(ctx, EXCP_RI);
28587 break;
28f99f08
YK
28588 }
28589 switch (MASK_MSA_3R(ctx->opcode)) {
28590 case OPC_DOTP_S_df:
28591 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28592 break;
28593 case OPC_DOTP_U_df:
28594 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28595 break;
28596 case OPC_DPADD_S_df:
28597 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28598 break;
28599 case OPC_DPADD_U_df:
28600 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28601 break;
28602 case OPC_DPSUB_S_df:
28603 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28604 break;
28605 case OPC_HADD_S_df:
28606 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28607 break;
28608 case OPC_DPSUB_U_df:
28609 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28610 break;
28611 case OPC_HADD_U_df:
28612 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28613 break;
28614 case OPC_HSUB_S_df:
28615 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28616 break;
28617 case OPC_HSUB_U_df:
28618 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28619 break;
28620 }
28621 break;
28622 default:
28623 MIPS_INVAL("MSA instruction");
9c708c7f 28624 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
28625 break;
28626 }
28627 tcg_temp_free_i32(twd);
28628 tcg_temp_free_i32(tws);
28629 tcg_temp_free_i32(twt);
28630 tcg_temp_free_i32(tdf);
28631}
28632
1e608ec1
YK
28633static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28634{
28635#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28636 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28637 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28638 TCGv telm = tcg_temp_new();
28639 TCGv_i32 tsr = tcg_const_i32(source);
28640 TCGv_i32 tdt = tcg_const_i32(dest);
28641
28642 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28643 case OPC_CTCMSA:
28644 gen_load_gpr(telm, source);
28645 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28646 break;
28647 case OPC_CFCMSA:
28648 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28649 gen_store_gpr(telm, dest);
28650 break;
28651 case OPC_MOVE_V:
28652 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28653 break;
28654 default:
28655 MIPS_INVAL("MSA instruction");
9c708c7f 28656 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28657 break;
28658 }
28659
28660 tcg_temp_free(telm);
28661 tcg_temp_free_i32(tdt);
28662 tcg_temp_free_i32(tsr);
28663}
28664
28665static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28666 uint32_t n)
28667{
28668#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28669 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28670 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28671
28672 TCGv_i32 tws = tcg_const_i32(ws);
28673 TCGv_i32 twd = tcg_const_i32(wd);
28674 TCGv_i32 tn = tcg_const_i32(n);
28675 TCGv_i32 tdf = tcg_const_i32(df);
28676
28677 switch (MASK_MSA_ELM(ctx->opcode)) {
28678 case OPC_SLDI_df:
28679 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28680 break;
28681 case OPC_SPLATI_df:
28682 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28683 break;
28684 case OPC_INSVE_df:
28685 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28686 break;
28687 case OPC_COPY_S_df:
28688 case OPC_COPY_U_df:
28689 case OPC_INSERT_df:
28690#if !defined(TARGET_MIPS64)
28691 /* Double format valid only for MIPS64 */
28692 if (df == DF_DOUBLE) {
9c708c7f 28693 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28694 break;
28695 }
41d28858
MM
28696 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28697 (df == DF_WORD)) {
28698 generate_exception_end(ctx, EXCP_RI);
28699 break;
28700 }
1e608ec1
YK
28701#endif
28702 switch (MASK_MSA_ELM(ctx->opcode)) {
28703 case OPC_COPY_S_df:
cab48881 28704 if (likely(wd != 0)) {
631c4674
MM
28705 switch (df) {
28706 case DF_BYTE:
28707 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28708 break;
28709 case DF_HALF:
28710 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28711 break;
28712 case DF_WORD:
28713 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28714 break;
28715#if defined(TARGET_MIPS64)
28716 case DF_DOUBLE:
28717 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28718 break;
28719#endif
28720 default:
28721 assert(0);
28722 }
cab48881 28723 }
1e608ec1
YK
28724 break;
28725 case OPC_COPY_U_df:
cab48881 28726 if (likely(wd != 0)) {
41d28858
MM
28727 switch (df) {
28728 case DF_BYTE:
28729 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28730 break;
28731 case DF_HALF:
28732 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28733 break;
28734#if defined(TARGET_MIPS64)
28735 case DF_WORD:
28736 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28737 break;
28738#endif
28739 default:
28740 assert(0);
28741 }
cab48881 28742 }
1e608ec1
YK
28743 break;
28744 case OPC_INSERT_df:
c1c9a10f
MM
28745 switch (df) {
28746 case DF_BYTE:
28747 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28748 break;
28749 case DF_HALF:
28750 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28751 break;
28752 case DF_WORD:
28753 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28754 break;
28755#if defined(TARGET_MIPS64)
28756 case DF_DOUBLE:
28757 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28758 break;
28759#endif
28760 default:
28761 assert(0);
28762 }
1e608ec1
YK
28763 break;
28764 }
28765 break;
28766 default:
28767 MIPS_INVAL("MSA instruction");
9c708c7f 28768 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28769 }
28770 tcg_temp_free_i32(twd);
28771 tcg_temp_free_i32(tws);
28772 tcg_temp_free_i32(tn);
28773 tcg_temp_free_i32(tdf);
28774}
28775
28776static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28777{
28778 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28779 uint32_t df = 0, n = 0;
28780
28781 if ((dfn & 0x30) == 0x00) {
28782 n = dfn & 0x0f;
28783 df = DF_BYTE;
28784 } else if ((dfn & 0x38) == 0x20) {
28785 n = dfn & 0x07;
28786 df = DF_HALF;
28787 } else if ((dfn & 0x3c) == 0x30) {
28788 n = dfn & 0x03;
28789 df = DF_WORD;
28790 } else if ((dfn & 0x3e) == 0x38) {
28791 n = dfn & 0x01;
28792 df = DF_DOUBLE;
28793 } else if (dfn == 0x3E) {
28794 /* CTCMSA, CFCMSA, MOVE.V */
28795 gen_msa_elm_3e(env, ctx);
28796 return;
28797 } else {
9c708c7f 28798 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28799 return;
28800 }
28801
28802 gen_msa_elm_df(env, ctx, df, n);
28803}
28804
7d05b9c8
YK
28805static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28806{
28807#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28808 uint8_t df = (ctx->opcode >> 21) & 0x1;
28809 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28810 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28811 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28812
28813 TCGv_i32 twd = tcg_const_i32(wd);
28814 TCGv_i32 tws = tcg_const_i32(ws);
28815 TCGv_i32 twt = tcg_const_i32(wt);
28816 TCGv_i32 tdf = tcg_temp_new_i32();
28817
28818 /* adjust df value for floating-point instruction */
28819 tcg_gen_movi_i32(tdf, df + 2);
28820
28821 switch (MASK_MSA_3RF(ctx->opcode)) {
28822 case OPC_FCAF_df:
28823 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28824 break;
28825 case OPC_FADD_df:
28826 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28827 break;
28828 case OPC_FCUN_df:
28829 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28830 break;
28831 case OPC_FSUB_df:
28832 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28833 break;
28834 case OPC_FCOR_df:
28835 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28836 break;
28837 case OPC_FCEQ_df:
28838 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28839 break;
28840 case OPC_FMUL_df:
28841 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28842 break;
28843 case OPC_FCUNE_df:
28844 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28845 break;
28846 case OPC_FCUEQ_df:
28847 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28848 break;
28849 case OPC_FDIV_df:
28850 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28851 break;
28852 case OPC_FCNE_df:
28853 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28854 break;
28855 case OPC_FCLT_df:
28856 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28857 break;
28858 case OPC_FMADD_df:
28859 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28860 break;
28861 case OPC_MUL_Q_df:
28862 tcg_gen_movi_i32(tdf, df + 1);
28863 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28864 break;
28865 case OPC_FCULT_df:
28866 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28867 break;
28868 case OPC_FMSUB_df:
28869 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28870 break;
28871 case OPC_MADD_Q_df:
28872 tcg_gen_movi_i32(tdf, df + 1);
28873 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28874 break;
28875 case OPC_FCLE_df:
28876 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28877 break;
28878 case OPC_MSUB_Q_df:
28879 tcg_gen_movi_i32(tdf, df + 1);
28880 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28881 break;
28882 case OPC_FCULE_df:
28883 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28884 break;
28885 case OPC_FEXP2_df:
28886 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28887 break;
28888 case OPC_FSAF_df:
28889 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28890 break;
28891 case OPC_FEXDO_df:
28892 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28893 break;
28894 case OPC_FSUN_df:
28895 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28896 break;
28897 case OPC_FSOR_df:
28898 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28899 break;
28900 case OPC_FSEQ_df:
28901 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28902 break;
28903 case OPC_FTQ_df:
28904 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28905 break;
28906 case OPC_FSUNE_df:
28907 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28908 break;
28909 case OPC_FSUEQ_df:
28910 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28911 break;
28912 case OPC_FSNE_df:
28913 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28914 break;
28915 case OPC_FSLT_df:
28916 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28917 break;
28918 case OPC_FMIN_df:
28919 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28920 break;
28921 case OPC_MULR_Q_df:
28922 tcg_gen_movi_i32(tdf, df + 1);
28923 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28924 break;
28925 case OPC_FSULT_df:
28926 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28927 break;
28928 case OPC_FMIN_A_df:
28929 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28930 break;
28931 case OPC_MADDR_Q_df:
28932 tcg_gen_movi_i32(tdf, df + 1);
28933 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28934 break;
28935 case OPC_FSLE_df:
28936 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28937 break;
28938 case OPC_FMAX_df:
28939 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28940 break;
28941 case OPC_MSUBR_Q_df:
28942 tcg_gen_movi_i32(tdf, df + 1);
28943 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28944 break;
28945 case OPC_FSULE_df:
28946 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28947 break;
28948 case OPC_FMAX_A_df:
28949 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28950 break;
28951 default:
28952 MIPS_INVAL("MSA instruction");
9c708c7f 28953 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
28954 break;
28955 }
28956
28957 tcg_temp_free_i32(twd);
28958 tcg_temp_free_i32(tws);
28959 tcg_temp_free_i32(twt);
28960 tcg_temp_free_i32(tdf);
28961}
28962
cbe50b9a
YK
28963static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28964{
28965#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28966 (op & (0x7 << 18)))
28967 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28968 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28969 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28970 uint8_t df = (ctx->opcode >> 16) & 0x3;
28971 TCGv_i32 twd = tcg_const_i32(wd);
28972 TCGv_i32 tws = tcg_const_i32(ws);
28973 TCGv_i32 twt = tcg_const_i32(wt);
28974 TCGv_i32 tdf = tcg_const_i32(df);
28975
28976 switch (MASK_MSA_2R(ctx->opcode)) {
28977 case OPC_FILL_df:
28978#if !defined(TARGET_MIPS64)
28979 /* Double format valid only for MIPS64 */
28980 if (df == DF_DOUBLE) {
9c708c7f 28981 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28982 break;
28983 }
28984#endif
28985 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28986 break;
cbe50b9a 28987 case OPC_NLOC_df:
81c4b059
AM
28988 switch (df) {
28989 case DF_BYTE:
28990 gen_helper_msa_nloc_b(cpu_env, twd, tws);
28991 break;
28992 case DF_HALF:
28993 gen_helper_msa_nloc_h(cpu_env, twd, tws);
28994 break;
28995 case DF_WORD:
28996 gen_helper_msa_nloc_w(cpu_env, twd, tws);
28997 break;
28998 case DF_DOUBLE:
28999 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29000 break;
29001 }
cbe50b9a
YK
29002 break;
29003 case OPC_NLZC_df:
81c4b059
AM
29004 switch (df) {
29005 case DF_BYTE:
29006 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29007 break;
29008 case DF_HALF:
29009 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29010 break;
29011 case DF_WORD:
29012 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29013 break;
29014 case DF_DOUBLE:
29015 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29016 break;
29017 }
cbe50b9a 29018 break;
4c5daf38
AM
29019 case OPC_PCNT_df:
29020 switch (df) {
29021 case DF_BYTE:
29022 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29023 break;
29024 case DF_HALF:
29025 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29026 break;
29027 case DF_WORD:
29028 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29029 break;
29030 case DF_DOUBLE:
29031 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29032 break;
29033 }
29034 break;
cbe50b9a
YK
29035 default:
29036 MIPS_INVAL("MSA instruction");
9c708c7f 29037 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29038 break;
29039 }
29040
29041 tcg_temp_free_i32(twd);
29042 tcg_temp_free_i32(tws);
29043 tcg_temp_free_i32(twt);
29044 tcg_temp_free_i32(tdf);
29045}
29046
3bdeb688
YK
29047static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29048{
29049#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29050 (op & (0xf << 17)))
29051 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29052 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29053 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29054 uint8_t df = (ctx->opcode >> 16) & 0x1;
29055 TCGv_i32 twd = tcg_const_i32(wd);
29056 TCGv_i32 tws = tcg_const_i32(ws);
29057 TCGv_i32 twt = tcg_const_i32(wt);
29058 /* adjust df value for floating-point instruction */
29059 TCGv_i32 tdf = tcg_const_i32(df + 2);
29060
29061 switch (MASK_MSA_2RF(ctx->opcode)) {
29062 case OPC_FCLASS_df:
29063 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29064 break;
29065 case OPC_FTRUNC_S_df:
29066 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29067 break;
29068 case OPC_FTRUNC_U_df:
29069 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29070 break;
29071 case OPC_FSQRT_df:
29072 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29073 break;
29074 case OPC_FRSQRT_df:
29075 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29076 break;
29077 case OPC_FRCP_df:
29078 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29079 break;
29080 case OPC_FRINT_df:
29081 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29082 break;
29083 case OPC_FLOG2_df:
29084 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29085 break;
29086 case OPC_FEXUPL_df:
29087 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29088 break;
29089 case OPC_FEXUPR_df:
29090 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29091 break;
29092 case OPC_FFQL_df:
29093 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29094 break;
29095 case OPC_FFQR_df:
29096 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29097 break;
29098 case OPC_FTINT_S_df:
29099 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29100 break;
29101 case OPC_FTINT_U_df:
29102 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29103 break;
29104 case OPC_FFINT_S_df:
29105 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29106 break;
29107 case OPC_FFINT_U_df:
29108 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29109 break;
29110 }
29111
29112 tcg_temp_free_i32(twd);
29113 tcg_temp_free_i32(tws);
29114 tcg_temp_free_i32(twt);
29115 tcg_temp_free_i32(tdf);
29116}
29117
cbe50b9a
YK
29118static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29119{
29120#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29121 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29122 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29123 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29124 TCGv_i32 twd = tcg_const_i32(wd);
29125 TCGv_i32 tws = tcg_const_i32(ws);
29126 TCGv_i32 twt = tcg_const_i32(wt);
29127
29128 switch (MASK_MSA_VEC(ctx->opcode)) {
29129 case OPC_AND_V:
29130 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29131 break;
29132 case OPC_OR_V:
29133 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29134 break;
29135 case OPC_NOR_V:
29136 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29137 break;
29138 case OPC_XOR_V:
29139 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29140 break;
29141 case OPC_BMNZ_V:
29142 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29143 break;
29144 case OPC_BMZ_V:
29145 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29146 break;
29147 case OPC_BSEL_V:
29148 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29149 break;
29150 default:
29151 MIPS_INVAL("MSA instruction");
9c708c7f 29152 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29153 break;
29154 }
29155
29156 tcg_temp_free_i32(twd);
29157 tcg_temp_free_i32(tws);
29158 tcg_temp_free_i32(twt);
29159}
29160
29161static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29162{
29163 switch (MASK_MSA_VEC(ctx->opcode)) {
29164 case OPC_AND_V:
29165 case OPC_OR_V:
29166 case OPC_NOR_V:
29167 case OPC_XOR_V:
29168 case OPC_BMNZ_V:
29169 case OPC_BMZ_V:
29170 case OPC_BSEL_V:
29171 gen_msa_vec_v(env, ctx);
29172 break;
29173 case OPC_MSA_2R:
29174 gen_msa_2r(env, ctx);
29175 break;
3bdeb688
YK
29176 case OPC_MSA_2RF:
29177 gen_msa_2rf(env, ctx);
29178 break;
cbe50b9a
YK
29179 default:
29180 MIPS_INVAL("MSA instruction");
9c708c7f 29181 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
29182 break;
29183 }
29184}
29185
4c789546
YK
29186static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29187{
29188 uint32_t opcode = ctx->opcode;
29189 check_insn(ctx, ASE_MSA);
29190 check_msa_access(ctx);
29191
29192 switch (MASK_MSA_MINOR(opcode)) {
29193 case OPC_MSA_I8_00:
29194 case OPC_MSA_I8_01:
29195 case OPC_MSA_I8_02:
29196 gen_msa_i8(env, ctx);
29197 break;
80e71591
YK
29198 case OPC_MSA_I5_06:
29199 case OPC_MSA_I5_07:
29200 gen_msa_i5(env, ctx);
29201 break;
d4cf28de
YK
29202 case OPC_MSA_BIT_09:
29203 case OPC_MSA_BIT_0A:
29204 gen_msa_bit(env, ctx);
29205 break;
28f99f08
YK
29206 case OPC_MSA_3R_0D:
29207 case OPC_MSA_3R_0E:
29208 case OPC_MSA_3R_0F:
29209 case OPC_MSA_3R_10:
29210 case OPC_MSA_3R_11:
29211 case OPC_MSA_3R_12:
29212 case OPC_MSA_3R_13:
29213 case OPC_MSA_3R_14:
29214 case OPC_MSA_3R_15:
29215 gen_msa_3r(env, ctx);
29216 break;
1e608ec1
YK
29217 case OPC_MSA_ELM:
29218 gen_msa_elm(env, ctx);
29219 break;
7d05b9c8
YK
29220 case OPC_MSA_3RF_1A:
29221 case OPC_MSA_3RF_1B:
29222 case OPC_MSA_3RF_1C:
29223 gen_msa_3rf(env, ctx);
29224 break;
cbe50b9a
YK
29225 case OPC_MSA_VEC:
29226 gen_msa_vec(env, ctx);
29227 break;
f7685877
YK
29228 case OPC_LD_B:
29229 case OPC_LD_H:
29230 case OPC_LD_W:
29231 case OPC_LD_D:
29232 case OPC_ST_B:
29233 case OPC_ST_H:
29234 case OPC_ST_W:
29235 case OPC_ST_D:
29236 {
29237 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29238 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29239 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29240 uint8_t df = (ctx->opcode >> 0) & 0x3;
29241
f7685877 29242 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
29243 TCGv taddr = tcg_temp_new();
29244 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
29245
29246 switch (MASK_MSA_MINOR(opcode)) {
29247 case OPC_LD_B:
adc370a4
YK
29248 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29249 break;
f7685877 29250 case OPC_LD_H:
adc370a4
YK
29251 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29252 break;
f7685877 29253 case OPC_LD_W:
adc370a4
YK
29254 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29255 break;
f7685877 29256 case OPC_LD_D:
adc370a4 29257 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
29258 break;
29259 case OPC_ST_B:
adc370a4
YK
29260 gen_helper_msa_st_b(cpu_env, twd, taddr);
29261 break;
f7685877 29262 case OPC_ST_H:
adc370a4
YK
29263 gen_helper_msa_st_h(cpu_env, twd, taddr);
29264 break;
f7685877 29265 case OPC_ST_W:
adc370a4
YK
29266 gen_helper_msa_st_w(cpu_env, twd, taddr);
29267 break;
f7685877 29268 case OPC_ST_D:
adc370a4 29269 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
29270 break;
29271 }
29272
29273 tcg_temp_free_i32(twd);
adc370a4 29274 tcg_temp_free(taddr);
f7685877
YK
29275 }
29276 break;
4c789546
YK
29277 default:
29278 MIPS_INVAL("MSA instruction");
9c708c7f 29279 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
29280 break;
29281 }
29282
29283}
29284
d2bfa6e6 29285static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
29286{
29287 int32_t offset;
29288 int rs, rt, rd, sa;
29289 uint32_t op, op1;
29290 int16_t imm;
29291
29292 /* make sure instructions are on a word boundary */
eeb3bba8
EC
29293 if (ctx->base.pc_next & 0x3) {
29294 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 29295 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
29296 return;
29297 }
29298
29299 /* Handle blikely not taken case */
29300 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 29301 TCGLabel *l1 = gen_new_label();
099e5b4d 29302
099e5b4d
LA
29303 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29304 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 29305 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
29306 gen_set_label(l1);
29307 }
29308
099e5b4d
LA
29309 op = MASK_OP_MAJOR(ctx->opcode);
29310 rs = (ctx->opcode >> 21) & 0x1f;
29311 rt = (ctx->opcode >> 16) & 0x1f;
29312 rd = (ctx->opcode >> 11) & 0x1f;
29313 sa = (ctx->opcode >> 6) & 0x1f;
29314 imm = (int16_t)ctx->opcode;
29315 switch (op) {
29316 case OPC_SPECIAL:
29317 decode_opc_special(env, ctx);
29318 break;
29319 case OPC_SPECIAL2:
37b9aae2 29320#if defined(TARGET_MIPS64)
71b8a6b3 29321 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 29322 decode_mmi(env, ctx);
37b9aae2
MM
29323#else
29324 if (ctx->insn_flags & ASE_MXU) {
0a348b9a 29325 decode_opc_mxu(env, ctx);
b621f018 29326#endif
71b8a6b3
FN
29327 } else {
29328 decode_opc_special2_legacy(env, ctx);
29329 }
099e5b4d
LA
29330 break;
29331 case OPC_SPECIAL3:
37b9aae2 29332#if defined(TARGET_MIPS64)
bb41e74b 29333 if (ctx->insn_flags & INSN_R5900) {
874b2879 29334 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
29335 } else {
29336 decode_opc_special3(env, ctx);
29337 }
37b9aae2
MM
29338#else
29339 decode_opc_special3(env, ctx);
29340#endif
099e5b4d 29341 break;
7a387fff
TS
29342 case OPC_REGIMM:
29343 op1 = MASK_REGIMM(ctx->opcode);
29344 switch (op1) {
fecd2646
LA
29345 case OPC_BLTZL: /* REGIMM branches */
29346 case OPC_BGEZL:
29347 case OPC_BLTZALL:
29348 case OPC_BGEZALL:
d9224450 29349 check_insn(ctx, ISA_MIPS2);
fecd2646 29350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29351 /* Fallthrough */
fecd2646
LA
29352 case OPC_BLTZ:
29353 case OPC_BGEZ:
b231c103 29354 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 29355 break;
fecd2646
LA
29356 case OPC_BLTZAL:
29357 case OPC_BGEZAL:
0aefa333
YK
29358 if (ctx->insn_flags & ISA_MIPS32R6) {
29359 if (rs == 0) {
29360 /* OPC_NAL, OPC_BAL */
b231c103 29361 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 29362 } else {
9c708c7f 29363 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
29364 }
29365 } else {
b231c103 29366 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 29367 }
c9602061 29368 break;
c2e19f3c
AM
29369 case OPC_TGEI: /* REGIMM traps */
29370 case OPC_TGEIU:
29371 case OPC_TLTI:
29372 case OPC_TLTIU:
29373 case OPC_TEQI:
29374
7a387fff 29375 case OPC_TNEI:
d9224450 29376 check_insn(ctx, ISA_MIPS2);
fecd2646 29377 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
29378 gen_trap(ctx, op1, rs, -1, imm);
29379 break;
bb238210
YK
29380 case OPC_SIGRIE:
29381 check_insn(ctx, ISA_MIPS32R6);
29382 generate_exception_end(ctx, EXCP_RI);
29383 break;
7a387fff 29384 case OPC_SYNCI:
d75c135e 29385 check_insn(ctx, ISA_MIPS32R2);
7480515f
AM
29386 /*
29387 * Break the TB to be able to sync copied instructions
29388 * immediately.
29389 */
eeb3bba8 29390 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 29391 break;
e45a93e2
JL
29392 case OPC_BPOSGE32: /* MIPS DSP branch */
29393#if defined(TARGET_MIPS64)
29394 case OPC_BPOSGE64:
29395#endif
29396 check_dsp(ctx);
b231c103 29397 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 29398 break;
d4ea6acd
LA
29399#if defined(TARGET_MIPS64)
29400 case OPC_DAHI:
29401 check_insn(ctx, ISA_MIPS32R6);
29402 check_mips_64(ctx);
29403 if (rs != 0) {
29404 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29405 }
d4ea6acd
LA
29406 break;
29407 case OPC_DATI:
29408 check_insn(ctx, ISA_MIPS32R6);
29409 check_mips_64(ctx);
29410 if (rs != 0) {
29411 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29412 }
d4ea6acd
LA
29413 break;
29414#endif
6af0bf9c 29415 default: /* Invalid */
923617a3 29416 MIPS_INVAL("regimm");
9c708c7f 29417 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29418 break;
29419 }
29420 break;
7a387fff 29421 case OPC_CP0:
387a8fe5 29422 check_cp0_enabled(ctx);
7a387fff 29423 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 29424 switch (op1) {
7a387fff
TS
29425 case OPC_MFC0:
29426 case OPC_MTC0:
ead9360e
TS
29427 case OPC_MFTR:
29428 case OPC_MTTR:
5204ea79
LA
29429 case OPC_MFHC0:
29430 case OPC_MTHC0:
d26bc211 29431#if defined(TARGET_MIPS64)
7a387fff
TS
29432 case OPC_DMFC0:
29433 case OPC_DMTC0:
29434#endif
f1aa6320 29435#ifndef CONFIG_USER_ONLY
932e71cd 29436 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 29437#endif /* !CONFIG_USER_ONLY */
7a387fff 29438 break;
c38a1d52
AR
29439 case OPC_C0:
29440 case OPC_C0_1:
29441 case OPC_C0_2:
29442 case OPC_C0_3:
29443 case OPC_C0_4:
29444 case OPC_C0_5:
29445 case OPC_C0_6:
29446 case OPC_C0_7:
29447 case OPC_C0_8:
29448 case OPC_C0_9:
29449 case OPC_C0_A:
29450 case OPC_C0_B:
29451 case OPC_C0_C:
29452 case OPC_C0_D:
29453 case OPC_C0_E:
29454 case OPC_C0_F:
f1aa6320 29455#ifndef CONFIG_USER_ONLY
932e71cd 29456 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 29457#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
29458 break;
29459 case OPC_MFMC0:
8706c382 29460#ifndef CONFIG_USER_ONLY
932e71cd 29461 {
099e5b4d 29462 uint32_t op2;
35fbce2c 29463 TCGv t0 = tcg_temp_new();
6c5c1e20 29464
0eaef5aa 29465 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
29466 switch (op2) {
29467 case OPC_DMT:
9affc1c5 29468 check_cp0_mt(ctx);
9ed5726c 29469 gen_helper_dmt(t0);
35fbce2c 29470 gen_store_gpr(t0, rt);
6c5c1e20
TS
29471 break;
29472 case OPC_EMT:
9affc1c5 29473 check_cp0_mt(ctx);
9ed5726c 29474 gen_helper_emt(t0);
35fbce2c 29475 gen_store_gpr(t0, rt);
da80682b 29476 break;
6c5c1e20 29477 case OPC_DVPE:
9affc1c5 29478 check_cp0_mt(ctx);
895c2d04 29479 gen_helper_dvpe(t0, cpu_env);
35fbce2c 29480 gen_store_gpr(t0, rt);
6c5c1e20
TS
29481 break;
29482 case OPC_EVPE:
9affc1c5 29483 check_cp0_mt(ctx);
895c2d04 29484 gen_helper_evpe(t0, cpu_env);
35fbce2c 29485 gen_store_gpr(t0, rt);
6c5c1e20 29486 break;
01bc435b
YK
29487 case OPC_DVP:
29488 check_insn(ctx, ISA_MIPS32R6);
29489 if (ctx->vp) {
29490 gen_helper_dvp(t0, cpu_env);
29491 gen_store_gpr(t0, rt);
29492 }
29493 break;
29494 case OPC_EVP:
29495 check_insn(ctx, ISA_MIPS32R6);
29496 if (ctx->vp) {
29497 gen_helper_evp(t0, cpu_env);
29498 gen_store_gpr(t0, rt);
29499 }
29500 break;
6c5c1e20 29501 case OPC_DI:
d75c135e 29502 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29503 save_cpu_state(ctx, 1);
895c2d04 29504 gen_helper_di(t0, cpu_env);
35fbce2c 29505 gen_store_gpr(t0, rt);
7480515f
AM
29506 /*
29507 * Stop translation as we may have switched
29508 * the execution mode.
29509 */
eeb3bba8 29510 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
29511 break;
29512 case OPC_EI:
d75c135e 29513 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29514 save_cpu_state(ctx, 1);
895c2d04 29515 gen_helper_ei(t0, cpu_env);
35fbce2c 29516 gen_store_gpr(t0, rt);
7480515f
AM
29517 /*
29518 * DISAS_STOP isn't sufficient, we need to ensure we break
29519 * out of translated code to check for pending interrupts.
29520 */
eeb3bba8
EC
29521 gen_save_pc(ctx->base.pc_next + 4);
29522 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
29523 break;
29524 default: /* Invalid */
29525 MIPS_INVAL("mfmc0");
9c708c7f 29526 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
29527 break;
29528 }
6c5c1e20 29529 tcg_temp_free(t0);
7a387fff 29530 }
0eaef5aa 29531#endif /* !CONFIG_USER_ONLY */
6af0bf9c 29532 break;
7a387fff 29533 case OPC_RDPGPR:
d75c135e 29534 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29535 gen_load_srsgpr(rt, rd);
ead9360e 29536 break;
7a387fff 29537 case OPC_WRPGPR:
d75c135e 29538 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29539 gen_store_srsgpr(rt, rd);
38121543 29540 break;
6af0bf9c 29541 default:
923617a3 29542 MIPS_INVAL("cp0");
9c708c7f 29543 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29544 break;
29545 }
29546 break;
31837be3
YK
29547 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29548 if (ctx->insn_flags & ISA_MIPS32R6) {
29549 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29550 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29551 } else {
29552 /* OPC_ADDI */
29553 /* Arithmetic with immediate opcode */
29554 gen_arith_imm(ctx, op, rt, rs, imm);
29555 }
29556 break;
324d9e32 29557 case OPC_ADDIU:
d75c135e 29558 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29559 break;
324d9e32
AJ
29560 case OPC_SLTI: /* Set on less than with immediate opcode */
29561 case OPC_SLTIU:
d75c135e 29562 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
29563 break;
29564 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 29565 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
29566 case OPC_ORI:
29567 case OPC_XORI:
d75c135e 29568 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 29569 break;
c2e19f3c
AM
29570 case OPC_J: /* Jump */
29571 case OPC_JAL:
7a387fff 29572 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 29573 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 29574 break;
31837be3
YK
29575 /* Branch */
29576 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29577 if (ctx->insn_flags & ISA_MIPS32R6) {
29578 if (rt == 0) {
9c708c7f 29579 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29580 break;
29581 }
29582 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29583 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29584 } else {
29585 /* OPC_BLEZL */
b231c103 29586 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29587 }
29588 break;
29589 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29590 if (ctx->insn_flags & ISA_MIPS32R6) {
29591 if (rt == 0) {
9c708c7f 29592 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29593 break;
29594 }
29595 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29596 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29597 } else {
29598 /* OPC_BGTZL */
b231c103 29599 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29600 }
29601 break;
29602 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29603 if (rt == 0) {
29604 /* OPC_BLEZ */
b231c103 29605 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29606 } else {
29607 check_insn(ctx, ISA_MIPS32R6);
29608 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29609 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29610 }
29611 break;
29612 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29613 if (rt == 0) {
29614 /* OPC_BGTZ */
b231c103 29615 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29616 } else {
29617 check_insn(ctx, ISA_MIPS32R6);
29618 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29619 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29620 }
29621 break;
29622 case OPC_BEQL:
29623 case OPC_BNEL:
d9224450 29624 check_insn(ctx, ISA_MIPS2);
fecd2646 29625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29626 /* Fallthrough */
31837be3
YK
29627 case OPC_BEQ:
29628 case OPC_BNE:
b231c103 29629 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 29630 break;
d9224450
MR
29631 case OPC_LL: /* Load and stores */
29632 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
29633 if (ctx->insn_flags & INSN_R5900) {
29634 check_insn_opc_user_only(ctx, INSN_R5900);
29635 }
d9224450
MR
29636 /* Fallthrough */
29637 case OPC_LWL:
fecd2646
LA
29638 case OPC_LWR:
29639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29640 /* Fallthrough */
c2e19f3c
AM
29641 case OPC_LB:
29642 case OPC_LH:
29643 case OPC_LW:
29644 case OPC_LWPC:
29645 case OPC_LBU:
29646 case OPC_LHU:
d75c135e 29647 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29648 break;
fecd2646 29649 case OPC_SWL:
7a387fff 29650 case OPC_SWR:
fecd2646 29651 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29652 /* fall through */
c2e19f3c
AM
29653 case OPC_SB:
29654 case OPC_SH:
fecd2646 29655 case OPC_SW:
5c13fdfd 29656 gen_st(ctx, op, rt, rs, imm);
7a387fff 29657 break;
d66c7132 29658 case OPC_SC:
d9224450 29659 check_insn(ctx, ISA_MIPS2);
4368b29a 29660 check_insn_opc_removed(ctx, ISA_MIPS32R6);
55fc7a69
FN
29661 if (ctx->insn_flags & INSN_R5900) {
29662 check_insn_opc_user_only(ctx, INSN_R5900);
29663 }
33a07fa2
LA
29664 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29665 break;
7a387fff 29666 case OPC_CACHE:
bf7910c6 29667 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 29668 check_cp0_enabled(ctx);
d75c135e 29669 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
29670 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29671 gen_cache_operation(ctx, rt, rs, imm);
29672 }
ead9360e 29673 /* Treat as NOP. */
34ae7b51 29674 break;
7a387fff 29675 case OPC_PREF:
bf7910c6 29676 check_insn_opc_removed(ctx, ISA_MIPS32R6);
992e8176
FN
29677 if (ctx->insn_flags & INSN_R5900) {
29678 /* Treat as NOP. */
29679 } else {
29680 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29681 /* Treat as NOP. */
29682 }
6af0bf9c 29683 break;
4ad40f36 29684
923617a3 29685 /* Floating point (COP1). */
7a387fff
TS
29686 case OPC_LWC1:
29687 case OPC_LDC1:
29688 case OPC_SWC1:
29689 case OPC_SDC1:
5ab5c041 29690 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
29691 break;
29692
7a387fff 29693 case OPC_CP1:
5692c6e1
YK
29694 op1 = MASK_CP1(ctx->opcode);
29695
29696 switch (op1) {
29697 case OPC_MFHC1:
29698 case OPC_MTHC1:
5e755519 29699 check_cp1_enabled(ctx);
5692c6e1 29700 check_insn(ctx, ISA_MIPS32R2);
146dd620 29701 /* fall through */
5692c6e1
YK
29702 case OPC_MFC1:
29703 case OPC_CFC1:
29704 case OPC_MTC1:
29705 case OPC_CTC1:
29706 check_cp1_enabled(ctx);
29707 gen_cp1(ctx, op1, rt, rd);
29708 break;
d26bc211 29709#if defined(TARGET_MIPS64)
5692c6e1
YK
29710 case OPC_DMFC1:
29711 case OPC_DMTC1:
29712 check_cp1_enabled(ctx);
29713 check_insn(ctx, ISA_MIPS3);
d9224450 29714 check_mips_64(ctx);
5692c6e1
YK
29715 gen_cp1(ctx, op1, rt, rd);
29716 break;
e189e748 29717#endif
5692c6e1
YK
29718 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29719 check_cp1_enabled(ctx);
29720 if (ctx->insn_flags & ISA_MIPS32R6) {
29721 /* OPC_BC1EQZ */
31837be3 29722 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29723 rt, imm << 2, 4);
5692c6e1
YK
29724 } else {
29725 /* OPC_BC1ANY2 */
b8aa4598 29726 check_cop1x(ctx);
d75c135e 29727 check_insn(ctx, ASE_MIPS3D);
d75c135e 29728 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 29729 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
29730 }
29731 break;
29732 case OPC_BC1NEZ:
29733 check_cp1_enabled(ctx);
29734 check_insn(ctx, ISA_MIPS32R6);
29735 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29736 rt, imm << 2, 4);
5692c6e1
YK
29737 break;
29738 case OPC_BC1ANY4:
29739 check_cp1_enabled(ctx);
29740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29741 check_cop1x(ctx);
29742 check_insn(ctx, ASE_MIPS3D);
29743 /* fall through */
29744 case OPC_BC1:
29745 check_cp1_enabled(ctx);
29746 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29747 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29748 (rt >> 2) & 0x7, imm << 2);
29749 break;
29750 case OPC_PS_FMT:
e29c9628 29751 check_ps(ctx);
b6f3b233 29752 /* fall through */
5692c6e1
YK
29753 case OPC_S_FMT:
29754 case OPC_D_FMT:
29755 check_cp1_enabled(ctx);
29756 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29757 (imm >> 8) & 0x7);
29758 break;
29759 case OPC_W_FMT:
29760 case OPC_L_FMT:
29761 {
29762 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29763 check_cp1_enabled(ctx);
29764 if (ctx->insn_flags & ISA_MIPS32R6) {
29765 switch (r6_op) {
29766 case R6_OPC_CMP_AF_S:
29767 case R6_OPC_CMP_UN_S:
29768 case R6_OPC_CMP_EQ_S:
29769 case R6_OPC_CMP_UEQ_S:
29770 case R6_OPC_CMP_LT_S:
29771 case R6_OPC_CMP_ULT_S:
29772 case R6_OPC_CMP_LE_S:
29773 case R6_OPC_CMP_ULE_S:
29774 case R6_OPC_CMP_SAF_S:
29775 case R6_OPC_CMP_SUN_S:
29776 case R6_OPC_CMP_SEQ_S:
29777 case R6_OPC_CMP_SEUQ_S:
29778 case R6_OPC_CMP_SLT_S:
29779 case R6_OPC_CMP_SULT_S:
29780 case R6_OPC_CMP_SLE_S:
29781 case R6_OPC_CMP_SULE_S:
29782 case R6_OPC_CMP_OR_S:
29783 case R6_OPC_CMP_UNE_S:
29784 case R6_OPC_CMP_NE_S:
29785 case R6_OPC_CMP_SOR_S:
29786 case R6_OPC_CMP_SUNE_S:
29787 case R6_OPC_CMP_SNE_S:
29788 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29789 break;
29790 case R6_OPC_CMP_AF_D:
29791 case R6_OPC_CMP_UN_D:
29792 case R6_OPC_CMP_EQ_D:
29793 case R6_OPC_CMP_UEQ_D:
29794 case R6_OPC_CMP_LT_D:
29795 case R6_OPC_CMP_ULT_D:
29796 case R6_OPC_CMP_LE_D:
29797 case R6_OPC_CMP_ULE_D:
29798 case R6_OPC_CMP_SAF_D:
29799 case R6_OPC_CMP_SUN_D:
29800 case R6_OPC_CMP_SEQ_D:
29801 case R6_OPC_CMP_SEUQ_D:
29802 case R6_OPC_CMP_SLT_D:
29803 case R6_OPC_CMP_SULT_D:
29804 case R6_OPC_CMP_SLE_D:
29805 case R6_OPC_CMP_SULE_D:
29806 case R6_OPC_CMP_OR_D:
29807 case R6_OPC_CMP_UNE_D:
29808 case R6_OPC_CMP_NE_D:
29809 case R6_OPC_CMP_SOR_D:
29810 case R6_OPC_CMP_SUNE_D:
29811 case R6_OPC_CMP_SNE_D:
29812 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29813 break;
29814 default:
d2bfa6e6
MR
29815 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29816 rt, rd, sa, (imm >> 8) & 0x7);
29817
5692c6e1 29818 break;
3f493883 29819 }
5692c6e1
YK
29820 } else {
29821 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29822 (imm >> 8) & 0x7);
36d23958 29823 }
5692c6e1
YK
29824 break;
29825 }
29826 case OPC_BZ_V:
29827 case OPC_BNZ_V:
29828 case OPC_BZ_B:
29829 case OPC_BZ_H:
29830 case OPC_BZ_W:
29831 case OPC_BZ_D:
29832 case OPC_BNZ_B:
29833 case OPC_BNZ_H:
29834 case OPC_BNZ_W:
29835 case OPC_BNZ_D:
29836 check_insn(ctx, ASE_MSA);
29837 gen_msa_branch(env, ctx, op1);
29838 break;
29839 default:
29840 MIPS_INVAL("cp1");
9c708c7f 29841 generate_exception_end(ctx, EXCP_RI);
5692c6e1 29842 break;
6ea83fed 29843 }
4ad40f36
FB
29844 break;
29845
31837be3
YK
29846 /* Compact branches [R6] and COP2 [non-R6] */
29847 case OPC_BC: /* OPC_LWC2 */
29848 case OPC_BALC: /* OPC_SWC2 */
29849 if (ctx->insn_flags & ISA_MIPS32R6) {
29850 /* OPC_BC, OPC_BALC */
29851 gen_compute_compact_branch(ctx, op, 0, 0,
29852 sextract32(ctx->opcode << 2, 0, 28));
29853 } else {
29854 /* OPC_LWC2, OPC_SWC2 */
29855 /* COP2: Not implemented. */
29856 generate_exception_err(ctx, EXCP_CpU, 2);
29857 }
29858 break;
29859 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29860 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29861 if (ctx->insn_flags & ISA_MIPS32R6) {
29862 if (rs != 0) {
29863 /* OPC_BEQZC, OPC_BNEZC */
29864 gen_compute_compact_branch(ctx, op, rs, 0,
29865 sextract32(ctx->opcode << 2, 0, 23));
29866 } else {
29867 /* OPC_JIC, OPC_JIALC */
29868 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29869 }
29870 } else {
29871 /* OPC_LWC2, OPC_SWC2 */
29872 /* COP2: Not implemented. */
29873 generate_exception_err(ctx, EXCP_CpU, 2);
29874 }
4ad40f36 29875 break;
bd277fa1 29876 case OPC_CP2:
d75c135e 29877 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
29878 /* Note that these instructions use different fields. */
29879 gen_loongson_multimedia(ctx, sa, rd, rt);
29880 break;
4ad40f36 29881
7a387fff 29882 case OPC_CP3:
fecd2646 29883 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 29884 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 29885 check_cp1_enabled(ctx);
36d23958
TS
29886 op1 = MASK_CP3(ctx->opcode);
29887 switch (op1) {
d9224450
MR
29888 case OPC_LUXC1:
29889 case OPC_SUXC1:
29890 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29891 /* Fallthrough */
5a5012ec
TS
29892 case OPC_LWXC1:
29893 case OPC_LDXC1:
5a5012ec
TS
29894 case OPC_SWXC1:
29895 case OPC_SDXC1:
d9224450 29896 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 29897 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 29898 break;
e0c84da7 29899 case OPC_PREFX:
d9224450 29900 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 29901 /* Treat as NOP. */
e0c84da7 29902 break;
5a5012ec 29903 case OPC_ALNV_PS:
d9224450
MR
29904 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29905 /* Fallthrough */
5a5012ec
TS
29906 case OPC_MADD_S:
29907 case OPC_MADD_D:
29908 case OPC_MADD_PS:
29909 case OPC_MSUB_S:
29910 case OPC_MSUB_D:
29911 case OPC_MSUB_PS:
29912 case OPC_NMADD_S:
29913 case OPC_NMADD_D:
29914 case OPC_NMADD_PS:
29915 case OPC_NMSUB_S:
29916 case OPC_NMSUB_D:
29917 case OPC_NMSUB_PS:
d9224450 29918 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
29919 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29920 break;
36d23958 29921 default:
923617a3 29922 MIPS_INVAL("cp3");
9c708c7f 29923 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
29924 break;
29925 }
29926 } else {
e397ee33 29927 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 29928 }
4ad40f36
FB
29929 break;
29930
d26bc211 29931#if defined(TARGET_MIPS64)
7a387fff 29932 /* MIPS64 opcodes */
96631327 29933 case OPC_LLD:
55fc7a69
FN
29934 if (ctx->insn_flags & INSN_R5900) {
29935 check_insn_opc_user_only(ctx, INSN_R5900);
29936 }
96631327 29937 /* fall through */
c2e19f3c
AM
29938 case OPC_LDL:
29939 case OPC_LDR:
fecd2646 29940 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29941 /* fall through */
fecd2646 29942 case OPC_LWU:
7a387fff 29943 case OPC_LD:
d75c135e 29944 check_insn(ctx, ISA_MIPS3);
5c13fdfd 29945 check_mips_64(ctx);
d75c135e 29946 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29947 break;
c2e19f3c
AM
29948 case OPC_SDL:
29949 case OPC_SDR:
fecd2646 29950 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29951 /* fall through */
7a387fff 29952 case OPC_SD:
d75c135e 29953 check_insn(ctx, ISA_MIPS3);
e189e748 29954 check_mips_64(ctx);
5c13fdfd 29955 gen_st(ctx, op, rt, rs, imm);
7a387fff 29956 break;
d66c7132 29957 case OPC_SCD:
bf7910c6 29958 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 29959 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
29960 if (ctx->insn_flags & INSN_R5900) {
29961 check_insn_opc_user_only(ctx, INSN_R5900);
29962 }
d66c7132 29963 check_mips_64(ctx);
33a07fa2 29964 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 29965 break;
31837be3
YK
29966 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29967 if (ctx->insn_flags & ISA_MIPS32R6) {
29968 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29969 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29970 } else {
29971 /* OPC_DADDI */
29972 check_insn(ctx, ISA_MIPS3);
29973 check_mips_64(ctx);
29974 gen_arith_imm(ctx, op, rt, rs, imm);
29975 }
29976 break;
324d9e32 29977 case OPC_DADDIU:
d75c135e 29978 check_insn(ctx, ISA_MIPS3);
e189e748 29979 check_mips_64(ctx);
d75c135e 29980 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29981 break;
31837be3
YK
29982#else
29983 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29984 if (ctx->insn_flags & ISA_MIPS32R6) {
29985 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29986 } else {
29987 MIPS_INVAL("major opcode");
9c708c7f 29988 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29989 }
29990 break;
6af0bf9c 29991#endif
d4ea6acd
LA
29992 case OPC_DAUI: /* OPC_JALX */
29993 if (ctx->insn_flags & ISA_MIPS32R6) {
29994#if defined(TARGET_MIPS64)
29995 /* OPC_DAUI */
29996 check_mips_64(ctx);
db77d852
LA
29997 if (rs == 0) {
29998 generate_exception(ctx, EXCP_RI);
29999 } else if (rt != 0) {
d4ea6acd
LA
30000 TCGv t0 = tcg_temp_new();
30001 gen_load_gpr(t0, rs);
30002 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30003 tcg_temp_free(t0);
30004 }
d4ea6acd 30005#else
9c708c7f 30006 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
30007 MIPS_INVAL("major opcode");
30008#endif
30009 } else {
30010 /* OPC_JALX */
30011 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30012 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30013 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 30014 }
364d4831 30015 break;
4c789546 30016 case OPC_MSA: /* OPC_MDMX */
f08099ad 30017 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 30018#if defined(TARGET_MIPS64)
874b2879 30019 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
37b9aae2 30020#endif
f08099ad
FN
30021 } else {
30022 /* MDMX: Not implemented. */
30023 gen_msa(env, ctx);
30024 }
d4ea6acd
LA
30025 break;
30026 case OPC_PCREL:
30027 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 30028 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 30029 break;
6af0bf9c 30030 default: /* Invalid */
923617a3 30031 MIPS_INVAL("major opcode");
9c708c7f 30032 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30033 break;
30034 }
6af0bf9c
FB
30035}
30036
18f440ed 30037static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 30038{
18f440ed 30039 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 30040 CPUMIPSState *env = cs->env_ptr;
12be9258 30041
18f440ed 30042 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
30043 ctx->saved_pc = -1;
30044 ctx->insn_flags = env->insn_flags;
30045 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 30046 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
30047 ctx->CP0_Config3 = env->CP0_Config3;
30048 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
30049 ctx->btarget = 0;
30050 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30051 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30052 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30053 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30054 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30055 ctx->PAMask = env->PAMask;
30056 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30057 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30058 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30059 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30060 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 30061 /* Restore delay slot state from the tb context. */
12be9258
EC
30062 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30063 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30064 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 30065 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
30066 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30067 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30068 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30069 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
30070 restore_cpu_state(env, ctx);
932e71cd 30071#ifdef CONFIG_USER_ONLY
12be9258 30072 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 30073#else
12be9258 30074 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 30075#endif
12be9258
EC
30076 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30077 MO_UNALN : MO_ALIGN;
190ce7fb 30078
18f440ed
EC
30079 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30080 ctx->hflags);
30081}
12be9258 30082
18f440ed
EC
30083static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30084{
30085}
b933066a 30086
18f440ed
EC
30087static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30088{
30089 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30090
18f440ed
EC
30091 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30092 ctx->btarget);
30093}
31837be3 30094
18f440ed
EC
30095static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30096 const CPUBreakpoint *bp)
30097{
30098 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 30099
18f440ed
EC
30100 save_cpu_state(ctx, 1);
30101 ctx->base.is_jmp = DISAS_NORETURN;
30102 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
30103 /*
30104 * The address covered by the breakpoint must be included in
30105 * [tb->pc, tb->pc + tb->size) in order to for it to be
30106 * properly cleared -- thus we increment the PC here so that
30107 * the logic setting tb->size below does the right thing.
30108 */
18f440ed
EC
30109 ctx->base.pc_next += 4;
30110 return true;
30111}
4ad40f36 30112
18f440ed
EC
30113static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30114{
30115 CPUMIPSState *env = cs->env_ptr;
30116 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30117 int insn_bytes;
30118 int is_slot;
4ad40f36 30119
18f440ed 30120 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
30121 if (ctx->insn_flags & ISA_NANOMIPS32) {
30122 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30123 insn_bytes = decode_nanomips_opc(env, ctx);
30124 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
30125 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30126 insn_bytes = 4;
30127 decode_opc(env, ctx);
30128 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30129 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30130 insn_bytes = decode_micromips_opc(env, ctx);
30131 } else if (ctx->insn_flags & ASE_MIPS16) {
30132 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30133 insn_bytes = decode_mips16_opc(env, ctx);
30134 } else {
30135 generate_exception_end(ctx, EXCP_RI);
30136 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30137 return;
30138 }
faf7aaa9 30139
18f440ed
EC
30140 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30141 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30142 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
30143 /*
30144 * Force to generate branch as there is neither delay nor
30145 * forbidden slot.
30146 */
18f440ed
EC
30147 is_slot = 1;
30148 }
30149 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30150 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
30151 /*
30152 * Force to generate branch as microMIPS R6 doesn't restrict
30153 * branches in the forbidden slot.
30154 */
18f440ed 30155 is_slot = 1;
eeb3bba8 30156 }
18f440ed
EC
30157 }
30158 if (is_slot) {
30159 gen_branch(ctx, insn_bytes);
30160 }
30161 ctx->base.pc_next += insn_bytes;
1b530a6d 30162
18f440ed
EC
30163 if (ctx->base.is_jmp != DISAS_NEXT) {
30164 return;
6af0bf9c 30165 }
7480515f
AM
30166 /*
30167 * Execute a branch and its delay slot as a single instruction.
30168 * This is what GDB expects and is consistent with what the
30169 * hardware does (e.g. if a delay slot instruction faults, the
30170 * reported PC is the PC of the branch).
30171 */
18f440ed
EC
30172 if (ctx->base.singlestep_enabled &&
30173 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30174 ctx->base.is_jmp = DISAS_TOO_MANY;
30175 }
30176 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30177 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 30178 }
18f440ed
EC
30179}
30180
30181static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30182{
30183 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30184
12be9258
EC
30185 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30186 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 30187 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 30188 } else {
12be9258 30189 switch (ctx->base.is_jmp) {
b28425ba 30190 case DISAS_STOP:
12be9258 30191 gen_save_pc(ctx->base.pc_next);
cd314a7d 30192 tcg_gen_lookup_and_goto_ptr();
df1561e2 30193 break;
b28425ba 30194 case DISAS_NEXT:
18f440ed 30195 case DISAS_TOO_MANY:
12be9258
EC
30196 save_cpu_state(ctx, 0);
30197 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 30198 break;
b28425ba 30199 case DISAS_EXIT:
07ea28b4 30200 tcg_gen_exit_tb(NULL, 0);
16c00cb2 30201 break;
b28425ba 30202 case DISAS_NORETURN:
5a5012ec 30203 break;
18f440ed
EC
30204 default:
30205 g_assert_not_reached();
6958549d 30206 }
6af0bf9c 30207 }
18f440ed
EC
30208}
30209
30210static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30211{
30212 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30213 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30214}
30215
30216static const TranslatorOps mips_tr_ops = {
30217 .init_disas_context = mips_tr_init_disas_context,
30218 .tb_start = mips_tr_tb_start,
30219 .insn_start = mips_tr_insn_start,
30220 .breakpoint_check = mips_tr_breakpoint_check,
30221 .translate_insn = mips_tr_translate_insn,
30222 .tb_stop = mips_tr_tb_stop,
30223 .disas_log = mips_tr_disas_log,
30224};
30225
8b86d6d2 30226void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
30227{
30228 DisasContext ctx;
30229
8b86d6d2 30230 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
30231}
30232
71375b59 30233static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
30234{
30235 int i;
5e755519 30236 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 30237
2a5612e6
SW
30238#define printfpr(fp) \
30239 do { \
30240 if (is_fpu64) \
90c84c56
MA
30241 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30242 " fd:%13g fs:%13g psu: %13g\n", \
30243 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30244 (double)(fp)->fd, \
30245 (double)(fp)->fs[FP_ENDIAN_IDX], \
30246 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
30247 else { \
30248 fpr_t tmp; \
30249 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30250 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
30251 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30252 " fd:%13g fs:%13g psu:%13g\n", \
30253 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30254 (double)tmp.fd, \
30255 (double)tmp.fs[FP_ENDIAN_IDX], \
30256 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 30257 } \
71375b59 30258 } while (0)
6ea83fed 30259
5a5012ec 30260
90c84c56
MA
30261 qemu_fprintf(f,
30262 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30263 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30264 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 30265 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 30266 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 30267 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
30268 }
30269
30270#undef printfpr
30271}
30272
90c84c56 30273void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 30274{
878096ee
AF
30275 MIPSCPU *cpu = MIPS_CPU(cs);
30276 CPUMIPSState *env = &cpu->env;
6af0bf9c 30277 int i;
3b46e624 30278
90c84c56
MA
30279 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30280 " LO=0x" TARGET_FMT_lx " ds %04x "
30281 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30282 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30283 env->hflags, env->btarget, env->bcond);
6af0bf9c 30284 for (i = 0; i < 32; i++) {
1f8929d2 30285 if ((i & 3) == 0) {
90c84c56 30286 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 30287 }
90c84c56
MA
30288 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30289 regnames[i], env->active_tc.gpr[i]);
1f8929d2 30290 if ((i & 3) == 3) {
90c84c56 30291 qemu_fprintf(f, "\n");
1f8929d2 30292 }
90c84c56
MA
30293 }
30294
71375b59
AM
30295 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30296 TARGET_FMT_lx "\n",
90c84c56
MA
30297 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30298 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30299 PRIx64 "\n",
30300 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30301 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30302 env->CP0_Config2, env->CP0_Config3);
30303 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30304 env->CP0_Config4, env->CP0_Config5);
1cc5af69 30305 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 30306 fpu_dump_state(env, f, flags);
1cc5af69 30307 }
6af0bf9c
FB
30308}
30309
78ce64f4 30310void mips_tcg_init(void)
39454628 30311{
f01be154 30312 int i;
39454628 30313
f764718d 30314 cpu_gpr[0] = NULL;
bb928dbe 30315 for (i = 1; i < 32; i++)
e1ccc054 30316 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
71375b59
AM
30317 offsetof(CPUMIPSState,
30318 active_tc.gpr[i]),
4b2eb8d2 30319 regnames[i]);
d73ee8a2 30320
863f264d
YK
30321 for (i = 0; i < 32; i++) {
30322 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30323 msa_wr_d[i * 2] =
e1ccc054 30324 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
7480515f
AM
30325 /*
30326 * The scalar floating-point unit (FPU) registers are mapped on
30327 * the MSA vector registers.
30328 */
cb269f27 30329 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
30330 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30331 msa_wr_d[i * 2 + 1] =
e1ccc054 30332 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
30333 }
30334
e1ccc054 30335 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 30336 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 30337 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 30338 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 30339 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 30340 regnames_HI[i]);
e1ccc054 30341 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 30342 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 30343 regnames_LO[i]);
4b2eb8d2 30344 }
e1ccc054 30345 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
30346 offsetof(CPUMIPSState,
30347 active_tc.DSPControl),
4b2eb8d2 30348 "DSPControl");
e1ccc054 30349 bcond = tcg_global_mem_new(cpu_env,
7db13fae 30350 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 30351 btarget = tcg_global_mem_new(cpu_env,
7db13fae 30352 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 30353 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 30354 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 30355
e1ccc054 30356 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 30357 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 30358 "fcr0");
e1ccc054 30359 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 30360 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 30361 "fcr31");
33a07fa2
LA
30362 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30363 "lladdr");
30364 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30365 "llval");
a168a796
FN
30366
30367#if defined(TARGET_MIPS64)
30368 cpu_mmr[0] = NULL;
30369 for (i = 1; i < 32; i++) {
30370 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30371 offsetof(CPUMIPSState,
30372 active_tc.mmr[i]),
30373 regnames[i]);
30374 }
30375#endif
30376
b621f018 30377#if !defined(TARGET_MIPS64)
eb5559f6
CJ
30378 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30379 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30380 offsetof(CPUMIPSState,
30381 active_tc.mxu_gpr[i]),
30382 mxuregnames[i]);
30383 }
30384
30385 mxu_CR = tcg_global_mem_new(cpu_env,
30386 offsetof(CPUMIPSState, active_tc.mxu_cr),
30387 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 30388#endif
39454628
TS
30389}
30390
5b27a92d 30391#include "translate_init.inc.c"
aaed909a 30392
27e38392
PMD
30393void cpu_mips_realize_env(CPUMIPSState *env)
30394{
30395 env->exception_base = (int32_t)0xBFC00000;
30396
30397#ifndef CONFIG_USER_ONLY
30398 mmu_init(env, env->cpu_model);
30399#endif
30400 fpu_init(env, env->cpu_model);
30401 mvp_init(env, env->cpu_model);
30402}
30403
a7519f2b 30404bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 30405{
a7519f2b
IM
30406 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30407 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
30408}
30409
5b1e0981 30410bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
bed9e5ce 30411{
a7519f2b
IM
30412 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30413 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
30414}
30415
89777fd1
LA
30416void cpu_set_exception_base(int vp_index, target_ulong address)
30417{
30418 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30419 vp->env.exception_base = address;
30420}
30421
1bba0dc9 30422void cpu_state_reset(CPUMIPSState *env)
6ae81775 30423{
5a7330b3 30424 CPUState *cs = env_cpu(env);
6ae81775 30425
51cc2e78
BS
30426 /* Reset registers to their default values */
30427 env->CP0_PRid = env->cpu_model->CP0_PRid;
30428 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30429#ifdef TARGET_WORDS_BIGENDIAN
30430 env->CP0_Config0 |= (1 << CP0C0_BE);
30431#endif
30432 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30433 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30434 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
30435 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30436 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
30437 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30438 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
30439 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30440 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
30441 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30442 << env->cpu_model->CP0_LLAddr_shift;
30443 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
30444 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30445 env->CCRes = env->cpu_model->CCRes;
30446 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30447 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30448 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30449 env->current_tc = 0;
30450 env->SEGBITS = env->cpu_model->SEGBITS;
30451 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30452#if defined(TARGET_MIPS64)
30453 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30454 env->SEGMask |= 3ULL << 62;
30455 }
30456#endif
30457 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
30458 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30459 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30460 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30461 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30462 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30463 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30464 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30465 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30466 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30467 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
30468 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30469 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 30470 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 30471 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 30472 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 30473 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 30474 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
30475 env->insn_flags = env->cpu_model->insn_flags;
30476
0eaef5aa 30477#if defined(CONFIG_USER_ONLY)
03e6e501 30478 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
30479# ifdef TARGET_MIPS64
30480 /* Enable 64-bit register mode. */
30481 env->CP0_Status |= (1 << CP0St_PX);
30482# endif
30483# ifdef TARGET_ABI_MIPSN64
30484 /* Enable 64-bit address mode. */
30485 env->CP0_Status |= (1 << CP0St_UX);
30486# endif
7480515f
AM
30487 /*
30488 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30489 * hardware registers.
30490 */
94159135 30491 env->CP0_HWREna |= 0x0000000F;
91a75935 30492 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 30493 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 30494 }
6f0af304
PJ
30495 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30496 env->CP0_Status |= (1 << CP0St_MX);
853c3240 30497 }
4d66261f
PJ
30498# if defined(TARGET_MIPS64)
30499 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30500 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30501 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
30502 env->CP0_Status |= (1 << CP0St_FR);
30503 }
4d66261f 30504# endif
932e71cd
AJ
30505#else
30506 if (env->hflags & MIPS_HFLAG_BMASK) {
7480515f
AM
30507 /*
30508 * If the exception was raised from a delay slot,
30509 * come back to the jump.
30510 */
c3577479
MR
30511 env->CP0_ErrorEPC = (env->active_tc.PC
30512 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 30513 } else {
932e71cd
AJ
30514 env->CP0_ErrorEPC = env->active_tc.PC;
30515 }
89777fd1 30516 env->active_tc.PC = env->exception_base;
51cc2e78
BS
30517 env->CP0_Random = env->tlb->nb_tlb - 1;
30518 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 30519 env->CP0_Wired = 0;
01bc435b 30520 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 30521 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 30522 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
30523 env->CP0_EBase |= 0x40000000;
30524 } else {
74dbf824 30525 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 30526 }
c870e3f5
YK
30527 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30528 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30529 }
a0c80608
PB
30530 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30531 0x3ff : 0xff;
932e71cd 30532 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
7480515f
AM
30533 /*
30534 * Vectored interrupts not implemented, timer on int 7,
30535 * no performance counters.
30536 */
932e71cd
AJ
30537 env->CP0_IntCtl = 0xe0000000;
30538 {
30539 int i;
30540
30541 for (i = 0; i < 7; i++) {
30542 env->CP0_WatchLo[i] = 0;
30543 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 30544 }
932e71cd
AJ
30545 env->CP0_WatchLo[7] = 0;
30546 env->CP0_WatchHi[7] = 0;
fd88b6ab 30547 }
932e71cd
AJ
30548 /* Count register increments in debug mode, EJTAG version 1 */
30549 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 30550
4b69c7e2
JH
30551 cpu_mips_store_count(env, 1);
30552
9e56e756
EI
30553 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30554 int i;
30555
30556 /* Only TC0 on VPE 0 starts as active. */
30557 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 30558 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
30559 env->tcs[i].CP0_TCHalt = 1;
30560 }
30561 env->active_tc.CP0_TCHalt = 1;
259186a7 30562 cs->halted = 1;
9e56e756 30563
55e5c285 30564 if (cs->cpu_index == 0) {
9e56e756
EI
30565 /* VPE0 starts up enabled. */
30566 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30567 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30568
30569 /* TC0 starts up unhalted. */
259186a7 30570 cs->halted = 0;
9e56e756
EI
30571 env->active_tc.CP0_TCHalt = 0;
30572 env->tcs[0].CP0_TCHalt = 0;
30573 /* With thread 0 active. */
30574 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30575 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30576 }
30577 }
cec56a73
JH
30578
30579 /*
30580 * Configure default legacy segmentation control. We use this regardless of
30581 * whether segmentation control is presented to the guest.
30582 */
30583 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30584 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30585 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30586 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30587 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30588 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30589 (2 << CP0SC_C);
30590 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30591 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30592 (3 << CP0SC_C)) << 16;
30593 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30594 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30595 (1 << CP0SC_EU) | (2 << CP0SC_C);
30596 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30597 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30598 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30599 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30600 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 30601#endif
ddc584bd
LA
30602 if ((env->insn_flags & ISA_MIPS32R6) &&
30603 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30604 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30605 env->CP0_Status |= (1 << CP0St_FR);
30606 }
30607
63010795
YK
30608 if (env->insn_flags & ISA_MIPS32R6) {
30609 /* PTW = 1 */
30610 env->CP0_PWSize = 0x40;
30611 /* GDI = 12 */
30612 /* UDI = 12 */
30613 /* MDI = 12 */
30614 /* PRI = 12 */
30615 /* PTEI = 2 */
30616 env->CP0_PWField = 0x0C30C302;
30617 } else {
30618 /* GDI = 0 */
30619 /* UDI = 0 */
30620 /* MDI = 0 */
30621 /* PRI = 0 */
30622 /* PTEI = 2 */
30623 env->CP0_PWField = 0x02;
30624 }
30625
0bbc0396
SM
30626 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30627 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
30628 env->hflags |= MIPS_HFLAG_M16;
30629 }
30630
863f264d
YK
30631 /* MSA */
30632 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30633 msa_reset(env);
30634 }
30635
03e6e501 30636 compute_hflags(env);
599bc5e8 30637 restore_fp_status(env);
e117f526 30638 restore_pamask(env);
27103424 30639 cs->exception_index = EXCP_NONE;
3b3c1694
LA
30640
30641 if (semihosting_get_argc()) {
30642 /* UHI interface can be used to obtain argc and argv */
30643 env->active_tc.gpr[4] = -1;
30644 }
6af0bf9c 30645}
d2856f1a 30646
bad729e2
RH
30647void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30648 target_ulong *data)
d2856f1a 30649{
bad729e2 30650 env->active_tc.PC = data[0];
d2856f1a 30651 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 30652 env->hflags |= data[1];
4636401d
AJ
30653 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30654 case MIPS_HFLAG_BR:
30655 break;
30656 case MIPS_HFLAG_BC:
30657 case MIPS_HFLAG_BL:
30658 case MIPS_HFLAG_B:
bad729e2 30659 env->btarget = data[2];
4636401d
AJ
30660 break;
30661 }
d2856f1a 30662}