]> Git Repo - qemu.git/blame - target/mips/translate.c
target/mips: Inline cpu_state_reset() in mips_cpu_reset()
[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
89975214 13 * version 2.1 of the License, or (at your option) any later version.
6af0bf9c
FB
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"
dcb32f1d 27#include "tcg/tcg-op.h"
f08b6170 28#include "exec/cpu_ldst.h"
2ef6175a
RH
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
f1672e6f 31#include "hw/semihosting/semihost.h"
a7812ae4 32
b44a7fb1 33#include "target/mips/trace.h"
a7e30d84 34#include "trace-tcg.h"
b28425ba 35#include "exec/translator.h"
508127e2 36#include "exec/log.h"
0442428a 37#include "qemu/qemu-print.h"
a7e30d84 38
fb7729e2 39#define MIPS_DEBUG_DISAS 0
6af0bf9c 40
7a387fff 41/* MIPS major opcodes */
71375b59 42#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
43
44enum {
45 /* indirect opcode tables */
7a387fff
TS
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 54 /* arithmetic with immediate */
7a387fff
TS
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
324d9e32 59 /* logic with immediate */
7a387fff
TS
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
324d9e32 64 /* arithmetic with immediate */
7a387fff
TS
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
e37e863f 67 /* Jump and branches */
7a387fff
TS
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
b231c103 78 OPC_JALX = (0x1D << 26),
d4ea6acd 79 OPC_DAUI = (0x1D << 26),
e37e863f 80 /* Load and stores */
7a387fff
TS
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
364d4831 87 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
364d4831 102 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
e37e863f 106 /* Floating point load/store */
7a387fff
TS
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
31837be3
YK
115 /* Compact Branches */
116 OPC_BLEZALC = (0x06 << 26),
117 OPC_BGEZALC = (0x06 << 26),
118 OPC_BGEUC = (0x06 << 26),
119 OPC_BGTZALC = (0x07 << 26),
120 OPC_BLTZALC = (0x07 << 26),
121 OPC_BLTUC = (0x07 << 26),
122 OPC_BOVC = (0x08 << 26),
123 OPC_BEQZALC = (0x08 << 26),
124 OPC_BEQC = (0x08 << 26),
125 OPC_BLEZC = (0x16 << 26),
126 OPC_BGEZC = (0x16 << 26),
127 OPC_BGEC = (0x16 << 26),
128 OPC_BGTZC = (0x17 << 26),
129 OPC_BLTZC = (0x17 << 26),
130 OPC_BLTC = (0x17 << 26),
131 OPC_BNVC = (0x18 << 26),
132 OPC_BNEZALC = (0x18 << 26),
133 OPC_BNEC = (0x18 << 26),
134 OPC_BC = (0x32 << 26),
135 OPC_BEQZC = (0x36 << 26),
136 OPC_JIC = (0x36 << 26),
137 OPC_BALC = (0x3A << 26),
138 OPC_BNEZC = (0x3E << 26),
139 OPC_JIALC = (0x3E << 26),
7a387fff
TS
140 /* MDMX ASE specific */
141 OPC_MDMX = (0x1E << 26),
239dfebe
YK
142 /* MSA ASE, same as MDMX */
143 OPC_MSA = OPC_MDMX,
e37e863f 144 /* Cache and prefetch */
7a387fff
TS
145 OPC_CACHE = (0x2F << 26),
146 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
147 /* PC-relative address computation / loads */
148 OPC_PCREL = (0x3B << 26),
149};
150
151/* PC-relative address computation / loads */
71375b59
AM
152#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
153#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
154enum {
155 /* Instructions determined by bits 19 and 20 */
156 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
157 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
158 OPC_LWUPC = OPC_PCREL | (2 << 19),
159
160 /* Instructions determined by bits 16 ... 20 */
161 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
162 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
163
164 /* Other */
165 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
166};
167
168/* MIPS special opcodes */
71375b59 169#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 170
e37e863f
FB
171enum {
172 /* Shifts */
7a387fff 173 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
174 /* NOP is SLL r0, r0, 0 */
175 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
176 /* EHB is SLL r0, r0, 3 */
177 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 178 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
179 OPC_SRA = 0x03 | OPC_SPECIAL,
180 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 181 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 182 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
183 OPC_SRAV = 0x07 | OPC_SPECIAL,
184 OPC_DSLLV = 0x14 | OPC_SPECIAL,
185 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 186 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
187 OPC_DSRAV = 0x17 | OPC_SPECIAL,
188 OPC_DSLL = 0x38 | OPC_SPECIAL,
189 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 190 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
191 OPC_DSRA = 0x3B | OPC_SPECIAL,
192 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
193 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 194 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 195 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 196 /* Multiplication / division */
7a387fff
TS
197 OPC_MULT = 0x18 | OPC_SPECIAL,
198 OPC_MULTU = 0x19 | OPC_SPECIAL,
199 OPC_DIV = 0x1A | OPC_SPECIAL,
200 OPC_DIVU = 0x1B | OPC_SPECIAL,
201 OPC_DMULT = 0x1C | OPC_SPECIAL,
202 OPC_DMULTU = 0x1D | OPC_SPECIAL,
203 OPC_DDIV = 0x1E | OPC_SPECIAL,
204 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 205
e37e863f 206 /* 2 registers arithmetic / logic */
7a387fff
TS
207 OPC_ADD = 0x20 | OPC_SPECIAL,
208 OPC_ADDU = 0x21 | OPC_SPECIAL,
209 OPC_SUB = 0x22 | OPC_SPECIAL,
210 OPC_SUBU = 0x23 | OPC_SPECIAL,
211 OPC_AND = 0x24 | OPC_SPECIAL,
212 OPC_OR = 0x25 | OPC_SPECIAL,
213 OPC_XOR = 0x26 | OPC_SPECIAL,
214 OPC_NOR = 0x27 | OPC_SPECIAL,
215 OPC_SLT = 0x2A | OPC_SPECIAL,
216 OPC_SLTU = 0x2B | OPC_SPECIAL,
217 OPC_DADD = 0x2C | OPC_SPECIAL,
218 OPC_DADDU = 0x2D | OPC_SPECIAL,
219 OPC_DSUB = 0x2E | OPC_SPECIAL,
220 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 221 /* Jumps */
7a387fff
TS
222 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
223 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 224 /* Traps */
7a387fff
TS
225 OPC_TGE = 0x30 | OPC_SPECIAL,
226 OPC_TGEU = 0x31 | OPC_SPECIAL,
227 OPC_TLT = 0x32 | OPC_SPECIAL,
228 OPC_TLTU = 0x33 | OPC_SPECIAL,
229 OPC_TEQ = 0x34 | OPC_SPECIAL,
230 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 231 /* HI / LO registers load & stores */
7a387fff
TS
232 OPC_MFHI = 0x10 | OPC_SPECIAL,
233 OPC_MTHI = 0x11 | OPC_SPECIAL,
234 OPC_MFLO = 0x12 | OPC_SPECIAL,
235 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 236 /* Conditional moves */
7a387fff
TS
237 OPC_MOVZ = 0x0A | OPC_SPECIAL,
238 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 239
b691d9d2
LA
240 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
241 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
242
7a387fff 243 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
244
245 /* Special */
a0d700e4 246 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
247 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
248 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 249 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
250 OPC_SYNC = 0x0F | OPC_SPECIAL,
251
7a387fff
TS
252 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
253 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
254 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
255 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
256};
257
7480515f
AM
258/*
259 * R6 Multiply and Divide instructions have the same opcode
260 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
261 */
71375b59 262#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
263
264enum {
265 R6_OPC_MUL = OPC_MULT | (2 << 6),
266 R6_OPC_MUH = OPC_MULT | (3 << 6),
267 R6_OPC_MULU = OPC_MULTU | (2 << 6),
268 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
269 R6_OPC_DIV = OPC_DIV | (2 << 6),
270 R6_OPC_MOD = OPC_DIV | (3 << 6),
271 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
272 R6_OPC_MODU = OPC_DIVU | (3 << 6),
273
274 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
275 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
276 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
277 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
278 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
279 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
280 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
281 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
282
283 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
284 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
285 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
286 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
287 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
288
289 OPC_LSA = 0x05 | OPC_SPECIAL,
290 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
291};
292
e9c71dd1 293/* Multiplication variants of the vr54xx. */
71375b59 294#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
295
296enum {
297 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
298 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
299 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
300 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
301 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
302 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
304 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
305 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
306 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
307 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
308 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
309 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
310 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
311};
312
7a387fff 313/* REGIMM (rt field) opcodes */
71375b59 314#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
315
316enum {
317 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
318 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
319 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
320 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
321 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
322 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
323 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
324 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
325 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
326 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
327 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
328 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
329 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
330 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 331 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 332 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
333
334 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
335 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
336};
337
7a387fff 338/* Special2 opcodes */
71375b59 339#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 340
e37e863f 341enum {
7a387fff
TS
342 /* Multiply & xxx operations */
343 OPC_MADD = 0x00 | OPC_SPECIAL2,
344 OPC_MADDU = 0x01 | OPC_SPECIAL2,
345 OPC_MUL = 0x02 | OPC_SPECIAL2,
346 OPC_MSUB = 0x04 | OPC_SPECIAL2,
347 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
348 /* Loongson 2F */
349 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
350 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
351 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
352 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
353 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
354 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
355 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
356 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
357 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
358 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
359 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
360 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 361 /* Misc */
7a387fff
TS
362 OPC_CLZ = 0x20 | OPC_SPECIAL2,
363 OPC_CLO = 0x21 | OPC_SPECIAL2,
364 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
365 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 366 /* Special */
7a387fff
TS
367 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
368};
369
370/* Special3 opcodes */
71375b59 371#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
372
373enum {
374 OPC_EXT = 0x00 | OPC_SPECIAL3,
375 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
376 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
377 OPC_DEXT = 0x03 | OPC_SPECIAL3,
378 OPC_INS = 0x04 | OPC_SPECIAL3,
379 OPC_DINSM = 0x05 | OPC_SPECIAL3,
380 OPC_DINSU = 0x06 | OPC_SPECIAL3,
381 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
382 OPC_FORK = 0x08 | OPC_SPECIAL3,
383 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
384 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
385 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
386 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
99029be1 387 OPC_GINV = 0x3D | OPC_SPECIAL3,
161f85e6
AJ
388
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
402
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 425 /* MIPS DSP Append Sub-class */
26690560 426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 431
76964147
JH
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
449
4368b29a 450 /* R6 */
bf7910c6
LA
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
457};
458
e10a0ca1
JY
459/* Loongson EXT load/store quad word opcodes */
460#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
461enum {
462 OPC_GSLQ = 0x0020 | OPC_LWC2,
463 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
464 OPC_GSSHFL = OPC_LWC2,
465 OPC_GSSQ = 0x0020 | OPC_SWC2,
466 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
467 OPC_GSSHFS = OPC_SWC2,
468};
469
fd723105
JY
470/* Loongson EXT shifted load/store opcodes */
471#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
472enum {
473 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
474 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
475 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
476 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
477 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
478 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
479 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
480 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
481};
482
90e22a57
JY
483/* Loongson EXT LDC2/SDC2 opcodes */
484#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
485
486enum {
487 OPC_GSLBX = 0x0 | OPC_LDC2,
488 OPC_GSLHX = 0x1 | OPC_LDC2,
489 OPC_GSLWX = 0x2 | OPC_LDC2,
490 OPC_GSLDX = 0x3 | OPC_LDC2,
491 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
492 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
493 OPC_GSSBX = 0x0 | OPC_SDC2,
494 OPC_GSSHX = 0x1 | OPC_SDC2,
495 OPC_GSSWX = 0x2 | OPC_SDC2,
496 OPC_GSSDX = 0x3 | OPC_SDC2,
497 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
498 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
499};
500
7a387fff 501/* BSHFL opcodes */
71375b59 502#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 503
e37e863f 504enum {
15eacb9b
YK
505 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
506 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
507 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
508 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
509 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
510 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
511 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 512 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
513};
514
7a387fff 515/* DBSHFL opcodes */
71375b59 516#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 517
e37e863f 518enum {
15eacb9b
YK
519 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
520 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
521 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
522 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
523 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
524 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
525 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
526 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
527 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
528 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 529 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
530};
531
e45a93e2
JL
532/* MIPS DSP REGIMM opcodes */
533enum {
534 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 535 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
536};
537
71375b59 538#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
539/* MIPS DSP Load */
540enum {
541 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
542 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
543 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 544 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
545};
546
71375b59 547#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
548enum {
549 /* MIPS DSP Arithmetic Sub-class */
550 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
551 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
552 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
553 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
554 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
555 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
557 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
558 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
559 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
560 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
561 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
564 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
565 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
566 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
567 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
568 /* MIPS DSP Multiply Sub-class insns */
569 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
570 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
571 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
572 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
573 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
574 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
575};
576
577#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 578#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
579enum {
580 /* MIPS DSP Arithmetic Sub-class */
581 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
583 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
585 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
590 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
591 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
593 /* MIPS DSP Multiply Sub-class insns */
594 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
595 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
596 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
597 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
598};
599
71375b59 600#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
601enum {
602 /* MIPS DSP Arithmetic Sub-class */
603 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
616 /* DSP Bit/Manipulation Sub-class */
617 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
620 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
621 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
622};
623
71375b59 624#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
625enum {
626 /* MIPS DSP Arithmetic Sub-class */
627 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
634 /* DSP Compare-Pick Sub-class */
635 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 650};
a22260ae 651
71375b59 652#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
653enum {
654 /* MIPS DSP GPR-Based Shift Sub-class */
655 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
677};
461c08df 678
71375b59 679#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
680enum {
681 /* MIPS DSP Multiply Sub-class insns */
682 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
696 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
699 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
700 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
701 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
702 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
703 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
704};
705
71375b59 706#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
707enum {
708 /* DSP Bit/Manipulation Sub-class */
709 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
710};
711
71375b59 712#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 713enum {
df6126a7 714 /* MIPS DSP Append Sub-class */
26690560
JL
715 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
716 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
717 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
718};
719
71375b59 720#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
721enum {
722 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
723 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
727 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
735 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
736 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
737 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
738 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
739 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
740};
741
71375b59 742#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
743enum {
744 /* MIPS DSP Arithmetic Sub-class */
745 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
762 /* DSP Bit/Manipulation Sub-class */
763 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
766 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
767 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
768 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 769};
461c08df 770
71375b59 771#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 772enum {
a22260ae
JL
773 /* MIPS DSP Multiply Sub-class insns */
774 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
775 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
776 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
777 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
778 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
779 /* MIPS DSP Arithmetic Sub-class */
780 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
783 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
784 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
793 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
794 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
801};
461c08df 802
71375b59 803#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 804enum {
26690560
JL
805 /* DSP Compare-Pick Sub-class */
806 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
825 /* MIPS DSP Arithmetic Sub-class */
826 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
830 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
831 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
834};
461c08df 835
71375b59 836#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 837enum {
df6126a7 838 /* DSP Append Sub-class */
26690560
JL
839 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
840 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
841 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
842 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
843};
26690560 844
71375b59 845#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
846enum {
847 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
848 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
849 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
869};
870
71375b59 871#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
872enum {
873 /* DSP Bit/Manipulation Sub-class */
874 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
875};
1cb6686c 876
71375b59 877#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
878enum {
879 /* MIPS DSP Multiply Sub-class insns */
880 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
906};
a22260ae 907
71375b59 908#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
909enum {
910 /* MIPS DSP GPR-Based Shift Sub-class */
911 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
937};
77c5fa8b 938
7a387fff 939/* Coprocessor 0 (rs field) */
71375b59 940#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 941
6ea83fed 942enum {
7a387fff
TS
943 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
944 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 945 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
946 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
947 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 948 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 949 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
950 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
951 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 952 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
953 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
954 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
955 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
956 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
957 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
958 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
959 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
960 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
961 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
962 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
963 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
964 OPC_C0_A = (0x1A << 21) | OPC_CP0,
965 OPC_C0_B = (0x1B << 21) | OPC_CP0,
966 OPC_C0_C = (0x1C << 21) | OPC_CP0,
967 OPC_C0_D = (0x1D << 21) | OPC_CP0,
968 OPC_C0_E = (0x1E << 21) | OPC_CP0,
969 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 970};
7a387fff
TS
971
972/* MFMC0 opcodes */
71375b59 973#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
974
975enum {
ead9360e
TS
976 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
977 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
978 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
979 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
980 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
981 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
982 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
983 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
984};
985
986/* Coprocessor 0 (with rs == C0) */
71375b59 987#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
988
989enum {
990 OPC_TLBR = 0x01 | OPC_C0,
991 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
992 OPC_TLBINV = 0x03 | OPC_C0,
993 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
994 OPC_TLBWR = 0x06 | OPC_C0,
995 OPC_TLBP = 0x08 | OPC_C0,
996 OPC_RFE = 0x10 | OPC_C0,
997 OPC_ERET = 0x18 | OPC_C0,
998 OPC_DERET = 0x1F | OPC_C0,
999 OPC_WAIT = 0x20 | OPC_C0,
1000};
1001
1002/* Coprocessor 1 (rs field) */
71375b59 1003#define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 1004
bf4120ad
NF
1005/* Values for the fmt field in FP instructions */
1006enum {
1007 /* 0 - 15 are reserved */
e459440a
AJ
1008 FMT_S = 16, /* single fp */
1009 FMT_D = 17, /* double fp */
1010 FMT_E = 18, /* extended fp */
1011 FMT_Q = 19, /* quad fp */
1012 FMT_W = 20, /* 32-bit fixed */
1013 FMT_L = 21, /* 64-bit fixed */
1014 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
1015 /* 23 - 31 are reserved */
1016};
1017
7a387fff
TS
1018enum {
1019 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
1020 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
1021 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 1022 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
1023 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
1024 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
1025 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 1026 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 1027 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
1028 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
1029 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
1030 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
1031 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
1032 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
1033 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
1034 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
1035 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
1036 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
1037 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1038 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
1039 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1040 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
1041 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1042 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1043 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1044 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1045 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1046 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1047 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1048 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
1049};
1050
71375b59
AM
1051#define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1052#define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
5a5012ec 1053
7a387fff
TS
1054enum {
1055 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1056 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1057 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1058 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1059};
1060
5a5012ec
TS
1061enum {
1062 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1063 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1064};
1065
1066enum {
1067 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1068 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1069};
7a387fff 1070
71375b59 1071#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
1072
1073enum {
1074 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1075 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1076 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1077 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1078 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1079 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1080 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1081 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1082 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1083 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1084 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1085};
1086
8e2d5831 1087#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1088
1089enum {
71375b59
AM
1090 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1091 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1092 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1093 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1094 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1095 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1096 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1097 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1098
1099 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1100 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1101 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1102 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1103 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1104 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1105 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1106 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1107
1108 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1109 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1110 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1111 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1112 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1113 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1114 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1115 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1116
1117 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1118 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1119 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1120 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1121 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1122 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1123 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1124 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1125
1126 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1127 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1128 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1129 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1130 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1131 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1132
1133 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1134 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1135 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1136 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1137 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1138 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1139
1140 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1141 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1142 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1143 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1144 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1145 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1146
1147 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1148 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1149 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1150 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1151 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1152 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1153
1154 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1155 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1156 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1157 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1158 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1159 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1160
1161 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1162 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1163 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1164 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1165 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1166 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1167
1168 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1169 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1170 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1171 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1172 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1173 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1174
1175 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1176 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1177 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1178 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1179 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1180 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1181};
1182
1183
71375b59 1184#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1185
1186enum {
71375b59
AM
1187 OPC_LWXC1 = 0x00 | OPC_CP3,
1188 OPC_LDXC1 = 0x01 | OPC_CP3,
1189 OPC_LUXC1 = 0x05 | OPC_CP3,
1190 OPC_SWXC1 = 0x08 | OPC_CP3,
1191 OPC_SDXC1 = 0x09 | OPC_CP3,
1192 OPC_SUXC1 = 0x0D | OPC_CP3,
1193 OPC_PREFX = 0x0F | OPC_CP3,
1194 OPC_ALNV_PS = 0x1E | OPC_CP3,
1195 OPC_MADD_S = 0x20 | OPC_CP3,
1196 OPC_MADD_D = 0x21 | OPC_CP3,
1197 OPC_MADD_PS = 0x26 | OPC_CP3,
1198 OPC_MSUB_S = 0x28 | OPC_CP3,
1199 OPC_MSUB_D = 0x29 | OPC_CP3,
1200 OPC_MSUB_PS = 0x2E | OPC_CP3,
1201 OPC_NMADD_S = 0x30 | OPC_CP3,
1202 OPC_NMADD_D = 0x31 | OPC_CP3,
1203 OPC_NMADD_PS = 0x36 | OPC_CP3,
1204 OPC_NMSUB_S = 0x38 | OPC_CP3,
1205 OPC_NMSUB_D = 0x39 | OPC_CP3,
1206 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1207};
1208
239dfebe 1209/* MSA Opcodes */
71375b59 1210#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
239dfebe
YK
1211enum {
1212 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1213 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1214 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1215 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1216 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1217 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1218 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1219 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1220 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1221 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1222 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1223 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1224 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1225 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1226 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1227 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1228 OPC_MSA_ELM = 0x19 | OPC_MSA,
1229 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1230 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1231 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1232 OPC_MSA_VEC = 0x1E | OPC_MSA,
1233
1234 /* MI10 instruction */
71375b59
AM
1235 OPC_LD_B = (0x20) | OPC_MSA,
1236 OPC_LD_H = (0x21) | OPC_MSA,
1237 OPC_LD_W = (0x22) | OPC_MSA,
1238 OPC_LD_D = (0x23) | OPC_MSA,
1239 OPC_ST_B = (0x24) | OPC_MSA,
1240 OPC_ST_H = (0x25) | OPC_MSA,
1241 OPC_ST_W = (0x26) | OPC_MSA,
1242 OPC_ST_D = (0x27) | OPC_MSA,
239dfebe
YK
1243};
1244
1245enum {
1246 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1247 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1248 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1249 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1250 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1251 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1252 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1253 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1254 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1255 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1256 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1257 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1258 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1259
1260 /* I8 instruction */
71375b59
AM
1261 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1262 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1263 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1264 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1265 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1266 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1267 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1268 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1269 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1270 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
239dfebe
YK
1271
1272 /* VEC/2R/2RF instruction */
71375b59
AM
1273 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1274 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1275 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1276 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1277 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1278 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1279 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
239dfebe
YK
1280
1281 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1282 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1283
1284 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
71375b59
AM
1285 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1286 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1287 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1288 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
239dfebe
YK
1289
1290 /* 2RF instruction df(bit 16) = _w, _d */
1291 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1292 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1293 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1294 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1295 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1296 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1297 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1298 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1299 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1300 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1301 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1302 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1303 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1304 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1305 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1306 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1307
1308 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1309 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1310 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1311 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1312 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1313 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1314 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1315 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1316 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1317 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1318 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1319 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1320 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1321 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1322 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1323 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1324 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1325 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1326 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1327 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1328 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1329 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1330 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1331 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1332 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1333 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1334 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1335 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1336 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1337 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1338 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1339 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1340 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1341 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1342 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1343 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1344 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1345 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1346 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1347 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1348 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1349 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1350 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1351 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1352 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1353 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1354 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1355 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1356 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1357 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1358 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1359 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1360 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1361 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1362 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1363 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1364 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1365 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1366 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1367 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1368 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1369 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1370 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1371 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1372
1373 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1374 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1375 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1376 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1377 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1378 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1379 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1380 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1381 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1382 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1383
1384 /* 3RF instruction _df(bit 21) = _w, _d */
1385 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1386 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1387 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1388 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1389 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1390 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1391 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1392 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1393 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1394 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1395 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1396 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1397 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1398 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1399 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1400 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1401 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1402 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1403 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1404 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1405 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1406 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1407 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1408 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1409 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1410 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1411 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1412 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1413 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1414 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1415 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1416 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1417 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1418 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1419 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1420 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1421 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1422 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1423 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1424 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1425 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1426
1427 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1428 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1429 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1430 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1431 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1432 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1433 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1434 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1435 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1436 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1437 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1438 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1439 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1440};
1441
b158d449
AM
1442
1443/*
b158d449 1444 *
84e2c895
AM
1445 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1446 * ============================================
1447 *
1448 *
1449 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
b158d449
AM
1450 * instructions set. It is designed to fit the needs of signal, graphical and
1451 * video processing applications. MXU instruction set is used in Xburst family
1452 * of microprocessors by Ingenic.
1453 *
1454 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1455 * the control register.
1456 *
093ade12 1457 *
84e2c895
AM
1458 * The notation used in MXU assembler mnemonics
1459 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1460 *
1461 * Register operands:
1d0e663c
AM
1462 *
1463 * XRa, XRb, XRc, XRd - MXU registers
1464 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
093ade12 1465 *
84e2c895 1466 * Non-register operands:
093ade12 1467 *
84e2c895
AM
1468 * aptn1 - 1-bit accumulate add/subtract pattern
1469 * aptn2 - 2-bit accumulate add/subtract pattern
1470 * eptn2 - 2-bit execute add/subtract pattern
1471 * optn2 - 2-bit operand pattern
1472 * optn3 - 3-bit operand pattern
1473 * sft4 - 4-bit shift amount
1474 * strd2 - 2-bit stride amount
093ade12
AM
1475 *
1476 * Prefixes:
1477 *
84e2c895
AM
1478 * Level of parallelism: Operand size:
1479 * S - single operation at a time 32 - word
1480 * D - two operations in parallel 16 - half word
1481 * Q - four operations in parallel 8 - byte
093ade12
AM
1482 *
1483 * Operations:
1484 *
1485 * ADD - Add or subtract
1486 * ADDC - Add with carry-in
1487 * ACC - Accumulate
1488 * ASUM - Sum together then accumulate (add or subtract)
1489 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1490 * AVG - Average between 2 operands
1491 * ABD - Absolute difference
1492 * ALN - Align data
1493 * AND - Logical bitwise 'and' operation
1494 * CPS - Copy sign
1495 * EXTR - Extract bits
1496 * I2M - Move from GPR register to MXU register
1497 * LDD - Load data from memory to XRF
1498 * LDI - Load data from memory to XRF (and increase the address base)
1499 * LUI - Load unsigned immediate
1500 * MUL - Multiply
1501 * MULU - Unsigned multiply
1502 * MADD - 64-bit operand add 32x32 product
1503 * MSUB - 64-bit operand subtract 32x32 product
1504 * MAC - Multiply and accumulate (add or subtract)
1505 * MAD - Multiply and add or subtract
1506 * MAX - Maximum between 2 operands
1507 * MIN - Minimum between 2 operands
1508 * M2I - Move from MXU register to GPR register
1509 * MOVZ - Move if zero
1510 * MOVN - Move if non-zero
1511 * NOR - Logical bitwise 'nor' operation
1512 * OR - Logical bitwise 'or' operation
1513 * STD - Store data from XRF to memory
1514 * SDI - Store data from XRF to memory (and increase the address base)
1515 * SLT - Set of less than comparison
1516 * SAD - Sum of absolute differences
1517 * SLL - Logical shift left
1518 * SLR - Logical shift right
1519 * SAR - Arithmetic shift right
1520 * SAT - Saturation
1521 * SFL - Shuffle
1522 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1523 * XOR - Logical bitwise 'exclusive or' operation
1d0e663c 1524 *
84e2c895
AM
1525 * Suffixes:
1526 *
1527 * E - Expand results
1528 * F - Fixed point multiplication
1529 * L - Low part result
1530 * R - Doing rounding
1531 * V - Variable instead of immediate
1532 * W - Combine above L and V
1533 *
1534 *
1535 * The list of MXU instructions grouped by functionality
1536 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1537 *
1d0e663c
AM
1538 * Load/Store instructions Multiplication instructions
1539 * ----------------------- ---------------------------
1540 *
1541 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1542 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
093ade12
AM
1543 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1544 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1d0e663c
AM
1545 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1546 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1547 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1548 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1549 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1550 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1551 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1552 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1553 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1554 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1555 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1556 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1557 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1558 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1559 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1560 * S16SDI XRa, Rb, s10, eptn2
1561 * S8LDD XRa, Rb, s8, eptn3
1562 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1563 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1564 * S8SDI XRa, Rb, s8, eptn3
1565 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1566 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1567 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1568 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1569 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1570 * S32CPS XRa, XRb, XRc
1571 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1572 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1573 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1574 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1575 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1576 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1577 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1578 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1579 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1580 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1581 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1582 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1583 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1584 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1585 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1586 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1587 * Q8SLT XRa, XRb, XRc
1588 * Q8SLTU XRa, XRb, XRc
1589 * Q8MOVZ XRa, XRb, XRc Shift instructions
1590 * Q8MOVN XRa, XRb, XRc ------------------
1591 *
1592 * D32SLL XRa, XRb, XRc, XRd, sft4
1593 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1594 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1595 * D32SARL XRa, XRb, XRc, sft4
1596 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1597 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1598 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1599 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1600 * Q16SLL XRa, XRb, XRc, XRd, sft4
1601 * Q16SLR XRa, XRb, XRc, XRd, sft4
eab0bdb0 1602 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1d0e663c
AM
1603 * ------------------------- Q16SLLV XRa, XRb, Rb
1604 * Q16SLRV XRa, XRb, Rb
1605 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1606 * S32ALN XRa, XRb, XRc, Rb
1607 * S32ALNI XRa, XRb, XRc, s3
1608 * S32LUI XRa, s8, optn3 Move instructions
1609 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1610 * S32EXTRV XRa, XRb, Rs, Rt
1611 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1612 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1613 *
9ef5bff9 1614 *
84e2c895
AM
1615 * The opcode organization of MXU instructions
1616 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1617 *
1618 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1619 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1620 * other bits up to the instruction level is as follows:
1621 *
9ef5bff9
AM
1622 * bits
1623 * 05..00
1624 *
1625 * ┌─ 000000 ─ OPC_MXU_S32MADD
1626 * ├─ 000001 ─ OPC_MXU_S32MADDU
eab0bdb0
AM
1627 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1628 * │
9ef5bff9
AM
1629 * │ 20..18
1630 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1631 * │ ├─ 001 ─ OPC_MXU_S32MIN
1632 * │ ├─ 010 ─ OPC_MXU_D16MAX
1633 * │ ├─ 011 ─ OPC_MXU_D16MIN
1634 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1635 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1636 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1637 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1638 * ├─ 000100 ─ OPC_MXU_S32MSUB
1639 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1640 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1641 * │ ├─ 001 ─ OPC_MXU_D16SLT
1642 * │ ├─ 010 ─ OPC_MXU_D16AVG
1643 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1644 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1645 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1646 * │ └─ 111 ─ OPC_MXU_Q8ADD
1647 * │
1648 * │ 20..18
1649 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1650 * │ ├─ 010 ─ OPC_MXU_D16CPS
1651 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1652 * │ └─ 110 ─ OPC_MXU_Q16SAT
1653 * ├─ 001000 ─ OPC_MXU_D16MUL
1654 * │ 25..24
1655 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1656 * │ └─ 01 ─ OPC_MXU_D16MULE
1657 * ├─ 001010 ─ OPC_MXU_D16MAC
1658 * ├─ 001011 ─ OPC_MXU_D16MACF
1659 * ├─ 001100 ─ OPC_MXU_D16MADL
eab0bdb0 1660 * ├─ 001101 ─ OPC_MXU_S16MAD
9ef5bff9 1661 * ├─ 001110 ─ OPC_MXU_Q16ADD
eab0bdb0
AM
1662 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1663 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1664 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
9ef5bff9
AM
1665 * │
1666 * │ 23
eab0bdb0 1667 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
9ef5bff9
AM
1668 * │ └─ 1 ─ OPC_MXU_S32STDR
1669 * │
1670 * │ 13..10
eab0bdb0 1671 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
9ef5bff9
AM
1672 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1673 * │
1674 * │ 13..10
eab0bdb0 1675 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
9ef5bff9
AM
1676 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1677 * │
1678 * │ 23
eab0bdb0 1679 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
9ef5bff9
AM
1680 * │ └─ 1 ─ OPC_MXU_S32LDIR
1681 * │
1682 * │ 23
eab0bdb0 1683 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
9ef5bff9
AM
1684 * │ └─ 1 ─ OPC_MXU_S32SDIR
1685 * │
1686 * │ 13..10
eab0bdb0 1687 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
9ef5bff9
AM
1688 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1689 * │
1690 * │ 13..10
eab0bdb0 1691 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
9ef5bff9
AM
1692 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1693 * ├─ 011000 ─ OPC_MXU_D32ADD
1694 * │ 23..22
eab0bdb0 1695 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
9ef5bff9
AM
1696 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1697 * │ └─ 10 ─ OPC_MXU_D32ASUM
1698 * ├─ 011010 ─ <not assigned>
1699 * │ 23..22
eab0bdb0 1700 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
9ef5bff9
AM
1701 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1702 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1703 * │
1704 * │ 23..22
eab0bdb0 1705 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
9ef5bff9
AM
1706 * │ ├─ 01 ─ OPC_MXU_D8SUM
1707 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1708 * ├─ 011110 ─ <not assigned>
1709 * ├─ 011111 ─ <not assigned>
eab0bdb0
AM
1710 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1711 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
9ef5bff9 1712 * ├─ 100010 ─ OPC_MXU_S8LDD
eab0bdb0
AM
1713 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1714 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1715 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
9ef5bff9 1716 * │ ├─ 00 ─ OPC_MXU_S32EXTR
eab0bdb0 1717 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
9ef5bff9
AM
1718 * │
1719 * │ 20..18
eab0bdb0 1720 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
9ef5bff9 1721 * │ ├─ 001 ─ OPC_MXU_S32ALN
c233bf07 1722 * │ ├─ 010 ─ OPC_MXU_S32ALNI
b621f018
AM
1723 * │ ├─ 011 ─ OPC_MXU_S32LUI
1724 * │ ├─ 100 ─ OPC_MXU_S32NOR
1725 * │ ├─ 101 ─ OPC_MXU_S32AND
1726 * │ ├─ 110 ─ OPC_MXU_S32OR
1727 * │ └─ 111 ─ OPC_MXU_S32XOR
c233bf07
AM
1728 * │
1729 * │ 7..5
1730 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1731 * │ ├─ 001 ─ OPC_MXU_LXH
1732 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1733 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1734 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1735 * ├─ 101100 ─ OPC_MXU_S16LDI
1736 * ├─ 101101 ─ OPC_MXU_S16SDI
9ef5bff9
AM
1737 * ├─ 101110 ─ OPC_MXU_S32M2I
1738 * ├─ 101111 ─ OPC_MXU_S32I2M
1739 * ├─ 110000 ─ OPC_MXU_D32SLL
eab0bdb0
AM
1740 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1741 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1742 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1743 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1744 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
9ef5bff9 1745 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
c233bf07 1746 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
eab0bdb0 1747 * │
9ef5bff9
AM
1748 * ├─ 110111 ─ OPC_MXU_Q16SAR
1749 * │ 23..22
c233bf07 1750 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
9ef5bff9
AM
1751 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1752 * │
1753 * │ 20..18
c233bf07 1754 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
9ef5bff9
AM
1755 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1756 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1757 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1758 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
84e2c895 1759 * │ └─ 101 ─ OPC_MXU_S32MOVN
9ef5bff9
AM
1760 * │
1761 * │ 23..22
c233bf07 1762 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
9ef5bff9
AM
1763 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1764 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1765 * ├─ 111100 ─ OPC_MXU_Q8MADL
1766 * ├─ 111101 ─ OPC_MXU_S32SFL
1767 * ├─ 111110 ─ OPC_MXU_Q8SAD
eab0bdb0 1768 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
9ef5bff9
AM
1769 *
1770 *
84e2c895 1771 * Compiled after:
b158d449
AM
1772 *
1773 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
84e2c895 1774 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
b158d449
AM
1775 */
1776
8bacd1ff
AM
1777enum {
1778 OPC_MXU_S32MADD = 0x00,
1779 OPC_MXU_S32MADDU = 0x01,
11d56f61 1780 OPC__MXU_MUL = 0x02,
8bacd1ff
AM
1781 OPC_MXU__POOL00 = 0x03,
1782 OPC_MXU_S32MSUB = 0x04,
1783 OPC_MXU_S32MSUBU = 0x05,
1784 OPC_MXU__POOL01 = 0x06,
1785 OPC_MXU__POOL02 = 0x07,
1786 OPC_MXU_D16MUL = 0x08,
1787 OPC_MXU__POOL03 = 0x09,
1788 OPC_MXU_D16MAC = 0x0A,
1789 OPC_MXU_D16MACF = 0x0B,
1790 OPC_MXU_D16MADL = 0x0C,
eab0bdb0 1791 OPC_MXU_S16MAD = 0x0D,
8bacd1ff
AM
1792 OPC_MXU_Q16ADD = 0x0E,
1793 OPC_MXU_D16MACE = 0x0F,
eab0bdb0
AM
1794 OPC_MXU__POOL04 = 0x10,
1795 OPC_MXU__POOL05 = 0x11,
1796 OPC_MXU__POOL06 = 0x12,
1797 OPC_MXU__POOL07 = 0x13,
1798 OPC_MXU__POOL08 = 0x14,
1799 OPC_MXU__POOL09 = 0x15,
1800 OPC_MXU__POOL10 = 0x16,
1801 OPC_MXU__POOL11 = 0x17,
8bacd1ff 1802 OPC_MXU_D32ADD = 0x18,
eab0bdb0 1803 OPC_MXU__POOL12 = 0x19,
8bacd1ff 1804 /* not assigned 0x1A */
eab0bdb0
AM
1805 OPC_MXU__POOL13 = 0x1B,
1806 OPC_MXU__POOL14 = 0x1C,
8bacd1ff
AM
1807 OPC_MXU_Q8ACCE = 0x1D,
1808 /* not assigned 0x1E */
1809 /* not assigned 0x1F */
1810 /* not assigned 0x20 */
1811 /* not assigned 0x21 */
1812 OPC_MXU_S8LDD = 0x22,
1813 OPC_MXU_S8STD = 0x23,
1814 OPC_MXU_S8LDI = 0x24,
1815 OPC_MXU_S8SDI = 0x25,
eab0bdb0
AM
1816 OPC_MXU__POOL15 = 0x26,
1817 OPC_MXU__POOL16 = 0x27,
c233bf07 1818 OPC_MXU__POOL17 = 0x28,
8bacd1ff
AM
1819 /* not assigned 0x29 */
1820 OPC_MXU_S16LDD = 0x2A,
1821 OPC_MXU_S16STD = 0x2B,
1822 OPC_MXU_S16LDI = 0x2C,
1823 OPC_MXU_S16SDI = 0x2D,
1824 OPC_MXU_S32M2I = 0x2E,
1825 OPC_MXU_S32I2M = 0x2F,
1826 OPC_MXU_D32SLL = 0x30,
1827 OPC_MXU_D32SLR = 0x31,
1828 OPC_MXU_D32SARL = 0x32,
1829 OPC_MXU_D32SAR = 0x33,
1830 OPC_MXU_Q16SLL = 0x34,
1831 OPC_MXU_Q16SLR = 0x35,
c233bf07 1832 OPC_MXU__POOL18 = 0x36,
8bacd1ff 1833 OPC_MXU_Q16SAR = 0x37,
c233bf07
AM
1834 OPC_MXU__POOL19 = 0x38,
1835 OPC_MXU__POOL20 = 0x39,
1836 OPC_MXU__POOL21 = 0x3A,
8bacd1ff
AM
1837 OPC_MXU_Q16SCOP = 0x3B,
1838 OPC_MXU_Q8MADL = 0x3C,
1839 OPC_MXU_S32SFL = 0x3D,
1840 OPC_MXU_Q8SAD = 0x3E,
1841 /* not assigned 0x3F */
1842};
1843
1844
1845/*
1846 * MXU pool 00
1847 */
1848enum {
1849 OPC_MXU_S32MAX = 0x00,
1850 OPC_MXU_S32MIN = 0x01,
1851 OPC_MXU_D16MAX = 0x02,
1852 OPC_MXU_D16MIN = 0x03,
1853 OPC_MXU_Q8MAX = 0x04,
1854 OPC_MXU_Q8MIN = 0x05,
1855 OPC_MXU_Q8SLT = 0x06,
1856 OPC_MXU_Q8SLTU = 0x07,
1857};
1858
1859/*
1860 * MXU pool 01
1861 */
1862enum {
1863 OPC_MXU_S32SLT = 0x00,
1864 OPC_MXU_D16SLT = 0x01,
1865 OPC_MXU_D16AVG = 0x02,
1866 OPC_MXU_D16AVGR = 0x03,
1867 OPC_MXU_Q8AVG = 0x04,
1868 OPC_MXU_Q8AVGR = 0x05,
1869 OPC_MXU_Q8ADD = 0x07,
1870};
1871
1872/*
1873 * MXU pool 02
1874 */
1875enum {
1876 OPC_MXU_S32CPS = 0x00,
1877 OPC_MXU_D16CPS = 0x02,
1878 OPC_MXU_Q8ABD = 0x04,
1879 OPC_MXU_Q16SAT = 0x06,
1880};
1881
1882/*
1883 * MXU pool 03
1884 */
1885enum {
1886 OPC_MXU_D16MULF = 0x00,
1887 OPC_MXU_D16MULE = 0x01,
1888};
1889
1890/*
1891 * MXU pool 04
1892 */
8bacd1ff
AM
1893enum {
1894 OPC_MXU_S32LDD = 0x00,
1895 OPC_MXU_S32LDDR = 0x01,
1896};
1897
1898/*
eab0bdb0 1899 * MXU pool 05
8bacd1ff
AM
1900 */
1901enum {
1902 OPC_MXU_S32STD = 0x00,
1903 OPC_MXU_S32STDR = 0x01,
1904};
1905
1906/*
eab0bdb0 1907 * MXU pool 06
8bacd1ff
AM
1908 */
1909enum {
1910 OPC_MXU_S32LDDV = 0x00,
1911 OPC_MXU_S32LDDVR = 0x01,
1912};
1913
1914/*
eab0bdb0 1915 * MXU pool 07
8bacd1ff
AM
1916 */
1917enum {
1918 OPC_MXU_S32STDV = 0x00,
1919 OPC_MXU_S32STDVR = 0x01,
1920};
1921
1922/*
eab0bdb0 1923 * MXU pool 08
8bacd1ff
AM
1924 */
1925enum {
1926 OPC_MXU_S32LDI = 0x00,
1927 OPC_MXU_S32LDIR = 0x01,
1928};
1929
1930/*
eab0bdb0 1931 * MXU pool 09
8bacd1ff
AM
1932 */
1933enum {
1934 OPC_MXU_S32SDI = 0x00,
1935 OPC_MXU_S32SDIR = 0x01,
1936};
1937
1938/*
eab0bdb0 1939 * MXU pool 10
8bacd1ff
AM
1940 */
1941enum {
1942 OPC_MXU_S32LDIV = 0x00,
1943 OPC_MXU_S32LDIVR = 0x01,
1944};
1945
1946/*
eab0bdb0 1947 * MXU pool 11
8bacd1ff
AM
1948 */
1949enum {
1950 OPC_MXU_S32SDIV = 0x00,
1951 OPC_MXU_S32SDIVR = 0x01,
1952};
1953
1954/*
eab0bdb0 1955 * MXU pool 12
8bacd1ff
AM
1956 */
1957enum {
1958 OPC_MXU_D32ACC = 0x00,
1959 OPC_MXU_D32ACCM = 0x01,
1960 OPC_MXU_D32ASUM = 0x02,
1961};
1962
1963/*
eab0bdb0 1964 * MXU pool 13
8bacd1ff
AM
1965 */
1966enum {
1967 OPC_MXU_Q16ACC = 0x00,
1968 OPC_MXU_Q16ACCM = 0x01,
1969 OPC_MXU_Q16ASUM = 0x02,
1970};
1971
1972/*
eab0bdb0 1973 * MXU pool 14
8bacd1ff
AM
1974 */
1975enum {
1976 OPC_MXU_Q8ADDE = 0x00,
1977 OPC_MXU_D8SUM = 0x01,
1978 OPC_MXU_D8SUMC = 0x02,
1979};
1980
1981/*
eab0bdb0 1982 * MXU pool 15
8bacd1ff
AM
1983 */
1984enum {
1985 OPC_MXU_S32MUL = 0x00,
1986 OPC_MXU_S32MULU = 0x01,
1987 OPC_MXU_S32EXTR = 0x02,
1988 OPC_MXU_S32EXTRV = 0x03,
1989};
1990
1991/*
eab0bdb0 1992 * MXU pool 16
8bacd1ff
AM
1993 */
1994enum {
1995 OPC_MXU_D32SARW = 0x00,
1996 OPC_MXU_S32ALN = 0x01,
1997 OPC_MXU_S32ALNI = 0x02,
b621f018
AM
1998 OPC_MXU_S32LUI = 0x03,
1999 OPC_MXU_S32NOR = 0x04,
2000 OPC_MXU_S32AND = 0x05,
2001 OPC_MXU_S32OR = 0x06,
2002 OPC_MXU_S32XOR = 0x07,
8bacd1ff
AM
2003};
2004
2005/*
eab0bdb0 2006 * MXU pool 17
8bacd1ff 2007 */
c233bf07
AM
2008enum {
2009 OPC_MXU_LXB = 0x00,
2010 OPC_MXU_LXH = 0x01,
2011 OPC_MXU_LXW = 0x03,
2012 OPC_MXU_LXBU = 0x04,
2013 OPC_MXU_LXHU = 0x05,
2014};
2015
2016/*
2017 * MXU pool 18
2018 */
8bacd1ff
AM
2019enum {
2020 OPC_MXU_D32SLLV = 0x00,
2021 OPC_MXU_D32SLRV = 0x01,
2022 OPC_MXU_D32SARV = 0x03,
2023 OPC_MXU_Q16SLLV = 0x04,
2024 OPC_MXU_Q16SLRV = 0x05,
2025 OPC_MXU_Q16SARV = 0x07,
2026};
2027
2028/*
c233bf07 2029 * MXU pool 19
8bacd1ff
AM
2030 */
2031enum {
2032 OPC_MXU_Q8MUL = 0x00,
2033 OPC_MXU_Q8MULSU = 0x01,
2034};
2035
2036/*
c233bf07 2037 * MXU pool 20
8bacd1ff
AM
2038 */
2039enum {
2040 OPC_MXU_Q8MOVZ = 0x00,
2041 OPC_MXU_Q8MOVN = 0x01,
2042 OPC_MXU_D16MOVZ = 0x02,
2043 OPC_MXU_D16MOVN = 0x03,
2044 OPC_MXU_S32MOVZ = 0x04,
2045 OPC_MXU_S32MOVN = 0x05,
2046};
2047
2048/*
c233bf07 2049 * MXU pool 21
8bacd1ff
AM
2050 */
2051enum {
2052 OPC_MXU_Q8MAC = 0x00,
2053 OPC_MXU_Q8MACSU = 0x01,
2054};
2055
497f072b
FN
2056/*
2057 * Overview of the TX79-specific instruction set
2058 * =============================================
2059 *
2060 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2061 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2062 * instructions and certain multimedia instructions (MMIs). These MMIs
2063 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2064 * or sixteen 8-bit paths.
2065 *
2066 * Reference:
2067 *
2068 * The Toshiba TX System RISC TX79 Core Architecture manual,
2069 * https://wiki.qemu.org/File:C790.pdf
2070 *
2071 * Three-Operand Multiply and Multiply-Add (4 instructions)
2072 * --------------------------------------------------------
2073 * MADD [rd,] rs, rt Multiply/Add
2074 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2075 * MULT [rd,] rs, rt Multiply (3-operand)
2076 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2077 *
2078 * Multiply Instructions for Pipeline 1 (10 instructions)
2079 * ------------------------------------------------------
2080 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2081 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2082 * DIV1 rs, rt Divide Pipeline 1
2083 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2084 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2085 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2086 * MFHI1 rd Move From HI1 Register
2087 * MFLO1 rd Move From LO1 Register
2088 * MTHI1 rs Move To HI1 Register
2089 * MTLO1 rs Move To LO1 Register
2090 *
2091 * Arithmetic (19 instructions)
2092 * ----------------------------
2093 * PADDB rd, rs, rt Parallel Add Byte
2094 * PSUBB rd, rs, rt Parallel Subtract Byte
2095 * PADDH rd, rs, rt Parallel Add Halfword
2096 * PSUBH rd, rs, rt Parallel Subtract Halfword
2097 * PADDW rd, rs, rt Parallel Add Word
2098 * PSUBW rd, rs, rt Parallel Subtract Word
2099 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2100 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2101 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2102 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2103 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2104 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2105 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2106 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2107 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2108 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2109 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2110 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2111 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2112 *
2113 * Min/Max (4 instructions)
2114 * ------------------------
2115 * PMAXH rd, rs, rt Parallel Maximum Halfword
2116 * PMINH rd, rs, rt Parallel Minimum Halfword
2117 * PMAXW rd, rs, rt Parallel Maximum Word
2118 * PMINW rd, rs, rt Parallel Minimum Word
2119 *
2120 * Absolute (2 instructions)
2121 * -------------------------
2122 * PABSH rd, rt Parallel Absolute Halfword
2123 * PABSW rd, rt Parallel Absolute Word
2124 *
2125 * Logical (4 instructions)
2126 * ------------------------
2127 * PAND rd, rs, rt Parallel AND
2128 * POR rd, rs, rt Parallel OR
2129 * PXOR rd, rs, rt Parallel XOR
2130 * PNOR rd, rs, rt Parallel NOR
2131 *
2132 * Shift (9 instructions)
2133 * ----------------------
2134 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2135 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2136 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2137 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2138 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2139 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2140 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2141 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2142 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2143 *
2144 * Compare (6 instructions)
2145 * ------------------------
2146 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2147 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2148 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2149 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2150 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2151 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2152 *
2153 * LZC (1 instruction)
2154 * -------------------
2155 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2156 *
2157 * Quadword Load and Store (2 instructions)
2158 * ----------------------------------------
2159 * LQ rt, offset(base) Load Quadword
2160 * SQ rt, offset(base) Store Quadword
2161 *
2162 * Multiply and Divide (19 instructions)
2163 * -------------------------------------
2164 * PMULTW rd, rs, rt Parallel Multiply Word
2165 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2166 * PDIVW rs, rt Parallel Divide Word
2167 * PDIVUW rs, rt Parallel Divide Unsigned Word
2168 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2169 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2170 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2171 * PMULTH rd, rs, rt Parallel Multiply Halfword
2172 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2173 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2174 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2175 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2176 * PDIVBW rs, rt Parallel Divide Broadcast Word
2177 * PMFHI rd Parallel Move From HI Register
2178 * PMFLO rd Parallel Move From LO Register
2179 * PMTHI rs Parallel Move To HI Register
2180 * PMTLO rs Parallel Move To LO Register
2181 * PMFHL rd Parallel Move From HI/LO Register
2182 * PMTHL rs Parallel Move To HI/LO Register
2183 *
2184 * Pack/Extend (11 instructions)
2185 * -----------------------------
2186 * PPAC5 rd, rt Parallel Pack to 5 bits
2187 * PPACB rd, rs, rt Parallel Pack to Byte
2188 * PPACH rd, rs, rt Parallel Pack to Halfword
2189 * PPACW rd, rs, rt Parallel Pack to Word
2190 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2191 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2192 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2193 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2194 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2195 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2196 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2197 *
2198 * Others (16 instructions)
2199 * ------------------------
2200 * PCPYH rd, rt Parallel Copy Halfword
2201 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2202 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2203 * PREVH rd, rt Parallel Reverse Halfword
2204 * PINTH rd, rs, rt Parallel Interleave Halfword
2205 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2206 * PEXEH rd, rt Parallel Exchange Even Halfword
2207 * PEXCH rd, rt Parallel Exchange Center Halfword
2208 * PEXEW rd, rt Parallel Exchange Even Word
2209 * PEXCW rd, rt Parallel Exchange Center Word
2210 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2211 * MFSA rd Move from Shift Amount Register
2212 * MTSA rs Move to Shift Amount Register
2213 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2214 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2215 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d 2216 *
baa609db
AM
2217 * MMI (MultiMedia Instruction) encodings
2218 * ======================================
f99c0d6d 2219 *
baa609db 2220 * MMI instructions encoding table keys:
f99c0d6d
FN
2221 *
2222 * * This code is reserved for future use. An attempt to execute it
2223 * causes a Reserved Instruction exception.
2224 * % This code indicates an instruction class. The instruction word
2225 * must be further decoded by examining additional tables that show
2226 * the values for other instruction fields.
2227 * # This code is reserved for the unsupported instructions DMULT,
2228 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2229 * to execute it causes a Reserved Instruction exception.
2230 *
baa609db 2231 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
2232 *
2233 * 31 26 0
2234 * +--------+----------------------------------------+
2235 * | opcode | |
2236 * +--------+----------------------------------------+
2237 *
2238 * opcode bits 28..26
2239 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2240 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2241 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2242 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2243 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2244 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2245 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2246 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2247 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2248 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2249 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2250 */
b158d449 2251
f99c0d6d 2252enum {
baa609db
AM
2253 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2254 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2255 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
2256};
2257
d3297211 2258/*
baa609db 2259 * MMI instructions with opcode field = MMI:
d3297211
FN
2260 *
2261 * 31 26 5 0
2262 * +--------+-------------------------------+--------+
2263 * | MMI | |function|
2264 * +--------+-------------------------------+--------+
2265 *
2266 * function bits 2..0
2267 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2268 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2269 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2270 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2271 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2272 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2273 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2274 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2275 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2276 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2277 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2278 */
2279
c8341e00 2280#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 2281enum {
baa609db
AM
2282 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2283 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2284 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2285 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2286 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2287 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2288 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2289 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2290 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2291 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2292 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2293 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2294 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2295 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2296 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2297 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2298 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2299 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2300 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2301 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2302 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2303 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2304 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2305 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2306 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
d3297211
FN
2307};
2308
3ef65697 2309/*
baa609db 2310 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
3ef65697
FN
2311 *
2312 * 31 26 10 6 5 0
2313 * +--------+----------------------+--------+--------+
2314 * | MMI | |function| MMI0 |
2315 * +--------+----------------------+--------+--------+
2316 *
2317 * function bits 7..6
2318 * bits | 0 | 1 | 2 | 3
2319 * 10..8 | 00 | 01 | 10 | 11
2320 * -------+-------+-------+-------+-------
2321 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2322 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2323 * 2 010 | PADDB | PSUBB | PCGTB | *
2324 * 3 011 | * | * | * | *
2325 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2326 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2327 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2328 * 7 111 | * | * | PEXT5 | PPAC5
2329 */
2330
c8341e00 2331#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
3ef65697 2332enum {
baa609db
AM
2333 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2334 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2335 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2336 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2337 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2338 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2339 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2340 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2341 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2342 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2343 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2344 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2345 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2346 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2347 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2348 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2349 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2350 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2351 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2352 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2353 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2354 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2355 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2356 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2357 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
3ef65697
FN
2358};
2359
77596541 2360/*
baa609db 2361 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
77596541
FN
2362 *
2363 * 31 26 10 6 5 0
2364 * +--------+----------------------+--------+--------+
2365 * | MMI | |function| MMI1 |
2366 * +--------+----------------------+--------+--------+
2367 *
2368 * function bits 7..6
2369 * bits | 0 | 1 | 2 | 3
2370 * 10..8 | 00 | 01 | 10 | 11
2371 * -------+-------+-------+-------+-------
2372 * 0 000 | * | PABSW | PCEQW | PMINW
2373 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2374 * 2 010 | * | * | PCEQB | *
2375 * 3 011 | * | * | * | *
2376 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2377 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2378 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2379 * 7 111 | * | * | * | *
2380 */
2381
c8341e00 2382#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
77596541 2383enum {
baa609db
AM
2384 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2385 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2386 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2387 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2388 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2389 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2390 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2391 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2392 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2393 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2394 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2395 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2396 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2397 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2398 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2399 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2400 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2401 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
77596541
FN
2402};
2403
6c03ef6a 2404/*
baa609db 2405 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
6c03ef6a
FN
2406 *
2407 * 31 26 10 6 5 0
2408 * +--------+----------------------+--------+--------+
2409 * | MMI | |function| MMI2 |
2410 * +--------+----------------------+--------+--------+
2411 *
2412 * function bits 7..6
2413 * bits | 0 | 1 | 2 | 3
2414 * 10..8 | 00 | 01 | 10 | 11
2415 * -------+-------+-------+-------+-------
2416 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2417 * 1 001 | PMSUBW| * | * | *
2418 * 2 010 | PMFHI | PMFLO | PINTH | *
2419 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2420 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2421 * 5 101 | PMSUBH| PHMSBH| * | *
2422 * 6 110 | * | * | PEXEH | PREVH
2423 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2424 */
2425
c8341e00 2426#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
6c03ef6a 2427enum {
baa609db
AM
2428 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2429 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2430 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2431 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2432 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2433 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2434 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2435 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2436 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2437 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2438 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2439 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2440 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2441 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2442 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2443 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2444 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2445 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2446 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2447 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2448 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2449 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
6c03ef6a
FN
2450};
2451
dd581bf9 2452/*
baa609db 2453 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
dd581bf9
FN
2454 *
2455 * 31 26 10 6 5 0
2456 * +--------+----------------------+--------+--------+
2457 * | MMI | |function| MMI3 |
2458 * +--------+----------------------+--------+--------+
2459 *
2460 * function bits 7..6
2461 * bits | 0 | 1 | 2 | 3
2462 * 10..8 | 00 | 01 | 10 | 11
2463 * -------+-------+-------+-------+-------
2464 * 0 000 |PMADDUW| * | * | PSRAVW
2465 * 1 001 | * | * | * | *
2466 * 2 010 | PMTHI | PMTLO | PINTEH| *
2467 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2468 * 4 100 | * | * | POR | PNOR
2469 * 5 101 | * | * | * | *
2470 * 6 110 | * | * | PEXCH | PCPYH
2471 * 7 111 | * | * | PEXCW | *
2472 */
2473
c8341e00 2474#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
dd581bf9 2475enum {
baa609db
AM
2476 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2477 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2478 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2479 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2480 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2481 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2482 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2483 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2484 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2485 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2486 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2487 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2488 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
dd581bf9
FN
2489};
2490
39454628 2491/* global register indices */
a7812ae4 2492static TCGv cpu_gpr[32], cpu_PC;
340fff72 2493static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607 2494static TCGv cpu_dspctrl, btarget, bcond;
33a07fa2 2495static TCGv cpu_lladdr, cpu_llval;
41db4607 2496static TCGv_i32 hflags;
a7812ae4 2497static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2498static TCGv_i64 fpu_f64[32];
863f264d 2499static TCGv_i64 msa_wr_d[64];
aa0bf00b 2500
a168a796
FN
2501#if defined(TARGET_MIPS64)
2502/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2503static TCGv_i64 cpu_mmr[32];
2504#endif
2505
b621f018 2506#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2507/* MXU registers */
2508static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2509static TCGv mxu_CR;
b621f018 2510#endif
eb5559f6 2511
022c62cb 2512#include "exec/gen-icount.h"
2e70f6ef 2513
895c2d04 2514#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2515 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2516 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 2517 tcg_temp_free_i32(helper_tmp); \
71375b59 2518 } while (0)
be24bb4f 2519
895c2d04 2520#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2521 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2522 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 2523 tcg_temp_free_i32(helper_tmp); \
71375b59 2524 } while (0)
be24bb4f 2525
895c2d04
BS
2526#define gen_helper_1e0i(name, ret, arg1) do { \
2527 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2528 gen_helper_##name(ret, cpu_env, helper_tmp); \
2529 tcg_temp_free_i32(helper_tmp); \
71375b59 2530 } while (0)
895c2d04
BS
2531
2532#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2533 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2534 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2535 tcg_temp_free_i32(helper_tmp); \
71375b59 2536 } while (0)
895c2d04
BS
2537
2538#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2539 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2540 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2541 tcg_temp_free_i32(helper_tmp); \
71375b59 2542 } while (0)
895c2d04
BS
2543
2544#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2545 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2546 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 2547 tcg_temp_free_i32(helper_tmp); \
71375b59 2548 } while (0)
be24bb4f 2549
895c2d04 2550#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2551 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2552 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 2553 tcg_temp_free_i32(helper_tmp); \
71375b59 2554 } while (0)
c239529e 2555
8e9ade68 2556typedef struct DisasContext {
eeb3bba8
EC
2557 DisasContextBase base;
2558 target_ulong saved_pc;
18f440ed 2559 target_ulong page_start;
8e9ade68 2560 uint32_t opcode;
f9c9cd63 2561 uint64_t insn_flags;
5ab5c041 2562 int32_t CP0_Config1;
49735f76 2563 int32_t CP0_Config2;
ab77fc61
DN
2564 int32_t CP0_Config3;
2565 int32_t CP0_Config5;
8e9ade68
TS
2566 /* Routine used to access memory */
2567 int mem_idx;
14776ab5 2568 MemOp default_tcg_memop_mask;
8e9ade68 2569 uint32_t hflags, saved_hflags;
8e9ade68 2570 target_ulong btarget;
d279279e 2571 bool ulri;
e98c0d17 2572 int kscrexist;
7207c7f9 2573 bool rxi;
9456c2fb 2574 int ie;
aea14095
LA
2575 bool bi;
2576 bool bp;
5204ea79
LA
2577 uint64_t PAMask;
2578 bool mvh;
76964147 2579 bool eva;
cec56a73 2580 bool sc;
5204ea79 2581 int CP0_LLAddr_shift;
e29c9628 2582 bool ps;
01bc435b 2583 bool vp;
c870e3f5 2584 bool cmgcr;
f6d4dd81 2585 bool mrp;
87552089 2586 bool nan2008;
6be77480 2587 bool abs2008;
5fb2dcd1 2588 bool saar;
feafe82c 2589 bool mi;
99029be1 2590 int gi;
8e9ade68
TS
2591} DisasContext;
2592
b28425ba
EC
2593#define DISAS_STOP DISAS_TARGET_0
2594#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2595
d73ee8a2
RH
2596static const char * const regnames[] = {
2597 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2598 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2599 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2600 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2601};
6af0bf9c 2602
d73ee8a2
RH
2603static const char * const regnames_HI[] = {
2604 "HI0", "HI1", "HI2", "HI3",
2605};
4b2eb8d2 2606
d73ee8a2
RH
2607static const char * const regnames_LO[] = {
2608 "LO0", "LO1", "LO2", "LO3",
2609};
4b2eb8d2 2610
d73ee8a2
RH
2611static const char * const fregnames[] = {
2612 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2613 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2614 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2615 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2616};
958fb4a9 2617
863f264d
YK
2618static const char * const msaregnames[] = {
2619 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2620 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2621 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2622 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2623 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2624 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2625 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2626 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2627 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2628 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2629 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2630 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2631 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2632 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2633 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2634 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2635};
2636
b621f018 2637#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2638static const char * const mxuregnames[] = {
2639 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2640 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2641};
b621f018 2642#endif
eb5559f6 2643
9d68ac14 2644#define LOG_DISAS(...) \
fb7729e2
RH
2645 do { \
2646 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2647 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2648 } \
2649 } while (0)
2650
9d68ac14 2651#define MIPS_INVAL(op) \
fb7729e2
RH
2652 do { \
2653 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2654 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2655 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2656 ctx->base.pc_next, ctx->opcode, op, \
2657 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2658 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2659 } \
2660 } while (0)
958fb4a9 2661
8e9ade68 2662/* General purpose registers moves. */
235785e8 2663static inline void gen_load_gpr(TCGv t, int reg)
aaa9128a 2664{
1f8929d2 2665 if (reg == 0) {
8e9ade68 2666 tcg_gen_movi_tl(t, 0);
1f8929d2 2667 } else {
4b2eb8d2 2668 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 2669 }
aaa9128a
TS
2670}
2671
235785e8 2672static inline void gen_store_gpr(TCGv t, int reg)
aaa9128a 2673{
1f8929d2 2674 if (reg != 0) {
4b2eb8d2 2675 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 2676 }
aaa9128a
TS
2677}
2678
8e9ade68 2679/* Moves to/from shadow registers. */
235785e8 2680static inline void gen_load_srsgpr(int from, int to)
aaa9128a 2681{
d9bea114 2682 TCGv t0 = tcg_temp_new();
be24bb4f 2683
1f8929d2 2684 if (from == 0) {
d9bea114 2685 tcg_gen_movi_tl(t0, 0);
1f8929d2 2686 } else {
d9bea114 2687 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2688 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2689
7db13fae 2690 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2691 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2692 tcg_gen_andi_i32(t2, t2, 0xf);
2693 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2694 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2695 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2696
d9bea114 2697 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2698 tcg_temp_free_ptr(addr);
d9bea114 2699 tcg_temp_free_i32(t2);
8e9ade68 2700 }
d9bea114
AJ
2701 gen_store_gpr(t0, to);
2702 tcg_temp_free(t0);
aaa9128a
TS
2703}
2704
71375b59 2705static inline void gen_store_srsgpr(int from, int to)
aaa9128a 2706{
be24bb4f 2707 if (to != 0) {
d9bea114
AJ
2708 TCGv t0 = tcg_temp_new();
2709 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2710 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2711
d9bea114 2712 gen_load_gpr(t0, from);
7db13fae 2713 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2714 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2715 tcg_gen_andi_i32(t2, t2, 0xf);
2716 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2717 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2718 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2719
d9bea114 2720 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2721 tcg_temp_free_ptr(addr);
d9bea114
AJ
2722 tcg_temp_free_i32(t2);
2723 tcg_temp_free(t0);
8e9ade68 2724 }
aaa9128a
TS
2725}
2726
b621f018 2727#if !defined(TARGET_MIPS64)
96992d1a
CJ
2728/* MXU General purpose registers moves. */
2729static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2730{
2731 if (reg == 0) {
2732 tcg_gen_movi_tl(t, 0);
2733 } else if (reg <= 15) {
2734 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2735 }
2736}
2737
2738static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2739{
2740 if (reg > 0 && reg <= 15) {
2741 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2742 }
2743}
2744
2745/* MXU control register moves. */
2746static inline void gen_load_mxu_cr(TCGv t)
2747{
2748 tcg_gen_mov_tl(t, mxu_CR);
2749}
2750
2751static inline void gen_store_mxu_cr(TCGv t)
2752{
2753 /* TODO: Add handling of RW rules for MXU_CR. */
2754 tcg_gen_mov_tl(mxu_CR, t);
2755}
b621f018 2756#endif
96992d1a
CJ
2757
2758
eab9944c
LA
2759/* Tests */
2760static inline void gen_save_pc(target_ulong pc)
2761{
2762 tcg_gen_movi_tl(cpu_PC, pc);
2763}
2764
2765static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2766{
2767 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2768 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2769 gen_save_pc(ctx->base.pc_next);
2770 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2771 }
2772 if (ctx->hflags != ctx->saved_hflags) {
2773 tcg_gen_movi_i32(hflags, ctx->hflags);
2774 ctx->saved_hflags = ctx->hflags;
2775 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2776 case MIPS_HFLAG_BR:
2777 break;
2778 case MIPS_HFLAG_BC:
2779 case MIPS_HFLAG_BL:
2780 case MIPS_HFLAG_B:
2781 tcg_gen_movi_tl(btarget, ctx->btarget);
2782 break;
2783 }
2784 }
2785}
2786
2787static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2788{
2789 ctx->saved_hflags = ctx->hflags;
2790 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2791 case MIPS_HFLAG_BR:
2792 break;
2793 case MIPS_HFLAG_BC:
2794 case MIPS_HFLAG_BL:
2795 case MIPS_HFLAG_B:
2796 ctx->btarget = env->btarget;
2797 break;
2798 }
2799}
2800
2801static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2802{
2803 TCGv_i32 texcp = tcg_const_i32(excp);
2804 TCGv_i32 terr = tcg_const_i32(err);
2805 save_cpu_state(ctx, 1);
2806 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2807 tcg_temp_free_i32(terr);
2808 tcg_temp_free_i32(texcp);
eeb3bba8 2809 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2810}
2811
2812static inline void generate_exception(DisasContext *ctx, int excp)
2813{
eab9944c
LA
2814 gen_helper_0e0i(raise_exception, excp);
2815}
2816
9c708c7f
PD
2817static inline void generate_exception_end(DisasContext *ctx, int excp)
2818{
2819 generate_exception_err(ctx, excp, 0);
2820}
2821
aaa9128a 2822/* Floating point register moves. */
7c979afd 2823static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2824{
7c979afd
LA
2825 if (ctx->hflags & MIPS_HFLAG_FRE) {
2826 generate_exception(ctx, EXCP_RI);
2827 }
ecc7b3aa 2828 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2829}
2830
7c979afd 2831static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2832{
7c979afd
LA
2833 TCGv_i64 t64;
2834 if (ctx->hflags & MIPS_HFLAG_FRE) {
2835 generate_exception(ctx, EXCP_RI);
2836 }
2837 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2838 tcg_gen_extu_i32_i64(t64, t);
2839 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2840 tcg_temp_free_i64(t64);
6d066274
AJ
2841}
2842
7f6613ce 2843static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2844{
7f6613ce 2845 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2846 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2847 } else {
7c979afd 2848 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2849 }
6d066274
AJ
2850}
2851
7f6613ce 2852static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2853{
7f6613ce
PJ
2854 if (ctx->hflags & MIPS_HFLAG_F64) {
2855 TCGv_i64 t64 = tcg_temp_new_i64();
2856 tcg_gen_extu_i32_i64(t64, t);
2857 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2858 tcg_temp_free_i64(t64);
2859 } else {
7c979afd 2860 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2861 }
aa0bf00b 2862}
6ea83fed 2863
d73ee8a2 2864static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2865{
f364515c 2866 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2867 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2868 } else {
d73ee8a2 2869 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2870 }
2871}
6ea83fed 2872
d73ee8a2 2873static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2874{
f364515c 2875 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2876 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2877 } else {
d73ee8a2
RH
2878 TCGv_i64 t0;
2879 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2880 t0 = tcg_temp_new_i64();
6d066274 2881 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2882 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2883 tcg_temp_free_i64(t0);
aa0bf00b
TS
2884 }
2885}
6ea83fed 2886
235785e8 2887static inline int get_fp_bit(int cc)
a16336e4 2888{
1f8929d2 2889 if (cc) {
d94536f4 2890 return 24 + cc;
1f8929d2 2891 } else {
d94536f4 2892 return 23;
1f8929d2 2893 }
a16336e4
TS
2894}
2895
48d38ca5 2896/* Addresses computation */
235785e8
AM
2897static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2898 TCGv arg1)
4ad40f36 2899{
941694d0 2900 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2901
2902#if defined(TARGET_MIPS64)
01f72885 2903 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2904 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2905 }
2906#endif
4ad40f36
FB
2907}
2908
bf0718c5
SM
2909static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2910 target_long ofs)
2911{
2912 tcg_gen_addi_tl(ret, base, ofs);
2913
2914#if defined(TARGET_MIPS64)
2915 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2916 tcg_gen_ext32s_i64(ret, ret);
2917 }
2918#endif
2919}
2920
31837be3
YK
2921/* Addresses computation (translation time) */
2922static target_long addr_add(DisasContext *ctx, target_long base,
2923 target_long offset)
2924{
2925 target_long sum = base + offset;
2926
2927#if defined(TARGET_MIPS64)
2928 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2929 sum = (int32_t)sum;
2930 }
2931#endif
2932 return sum;
2933}
2934
71f303cd 2935/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2936static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2937{
2938#if defined(TARGET_MIPS64)
71f303cd
RH
2939 tcg_gen_ext32s_i64(ret, arg);
2940#else
2941 tcg_gen_extrl_i64_i32(ret, arg);
2942#endif
2943}
2944
2945/* Sign-extract the high 32-bits to a target_long. */
2946static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2947{
2948#if defined(TARGET_MIPS64)
2949 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2950#else
71f303cd 2951 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2952#endif
2953}
2954
356265ae 2955static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2956{
1f8929d2 2957 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
c2c65dab 2958 generate_exception_err(ctx, EXCP_CpU, 0);
1f8929d2 2959 }
387a8fe5
TS
2960}
2961
356265ae 2962static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2963{
1f8929d2 2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 2965 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 2966 }
5e755519
TS
2967}
2968
7480515f
AM
2969/*
2970 * Verify that the processor is running with COP1X instructions enabled.
2971 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2972 * opcode tables.
2973 */
356265ae 2974static inline void check_cop1x(DisasContext *ctx)
b8aa4598 2975{
1f8929d2 2976 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
9c708c7f 2977 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2978 }
b8aa4598
TS
2979}
2980
7480515f
AM
2981/*
2982 * Verify that the processor is running with 64-bit floating-point
2983 * operations enabled.
2984 */
356265ae 2985static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2986{
1f8929d2 2987 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
9c708c7f 2988 generate_exception_end(ctx, EXCP_RI);
1f8929d2 2989 }
5e755519
TS
2990}
2991
2992/*
2993 * Verify if floating point register is valid; an operation is not defined
2994 * if bit 0 of any register specification is set and the FR bit in the
2995 * Status register equals zero, since the register numbers specify an
2996 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2997 * in the Status register equals one, both even and odd register numbers
2998 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2999 *
3000 * Multiple 64 bit wide registers can be checked by calling
3001 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
3002 */
356265ae 3003static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 3004{
1f8929d2 3005 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
9c708c7f 3006 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3007 }
5e755519
TS
3008}
3009
7480515f
AM
3010/*
3011 * Verify that the processor is running with DSP instructions enabled.
3012 * This is enabled by CP0 Status register MX(24) bit.
853c3240 3013 */
853c3240
JL
3014static inline void check_dsp(DisasContext *ctx)
3015{
3016 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 3017 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 3018 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 3019 } else {
9c708c7f 3020 generate_exception_end(ctx, EXCP_RI);
ad153f15 3021 }
853c3240
JL
3022 }
3023}
3024
908f6be1 3025static inline void check_dsp_r2(DisasContext *ctx)
853c3240 3026{
908f6be1 3027 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 3028 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 3029 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 3030 } else {
9c708c7f 3031 generate_exception_end(ctx, EXCP_RI);
ad153f15 3032 }
853c3240
JL
3033 }
3034}
3035
908f6be1 3036static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 3037{
908f6be1 3038 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
3039 if (ctx->insn_flags & ASE_DSP) {
3040 generate_exception_end(ctx, EXCP_DSPDIS);
3041 } else {
3042 generate_exception_end(ctx, EXCP_RI);
3043 }
3044 }
3045}
3046
7480515f
AM
3047/*
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support the instruction set corresponding to flags.
3050 */
f9c9cd63 3051static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 3052{
d75c135e 3053 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 3054 generate_exception_end(ctx, EXCP_RI);
d75c135e 3055 }
3a95e3a7
TS
3056}
3057
7480515f
AM
3058/*
3059 * This code generates a "reserved instruction" exception if the
3060 * CPU has corresponding flag set which indicates that the instruction
3061 * has been removed.
3062 */
f9c9cd63 3063static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3064{
3065 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3066 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3067 }
3068}
3069
96631327
FN
3070/*
3071 * The Linux kernel traps certain reserved instruction exceptions to
3072 * emulate the corresponding instructions. QEMU is the kernel in user
3073 * mode, so those traps are emulated by accepting the instructions.
3074 *
3075 * A reserved instruction exception is generated for flagged CPUs if
3076 * QEMU runs in system mode.
3077 */
3078static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3079{
3080#ifndef CONFIG_USER_ONLY
3081 check_insn_opc_removed(ctx, flags);
3082#endif
3083}
3084
7480515f
AM
3085/*
3086 * This code generates a "reserved instruction" exception if the
3087 * CPU does not support 64-bit paired-single (PS) floating point data type.
3088 */
e29c9628
YK
3089static inline void check_ps(DisasContext *ctx)
3090{
3091 if (unlikely(!ctx->ps)) {
3092 generate_exception(ctx, EXCP_RI);
3093 }
3094 check_cp1_64bitmode(ctx);
3095}
3096
c7986fd6 3097#ifdef TARGET_MIPS64
7480515f
AM
3098/*
3099 * This code generates a "reserved instruction" exception if 64-bit
3100 * instructions are not enabled.
3101 */
356265ae 3102static inline void check_mips_64(DisasContext *ctx)
e189e748 3103{
1f8929d2 3104 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
9c708c7f 3105 generate_exception_end(ctx, EXCP_RI);
1f8929d2 3106 }
e189e748 3107}
c7986fd6 3108#endif
e189e748 3109
5204ea79
LA
3110#ifndef CONFIG_USER_ONLY
3111static inline void check_mvh(DisasContext *ctx)
3112{
3113 if (unlikely(!ctx->mvh)) {
3114 generate_exception(ctx, EXCP_RI);
3115 }
3116}
3117#endif
3118
0b16dcd1
AR
3119/*
3120 * This code generates a "reserved instruction" exception if the
3121 * Config5 XNP bit is set.
3122 */
3123static inline void check_xnp(DisasContext *ctx)
3124{
3125 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3126 generate_exception_end(ctx, EXCP_RI);
3127 }
3128}
3129
5e31fdd5
YK
3130#ifndef CONFIG_USER_ONLY
3131/*
3132 * This code generates a "reserved instruction" exception if the
3133 * Config3 PW bit is NOT set.
3134 */
3135static inline void check_pw(DisasContext *ctx)
3136{
3137 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3138 generate_exception_end(ctx, EXCP_RI);
3139 }
3140}
3141#endif
3142
9affc1c5
AR
3143/*
3144 * This code generates a "reserved instruction" exception if the
3145 * Config3 MT bit is NOT set.
3146 */
3147static inline void check_mt(DisasContext *ctx)
3148{
3149 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3150 generate_exception_end(ctx, EXCP_RI);
3151 }
3152}
3153
3154#ifndef CONFIG_USER_ONLY
3155/*
3156 * This code generates a "coprocessor unusable" exception if CP0 is not
3157 * available, and, if that is not the case, generates a "reserved instruction"
3158 * exception if the Config5 MT bit is NOT set. This is needed for availability
3159 * control of some of MT ASE instructions.
3160 */
3161static inline void check_cp0_mt(DisasContext *ctx)
3162{
3163 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3164 generate_exception_err(ctx, EXCP_CpU, 0);
3165 } else {
3166 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3167 generate_exception_err(ctx, EXCP_RI, 0);
3168 }
3169 }
3170}
3171#endif
3172
fb32f8c8
DN
3173/*
3174 * This code generates a "reserved instruction" exception if the
3175 * Config5 NMS bit is set.
3176 */
3177static inline void check_nms(DisasContext *ctx)
3178{
3179 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3180 generate_exception_end(ctx, EXCP_RI);
3181 }
3182}
3183
d046a9ea
DN
3184/*
3185 * This code generates a "reserved instruction" exception if the
3186 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3187 * Config2 TL, and Config5 L2C are unset.
3188 */
3189static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3190{
1f8929d2
AM
3191 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3192 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3193 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3194 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3195 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3196 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
d046a9ea
DN
3197 generate_exception_end(ctx, EXCP_RI);
3198 }
3199}
3200
3201/*
3202 * This code generates a "reserved instruction" exception if the
3203 * Config5 EVA bit is NOT set.
3204 */
3205static inline void check_eva(DisasContext *ctx)
3206{
3207 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3208 generate_exception_end(ctx, EXCP_RI);
3209 }
3210}
3211
0b16dcd1 3212
7480515f
AM
3213/*
3214 * Define small wrappers for gen_load_fpr* so that we have a uniform
3215 * calling interface for 32 and 64-bit FPRs. No sense in changing
3216 * all callers for gen_load_fpr32 when we need the CTX parameter for
3217 * this one use.
3218 */
7c979afd 3219#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3220#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3221#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3222static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3223 int ft, int fs, int cc) \
3224{ \
71375b59
AM
3225 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3226 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
3227 switch (ifmt) { \
3228 case FMT_PS: \
e29c9628 3229 check_ps(ctx); \
8153667c
NF
3230 break; \
3231 case FMT_D: \
3232 if (abs) { \
3233 check_cop1x(ctx); \
3234 } \
3235 check_cp1_registers(ctx, fs | ft); \
3236 break; \
3237 case FMT_S: \
3238 if (abs) { \
3239 check_cop1x(ctx); \
3240 } \
3241 break; \
3242 } \
71375b59
AM
3243 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3244 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 3245 switch (n) { \
1f8929d2
AM
3246 case 0: \
3247 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3248 break; \
3249 case 1: \
3250 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3251 break; \
3252 case 2: \
3253 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3254 break; \
3255 case 3: \
3256 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3257 break; \
3258 case 4: \
3259 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3260 break; \
3261 case 5: \
3262 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3263 break; \
3264 case 6: \
3265 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3266 break; \
3267 case 7: \
3268 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3269 break; \
3270 case 8: \
3271 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3272 break; \
3273 case 9: \
3274 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3275 break; \
3276 case 10: \
3277 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3278 break; \
3279 case 11: \
3280 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3281 break; \
3282 case 12: \
3283 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3284 break; \
3285 case 13: \
3286 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3287 break; \
3288 case 14: \
3289 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3290 break; \
3291 case 15: \
3292 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3293 break; \
3294 default: \
3295 abort(); \
8153667c 3296 } \
71375b59
AM
3297 tcg_temp_free_i##bits(fp0); \
3298 tcg_temp_free_i##bits(fp1); \
8153667c
NF
3299}
3300
3301FOP_CONDS(, 0, d, FMT_D, 64)
3302FOP_CONDS(abs, 1, d, FMT_D, 64)
3303FOP_CONDS(, 0, s, FMT_S, 32)
3304FOP_CONDS(abs, 1, s, FMT_S, 32)
3305FOP_CONDS(, 0, ps, FMT_PS, 64)
3306FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3307#undef FOP_CONDS
3f493883
YK
3308
3309#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 3310static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
3311 int ft, int fs, int fd) \
3312{ \
3313 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3314 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3315 if (ifmt == FMT_D) { \
3f493883 3316 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3317 } \
3318 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3319 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3320 switch (n) { \
3321 case 0: \
3322 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3323 break; \
3324 case 1: \
3325 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3326 break; \
3327 case 2: \
3328 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3329 break; \
3330 case 3: \
3331 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3332 break; \
3333 case 4: \
3334 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3335 break; \
3336 case 5: \
3337 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3338 break; \
3339 case 6: \
3340 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3341 break; \
3342 case 7: \
3343 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3344 break; \
3345 case 8: \
3346 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3347 break; \
3348 case 9: \
3349 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3350 break; \
3351 case 10: \
3352 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3353 break; \
3354 case 11: \
3355 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3356 break; \
3357 case 12: \
3358 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3359 break; \
3360 case 13: \
3361 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3362 break; \
3363 case 14: \
3364 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3365 break; \
3366 case 15: \
3367 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3368 break; \
3369 case 17: \
3370 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3371 break; \
3372 case 18: \
3373 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3374 break; \
3375 case 19: \
3376 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3377 break; \
3378 case 25: \
3379 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3380 break; \
3381 case 26: \
3382 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3383 break; \
3384 case 27: \
3385 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3386 break; \
3387 default: \
3388 abort(); \
3389 } \
3390 STORE; \
71375b59
AM
3391 tcg_temp_free_i ## bits(fp0); \
3392 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
3393}
3394
3395FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3396FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3397#undef FOP_CONDNS
8153667c
NF
3398#undef gen_ldcmp_fpr32
3399#undef gen_ldcmp_fpr64
3400
958fb4a9 3401/* load/store instructions. */
e7139c44 3402#ifdef CONFIG_USER_ONLY
71375b59 3403#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3404static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3405 DisasContext *ctx) \
d9bea114
AJ
3406{ \
3407 TCGv t0 = tcg_temp_new(); \
3408 tcg_gen_mov_tl(t0, arg1); \
3409 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
3410 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3411 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3412 tcg_temp_free(t0); \
aaa9128a 3413}
e7139c44 3414#else
71375b59 3415#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
3416static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3417 DisasContext *ctx) \
e7139c44 3418{ \
dd4096cd 3419 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3420}
3421#endif
71375b59 3422OP_LD_ATOMIC(ll, ld32s);
aaa9128a 3423#if defined(TARGET_MIPS64)
71375b59 3424OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
3425#endif
3426#undef OP_LD_ATOMIC
3427
235785e8
AM
3428static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3429 int base, int offset)
662d7485
NF
3430{
3431 if (base == 0) {
3432 tcg_gen_movi_tl(addr, offset);
3433 } else if (offset == 0) {
3434 gen_load_gpr(addr, base);
3435 } else {
3436 tcg_gen_movi_tl(addr, offset);
3437 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3438 }
3439}
3440
235785e8 3441static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 3442{
eeb3bba8 3443 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3444
3445 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3446 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3447
3448 pc -= branch_bytes;
3449 }
3450
3451 pc &= ~(target_ulong)3;
3452 return pc;
3453}
3454
5c13fdfd 3455/* Load */
d75c135e 3456static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3457 int rt, int base, int offset)
6af0bf9c 3458{
fc40787a 3459 TCGv t0, t1, t2;
dd4096cd 3460 int mem_idx = ctx->mem_idx;
afa88c3a 3461
8e2d5831
JY
3462 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3463 INSN_LOONGSON3A)) {
7480515f
AM
3464 /*
3465 * Loongson CPU uses a load to zero register for prefetch.
3466 * We emulate it as a NOP. On other CPU we must perform the
3467 * actual memory access.
3468 */
afa88c3a
AJ
3469 return;
3470 }
6af0bf9c 3471
afa88c3a 3472 t0 = tcg_temp_new();
662d7485 3473 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3474
6af0bf9c 3475 switch (opc) {
d26bc211 3476#if defined(TARGET_MIPS64)
6e473128 3477 case OPC_LWU:
dd4096cd 3478 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3479 ctx->default_tcg_memop_mask);
78723684 3480 gen_store_gpr(t0, rt);
6e473128 3481 break;
6af0bf9c 3482 case OPC_LD:
dd4096cd 3483 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3484 ctx->default_tcg_memop_mask);
78723684 3485 gen_store_gpr(t0, rt);
6af0bf9c 3486 break;
7a387fff 3487 case OPC_LLD:
bf7910c6 3488 case R6_OPC_LLD:
dd4096cd 3489 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3490 gen_store_gpr(t0, rt);
7a387fff 3491 break;
6af0bf9c 3492 case OPC_LDL:
3cee3050 3493 t1 = tcg_temp_new();
7480515f
AM
3494 /*
3495 * Do a byte access to possibly trigger a page
3496 * fault with the unaligned address.
3497 */
dd4096cd 3498 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3499 tcg_gen_andi_tl(t1, t0, 7);
3500#ifndef TARGET_WORDS_BIGENDIAN
3501 tcg_gen_xori_tl(t1, t1, 7);
3502#endif
3503 tcg_gen_shli_tl(t1, t1, 3);
3504 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3505 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3506 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3507 t2 = tcg_const_tl(-1);
3508 tcg_gen_shl_tl(t2, t2, t1);
78723684 3509 gen_load_gpr(t1, rt);
eb02cc3f 3510 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3511 tcg_temp_free(t2);
3512 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3513 tcg_temp_free(t1);
fc40787a 3514 gen_store_gpr(t0, rt);
6af0bf9c 3515 break;
6af0bf9c 3516 case OPC_LDR:
3cee3050 3517 t1 = tcg_temp_new();
7480515f
AM
3518 /*
3519 * Do a byte access to possibly trigger a page
3520 * fault with the unaligned address.
3521 */
dd4096cd 3522 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3523 tcg_gen_andi_tl(t1, t0, 7);
3524#ifdef TARGET_WORDS_BIGENDIAN
3525 tcg_gen_xori_tl(t1, t1, 7);
3526#endif
3527 tcg_gen_shli_tl(t1, t1, 3);
3528 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3530 tcg_gen_shr_tl(t0, t0, t1);
3531 tcg_gen_xori_tl(t1, t1, 63);
3532 t2 = tcg_const_tl(0xfffffffffffffffeull);
3533 tcg_gen_shl_tl(t2, t2, t1);
78723684 3534 gen_load_gpr(t1, rt);
fc40787a
AJ
3535 tcg_gen_and_tl(t1, t1, t2);
3536 tcg_temp_free(t2);
3537 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3538 tcg_temp_free(t1);
fc40787a 3539 gen_store_gpr(t0, rt);
6af0bf9c 3540 break;
364d4831 3541 case OPC_LDPC:
3cee3050 3542 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3543 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3544 tcg_temp_free(t1);
dd4096cd 3545 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3546 gen_store_gpr(t0, rt);
3547 break;
6af0bf9c 3548#endif
364d4831 3549 case OPC_LWPC:
3cee3050 3550 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3551 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3552 tcg_temp_free(t1);
dd4096cd 3553 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3554 gen_store_gpr(t0, rt);
3555 break;
76964147
JH
3556 case OPC_LWE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
6af0bf9c 3559 case OPC_LW:
dd4096cd 3560 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3561 ctx->default_tcg_memop_mask);
78723684 3562 gen_store_gpr(t0, rt);
6af0bf9c 3563 break;
76964147
JH
3564 case OPC_LHE:
3565 mem_idx = MIPS_HFLAG_UM;
3566 /* fall through */
6af0bf9c 3567 case OPC_LH:
dd4096cd 3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3569 ctx->default_tcg_memop_mask);
78723684 3570 gen_store_gpr(t0, rt);
6af0bf9c 3571 break;
76964147
JH
3572 case OPC_LHUE:
3573 mem_idx = MIPS_HFLAG_UM;
3574 /* fall through */
6af0bf9c 3575 case OPC_LHU:
dd4096cd 3576 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3577 ctx->default_tcg_memop_mask);
78723684 3578 gen_store_gpr(t0, rt);
6af0bf9c 3579 break;
76964147
JH
3580 case OPC_LBE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
6af0bf9c 3583 case OPC_LB:
dd4096cd 3584 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3585 gen_store_gpr(t0, rt);
6af0bf9c 3586 break;
76964147
JH
3587 case OPC_LBUE:
3588 mem_idx = MIPS_HFLAG_UM;
3589 /* fall through */
6af0bf9c 3590 case OPC_LBU:
dd4096cd 3591 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3592 gen_store_gpr(t0, rt);
6af0bf9c 3593 break;
76964147
JH
3594 case OPC_LWLE:
3595 mem_idx = MIPS_HFLAG_UM;
3596 /* fall through */
6af0bf9c 3597 case OPC_LWL:
3cee3050 3598 t1 = tcg_temp_new();
7480515f
AM
3599 /*
3600 * Do a byte access to possibly trigger a page
3601 * fault with the unaligned address.
3602 */
dd4096cd 3603 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3604 tcg_gen_andi_tl(t1, t0, 3);
3605#ifndef TARGET_WORDS_BIGENDIAN
3606 tcg_gen_xori_tl(t1, t1, 3);
3607#endif
3608 tcg_gen_shli_tl(t1, t1, 3);
3609 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3610 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3611 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3612 t2 = tcg_const_tl(-1);
3613 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3614 gen_load_gpr(t1, rt);
eb02cc3f 3615 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3616 tcg_temp_free(t2);
3617 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3618 tcg_temp_free(t1);
fc40787a
AJ
3619 tcg_gen_ext32s_tl(t0, t0);
3620 gen_store_gpr(t0, rt);
6af0bf9c 3621 break;
76964147
JH
3622 case OPC_LWRE:
3623 mem_idx = MIPS_HFLAG_UM;
3624 /* fall through */
6af0bf9c 3625 case OPC_LWR:
3cee3050 3626 t1 = tcg_temp_new();
7480515f
AM
3627 /*
3628 * Do a byte access to possibly trigger a page
3629 * fault with the unaligned address.
3630 */
dd4096cd 3631 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3632 tcg_gen_andi_tl(t1, t0, 3);
3633#ifdef TARGET_WORDS_BIGENDIAN
3634 tcg_gen_xori_tl(t1, t1, 3);
3635#endif
3636 tcg_gen_shli_tl(t1, t1, 3);
3637 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3638 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3639 tcg_gen_shr_tl(t0, t0, t1);
3640 tcg_gen_xori_tl(t1, t1, 31);
3641 t2 = tcg_const_tl(0xfffffffeull);
3642 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3643 gen_load_gpr(t1, rt);
fc40787a
AJ
3644 tcg_gen_and_tl(t1, t1, t2);
3645 tcg_temp_free(t2);
3646 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3647 tcg_temp_free(t1);
c728154b 3648 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3649 gen_store_gpr(t0, rt);
6af0bf9c 3650 break;
76964147
JH
3651 case OPC_LLE:
3652 mem_idx = MIPS_HFLAG_UM;
3653 /* fall through */
6af0bf9c 3654 case OPC_LL:
4368b29a 3655 case R6_OPC_LL:
dd4096cd 3656 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3657 gen_store_gpr(t0, rt);
6af0bf9c 3658 break;
d66c7132 3659 }
d66c7132 3660 tcg_temp_free(t0);
d66c7132
AJ
3661}
3662
0b16dcd1
AR
3663static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3664 uint32_t reg1, uint32_t reg2)
3665{
3666 TCGv taddr = tcg_temp_new();
3667 TCGv_i64 tval = tcg_temp_new_i64();
3668 TCGv tmp1 = tcg_temp_new();
3669 TCGv tmp2 = tcg_temp_new();
3670
3671 gen_base_offset_addr(ctx, taddr, base, offset);
3672 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3673#ifdef TARGET_WORDS_BIGENDIAN
3674 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3675#else
3676 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3677#endif
3678 gen_store_gpr(tmp1, reg1);
3679 tcg_temp_free(tmp1);
3680 gen_store_gpr(tmp2, reg2);
3681 tcg_temp_free(tmp2);
3682 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3683 tcg_temp_free_i64(tval);
3684 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3685 tcg_temp_free(taddr);
3686}
3687
5c13fdfd 3688/* Store */
235785e8
AM
3689static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3690 int base, int offset)
5c13fdfd 3691{
5c13fdfd
AJ
3692 TCGv t0 = tcg_temp_new();
3693 TCGv t1 = tcg_temp_new();
dd4096cd 3694 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3695
3696 gen_base_offset_addr(ctx, t0, base, offset);
3697 gen_load_gpr(t1, rt);
3698 switch (opc) {
3699#if defined(TARGET_MIPS64)
3700 case OPC_SD:
dd4096cd 3701 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3702 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3703 break;
3704 case OPC_SDL:
dd4096cd 3705 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3706 break;
3707 case OPC_SDR:
dd4096cd 3708 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3709 break;
3710#endif
76964147
JH
3711 case OPC_SWE:
3712 mem_idx = MIPS_HFLAG_UM;
3713 /* fall through */
5c13fdfd 3714 case OPC_SW:
dd4096cd 3715 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3716 ctx->default_tcg_memop_mask);
5c13fdfd 3717 break;
76964147
JH
3718 case OPC_SHE:
3719 mem_idx = MIPS_HFLAG_UM;
3720 /* fall through */
5c13fdfd 3721 case OPC_SH:
dd4096cd 3722 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3723 ctx->default_tcg_memop_mask);
5c13fdfd 3724 break;
76964147
JH
3725 case OPC_SBE:
3726 mem_idx = MIPS_HFLAG_UM;
3727 /* fall through */
5c13fdfd 3728 case OPC_SB:
dd4096cd 3729 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3730 break;
76964147
JH
3731 case OPC_SWLE:
3732 mem_idx = MIPS_HFLAG_UM;
3733 /* fall through */
5c13fdfd 3734 case OPC_SWL:
dd4096cd 3735 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3736 break;
76964147
JH
3737 case OPC_SWRE:
3738 mem_idx = MIPS_HFLAG_UM;
3739 /* fall through */
5c13fdfd 3740 case OPC_SWR:
dd4096cd 3741 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3742 break;
3743 }
5c13fdfd
AJ
3744 tcg_temp_free(t0);
3745 tcg_temp_free(t1);
3746}
3747
3748
d66c7132 3749/* Store conditional */
33a07fa2 3750static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 3751 MemOp tcg_mo, bool eva)
d66c7132 3752{
33a07fa2
LA
3753 TCGv addr, t0, val;
3754 TCGLabel *l1 = gen_new_label();
3755 TCGLabel *done = gen_new_label();
d66c7132 3756
2d2826b9 3757 t0 = tcg_temp_new();
33a07fa2 3758 addr = tcg_temp_new();
8cdf8869 3759 /* compare the address against that of the preceding LL */
33a07fa2
LA
3760 gen_base_offset_addr(ctx, addr, base, offset);
3761 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3762 tcg_temp_free(addr);
3763 tcg_gen_movi_tl(t0, 0);
3764 gen_store_gpr(t0, rt);
3765 tcg_gen_br(done);
3766
3767 gen_set_label(l1);
3768 /* generate cmpxchg */
3769 val = tcg_temp_new();
3770 gen_load_gpr(val, rt);
3771 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3772 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3773 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3774 gen_store_gpr(t0, rt);
3775 tcg_temp_free(val);
3776
3777 gen_set_label(done);
d66c7132 3778 tcg_temp_free(t0);
6af0bf9c
FB
3779}
3780
33a07fa2 3781
0b16dcd1 3782static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 3783 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
3784{
3785 TCGv taddr = tcg_temp_local_new();
3786 TCGv lladdr = tcg_temp_local_new();
3787 TCGv_i64 tval = tcg_temp_new_i64();
3788 TCGv_i64 llval = tcg_temp_new_i64();
3789 TCGv_i64 val = tcg_temp_new_i64();
3790 TCGv tmp1 = tcg_temp_new();
3791 TCGv tmp2 = tcg_temp_new();
3792 TCGLabel *lab_fail = gen_new_label();
3793 TCGLabel *lab_done = gen_new_label();
3794
3795 gen_base_offset_addr(ctx, taddr, base, offset);
3796
3797 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3798 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3799
3800 gen_load_gpr(tmp1, reg1);
3801 gen_load_gpr(tmp2, reg2);
3802
3803#ifdef TARGET_WORDS_BIGENDIAN
3804 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3805#else
3806 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3807#endif
3808
3809 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3810 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 3811 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
3812 if (reg1 != 0) {
3813 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3814 }
3815 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3816
3817 gen_set_label(lab_fail);
3818
3819 if (reg1 != 0) {
3820 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3821 }
3822 gen_set_label(lab_done);
3823 tcg_gen_movi_tl(lladdr, -1);
3824 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3825}
3826
6ea83fed 3827/* Load and store */
235785e8
AM
3828static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3829 TCGv t0)
6ea83fed 3830{
7480515f
AM
3831 /*
3832 * Don't do NOP if destination is zero: we must perform the actual
3833 * memory access.
3834 */
6ea83fed
FB
3835 switch (opc) {
3836 case OPC_LWC1:
b6d96bed 3837 {
a7812ae4 3838 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3839 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3840 ctx->default_tcg_memop_mask);
7c979afd 3841 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3842 tcg_temp_free_i32(fp0);
b6d96bed 3843 }
6ea83fed
FB
3844 break;
3845 case OPC_SWC1:
b6d96bed 3846 {
a7812ae4 3847 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3848 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3849 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3850 ctx->default_tcg_memop_mask);
a7812ae4 3851 tcg_temp_free_i32(fp0);
b6d96bed 3852 }
6ea83fed
FB
3853 break;
3854 case OPC_LDC1:
b6d96bed 3855 {
a7812ae4 3856 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3857 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3858 ctx->default_tcg_memop_mask);
b6d96bed 3859 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3860 tcg_temp_free_i64(fp0);
b6d96bed 3861 }
6ea83fed
FB
3862 break;
3863 case OPC_SDC1:
b6d96bed 3864 {
a7812ae4 3865 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3866 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3867 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3868 ctx->default_tcg_memop_mask);
a7812ae4 3869 tcg_temp_free_i64(fp0);
b6d96bed 3870 }
6ea83fed
FB
3871 break;
3872 default:
9d68ac14 3873 MIPS_INVAL("flt_ldst");
9c708c7f 3874 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3875 break;
6ea83fed 3876 }
6ea83fed 3877}
6ea83fed 3878
5ab5c041
AJ
3879static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3880 int rs, int16_t imm)
26ebe468 3881{
b52d3bfa
YK
3882 TCGv t0 = tcg_temp_new();
3883
5ab5c041 3884 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3885 check_cp1_enabled(ctx);
d9224450
MR
3886 switch (op) {
3887 case OPC_LDC1:
3888 case OPC_SDC1:
3889 check_insn(ctx, ISA_MIPS2);
3890 /* Fallthrough */
3891 default:
b52d3bfa
YK
3892 gen_base_offset_addr(ctx, t0, rs, imm);
3893 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3894 }
26ebe468
NF
3895 } else {
3896 generate_exception_err(ctx, EXCP_CpU, 1);
3897 }
b52d3bfa 3898 tcg_temp_free(t0);
26ebe468
NF
3899}
3900
6af0bf9c 3901/* Arithmetic with immediate operand */
d75c135e 3902static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3903 int rt, int rs, int imm)
6af0bf9c 3904{
324d9e32 3905 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3906
7a387fff 3907 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
3908 /*
3909 * If no destination, treat it as a NOP.
3910 * For addi, we must generate the overflow exception when needed.
3911 */
324d9e32 3912 return;
6af0bf9c
FB
3913 }
3914 switch (opc) {
3915 case OPC_ADDI:
48d38ca5 3916 {
324d9e32
AJ
3917 TCGv t0 = tcg_temp_local_new();
3918 TCGv t1 = tcg_temp_new();
3919 TCGv t2 = tcg_temp_new();
42a268c2 3920 TCGLabel *l1 = gen_new_label();
48d38ca5 3921
324d9e32
AJ
3922 gen_load_gpr(t1, rs);
3923 tcg_gen_addi_tl(t0, t1, uimm);
3924 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3925
324d9e32
AJ
3926 tcg_gen_xori_tl(t1, t1, ~uimm);
3927 tcg_gen_xori_tl(t2, t0, uimm);
3928 tcg_gen_and_tl(t1, t1, t2);
3929 tcg_temp_free(t2);
3930 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3931 tcg_temp_free(t1);
48d38ca5
TS
3932 /* operands of same sign, result different sign */
3933 generate_exception(ctx, EXCP_OVERFLOW);
3934 gen_set_label(l1);
78723684 3935 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3936 gen_store_gpr(t0, rt);
3937 tcg_temp_free(t0);
48d38ca5 3938 }
6af0bf9c
FB
3939 break;
3940 case OPC_ADDIU:
324d9e32
AJ
3941 if (rs != 0) {
3942 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3943 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3944 } else {
3945 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3946 }
6af0bf9c 3947 break;
d26bc211 3948#if defined(TARGET_MIPS64)
7a387fff 3949 case OPC_DADDI:
48d38ca5 3950 {
324d9e32
AJ
3951 TCGv t0 = tcg_temp_local_new();
3952 TCGv t1 = tcg_temp_new();
3953 TCGv t2 = tcg_temp_new();
42a268c2 3954 TCGLabel *l1 = gen_new_label();
48d38ca5 3955
324d9e32
AJ
3956 gen_load_gpr(t1, rs);
3957 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3958
324d9e32
AJ
3959 tcg_gen_xori_tl(t1, t1, ~uimm);
3960 tcg_gen_xori_tl(t2, t0, uimm);
3961 tcg_gen_and_tl(t1, t1, t2);
3962 tcg_temp_free(t2);
3963 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3964 tcg_temp_free(t1);
48d38ca5
TS
3965 /* operands of same sign, result different sign */
3966 generate_exception(ctx, EXCP_OVERFLOW);
3967 gen_set_label(l1);
324d9e32
AJ
3968 gen_store_gpr(t0, rt);
3969 tcg_temp_free(t0);
48d38ca5 3970 }
7a387fff
TS
3971 break;
3972 case OPC_DADDIU:
324d9e32
AJ
3973 if (rs != 0) {
3974 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3975 } else {
3976 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3977 }
7a387fff
TS
3978 break;
3979#endif
324d9e32 3980 }
324d9e32
AJ
3981}
3982
3983/* Logic with immediate operand */
d75c135e 3984static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3985 int rt, int rs, int16_t imm)
324d9e32
AJ
3986{
3987 target_ulong uimm;
324d9e32
AJ
3988
3989 if (rt == 0) {
3990 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3991 return;
3992 }
3993 uimm = (uint16_t)imm;
3994 switch (opc) {
6af0bf9c 3995 case OPC_ANDI:
1f8929d2 3996 if (likely(rs != 0)) {
324d9e32 3997 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 3998 } else {
324d9e32 3999 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 4000 }
6af0bf9c
FB
4001 break;
4002 case OPC_ORI:
1f8929d2 4003 if (rs != 0) {
324d9e32 4004 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 4005 } else {
324d9e32 4006 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 4007 }
6af0bf9c
FB
4008 break;
4009 case OPC_XORI:
1f8929d2 4010 if (likely(rs != 0)) {
324d9e32 4011 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 4012 } else {
324d9e32 4013 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 4014 }
6af0bf9c
FB
4015 break;
4016 case OPC_LUI:
2e211e0a 4017 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
d4ea6acd
LA
4018 /* OPC_AUI */
4019 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
4020 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
4021 } else {
4022 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 4023 }
7c2c3ea3
EJ
4024 break;
4025
4026 default:
6af0bf9c 4027 break;
324d9e32 4028 }
324d9e32
AJ
4029}
4030
4031/* Set on less than with immediate operand */
d75c135e 4032static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 4033 int rt, int rs, int16_t imm)
324d9e32
AJ
4034{
4035 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
4036 TCGv t0;
4037
4038 if (rt == 0) {
4039 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4040 return;
4041 }
4042 t0 = tcg_temp_new();
4043 gen_load_gpr(t0, rs);
4044 switch (opc) {
4045 case OPC_SLTI:
e68dd28f 4046 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4047 break;
4048 case OPC_SLTIU:
e68dd28f 4049 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
4050 break;
4051 }
324d9e32
AJ
4052 tcg_temp_free(t0);
4053}
4054
4055/* Shifts with immediate operand */
d75c135e 4056static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
4057 int rt, int rs, int16_t imm)
4058{
4059 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
4060 TCGv t0;
4061
4062 if (rt == 0) {
4063 /* If no destination, treat it as a NOP. */
324d9e32
AJ
4064 return;
4065 }
4066
4067 t0 = tcg_temp_new();
4068 gen_load_gpr(t0, rs);
4069 switch (opc) {
6af0bf9c 4070 case OPC_SLL:
78723684 4071 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 4072 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4073 break;
4074 case OPC_SRA:
324d9e32 4075 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4076 break;
4077 case OPC_SRL:
ea63e2c3
NF
4078 if (uimm != 0) {
4079 tcg_gen_ext32u_tl(t0, t0);
4080 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4081 } else {
4082 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4083 }
ea63e2c3
NF
4084 break;
4085 case OPC_ROTR:
4086 if (uimm != 0) {
4087 TCGv_i32 t1 = tcg_temp_new_i32();
4088
4089 tcg_gen_trunc_tl_i32(t1, t0);
4090 tcg_gen_rotri_i32(t1, t1, uimm);
4091 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4092 tcg_temp_free_i32(t1);
3399e30f
NF
4093 } else {
4094 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4095 }
7a387fff 4096 break;
d26bc211 4097#if defined(TARGET_MIPS64)
7a387fff 4098 case OPC_DSLL:
324d9e32 4099 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4100 break;
4101 case OPC_DSRA:
324d9e32 4102 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4103 break;
4104 case OPC_DSRL:
ea63e2c3 4105 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4106 break;
4107 case OPC_DROTR:
4108 if (uimm != 0) {
4109 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4110 } else {
4111 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4112 }
7a387fff
TS
4113 break;
4114 case OPC_DSLL32:
324d9e32 4115 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4116 break;
4117 case OPC_DSRA32:
324d9e32 4118 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4119 break;
4120 case OPC_DSRL32:
ea63e2c3 4121 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4122 break;
4123 case OPC_DROTR32:
4124 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4125 break;
7a387fff 4126#endif
6af0bf9c 4127 }
78723684 4128 tcg_temp_free(t0);
6af0bf9c
FB
4129}
4130
4131/* Arithmetic */
d75c135e
AJ
4132static void gen_arith(DisasContext *ctx, uint32_t opc,
4133 int rd, int rs, int rt)
6af0bf9c 4134{
7a387fff
TS
4135 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4136 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
4137 /*
4138 * If no destination, treat it as a NOP.
4139 * For add & sub, we must generate the overflow exception when needed.
4140 */
460f00c4 4141 return;
185f0762 4142 }
460f00c4 4143
6af0bf9c
FB
4144 switch (opc) {
4145 case OPC_ADD:
48d38ca5 4146 {
460f00c4
AJ
4147 TCGv t0 = tcg_temp_local_new();
4148 TCGv t1 = tcg_temp_new();
4149 TCGv t2 = tcg_temp_new();
42a268c2 4150 TCGLabel *l1 = gen_new_label();
48d38ca5 4151
460f00c4
AJ
4152 gen_load_gpr(t1, rs);
4153 gen_load_gpr(t2, rt);
4154 tcg_gen_add_tl(t0, t1, t2);
4155 tcg_gen_ext32s_tl(t0, t0);
4156 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4157 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4158 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4159 tcg_temp_free(t2);
4160 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4161 tcg_temp_free(t1);
48d38ca5
TS
4162 /* operands of same sign, result different sign */
4163 generate_exception(ctx, EXCP_OVERFLOW);
4164 gen_set_label(l1);
460f00c4
AJ
4165 gen_store_gpr(t0, rd);
4166 tcg_temp_free(t0);
48d38ca5 4167 }
6af0bf9c
FB
4168 break;
4169 case OPC_ADDU:
460f00c4
AJ
4170 if (rs != 0 && rt != 0) {
4171 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs == 0 && rt != 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4175 } else if (rs != 0 && rt == 0) {
4176 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4177 } else {
4178 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4179 }
6af0bf9c
FB
4180 break;
4181 case OPC_SUB:
48d38ca5 4182 {
460f00c4
AJ
4183 TCGv t0 = tcg_temp_local_new();
4184 TCGv t1 = tcg_temp_new();
4185 TCGv t2 = tcg_temp_new();
42a268c2 4186 TCGLabel *l1 = gen_new_label();
48d38ca5 4187
460f00c4
AJ
4188 gen_load_gpr(t1, rs);
4189 gen_load_gpr(t2, rt);
4190 tcg_gen_sub_tl(t0, t1, t2);
4191 tcg_gen_ext32s_tl(t0, t0);
4192 tcg_gen_xor_tl(t2, t1, t2);
4193 tcg_gen_xor_tl(t1, t0, t1);
4194 tcg_gen_and_tl(t1, t1, t2);
4195 tcg_temp_free(t2);
4196 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4197 tcg_temp_free(t1);
7480515f
AM
4198 /*
4199 * operands of different sign, first operand and the result
4200 * of different sign
4201 */
48d38ca5
TS
4202 generate_exception(ctx, EXCP_OVERFLOW);
4203 gen_set_label(l1);
460f00c4
AJ
4204 gen_store_gpr(t0, rd);
4205 tcg_temp_free(t0);
48d38ca5 4206 }
6af0bf9c
FB
4207 break;
4208 case OPC_SUBU:
460f00c4
AJ
4209 if (rs != 0 && rt != 0) {
4210 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4211 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4212 } else if (rs == 0 && rt != 0) {
4213 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4214 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4215 } else if (rs != 0 && rt == 0) {
4216 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4217 } else {
4218 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4219 }
6af0bf9c 4220 break;
d26bc211 4221#if defined(TARGET_MIPS64)
7a387fff 4222 case OPC_DADD:
48d38ca5 4223 {
460f00c4
AJ
4224 TCGv t0 = tcg_temp_local_new();
4225 TCGv t1 = tcg_temp_new();
4226 TCGv t2 = tcg_temp_new();
42a268c2 4227 TCGLabel *l1 = gen_new_label();
48d38ca5 4228
460f00c4
AJ
4229 gen_load_gpr(t1, rs);
4230 gen_load_gpr(t2, rt);
4231 tcg_gen_add_tl(t0, t1, t2);
4232 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4233 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4234 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4235 tcg_temp_free(t2);
4236 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4237 tcg_temp_free(t1);
48d38ca5
TS
4238 /* operands of same sign, result different sign */
4239 generate_exception(ctx, EXCP_OVERFLOW);
4240 gen_set_label(l1);
460f00c4
AJ
4241 gen_store_gpr(t0, rd);
4242 tcg_temp_free(t0);
48d38ca5 4243 }
7a387fff
TS
4244 break;
4245 case OPC_DADDU:
460f00c4
AJ
4246 if (rs != 0 && rt != 0) {
4247 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4248 } else if (rs == 0 && rt != 0) {
4249 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4250 } else if (rs != 0 && rt == 0) {
4251 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4252 } else {
4253 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4254 }
7a387fff
TS
4255 break;
4256 case OPC_DSUB:
48d38ca5 4257 {
460f00c4
AJ
4258 TCGv t0 = tcg_temp_local_new();
4259 TCGv t1 = tcg_temp_new();
4260 TCGv t2 = tcg_temp_new();
42a268c2 4261 TCGLabel *l1 = gen_new_label();
48d38ca5 4262
460f00c4
AJ
4263 gen_load_gpr(t1, rs);
4264 gen_load_gpr(t2, rt);
4265 tcg_gen_sub_tl(t0, t1, t2);
4266 tcg_gen_xor_tl(t2, t1, t2);
4267 tcg_gen_xor_tl(t1, t0, t1);
4268 tcg_gen_and_tl(t1, t1, t2);
4269 tcg_temp_free(t2);
4270 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4271 tcg_temp_free(t1);
71375b59
AM
4272 /*
4273 * Operands of different sign, first operand and result different
4274 * sign.
4275 */
48d38ca5
TS
4276 generate_exception(ctx, EXCP_OVERFLOW);
4277 gen_set_label(l1);
460f00c4
AJ
4278 gen_store_gpr(t0, rd);
4279 tcg_temp_free(t0);
48d38ca5 4280 }
7a387fff
TS
4281 break;
4282 case OPC_DSUBU:
460f00c4
AJ
4283 if (rs != 0 && rt != 0) {
4284 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4285 } else if (rs == 0 && rt != 0) {
4286 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4287 } else if (rs != 0 && rt == 0) {
4288 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4289 } else {
4290 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4291 }
7a387fff
TS
4292 break;
4293#endif
460f00c4
AJ
4294 case OPC_MUL:
4295 if (likely(rs != 0 && rt != 0)) {
4296 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4297 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4298 } else {
4299 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4300 }
6af0bf9c 4301 break;
460f00c4 4302 }
460f00c4
AJ
4303}
4304
4305/* Conditional move */
d75c135e 4306static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4307 int rd, int rs, int rt)
460f00c4 4308{
acf12465 4309 TCGv t0, t1, t2;
460f00c4
AJ
4310
4311 if (rd == 0) {
acf12465 4312 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4313 return;
4314 }
4315
acf12465
AJ
4316 t0 = tcg_temp_new();
4317 gen_load_gpr(t0, rt);
4318 t1 = tcg_const_tl(0);
4319 t2 = tcg_temp_new();
4320 gen_load_gpr(t2, rs);
460f00c4
AJ
4321 switch (opc) {
4322 case OPC_MOVN:
acf12465 4323 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4324 break;
460f00c4 4325 case OPC_MOVZ:
acf12465 4326 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4327 break;
b691d9d2
LA
4328 case OPC_SELNEZ:
4329 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4330 break;
4331 case OPC_SELEQZ:
4332 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4333 break;
460f00c4 4334 }
acf12465
AJ
4335 tcg_temp_free(t2);
4336 tcg_temp_free(t1);
4337 tcg_temp_free(t0);
460f00c4
AJ
4338}
4339
4340/* Logic */
d75c135e 4341static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4342 int rd, int rs, int rt)
460f00c4 4343{
460f00c4
AJ
4344 if (rd == 0) {
4345 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4346 return;
4347 }
4348
4349 switch (opc) {
6af0bf9c 4350 case OPC_AND:
460f00c4
AJ
4351 if (likely(rs != 0 && rt != 0)) {
4352 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4353 } else {
4354 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4355 }
6af0bf9c
FB
4356 break;
4357 case OPC_NOR:
460f00c4
AJ
4358 if (rs != 0 && rt != 0) {
4359 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4360 } else if (rs == 0 && rt != 0) {
4361 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4362 } else if (rs != 0 && rt == 0) {
4363 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4364 } else {
4365 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4366 }
6af0bf9c
FB
4367 break;
4368 case OPC_OR:
460f00c4
AJ
4369 if (likely(rs != 0 && rt != 0)) {
4370 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4371 } else if (rs == 0 && rt != 0) {
4372 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4373 } else if (rs != 0 && rt == 0) {
4374 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4375 } else {
4376 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4377 }
6af0bf9c
FB
4378 break;
4379 case OPC_XOR:
460f00c4
AJ
4380 if (likely(rs != 0 && rt != 0)) {
4381 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4382 } else if (rs == 0 && rt != 0) {
4383 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4384 } else if (rs != 0 && rt == 0) {
4385 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4386 } else {
4387 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4388 }
6af0bf9c 4389 break;
460f00c4 4390 }
460f00c4
AJ
4391}
4392
4393/* Set on lower than */
d75c135e 4394static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4395 int rd, int rs, int rt)
460f00c4 4396{
460f00c4
AJ
4397 TCGv t0, t1;
4398
4399 if (rd == 0) {
4400 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4401 return;
4402 }
4403
4404 t0 = tcg_temp_new();
4405 t1 = tcg_temp_new();
4406 gen_load_gpr(t0, rs);
4407 gen_load_gpr(t1, rt);
4408 switch (opc) {
4409 case OPC_SLT:
e68dd28f 4410 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4411 break;
460f00c4 4412 case OPC_SLTU:
e68dd28f 4413 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4414 break;
4415 }
460f00c4
AJ
4416 tcg_temp_free(t0);
4417 tcg_temp_free(t1);
4418}
20c4c97c 4419
460f00c4 4420/* Shifts */
d75c135e
AJ
4421static void gen_shift(DisasContext *ctx, uint32_t opc,
4422 int rd, int rs, int rt)
460f00c4 4423{
460f00c4 4424 TCGv t0, t1;
20c4c97c 4425
460f00c4 4426 if (rd == 0) {
7480515f
AM
4427 /*
4428 * If no destination, treat it as a NOP.
4429 * For add & sub, we must generate the overflow exception when needed.
4430 */
460f00c4
AJ
4431 return;
4432 }
4433
4434 t0 = tcg_temp_new();
4435 t1 = tcg_temp_new();
4436 gen_load_gpr(t0, rs);
4437 gen_load_gpr(t1, rt);
4438 switch (opc) {
6af0bf9c 4439 case OPC_SLLV:
78723684
TS
4440 tcg_gen_andi_tl(t0, t0, 0x1f);
4441 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4442 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4443 break;
4444 case OPC_SRAV:
78723684 4445 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4446 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4447 break;
4448 case OPC_SRLV:
ea63e2c3
NF
4449 tcg_gen_ext32u_tl(t1, t1);
4450 tcg_gen_andi_tl(t0, t0, 0x1f);
4451 tcg_gen_shr_tl(t0, t1, t0);
4452 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4453 break;
4454 case OPC_ROTRV:
4455 {
4456 TCGv_i32 t2 = tcg_temp_new_i32();
4457 TCGv_i32 t3 = tcg_temp_new_i32();
4458
4459 tcg_gen_trunc_tl_i32(t2, t0);
4460 tcg_gen_trunc_tl_i32(t3, t1);
4461 tcg_gen_andi_i32(t2, t2, 0x1f);
4462 tcg_gen_rotr_i32(t2, t3, t2);
4463 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4464 tcg_temp_free_i32(t2);
4465 tcg_temp_free_i32(t3);
5a63bcb2 4466 }
7a387fff 4467 break;
d26bc211 4468#if defined(TARGET_MIPS64)
7a387fff 4469 case OPC_DSLLV:
78723684 4470 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4471 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4472 break;
4473 case OPC_DSRAV:
78723684 4474 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4475 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4476 break;
4477 case OPC_DSRLV:
ea63e2c3
NF
4478 tcg_gen_andi_tl(t0, t0, 0x3f);
4479 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4480 break;
4481 case OPC_DROTRV:
4482 tcg_gen_andi_tl(t0, t0, 0x3f);
4483 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4484 break;
7a387fff 4485#endif
6af0bf9c 4486 }
78723684
TS
4487 tcg_temp_free(t0);
4488 tcg_temp_free(t1);
6af0bf9c
FB
4489}
4490
37b9aae2 4491#if defined(TARGET_MIPS64)
86efbfb6
FN
4492/* Copy GPR to and from TX79 HI1/LO1 register. */
4493static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4494{
baa609db 4495 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4496 /* Treat as NOP. */
4497 return;
4498 }
4499
4500 switch (opc) {
baa609db 4501 case MMI_OPC_MFHI1:
86efbfb6
FN
4502 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4503 break;
baa609db 4504 case MMI_OPC_MFLO1:
86efbfb6
FN
4505 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4506 break;
baa609db 4507 case MMI_OPC_MTHI1:
86efbfb6
FN
4508 if (reg != 0) {
4509 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4510 } else {
4511 tcg_gen_movi_tl(cpu_HI[1], 0);
4512 }
4513 break;
baa609db 4514 case MMI_OPC_MTLO1:
86efbfb6
FN
4515 if (reg != 0) {
4516 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4517 } else {
4518 tcg_gen_movi_tl(cpu_LO[1], 0);
4519 }
4520 break;
4521 default:
4522 MIPS_INVAL("mfthilo1 TX79");
4523 generate_exception_end(ctx, EXCP_RI);
4524 break;
4525 }
4526}
37b9aae2 4527#endif
86efbfb6 4528
6af0bf9c 4529/* Arithmetic on HI/LO registers */
26135ead 4530static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4531{
86efbfb6 4532 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4533 /* Treat as NOP. */
a1f6684d 4534 return;
6af0bf9c 4535 }
4133498f 4536
4133498f 4537 if (acc != 0) {
86efbfb6 4538 check_dsp(ctx);
4133498f
JL
4539 }
4540
6af0bf9c
FB
4541 switch (opc) {
4542 case OPC_MFHI:
4133498f
JL
4543#if defined(TARGET_MIPS64)
4544 if (acc != 0) {
4545 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4546 } else
4547#endif
4548 {
4549 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4550 }
6af0bf9c
FB
4551 break;
4552 case OPC_MFLO:
4133498f
JL
4553#if defined(TARGET_MIPS64)
4554 if (acc != 0) {
4555 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4556 } else
4557#endif
4558 {
4559 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4560 }
6af0bf9c
FB
4561 break;
4562 case OPC_MTHI:
4133498f
JL
4563 if (reg != 0) {
4564#if defined(TARGET_MIPS64)
4565 if (acc != 0) {
4566 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4567 } else
4568#endif
4569 {
4570 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4571 }
4572 } else {
4573 tcg_gen_movi_tl(cpu_HI[acc], 0);
4574 }
6af0bf9c
FB
4575 break;
4576 case OPC_MTLO:
4133498f
JL
4577 if (reg != 0) {
4578#if defined(TARGET_MIPS64)
4579 if (acc != 0) {
4580 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4581 } else
4582#endif
4583 {
4584 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4585 }
4586 } else {
4587 tcg_gen_movi_tl(cpu_LO[acc], 0);
4588 }
6af0bf9c 4589 break;
6af0bf9c 4590 }
6af0bf9c
FB
4591}
4592
d4ea6acd 4593static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 4594 MemOp memop)
d4ea6acd
LA
4595{
4596 TCGv t0 = tcg_const_tl(addr);
4597 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4598 gen_store_gpr(t0, reg);
4599 tcg_temp_free(t0);
4600}
4601
ab39ee45
YK
4602static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4603 int rs)
d4ea6acd
LA
4604{
4605 target_long offset;
4606 target_long addr;
4607
ab39ee45 4608 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4609 case OPC_ADDIUPC:
4610 if (rs != 0) {
4611 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4612 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4613 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4614 }
4615 break;
4616 case R6_OPC_LWPC:
4617 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4618 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4619 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4620 break;
4621#if defined(TARGET_MIPS64)
4622 case OPC_LWUPC:
4623 check_mips_64(ctx);
4624 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4625 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4626 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4627 break;
4628#endif
4629 default:
ab39ee45 4630 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4631 case OPC_AUIPC:
4632 if (rs != 0) {
ab39ee45
YK
4633 offset = sextract32(ctx->opcode, 0, 16) << 16;
4634 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4635 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4636 }
4637 break;
4638 case OPC_ALUIPC:
4639 if (rs != 0) {
ab39ee45
YK
4640 offset = sextract32(ctx->opcode, 0, 16) << 16;
4641 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4642 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4643 }
4644 break;
4645#if defined(TARGET_MIPS64)
4646 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4647 case R6_OPC_LDPC + (1 << 16):
4648 case R6_OPC_LDPC + (2 << 16):
4649 case R6_OPC_LDPC + (3 << 16):
4650 check_mips_64(ctx);
4651 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4652 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4653 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4654 break;
4655#endif
4656 default:
4657 MIPS_INVAL("OPC_PCREL");
9c708c7f 4658 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4659 break;
4660 }
4661 break;
4662 }
4663}
4664
b42ee5e1
LA
4665static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4666{
b42ee5e1
LA
4667 TCGv t0, t1;
4668
4669 if (rd == 0) {
4670 /* Treat as NOP. */
b42ee5e1
LA
4671 return;
4672 }
4673
4674 t0 = tcg_temp_new();
4675 t1 = tcg_temp_new();
4676
4677 gen_load_gpr(t0, rs);
4678 gen_load_gpr(t1, rt);
4679
4680 switch (opc) {
4681 case R6_OPC_DIV:
4682 {
4683 TCGv t2 = tcg_temp_new();
4684 TCGv t3 = tcg_temp_new();
4685 tcg_gen_ext32s_tl(t0, t0);
4686 tcg_gen_ext32s_tl(t1, t1);
4687 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4688 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4689 tcg_gen_and_tl(t2, t2, t3);
4690 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4691 tcg_gen_or_tl(t2, t2, t3);
4692 tcg_gen_movi_tl(t3, 0);
4693 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4694 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4695 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4696 tcg_temp_free(t3);
4697 tcg_temp_free(t2);
4698 }
b42ee5e1
LA
4699 break;
4700 case R6_OPC_MOD:
4701 {
4702 TCGv t2 = tcg_temp_new();
4703 TCGv t3 = tcg_temp_new();
4704 tcg_gen_ext32s_tl(t0, t0);
4705 tcg_gen_ext32s_tl(t1, t1);
4706 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4707 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4708 tcg_gen_and_tl(t2, t2, t3);
4709 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4710 tcg_gen_or_tl(t2, t2, t3);
4711 tcg_gen_movi_tl(t3, 0);
4712 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4713 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4714 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4715 tcg_temp_free(t3);
4716 tcg_temp_free(t2);
4717 }
b42ee5e1
LA
4718 break;
4719 case R6_OPC_DIVU:
4720 {
4721 TCGv t2 = tcg_const_tl(0);
4722 TCGv t3 = tcg_const_tl(1);
4723 tcg_gen_ext32u_tl(t0, t0);
4724 tcg_gen_ext32u_tl(t1, t1);
4725 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4726 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4727 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4728 tcg_temp_free(t3);
4729 tcg_temp_free(t2);
4730 }
b42ee5e1
LA
4731 break;
4732 case R6_OPC_MODU:
4733 {
4734 TCGv t2 = tcg_const_tl(0);
4735 TCGv t3 = tcg_const_tl(1);
4736 tcg_gen_ext32u_tl(t0, t0);
4737 tcg_gen_ext32u_tl(t1, t1);
4738 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4739 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4740 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4741 tcg_temp_free(t3);
4742 tcg_temp_free(t2);
4743 }
b42ee5e1
LA
4744 break;
4745 case R6_OPC_MUL:
4746 {
4747 TCGv_i32 t2 = tcg_temp_new_i32();
4748 TCGv_i32 t3 = tcg_temp_new_i32();
4749 tcg_gen_trunc_tl_i32(t2, t0);
4750 tcg_gen_trunc_tl_i32(t3, t1);
4751 tcg_gen_mul_i32(t2, t2, t3);
4752 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4753 tcg_temp_free_i32(t2);
4754 tcg_temp_free_i32(t3);
4755 }
b42ee5e1
LA
4756 break;
4757 case R6_OPC_MUH:
4758 {
4759 TCGv_i32 t2 = tcg_temp_new_i32();
4760 TCGv_i32 t3 = tcg_temp_new_i32();
4761 tcg_gen_trunc_tl_i32(t2, t0);
4762 tcg_gen_trunc_tl_i32(t3, t1);
4763 tcg_gen_muls2_i32(t2, t3, t2, t3);
4764 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4765 tcg_temp_free_i32(t2);
4766 tcg_temp_free_i32(t3);
4767 }
b42ee5e1
LA
4768 break;
4769 case R6_OPC_MULU:
4770 {
4771 TCGv_i32 t2 = tcg_temp_new_i32();
4772 TCGv_i32 t3 = tcg_temp_new_i32();
4773 tcg_gen_trunc_tl_i32(t2, t0);
4774 tcg_gen_trunc_tl_i32(t3, t1);
4775 tcg_gen_mul_i32(t2, t2, t3);
4776 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4777 tcg_temp_free_i32(t2);
4778 tcg_temp_free_i32(t3);
4779 }
b42ee5e1
LA
4780 break;
4781 case R6_OPC_MUHU:
4782 {
4783 TCGv_i32 t2 = tcg_temp_new_i32();
4784 TCGv_i32 t3 = tcg_temp_new_i32();
4785 tcg_gen_trunc_tl_i32(t2, t0);
4786 tcg_gen_trunc_tl_i32(t3, t1);
4787 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4788 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4789 tcg_temp_free_i32(t2);
4790 tcg_temp_free_i32(t3);
4791 }
b42ee5e1
LA
4792 break;
4793#if defined(TARGET_MIPS64)
4794 case R6_OPC_DDIV:
4795 {
4796 TCGv t2 = tcg_temp_new();
4797 TCGv t3 = tcg_temp_new();
4798 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4799 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4800 tcg_gen_and_tl(t2, t2, t3);
4801 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4802 tcg_gen_or_tl(t2, t2, t3);
4803 tcg_gen_movi_tl(t3, 0);
4804 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4805 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4806 tcg_temp_free(t3);
4807 tcg_temp_free(t2);
4808 }
b42ee5e1
LA
4809 break;
4810 case R6_OPC_DMOD:
4811 {
4812 TCGv t2 = tcg_temp_new();
4813 TCGv t3 = tcg_temp_new();
4814 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4815 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4816 tcg_gen_and_tl(t2, t2, t3);
4817 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4818 tcg_gen_or_tl(t2, t2, t3);
4819 tcg_gen_movi_tl(t3, 0);
4820 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4821 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4822 tcg_temp_free(t3);
4823 tcg_temp_free(t2);
4824 }
b42ee5e1
LA
4825 break;
4826 case R6_OPC_DDIVU:
4827 {
4828 TCGv t2 = tcg_const_tl(0);
4829 TCGv t3 = tcg_const_tl(1);
4830 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4831 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4832 tcg_temp_free(t3);
4833 tcg_temp_free(t2);
4834 }
b42ee5e1
LA
4835 break;
4836 case R6_OPC_DMODU:
4837 {
4838 TCGv t2 = tcg_const_tl(0);
4839 TCGv t3 = tcg_const_tl(1);
4840 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4841 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4842 tcg_temp_free(t3);
4843 tcg_temp_free(t2);
4844 }
b42ee5e1
LA
4845 break;
4846 case R6_OPC_DMUL:
4847 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4848 break;
4849 case R6_OPC_DMUH:
4850 {
4851 TCGv t2 = tcg_temp_new();
4852 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4853 tcg_temp_free(t2);
4854 }
b42ee5e1
LA
4855 break;
4856 case R6_OPC_DMULU:
4857 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4858 break;
4859 case R6_OPC_DMUHU:
4860 {
4861 TCGv t2 = tcg_temp_new();
4862 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4863 tcg_temp_free(t2);
4864 }
b42ee5e1
LA
4865 break;
4866#endif
4867 default:
9d68ac14 4868 MIPS_INVAL("r6 mul/div");
9c708c7f 4869 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4870 goto out;
4871 }
b42ee5e1
LA
4872 out:
4873 tcg_temp_free(t0);
4874 tcg_temp_free(t1);
4875}
4876
37b9aae2 4877#if defined(TARGET_MIPS64)
c42171c3
FN
4878static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4879{
4880 TCGv t0, t1;
4881
4882 t0 = tcg_temp_new();
4883 t1 = tcg_temp_new();
4884
4885 gen_load_gpr(t0, rs);
4886 gen_load_gpr(t1, rt);
4887
4888 switch (opc) {
baa609db 4889 case MMI_OPC_DIV1:
c42171c3
FN
4890 {
4891 TCGv t2 = tcg_temp_new();
4892 TCGv t3 = tcg_temp_new();
4893 tcg_gen_ext32s_tl(t0, t0);
4894 tcg_gen_ext32s_tl(t1, t1);
4895 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4896 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4897 tcg_gen_and_tl(t2, t2, t3);
4898 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4899 tcg_gen_or_tl(t2, t2, t3);
4900 tcg_gen_movi_tl(t3, 0);
4901 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4902 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4903 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4904 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4905 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4906 tcg_temp_free(t3);
4907 tcg_temp_free(t2);
4908 }
4909 break;
baa609db 4910 case MMI_OPC_DIVU1:
c42171c3
FN
4911 {
4912 TCGv t2 = tcg_const_tl(0);
4913 TCGv t3 = tcg_const_tl(1);
4914 tcg_gen_ext32u_tl(t0, t0);
4915 tcg_gen_ext32u_tl(t1, t1);
4916 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4917 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4918 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4919 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4920 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4921 tcg_temp_free(t3);
4922 tcg_temp_free(t2);
4923 }
4924 break;
4925 default:
4926 MIPS_INVAL("div1 TX79");
4927 generate_exception_end(ctx, EXCP_RI);
4928 goto out;
4929 }
4930 out:
4931 tcg_temp_free(t0);
4932 tcg_temp_free(t1);
4933}
37b9aae2 4934#endif
c42171c3 4935
26135ead
RS
4936static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4937 int acc, int rs, int rt)
6af0bf9c 4938{
d45f89f4
AJ
4939 TCGv t0, t1;
4940
51127181
AJ
4941 t0 = tcg_temp_new();
4942 t1 = tcg_temp_new();
6af0bf9c 4943
78723684
TS
4944 gen_load_gpr(t0, rs);
4945 gen_load_gpr(t1, rt);
51127181 4946
26135ead 4947 if (acc != 0) {
c42171c3 4948 check_dsp(ctx);
26135ead
RS
4949 }
4950
6af0bf9c
FB
4951 switch (opc) {
4952 case OPC_DIV:
48d38ca5 4953 {
51127181
AJ
4954 TCGv t2 = tcg_temp_new();
4955 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4956 tcg_gen_ext32s_tl(t0, t0);
4957 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4958 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4959 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4960 tcg_gen_and_tl(t2, t2, t3);
4961 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4962 tcg_gen_or_tl(t2, t2, t3);
4963 tcg_gen_movi_tl(t3, 0);
4964 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4965 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4966 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4967 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4968 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4969 tcg_temp_free(t3);
4970 tcg_temp_free(t2);
48d38ca5 4971 }
6af0bf9c
FB
4972 break;
4973 case OPC_DIVU:
48d38ca5 4974 {
51127181
AJ
4975 TCGv t2 = tcg_const_tl(0);
4976 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4977 tcg_gen_ext32u_tl(t0, t0);
4978 tcg_gen_ext32u_tl(t1, t1);
51127181 4979 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4980 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4981 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4982 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4983 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4984 tcg_temp_free(t3);
4985 tcg_temp_free(t2);
48d38ca5 4986 }
6af0bf9c
FB
4987 break;
4988 case OPC_MULT:
214c465f 4989 {
ce1dd5d1
RH
4990 TCGv_i32 t2 = tcg_temp_new_i32();
4991 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4992 tcg_gen_trunc_tl_i32(t2, t0);
4993 tcg_gen_trunc_tl_i32(t3, t1);
4994 tcg_gen_muls2_i32(t2, t3, t2, t3);
4995 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4996 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4997 tcg_temp_free_i32(t2);
4998 tcg_temp_free_i32(t3);
214c465f 4999 }
6af0bf9c
FB
5000 break;
5001 case OPC_MULTU:
214c465f 5002 {
ce1dd5d1
RH
5003 TCGv_i32 t2 = tcg_temp_new_i32();
5004 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
5005 tcg_gen_trunc_tl_i32(t2, t0);
5006 tcg_gen_trunc_tl_i32(t3, t1);
5007 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5008 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5009 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5010 tcg_temp_free_i32(t2);
5011 tcg_temp_free_i32(t3);
214c465f 5012 }
6af0bf9c 5013 break;
d26bc211 5014#if defined(TARGET_MIPS64)
7a387fff 5015 case OPC_DDIV:
48d38ca5 5016 {
51127181
AJ
5017 TCGv t2 = tcg_temp_new();
5018 TCGv t3 = tcg_temp_new();
5019 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
5020 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
5021 tcg_gen_and_tl(t2, t2, t3);
5022 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
5023 tcg_gen_or_tl(t2, t2, t3);
5024 tcg_gen_movi_tl(t3, 0);
5025 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
5026 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
5027 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
5028 tcg_temp_free(t3);
5029 tcg_temp_free(t2);
48d38ca5 5030 }
7a387fff
TS
5031 break;
5032 case OPC_DDIVU:
48d38ca5 5033 {
51127181
AJ
5034 TCGv t2 = tcg_const_tl(0);
5035 TCGv t3 = tcg_const_tl(1);
5036 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
5037 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
5038 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
5039 tcg_temp_free(t3);
5040 tcg_temp_free(t2);
48d38ca5 5041 }
7a387fff
TS
5042 break;
5043 case OPC_DMULT:
26135ead 5044 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5045 break;
5046 case OPC_DMULTU:
26135ead 5047 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
5048 break;
5049#endif
6af0bf9c 5050 case OPC_MADD:
214c465f 5051 {
d45f89f4
AJ
5052 TCGv_i64 t2 = tcg_temp_new_i64();
5053 TCGv_i64 t3 = tcg_temp_new_i64();
5054
5055 tcg_gen_ext_tl_i64(t2, t0);
5056 tcg_gen_ext_tl_i64(t3, t1);
5057 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5058 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5059 tcg_gen_add_i64(t2, t2, t3);
5060 tcg_temp_free_i64(t3);
71f303cd
RH
5061 gen_move_low32(cpu_LO[acc], t2);
5062 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5063 tcg_temp_free_i64(t2);
214c465f 5064 }
6af0bf9c
FB
5065 break;
5066 case OPC_MADDU:
4133498f 5067 {
d45f89f4
AJ
5068 TCGv_i64 t2 = tcg_temp_new_i64();
5069 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5070
78723684
TS
5071 tcg_gen_ext32u_tl(t0, t0);
5072 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5073 tcg_gen_extu_tl_i64(t2, t0);
5074 tcg_gen_extu_tl_i64(t3, t1);
5075 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5076 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
5077 tcg_gen_add_i64(t2, t2, t3);
5078 tcg_temp_free_i64(t3);
71f303cd
RH
5079 gen_move_low32(cpu_LO[acc], t2);
5080 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5081 tcg_temp_free_i64(t2);
214c465f 5082 }
6af0bf9c
FB
5083 break;
5084 case OPC_MSUB:
214c465f 5085 {
d45f89f4
AJ
5086 TCGv_i64 t2 = tcg_temp_new_i64();
5087 TCGv_i64 t3 = tcg_temp_new_i64();
5088
5089 tcg_gen_ext_tl_i64(t2, t0);
5090 tcg_gen_ext_tl_i64(t3, t1);
5091 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5092 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5093 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5094 tcg_temp_free_i64(t3);
71f303cd
RH
5095 gen_move_low32(cpu_LO[acc], t2);
5096 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5097 tcg_temp_free_i64(t2);
214c465f 5098 }
6af0bf9c
FB
5099 break;
5100 case OPC_MSUBU:
214c465f 5101 {
d45f89f4
AJ
5102 TCGv_i64 t2 = tcg_temp_new_i64();
5103 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5104
78723684
TS
5105 tcg_gen_ext32u_tl(t0, t0);
5106 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5107 tcg_gen_extu_tl_i64(t2, t0);
5108 tcg_gen_extu_tl_i64(t3, t1);
5109 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5110 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5111 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5112 tcg_temp_free_i64(t3);
71f303cd
RH
5113 gen_move_low32(cpu_LO[acc], t2);
5114 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5115 tcg_temp_free_i64(t2);
214c465f 5116 }
6af0bf9c
FB
5117 break;
5118 default:
9d68ac14 5119 MIPS_INVAL("mul/div");
9c708c7f 5120 generate_exception_end(ctx, EXCP_RI);
78723684 5121 goto out;
6af0bf9c 5122 }
78723684
TS
5123 out:
5124 tcg_temp_free(t0);
5125 tcg_temp_free(t1);
6af0bf9c
FB
5126}
5127
21e8e8b2 5128/*
3b948f05
PMD
5129 * These MULT[U] and MADD[U] instructions implemented in for example
5130 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5131 * architectures are special three-operand variants with the syntax
5132 *
06de726b 5133 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5134 *
5135 * such that
5136 *
5137 * (rd, LO, HI) <- rs * rt
5138 *
3b948f05
PMD
5139 * and
5140 *
a95c4c26 5141 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5142 *
5143 * such that
5144 *
5145 * (rd, LO, HI) <- (LO, HI) + rs * rt
5146 *
21e8e8b2
FN
5147 * where the low-order 32-bits of the result is placed into both the
5148 * GPR rd and the special register LO. The high-order 32-bits of the
5149 * result is placed into the special register HI.
5150 *
5151 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5152 * which is the zero register that always reads as 0.
5153 */
5154static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5155 int rd, int rs, int rt)
5156{
5157 TCGv t0 = tcg_temp_new();
5158 TCGv t1 = tcg_temp_new();
5159 int acc = 0;
5160
5161 gen_load_gpr(t0, rs);
5162 gen_load_gpr(t1, rt);
5163
5164 switch (opc) {
baa609db 5165 case MMI_OPC_MULT1:
06de726b
FN
5166 acc = 1;
5167 /* Fall through */
21e8e8b2
FN
5168 case OPC_MULT:
5169 {
5170 TCGv_i32 t2 = tcg_temp_new_i32();
5171 TCGv_i32 t3 = tcg_temp_new_i32();
5172 tcg_gen_trunc_tl_i32(t2, t0);
5173 tcg_gen_trunc_tl_i32(t3, t1);
5174 tcg_gen_muls2_i32(t2, t3, t2, t3);
5175 if (rd) {
5176 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5177 }
5178 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5179 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5180 tcg_temp_free_i32(t2);
5181 tcg_temp_free_i32(t3);
5182 }
5183 break;
baa609db 5184 case MMI_OPC_MULTU1:
06de726b
FN
5185 acc = 1;
5186 /* Fall through */
21e8e8b2
FN
5187 case OPC_MULTU:
5188 {
5189 TCGv_i32 t2 = tcg_temp_new_i32();
5190 TCGv_i32 t3 = tcg_temp_new_i32();
5191 tcg_gen_trunc_tl_i32(t2, t0);
5192 tcg_gen_trunc_tl_i32(t3, t1);
5193 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5194 if (rd) {
5195 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5196 }
5197 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5198 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5199 tcg_temp_free_i32(t2);
5200 tcg_temp_free_i32(t3);
5201 }
5202 break;
a95c4c26
FN
5203 case MMI_OPC_MADD1:
5204 acc = 1;
5205 /* Fall through */
3b948f05
PMD
5206 case MMI_OPC_MADD:
5207 {
5208 TCGv_i64 t2 = tcg_temp_new_i64();
5209 TCGv_i64 t3 = tcg_temp_new_i64();
5210
5211 tcg_gen_ext_tl_i64(t2, t0);
5212 tcg_gen_ext_tl_i64(t3, t1);
5213 tcg_gen_mul_i64(t2, t2, t3);
5214 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5215 tcg_gen_add_i64(t2, t2, t3);
5216 tcg_temp_free_i64(t3);
5217 gen_move_low32(cpu_LO[acc], t2);
5218 gen_move_high32(cpu_HI[acc], t2);
5219 if (rd) {
5220 gen_move_low32(cpu_gpr[rd], t2);
5221 }
5222 tcg_temp_free_i64(t2);
5223 }
5224 break;
a95c4c26
FN
5225 case MMI_OPC_MADDU1:
5226 acc = 1;
5227 /* Fall through */
3b948f05
PMD
5228 case MMI_OPC_MADDU:
5229 {
5230 TCGv_i64 t2 = tcg_temp_new_i64();
5231 TCGv_i64 t3 = tcg_temp_new_i64();
5232
5233 tcg_gen_ext32u_tl(t0, t0);
5234 tcg_gen_ext32u_tl(t1, t1);
5235 tcg_gen_extu_tl_i64(t2, t0);
5236 tcg_gen_extu_tl_i64(t3, t1);
5237 tcg_gen_mul_i64(t2, t2, t3);
5238 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5239 tcg_gen_add_i64(t2, t2, t3);
5240 tcg_temp_free_i64(t3);
5241 gen_move_low32(cpu_LO[acc], t2);
5242 gen_move_high32(cpu_HI[acc], t2);
5243 if (rd) {
5244 gen_move_low32(cpu_gpr[rd], t2);
5245 }
5246 tcg_temp_free_i64(t2);
5247 }
5248 break;
21e8e8b2 5249 default:
3b948f05 5250 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5251 generate_exception_end(ctx, EXCP_RI);
5252 goto out;
5253 }
5254
5255 out:
5256 tcg_temp_free(t0);
5257 tcg_temp_free(t1);
5258}
5259
235785e8
AM
5260static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5261 int rd, int rs, int rt)
e9c71dd1 5262{
f157bfe1
AJ
5263 TCGv t0 = tcg_temp_new();
5264 TCGv t1 = tcg_temp_new();
e9c71dd1 5265
6c5c1e20
TS
5266 gen_load_gpr(t0, rs);
5267 gen_load_gpr(t1, rt);
e9c71dd1
TS
5268
5269 switch (opc) {
5270 case OPC_VR54XX_MULS:
895c2d04 5271 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5272 break;
e9c71dd1 5273 case OPC_VR54XX_MULSU:
895c2d04 5274 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5275 break;
e9c71dd1 5276 case OPC_VR54XX_MACC:
895c2d04 5277 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5278 break;
e9c71dd1 5279 case OPC_VR54XX_MACCU:
895c2d04 5280 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5281 break;
e9c71dd1 5282 case OPC_VR54XX_MSAC:
895c2d04 5283 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5284 break;
e9c71dd1 5285 case OPC_VR54XX_MSACU:
895c2d04 5286 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5287 break;
e9c71dd1 5288 case OPC_VR54XX_MULHI:
895c2d04 5289 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5290 break;
e9c71dd1 5291 case OPC_VR54XX_MULHIU:
895c2d04 5292 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5293 break;
e9c71dd1 5294 case OPC_VR54XX_MULSHI:
895c2d04 5295 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5296 break;
e9c71dd1 5297 case OPC_VR54XX_MULSHIU:
895c2d04 5298 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5299 break;
e9c71dd1 5300 case OPC_VR54XX_MACCHI:
895c2d04 5301 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5302 break;
e9c71dd1 5303 case OPC_VR54XX_MACCHIU:
895c2d04 5304 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5305 break;
e9c71dd1 5306 case OPC_VR54XX_MSACHI:
895c2d04 5307 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5308 break;
e9c71dd1 5309 case OPC_VR54XX_MSACHIU:
895c2d04 5310 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5311 break;
e9c71dd1
TS
5312 default:
5313 MIPS_INVAL("mul vr54xx");
9c708c7f 5314 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5315 goto out;
e9c71dd1 5316 }
6c5c1e20 5317 gen_store_gpr(t0, rd);
6c5c1e20
TS
5318
5319 out:
5320 tcg_temp_free(t0);
5321 tcg_temp_free(t1);
e9c71dd1
TS
5322}
5323
235785e8
AM
5324static void gen_cl(DisasContext *ctx, uint32_t opc,
5325 int rd, int rs)
6af0bf9c 5326{
20e1fb52 5327 TCGv t0;
6c5c1e20 5328
6af0bf9c 5329 if (rd == 0) {
ead9360e 5330 /* Treat as NOP. */
20e1fb52 5331 return;
6af0bf9c 5332 }
1a0196c5 5333 t0 = cpu_gpr[rd];
6c5c1e20 5334 gen_load_gpr(t0, rs);
1a0196c5 5335
6af0bf9c
FB
5336 switch (opc) {
5337 case OPC_CLO:
4267d3e6 5338 case R6_OPC_CLO:
1a0196c5
RH
5339#if defined(TARGET_MIPS64)
5340 case OPC_DCLO:
5341 case R6_OPC_DCLO:
5342#endif
5343 tcg_gen_not_tl(t0, t0);
6af0bf9c 5344 break;
1a0196c5
RH
5345 }
5346
5347 switch (opc) {
5348 case OPC_CLO:
5349 case R6_OPC_CLO:
6af0bf9c 5350 case OPC_CLZ:
4267d3e6 5351 case R6_OPC_CLZ:
1a0196c5
RH
5352 tcg_gen_ext32u_tl(t0, t0);
5353 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5354 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5355 break;
d26bc211 5356#if defined(TARGET_MIPS64)
7a387fff 5357 case OPC_DCLO:
4267d3e6 5358 case R6_OPC_DCLO:
7a387fff 5359 case OPC_DCLZ:
4267d3e6 5360 case R6_OPC_DCLZ:
1a0196c5 5361 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5362 break;
5363#endif
6af0bf9c 5364 }
6af0bf9c
FB
5365}
5366
161f85e6 5367/* Godson integer instructions */
bd277fa1
RH
5368static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5369 int rd, int rs, int rt)
161f85e6 5370{
161f85e6
AJ
5371 TCGv t0, t1;
5372
5373 if (rd == 0) {
5374 /* Treat as NOP. */
161f85e6
AJ
5375 return;
5376 }
5377
5378 switch (opc) {
5379 case OPC_MULT_G_2E:
5380 case OPC_MULT_G_2F:
5381 case OPC_MULTU_G_2E:
5382 case OPC_MULTU_G_2F:
5383#if defined(TARGET_MIPS64)
5384 case OPC_DMULT_G_2E:
5385 case OPC_DMULT_G_2F:
5386 case OPC_DMULTU_G_2E:
5387 case OPC_DMULTU_G_2F:
5388#endif
5389 t0 = tcg_temp_new();
5390 t1 = tcg_temp_new();
5391 break;
5392 default:
5393 t0 = tcg_temp_local_new();
5394 t1 = tcg_temp_local_new();
5395 break;
5396 }
5397
5398 gen_load_gpr(t0, rs);
5399 gen_load_gpr(t1, rt);
5400
5401 switch (opc) {
5402 case OPC_MULT_G_2E:
5403 case OPC_MULT_G_2F:
5404 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5405 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5406 break;
5407 case OPC_MULTU_G_2E:
5408 case OPC_MULTU_G_2F:
5409 tcg_gen_ext32u_tl(t0, t0);
5410 tcg_gen_ext32u_tl(t1, t1);
5411 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5412 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5413 break;
5414 case OPC_DIV_G_2E:
5415 case OPC_DIV_G_2F:
5416 {
42a268c2
RH
5417 TCGLabel *l1 = gen_new_label();
5418 TCGLabel *l2 = gen_new_label();
5419 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5420 tcg_gen_ext32s_tl(t0, t0);
5421 tcg_gen_ext32s_tl(t1, t1);
5422 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5423 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5424 tcg_gen_br(l3);
5425 gen_set_label(l1);
5426 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5427 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5428 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5429 tcg_gen_br(l3);
5430 gen_set_label(l2);
5431 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5432 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5433 gen_set_label(l3);
5434 }
161f85e6
AJ
5435 break;
5436 case OPC_DIVU_G_2E:
5437 case OPC_DIVU_G_2F:
5438 {
42a268c2
RH
5439 TCGLabel *l1 = gen_new_label();
5440 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5441 tcg_gen_ext32u_tl(t0, t0);
5442 tcg_gen_ext32u_tl(t1, t1);
5443 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5444 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5445 tcg_gen_br(l2);
5446 gen_set_label(l1);
5447 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5448 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5449 gen_set_label(l2);
5450 }
161f85e6
AJ
5451 break;
5452 case OPC_MOD_G_2E:
5453 case OPC_MOD_G_2F:
5454 {
42a268c2
RH
5455 TCGLabel *l1 = gen_new_label();
5456 TCGLabel *l2 = gen_new_label();
5457 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5458 tcg_gen_ext32u_tl(t0, t0);
5459 tcg_gen_ext32u_tl(t1, t1);
5460 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5462 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5463 gen_set_label(l1);
5464 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5465 tcg_gen_br(l3);
5466 gen_set_label(l2);
5467 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5468 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5469 gen_set_label(l3);
5470 }
161f85e6
AJ
5471 break;
5472 case OPC_MODU_G_2E:
5473 case OPC_MODU_G_2F:
5474 {
42a268c2
RH
5475 TCGLabel *l1 = gen_new_label();
5476 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5477 tcg_gen_ext32u_tl(t0, t0);
5478 tcg_gen_ext32u_tl(t1, t1);
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_remu_tl(cpu_gpr[rd], t0, t1);
5484 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5485 gen_set_label(l2);
5486 }
161f85e6
AJ
5487 break;
5488#if defined(TARGET_MIPS64)
5489 case OPC_DMULT_G_2E:
5490 case OPC_DMULT_G_2F:
5491 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5492 break;
5493 case OPC_DMULTU_G_2E:
5494 case OPC_DMULTU_G_2F:
5495 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5496 break;
5497 case OPC_DDIV_G_2E:
5498 case OPC_DDIV_G_2F:
5499 {
42a268c2
RH
5500 TCGLabel *l1 = gen_new_label();
5501 TCGLabel *l2 = gen_new_label();
5502 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5503 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5504 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5505 tcg_gen_br(l3);
5506 gen_set_label(l1);
5507 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5508 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5509 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5510 tcg_gen_br(l3);
5511 gen_set_label(l2);
5512 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5513 gen_set_label(l3);
5514 }
161f85e6
AJ
5515 break;
5516 case OPC_DDIVU_G_2E:
5517 case OPC_DDIVU_G_2F:
5518 {
42a268c2
RH
5519 TCGLabel *l1 = gen_new_label();
5520 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5521 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5522 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5523 tcg_gen_br(l2);
5524 gen_set_label(l1);
5525 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5526 gen_set_label(l2);
5527 }
161f85e6
AJ
5528 break;
5529 case OPC_DMOD_G_2E:
5530 case OPC_DMOD_G_2F:
5531 {
42a268c2
RH
5532 TCGLabel *l1 = gen_new_label();
5533 TCGLabel *l2 = gen_new_label();
5534 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5535 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5537 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5538 gen_set_label(l1);
5539 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5540 tcg_gen_br(l3);
5541 gen_set_label(l2);
5542 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5543 gen_set_label(l3);
5544 }
161f85e6
AJ
5545 break;
5546 case OPC_DMODU_G_2E:
5547 case OPC_DMODU_G_2F:
5548 {
42a268c2
RH
5549 TCGLabel *l1 = gen_new_label();
5550 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5551 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5552 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5553 tcg_gen_br(l2);
5554 gen_set_label(l1);
5555 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5556 gen_set_label(l2);
5557 }
161f85e6
AJ
5558 break;
5559#endif
5560 }
5561
161f85e6
AJ
5562 tcg_temp_free(t0);
5563 tcg_temp_free(t1);
5564}
5565
bd277fa1
RH
5566/* Loongson multimedia instructions */
5567static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5568{
bd277fa1
RH
5569 uint32_t opc, shift_max;
5570 TCGv_i64 t0, t1;
84878f4c 5571 TCGCond cond;
bd277fa1 5572
8e2d5831 5573 opc = MASK_LMMI(ctx->opcode);
bd277fa1
RH
5574 switch (opc) {
5575 case OPC_ADD_CP2:
5576 case OPC_SUB_CP2:
5577 case OPC_DADD_CP2:
5578 case OPC_DSUB_CP2:
5579 t0 = tcg_temp_local_new_i64();
5580 t1 = tcg_temp_local_new_i64();
5581 break;
5582 default:
5583 t0 = tcg_temp_new_i64();
5584 t1 = tcg_temp_new_i64();
5585 break;
5586 }
5587
b5a587b6 5588 check_cp1_enabled(ctx);
bd277fa1
RH
5589 gen_load_fpr64(ctx, t0, rs);
5590 gen_load_fpr64(ctx, t1, rt);
5591
bd277fa1 5592 switch (opc) {
b1cf82f0
AM
5593 case OPC_PADDSH:
5594 gen_helper_paddsh(t0, t0, t1);
5595 break;
5596 case OPC_PADDUSH:
5597 gen_helper_paddush(t0, t0, t1);
5598 break;
5599 case OPC_PADDH:
5600 gen_helper_paddh(t0, t0, t1);
5601 break;
5602 case OPC_PADDW:
5603 gen_helper_paddw(t0, t0, t1);
5604 break;
5605 case OPC_PADDSB:
5606 gen_helper_paddsb(t0, t0, t1);
5607 break;
5608 case OPC_PADDUSB:
5609 gen_helper_paddusb(t0, t0, t1);
5610 break;
5611 case OPC_PADDB:
5612 gen_helper_paddb(t0, t0, t1);
5613 break;
5614
5615 case OPC_PSUBSH:
5616 gen_helper_psubsh(t0, t0, t1);
5617 break;
5618 case OPC_PSUBUSH:
5619 gen_helper_psubush(t0, t0, t1);
5620 break;
5621 case OPC_PSUBH:
5622 gen_helper_psubh(t0, t0, t1);
5623 break;
5624 case OPC_PSUBW:
5625 gen_helper_psubw(t0, t0, t1);
5626 break;
5627 case OPC_PSUBSB:
5628 gen_helper_psubsb(t0, t0, t1);
5629 break;
5630 case OPC_PSUBUSB:
5631 gen_helper_psubusb(t0, t0, t1);
5632 break;
5633 case OPC_PSUBB:
5634 gen_helper_psubb(t0, t0, t1);
5635 break;
5636
5637 case OPC_PSHUFH:
5638 gen_helper_pshufh(t0, t0, t1);
5639 break;
5640 case OPC_PACKSSWH:
5641 gen_helper_packsswh(t0, t0, t1);
5642 break;
5643 case OPC_PACKSSHB:
5644 gen_helper_packsshb(t0, t0, t1);
5645 break;
5646 case OPC_PACKUSHB:
5647 gen_helper_packushb(t0, t0, t1);
5648 break;
5649
5650 case OPC_PUNPCKLHW:
5651 gen_helper_punpcklhw(t0, t0, t1);
5652 break;
5653 case OPC_PUNPCKHHW:
5654 gen_helper_punpckhhw(t0, t0, t1);
5655 break;
5656 case OPC_PUNPCKLBH:
5657 gen_helper_punpcklbh(t0, t0, t1);
5658 break;
5659 case OPC_PUNPCKHBH:
5660 gen_helper_punpckhbh(t0, t0, t1);
5661 break;
5662 case OPC_PUNPCKLWD:
5663 gen_helper_punpcklwd(t0, t0, t1);
5664 break;
5665 case OPC_PUNPCKHWD:
5666 gen_helper_punpckhwd(t0, t0, t1);
5667 break;
5668
5669 case OPC_PAVGH:
5670 gen_helper_pavgh(t0, t0, t1);
5671 break;
5672 case OPC_PAVGB:
5673 gen_helper_pavgb(t0, t0, t1);
5674 break;
5675 case OPC_PMAXSH:
5676 gen_helper_pmaxsh(t0, t0, t1);
5677 break;
5678 case OPC_PMINSH:
5679 gen_helper_pminsh(t0, t0, t1);
5680 break;
5681 case OPC_PMAXUB:
5682 gen_helper_pmaxub(t0, t0, t1);
5683 break;
5684 case OPC_PMINUB:
5685 gen_helper_pminub(t0, t0, t1);
5686 break;
5687
5688 case OPC_PCMPEQW:
5689 gen_helper_pcmpeqw(t0, t0, t1);
5690 break;
5691 case OPC_PCMPGTW:
5692 gen_helper_pcmpgtw(t0, t0, t1);
5693 break;
5694 case OPC_PCMPEQH:
5695 gen_helper_pcmpeqh(t0, t0, t1);
5696 break;
5697 case OPC_PCMPGTH:
5698 gen_helper_pcmpgth(t0, t0, t1);
5699 break;
5700 case OPC_PCMPEQB:
5701 gen_helper_pcmpeqb(t0, t0, t1);
5702 break;
5703 case OPC_PCMPGTB:
5704 gen_helper_pcmpgtb(t0, t0, t1);
5705 break;
5706
5707 case OPC_PSLLW:
5708 gen_helper_psllw(t0, t0, t1);
5709 break;
5710 case OPC_PSLLH:
5711 gen_helper_psllh(t0, t0, t1);
5712 break;
5713 case OPC_PSRLW:
5714 gen_helper_psrlw(t0, t0, t1);
5715 break;
5716 case OPC_PSRLH:
5717 gen_helper_psrlh(t0, t0, t1);
5718 break;
5719 case OPC_PSRAW:
5720 gen_helper_psraw(t0, t0, t1);
5721 break;
5722 case OPC_PSRAH:
5723 gen_helper_psrah(t0, t0, t1);
5724 break;
5725
5726 case OPC_PMULLH:
5727 gen_helper_pmullh(t0, t0, t1);
5728 break;
5729 case OPC_PMULHH:
5730 gen_helper_pmulhh(t0, t0, t1);
5731 break;
5732 case OPC_PMULHUH:
5733 gen_helper_pmulhuh(t0, t0, t1);
5734 break;
5735 case OPC_PMADDHW:
5736 gen_helper_pmaddhw(t0, t0, t1);
5737 break;
5738
5739 case OPC_PASUBUB:
5740 gen_helper_pasubub(t0, t0, t1);
5741 break;
5742 case OPC_BIADD:
5743 gen_helper_biadd(t0, t0);
5744 break;
5745 case OPC_PMOVMSKB:
5746 gen_helper_pmovmskb(t0, t0);
5747 break;
5748
5749 case OPC_PADDD:
5750 tcg_gen_add_i64(t0, t0, t1);
5751 break;
5752 case OPC_PSUBD:
5753 tcg_gen_sub_i64(t0, t0, t1);
5754 break;
5755 case OPC_XOR_CP2:
5756 tcg_gen_xor_i64(t0, t0, t1);
5757 break;
5758 case OPC_NOR_CP2:
5759 tcg_gen_nor_i64(t0, t0, t1);
5760 break;
5761 case OPC_AND_CP2:
5762 tcg_gen_and_i64(t0, t0, t1);
5763 break;
5764 case OPC_OR_CP2:
5765 tcg_gen_or_i64(t0, t0, t1);
5766 break;
bd277fa1 5767
9099a36b
H
5768 case OPC_PANDN:
5769 tcg_gen_andc_i64(t0, t1, t0);
5770 break;
5771
bd277fa1
RH
5772 case OPC_PINSRH_0:
5773 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5774 break;
5775 case OPC_PINSRH_1:
5776 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5777 break;
5778 case OPC_PINSRH_2:
5779 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5780 break;
5781 case OPC_PINSRH_3:
5782 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5783 break;
5784
5785 case OPC_PEXTRH:
5786 tcg_gen_andi_i64(t1, t1, 3);
5787 tcg_gen_shli_i64(t1, t1, 4);
5788 tcg_gen_shr_i64(t0, t0, t1);
5789 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5790 break;
5791
5792 case OPC_ADDU_CP2:
5793 tcg_gen_add_i64(t0, t0, t1);
5794 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5795 break;
5796 case OPC_SUBU_CP2:
5797 tcg_gen_sub_i64(t0, t0, t1);
5798 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5799 break;
5800
5801 case OPC_SLL_CP2:
bd277fa1
RH
5802 shift_max = 32;
5803 goto do_shift;
5804 case OPC_SRL_CP2:
bd277fa1
RH
5805 shift_max = 32;
5806 goto do_shift;
5807 case OPC_SRA_CP2:
bd277fa1
RH
5808 shift_max = 32;
5809 goto do_shift;
5810 case OPC_DSLL_CP2:
bd277fa1
RH
5811 shift_max = 64;
5812 goto do_shift;
5813 case OPC_DSRL_CP2:
bd277fa1
RH
5814 shift_max = 64;
5815 goto do_shift;
5816 case OPC_DSRA_CP2:
bd277fa1
RH
5817 shift_max = 64;
5818 goto do_shift;
5819 do_shift:
5820 /* Make sure shift count isn't TCG undefined behaviour. */
5821 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5822
5823 switch (opc) {
5824 case OPC_SLL_CP2:
5825 case OPC_DSLL_CP2:
5826 tcg_gen_shl_i64(t0, t0, t1);
5827 break;
5828 case OPC_SRA_CP2:
5829 case OPC_DSRA_CP2:
7480515f
AM
5830 /*
5831 * Since SRA is UndefinedResult without sign-extended inputs,
5832 * we can treat SRA and DSRA the same.
5833 */
bd277fa1
RH
5834 tcg_gen_sar_i64(t0, t0, t1);
5835 break;
5836 case OPC_SRL_CP2:
5837 /* We want to shift in zeros for SRL; zero-extend first. */
5838 tcg_gen_ext32u_i64(t0, t0);
5839 /* FALLTHRU */
5840 case OPC_DSRL_CP2:
5841 tcg_gen_shr_i64(t0, t0, t1);
5842 break;
5843 }
5844
5845 if (shift_max == 32) {
5846 tcg_gen_ext32s_i64(t0, t0);
5847 }
5848
5849 /* Shifts larger than MAX produce zero. */
5850 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5851 tcg_gen_neg_i64(t1, t1);
5852 tcg_gen_and_i64(t0, t0, t1);
5853 break;
5854
5855 case OPC_ADD_CP2:
5856 case OPC_DADD_CP2:
5857 {
5858 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5859 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5860
5861 tcg_gen_mov_i64(t2, t0);
5862 tcg_gen_add_i64(t0, t1, t2);
5863 if (opc == OPC_ADD_CP2) {
5864 tcg_gen_ext32s_i64(t0, t0);
5865 }
5866 tcg_gen_xor_i64(t1, t1, t2);
5867 tcg_gen_xor_i64(t2, t2, t0);
5868 tcg_gen_andc_i64(t1, t2, t1);
5869 tcg_temp_free_i64(t2);
5870 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5871 generate_exception(ctx, EXCP_OVERFLOW);
5872 gen_set_label(lab);
bd277fa1
RH
5873 break;
5874 }
5875
5876 case OPC_SUB_CP2:
5877 case OPC_DSUB_CP2:
5878 {
5879 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5880 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5881
5882 tcg_gen_mov_i64(t2, t0);
5883 tcg_gen_sub_i64(t0, t1, t2);
5884 if (opc == OPC_SUB_CP2) {
5885 tcg_gen_ext32s_i64(t0, t0);
5886 }
5887 tcg_gen_xor_i64(t1, t1, t2);
5888 tcg_gen_xor_i64(t2, t2, t0);
5889 tcg_gen_and_i64(t1, t1, t2);
5890 tcg_temp_free_i64(t2);
5891 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5892 generate_exception(ctx, EXCP_OVERFLOW);
5893 gen_set_label(lab);
bd277fa1
RH
5894 break;
5895 }
5896
5897 case OPC_PMULUW:
5898 tcg_gen_ext32u_i64(t0, t0);
5899 tcg_gen_ext32u_i64(t1, t1);
5900 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5901 break;
5902
5903 case OPC_SEQU_CP2:
5904 case OPC_SEQ_CP2:
84878f4c
JY
5905 cond = TCG_COND_EQ;
5906 goto do_cc_cond;
5907 break;
bd277fa1 5908 case OPC_SLTU_CP2:
84878f4c
JY
5909 cond = TCG_COND_LTU;
5910 goto do_cc_cond;
5911 break;
bd277fa1 5912 case OPC_SLT_CP2:
84878f4c
JY
5913 cond = TCG_COND_LT;
5914 goto do_cc_cond;
5915 break;
bd277fa1 5916 case OPC_SLEU_CP2:
84878f4c
JY
5917 cond = TCG_COND_LEU;
5918 goto do_cc_cond;
5919 break;
bd277fa1 5920 case OPC_SLE_CP2:
84878f4c
JY
5921 cond = TCG_COND_LE;
5922 do_cc_cond:
5923 {
5924 int cc = (ctx->opcode >> 8) & 0x7;
5925 TCGv_i64 t64 = tcg_temp_new_i64();
5926 TCGv_i32 t32 = tcg_temp_new_i32();
5927
5928 tcg_gen_setcond_i64(cond, t64, t0, t1);
5929 tcg_gen_extrl_i64_i32(t32, t64);
5930 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5931 get_fp_bit(cc), 1);
5932
5933 tcg_temp_free_i32(t32);
5934 tcg_temp_free_i64(t64);
5935 }
5936 goto no_rd;
5937 break;
bd277fa1 5938 default:
9d68ac14 5939 MIPS_INVAL("loongson_cp2");
9c708c7f 5940 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5941 return;
5942 }
5943
bd277fa1
RH
5944 gen_store_fpr64(ctx, t0, rd);
5945
84878f4c 5946no_rd:
bd277fa1
RH
5947 tcg_temp_free_i64(t0);
5948 tcg_temp_free_i64(t1);
5949}
5950
e10a0ca1
JY
5951static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5952 int rs, int rd)
5953{
fd723105
JY
5954 TCGv t0, t1, t2;
5955 TCGv_i32 fp0;
e10a0ca1 5956#if defined(TARGET_MIPS64)
e10a0ca1
JY
5957 int lsq_rt1 = ctx->opcode & 0x1f;
5958 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5959#endif
fd723105 5960 int shf_offset = sextract32(ctx->opcode, 6, 8);
e10a0ca1
JY
5961
5962 t0 = tcg_temp_new();
5963
5964 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5965#if defined(TARGET_MIPS64)
5966 case OPC_GSLQ:
5967 t1 = tcg_temp_new();
5968 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5969 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5970 ctx->default_tcg_memop_mask);
5971 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5972 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5973 ctx->default_tcg_memop_mask);
5974 gen_store_gpr(t1, rt);
5975 gen_store_gpr(t0, lsq_rt1);
5976 tcg_temp_free(t1);
5977 break;
5978 case OPC_GSLQC1:
5979 check_cp1_enabled(ctx);
5980 t1 = tcg_temp_new();
5981 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5982 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5983 ctx->default_tcg_memop_mask);
5984 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5985 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5986 ctx->default_tcg_memop_mask);
5987 gen_store_fpr64(ctx, t1, rt);
5988 gen_store_fpr64(ctx, t0, lsq_rt1);
5989 tcg_temp_free(t1);
5990 break;
5991 case OPC_GSSQ:
5992 t1 = tcg_temp_new();
5993 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5994 gen_load_gpr(t1, rt);
5995 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5996 ctx->default_tcg_memop_mask);
5997 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5998 gen_load_gpr(t1, lsq_rt1);
5999 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6000 ctx->default_tcg_memop_mask);
6001 tcg_temp_free(t1);
6002 break;
6003 case OPC_GSSQC1:
6004 check_cp1_enabled(ctx);
6005 t1 = tcg_temp_new();
6006 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
6007 gen_load_fpr64(ctx, t1, rt);
6008 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6009 ctx->default_tcg_memop_mask);
6010 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
6011 gen_load_fpr64(ctx, t1, lsq_rt1);
6012 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6013 ctx->default_tcg_memop_mask);
6014 tcg_temp_free(t1);
6015 break;
6016#endif
fd723105
JY
6017 case OPC_GSSHFL:
6018 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6019 case OPC_GSLWLC1:
6020 check_cp1_enabled(ctx);
6021 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6022 t1 = tcg_temp_new();
6023 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6024 tcg_gen_andi_tl(t1, t0, 3);
6025#ifndef TARGET_WORDS_BIGENDIAN
6026 tcg_gen_xori_tl(t1, t1, 3);
6027#endif
6028 tcg_gen_shli_tl(t1, t1, 3);
6029 tcg_gen_andi_tl(t0, t0, ~3);
6030 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6031 tcg_gen_shl_tl(t0, t0, t1);
6032 t2 = tcg_const_tl(-1);
6033 tcg_gen_shl_tl(t2, t2, t1);
6034 fp0 = tcg_temp_new_i32();
6035 gen_load_fpr32(ctx, fp0, rt);
6036 tcg_gen_ext_i32_tl(t1, fp0);
6037 tcg_gen_andc_tl(t1, t1, t2);
6038 tcg_temp_free(t2);
6039 tcg_gen_or_tl(t0, t0, t1);
6040 tcg_temp_free(t1);
6041#if defined(TARGET_MIPS64)
6042 tcg_gen_extrl_i64_i32(fp0, t0);
6043#else
6044 tcg_gen_ext32s_tl(fp0, t0);
6045#endif
6046 gen_store_fpr32(ctx, fp0, rt);
6047 tcg_temp_free_i32(fp0);
6048 break;
6049 case OPC_GSLWRC1:
6050 check_cp1_enabled(ctx);
6051 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6052 t1 = tcg_temp_new();
6053 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6054 tcg_gen_andi_tl(t1, t0, 3);
6055#ifdef TARGET_WORDS_BIGENDIAN
6056 tcg_gen_xori_tl(t1, t1, 3);
6057#endif
6058 tcg_gen_shli_tl(t1, t1, 3);
6059 tcg_gen_andi_tl(t0, t0, ~3);
6060 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6061 tcg_gen_shr_tl(t0, t0, t1);
6062 tcg_gen_xori_tl(t1, t1, 31);
6063 t2 = tcg_const_tl(0xfffffffeull);
6064 tcg_gen_shl_tl(t2, t2, t1);
6065 fp0 = tcg_temp_new_i32();
6066 gen_load_fpr32(ctx, fp0, rt);
6067 tcg_gen_ext_i32_tl(t1, fp0);
6068 tcg_gen_and_tl(t1, t1, t2);
6069 tcg_temp_free(t2);
6070 tcg_gen_or_tl(t0, t0, t1);
6071 tcg_temp_free(t1);
6072#if defined(TARGET_MIPS64)
6073 tcg_gen_extrl_i64_i32(fp0, t0);
6074#else
6075 tcg_gen_ext32s_tl(fp0, t0);
6076#endif
6077 gen_store_fpr32(ctx, fp0, rt);
6078 tcg_temp_free_i32(fp0);
6079 break;
6080#if defined(TARGET_MIPS64)
6081 case OPC_GSLDLC1:
6082 check_cp1_enabled(ctx);
6083 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6084 t1 = tcg_temp_new();
6085 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6086 tcg_gen_andi_tl(t1, t0, 7);
6087#ifndef TARGET_WORDS_BIGENDIAN
6088 tcg_gen_xori_tl(t1, t1, 7);
6089#endif
6090 tcg_gen_shli_tl(t1, t1, 3);
6091 tcg_gen_andi_tl(t0, t0, ~7);
6092 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6093 tcg_gen_shl_tl(t0, t0, t1);
6094 t2 = tcg_const_tl(-1);
6095 tcg_gen_shl_tl(t2, t2, t1);
6096 gen_load_fpr64(ctx, t1, rt);
6097 tcg_gen_andc_tl(t1, t1, t2);
6098 tcg_temp_free(t2);
6099 tcg_gen_or_tl(t0, t0, t1);
6100 tcg_temp_free(t1);
6101 gen_store_fpr64(ctx, t0, rt);
6102 break;
6103 case OPC_GSLDRC1:
6104 check_cp1_enabled(ctx);
6105 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6106 t1 = tcg_temp_new();
6107 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6108 tcg_gen_andi_tl(t1, t0, 7);
6109#ifdef TARGET_WORDS_BIGENDIAN
6110 tcg_gen_xori_tl(t1, t1, 7);
6111#endif
6112 tcg_gen_shli_tl(t1, t1, 3);
6113 tcg_gen_andi_tl(t0, t0, ~7);
6114 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6115 tcg_gen_shr_tl(t0, t0, t1);
6116 tcg_gen_xori_tl(t1, t1, 63);
6117 t2 = tcg_const_tl(0xfffffffffffffffeull);
6118 tcg_gen_shl_tl(t2, t2, t1);
6119 gen_load_fpr64(ctx, t1, rt);
6120 tcg_gen_and_tl(t1, t1, t2);
6121 tcg_temp_free(t2);
6122 tcg_gen_or_tl(t0, t0, t1);
6123 tcg_temp_free(t1);
6124 gen_store_fpr64(ctx, t0, rt);
6125 break;
6126#endif
6127 default:
6128 MIPS_INVAL("loongson_gsshfl");
6129 generate_exception_end(ctx, EXCP_RI);
6130 break;
6131 }
6132 break;
6133 case OPC_GSSHFS:
6134 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6135 case OPC_GSSWLC1:
6136 check_cp1_enabled(ctx);
6137 t1 = tcg_temp_new();
6138 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6139 fp0 = tcg_temp_new_i32();
6140 gen_load_fpr32(ctx, fp0, rt);
6141 tcg_gen_ext_i32_tl(t1, fp0);
6142 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6143 tcg_temp_free_i32(fp0);
6144 tcg_temp_free(t1);
6145 break;
6146 case OPC_GSSWRC1:
6147 check_cp1_enabled(ctx);
6148 t1 = tcg_temp_new();
6149 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6150 fp0 = tcg_temp_new_i32();
6151 gen_load_fpr32(ctx, fp0, rt);
6152 tcg_gen_ext_i32_tl(t1, fp0);
6153 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6154 tcg_temp_free_i32(fp0);
6155 tcg_temp_free(t1);
6156 break;
6157#if defined(TARGET_MIPS64)
6158 case OPC_GSSDLC1:
6159 check_cp1_enabled(ctx);
6160 t1 = tcg_temp_new();
6161 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6162 gen_load_fpr64(ctx, t1, rt);
6163 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6164 tcg_temp_free(t1);
6165 break;
6166 case OPC_GSSDRC1:
6167 check_cp1_enabled(ctx);
6168 t1 = tcg_temp_new();
6169 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6170 gen_load_fpr64(ctx, t1, rt);
6171 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6172 tcg_temp_free(t1);
6173 break;
6174#endif
6175 default:
6176 MIPS_INVAL("loongson_gsshfs");
6177 generate_exception_end(ctx, EXCP_RI);
6178 break;
6179 }
6180 break;
e10a0ca1
JY
6181 default:
6182 MIPS_INVAL("loongson_gslsq");
6183 generate_exception_end(ctx, EXCP_RI);
6184 break;
6185 }
6186 tcg_temp_free(t0);
6187}
6188
90e22a57
JY
6189/* Loongson EXT LDC2/SDC2 */
6190static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6191 int rs, int rd)
6192{
6193 int offset = sextract32(ctx->opcode, 3, 8);
6194 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6195 TCGv t0, t1;
6196 TCGv_i32 fp0;
6197
6198 /* Pre-conditions */
6199 switch (opc) {
6200 case OPC_GSLBX:
6201 case OPC_GSLHX:
6202 case OPC_GSLWX:
6203 case OPC_GSLDX:
6204 /* prefetch, implement as NOP */
6205 if (rt == 0) {
6206 return;
6207 }
6208 break;
6209 case OPC_GSSBX:
6210 case OPC_GSSHX:
6211 case OPC_GSSWX:
6212 case OPC_GSSDX:
6213 break;
6214 case OPC_GSLWXC1:
6215#if defined(TARGET_MIPS64)
6216 case OPC_GSLDXC1:
6217#endif
6218 check_cp1_enabled(ctx);
6219 /* prefetch, implement as NOP */
6220 if (rt == 0) {
6221 return;
6222 }
6223 break;
6224 case OPC_GSSWXC1:
6225#if defined(TARGET_MIPS64)
6226 case OPC_GSSDXC1:
6227#endif
6228 check_cp1_enabled(ctx);
6229 break;
6230 default:
6231 MIPS_INVAL("loongson_lsdc2");
6232 generate_exception_end(ctx, EXCP_RI);
6233 return;
6234 break;
6235 }
6236
6237 t0 = tcg_temp_new();
6238
6239 gen_base_offset_addr(ctx, t0, rs, offset);
6240 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6241
6242 switch (opc) {
6243 case OPC_GSLBX:
6244 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6245 gen_store_gpr(t0, rt);
6246 break;
6247 case OPC_GSLHX:
6248 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6249 ctx->default_tcg_memop_mask);
6250 gen_store_gpr(t0, rt);
6251 break;
6252 case OPC_GSLWX:
6253 gen_base_offset_addr(ctx, t0, rs, offset);
6254 if (rd) {
6255 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6256 }
6257 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6258 ctx->default_tcg_memop_mask);
6259 gen_store_gpr(t0, rt);
6260 break;
6261#if defined(TARGET_MIPS64)
6262 case OPC_GSLDX:
6263 gen_base_offset_addr(ctx, t0, rs, offset);
6264 if (rd) {
6265 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6266 }
6267 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6268 ctx->default_tcg_memop_mask);
6269 gen_store_gpr(t0, rt);
6270 break;
6271#endif
6272 case OPC_GSLWXC1:
6273 check_cp1_enabled(ctx);
6274 gen_base_offset_addr(ctx, t0, rs, offset);
6275 if (rd) {
6276 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6277 }
6278 fp0 = tcg_temp_new_i32();
6279 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6280 ctx->default_tcg_memop_mask);
6281 gen_store_fpr32(ctx, fp0, rt);
6282 tcg_temp_free_i32(fp0);
6283 break;
6284#if defined(TARGET_MIPS64)
6285 case OPC_GSLDXC1:
6286 check_cp1_enabled(ctx);
6287 gen_base_offset_addr(ctx, t0, rs, offset);
6288 if (rd) {
6289 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6290 }
6291 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6292 ctx->default_tcg_memop_mask);
6293 gen_store_fpr64(ctx, t0, rt);
6294 break;
6295#endif
6296 case OPC_GSSBX:
6297 t1 = tcg_temp_new();
6298 gen_load_gpr(t1, rt);
6299 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6300 tcg_temp_free(t1);
6301 break;
6302 case OPC_GSSHX:
6303 t1 = tcg_temp_new();
6304 gen_load_gpr(t1, rt);
6305 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6306 ctx->default_tcg_memop_mask);
6307 tcg_temp_free(t1);
6308 break;
6309 case OPC_GSSWX:
6310 t1 = tcg_temp_new();
6311 gen_load_gpr(t1, rt);
6312 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6313 ctx->default_tcg_memop_mask);
6314 tcg_temp_free(t1);
6315 break;
6316#if defined(TARGET_MIPS64)
6317 case OPC_GSSDX:
6318 t1 = tcg_temp_new();
6319 gen_load_gpr(t1, rt);
6320 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6321 ctx->default_tcg_memop_mask);
6322 tcg_temp_free(t1);
6323 break;
6324#endif
6325 case OPC_GSSWXC1:
6326 fp0 = tcg_temp_new_i32();
6327 gen_load_fpr32(ctx, fp0, rt);
6328 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6329 ctx->default_tcg_memop_mask);
6330 tcg_temp_free_i32(fp0);
6331 break;
6332#if defined(TARGET_MIPS64)
6333 case OPC_GSSDXC1:
6334 t1 = tcg_temp_new();
6335 gen_load_fpr64(ctx, t1, rt);
6336 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6337 ctx->default_tcg_memop_mask);
6338 tcg_temp_free(t1);
6339 break;
6340#endif
6341 default:
6342 break;
6343 }
6344
6345 tcg_temp_free(t0);
6346}
6347
6af0bf9c 6348/* Traps */
71375b59
AM
6349static void gen_trap(DisasContext *ctx, uint32_t opc,
6350 int rs, int rt, int16_t imm)
6af0bf9c
FB
6351{
6352 int cond;
cdc0faa6 6353 TCGv t0 = tcg_temp_new();
1ba74fb8 6354 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
6355
6356 cond = 0;
6357 /* Load needed operands */
6358 switch (opc) {
6359 case OPC_TEQ:
6360 case OPC_TGE:
6361 case OPC_TGEU:
6362 case OPC_TLT:
6363 case OPC_TLTU:
6364 case OPC_TNE:
6365 /* Compare two registers */
6366 if (rs != rt) {
be24bb4f
TS
6367 gen_load_gpr(t0, rs);
6368 gen_load_gpr(t1, rt);
6af0bf9c
FB
6369 cond = 1;
6370 }
179e32bb 6371 break;
6af0bf9c
FB
6372 case OPC_TEQI:
6373 case OPC_TGEI:
6374 case OPC_TGEIU:
6375 case OPC_TLTI:
6376 case OPC_TLTIU:
6377 case OPC_TNEI:
6378 /* Compare register to immediate */
6379 if (rs != 0 || imm != 0) {
be24bb4f
TS
6380 gen_load_gpr(t0, rs);
6381 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
6382 cond = 1;
6383 }
6384 break;
6385 }
6386 if (cond == 0) {
6387 switch (opc) {
6388 case OPC_TEQ: /* rs == rs */
6389 case OPC_TEQI: /* r0 == 0 */
6390 case OPC_TGE: /* rs >= rs */
6391 case OPC_TGEI: /* r0 >= 0 */
6392 case OPC_TGEU: /* rs >= rs unsigned */
6393 case OPC_TGEIU: /* r0 >= 0 unsigned */
6394 /* Always trap */
9c708c7f 6395 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
6396 break;
6397 case OPC_TLT: /* rs < rs */
6398 case OPC_TLTI: /* r0 < 0 */
6399 case OPC_TLTU: /* rs < rs unsigned */
6400 case OPC_TLTIU: /* r0 < 0 unsigned */
6401 case OPC_TNE: /* rs != rs */
6402 case OPC_TNEI: /* r0 != 0 */
ead9360e 6403 /* Never trap: treat as NOP. */
cdc0faa6 6404 break;
6af0bf9c
FB
6405 }
6406 } else {
42a268c2 6407 TCGLabel *l1 = gen_new_label();
cdc0faa6 6408
6af0bf9c
FB
6409 switch (opc) {
6410 case OPC_TEQ:
6411 case OPC_TEQI:
cdc0faa6 6412 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
6413 break;
6414 case OPC_TGE:
6415 case OPC_TGEI:
cdc0faa6 6416 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
6417 break;
6418 case OPC_TGEU:
6419 case OPC_TGEIU:
cdc0faa6 6420 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
6421 break;
6422 case OPC_TLT:
6423 case OPC_TLTI:
cdc0faa6 6424 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
6425 break;
6426 case OPC_TLTU:
6427 case OPC_TLTIU:
cdc0faa6 6428 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
6429 break;
6430 case OPC_TNE:
6431 case OPC_TNEI:
cdc0faa6 6432 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 6433 break;
6af0bf9c 6434 }
cdc0faa6 6435 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
6436 gen_set_label(l1);
6437 }
be24bb4f
TS
6438 tcg_temp_free(t0);
6439 tcg_temp_free(t1);
6af0bf9c
FB
6440}
6441
90aa39a1
SF
6442static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6443{
eeb3bba8 6444 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
6445 return false;
6446 }
6447
6448#ifndef CONFIG_USER_ONLY
eeb3bba8 6449 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
6450#else
6451 return true;
6452#endif
6453}
6454
356265ae 6455static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 6456{
90aa39a1 6457 if (use_goto_tb(ctx, dest)) {
57fec1fe 6458 tcg_gen_goto_tb(n);
9b9e4393 6459 gen_save_pc(dest);
07ea28b4 6460 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 6461 } else {
9b9e4393 6462 gen_save_pc(dest);
eeb3bba8 6463 if (ctx->base.singlestep_enabled) {
7b270ef2 6464 save_cpu_state(ctx, 0);
9c708c7f 6465 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 6466 }
7f11636d 6467 tcg_gen_lookup_and_goto_ptr();
6e256c93 6468 }
c53be334
FB
6469}
6470
6af0bf9c 6471/* Branches (before delay slot) */
71375b59
AM
6472static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6473 int insn_bytes,
6474 int rs, int rt, int32_t offset,
6475 int delayslot_size)
6af0bf9c 6476{
d077b6f7 6477 target_ulong btgt = -1;
3ad4bb2d 6478 int blink = 0;
2fdbad25 6479 int bcond_compute = 0;
1ba74fb8
AJ
6480 TCGv t0 = tcg_temp_new();
6481 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
6482
6483 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 6484#ifdef MIPS_DEBUG_DISAS
339cd2a8 6485 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 6486 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 6487#endif
9c708c7f 6488 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6489 goto out;
3ad4bb2d 6490 }
6af0bf9c 6491
6af0bf9c
FB
6492 /* Load needed operands */
6493 switch (opc) {
6494 case OPC_BEQ:
6495 case OPC_BEQL:
6496 case OPC_BNE:
6497 case OPC_BNEL:
6498 /* Compare two registers */
6499 if (rs != rt) {
6c5c1e20
TS
6500 gen_load_gpr(t0, rs);
6501 gen_load_gpr(t1, rt);
2fdbad25 6502 bcond_compute = 1;
6af0bf9c 6503 }
eeb3bba8 6504 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
6505 break;
6506 case OPC_BGEZ:
6507 case OPC_BGEZAL:
6508 case OPC_BGEZALL:
6509 case OPC_BGEZL:
6510 case OPC_BGTZ:
6511 case OPC_BGTZL:
6512 case OPC_BLEZ:
6513 case OPC_BLEZL:
6514 case OPC_BLTZ:
6515 case OPC_BLTZAL:
6516 case OPC_BLTZALL:
6517 case OPC_BLTZL:
6518 /* Compare to zero */
6519 if (rs != 0) {
6c5c1e20 6520 gen_load_gpr(t0, rs);
2fdbad25 6521 bcond_compute = 1;
6af0bf9c 6522 }
eeb3bba8 6523 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 6524 break;
e45a93e2
JL
6525 case OPC_BPOSGE32:
6526#if defined(TARGET_MIPS64)
6527 case OPC_BPOSGE64:
6528 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6529#else
6530 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6531#endif
6532 bcond_compute = 1;
eeb3bba8 6533 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 6534 break;
6af0bf9c
FB
6535 case OPC_J:
6536 case OPC_JAL:
364d4831 6537 case OPC_JALX:
6af0bf9c 6538 /* Jump to immediate */
eeb3bba8
EC
6539 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6540 (uint32_t)offset;
6af0bf9c
FB
6541 break;
6542 case OPC_JR:
6543 case OPC_JALR:
6544 /* Jump to register */
7a387fff 6545 if (offset != 0 && offset != 16) {
7480515f
AM
6546 /*
6547 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6548 * others are reserved.
6549 */
923617a3 6550 MIPS_INVAL("jump hint");
9c708c7f 6551 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6552 goto out;
6af0bf9c 6553 }
d077b6f7 6554 gen_load_gpr(btarget, rs);
6af0bf9c
FB
6555 break;
6556 default:
6557 MIPS_INVAL("branch/jump");
9c708c7f 6558 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6559 goto out;
6af0bf9c 6560 }
2fdbad25 6561 if (bcond_compute == 0) {
6af0bf9c
FB
6562 /* No condition to be computed */
6563 switch (opc) {
6564 case OPC_BEQ: /* rx == rx */
6565 case OPC_BEQL: /* rx == rx likely */
6566 case OPC_BGEZ: /* 0 >= 0 */
6567 case OPC_BGEZL: /* 0 >= 0 likely */
6568 case OPC_BLEZ: /* 0 <= 0 */
6569 case OPC_BLEZL: /* 0 <= 0 likely */
6570 /* Always take */
4ad40f36 6571 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6572 break;
6573 case OPC_BGEZAL: /* 0 >= 0 */
6574 case OPC_BGEZALL: /* 0 >= 0 likely */
6575 /* Always take and link */
6576 blink = 31;
4ad40f36 6577 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6578 break;
6579 case OPC_BNE: /* rx != rx */
6580 case OPC_BGTZ: /* 0 > 0 */
6581 case OPC_BLTZ: /* 0 < 0 */
ead9360e 6582 /* Treat as NOP. */
6c5c1e20 6583 goto out;
eeef26cd 6584 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
6585 /*
6586 * Handle as an unconditional branch to get correct delay
6587 * slot checking.
6588 */
3c824109 6589 blink = 31;
eeb3bba8 6590 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 6591 ctx->hflags |= MIPS_HFLAG_B;
3c824109 6592 break;
eeef26cd 6593 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 6594 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 6595 /* Skip the instruction in the delay slot */
eeb3bba8 6596 ctx->base.pc_next += 4;
6c5c1e20 6597 goto out;
6af0bf9c
FB
6598 case OPC_BNEL: /* rx != rx likely */
6599 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
6600 case OPC_BLTZL: /* 0 < 0 likely */
6601 /* Skip the instruction in the delay slot */
eeb3bba8 6602 ctx->base.pc_next += 4;
6c5c1e20 6603 goto out;
6af0bf9c 6604 case OPC_J:
4ad40f36 6605 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 6606 break;
364d4831
NF
6607 case OPC_JALX:
6608 ctx->hflags |= MIPS_HFLAG_BX;
6609 /* Fallthrough */
6af0bf9c
FB
6610 case OPC_JAL:
6611 blink = 31;
4ad40f36 6612 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
6613 break;
6614 case OPC_JR:
4ad40f36 6615 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6616 break;
6617 case OPC_JALR:
6618 blink = rt;
4ad40f36 6619 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6620 break;
6621 default:
6622 MIPS_INVAL("branch/jump");
9c708c7f 6623 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6624 goto out;
6af0bf9c
FB
6625 }
6626 } else {
6627 switch (opc) {
6628 case OPC_BEQ:
e68dd28f 6629 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6630 goto not_likely;
6631 case OPC_BEQL:
e68dd28f 6632 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6633 goto likely;
6634 case OPC_BNE:
e68dd28f 6635 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6636 goto not_likely;
6637 case OPC_BNEL:
e68dd28f 6638 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6639 goto likely;
6640 case OPC_BGEZ:
e68dd28f 6641 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6642 goto not_likely;
6643 case OPC_BGEZL:
e68dd28f 6644 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6645 goto likely;
6646 case OPC_BGEZAL:
e68dd28f 6647 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6648 blink = 31;
6649 goto not_likely;
6650 case OPC_BGEZALL:
e68dd28f 6651 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6652 blink = 31;
6af0bf9c
FB
6653 goto likely;
6654 case OPC_BGTZ:
e68dd28f 6655 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6656 goto not_likely;
6657 case OPC_BGTZL:
e68dd28f 6658 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6659 goto likely;
6660 case OPC_BLEZ:
e68dd28f 6661 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6662 goto not_likely;
6663 case OPC_BLEZL:
e68dd28f 6664 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6665 goto likely;
6666 case OPC_BLTZ:
e68dd28f 6667 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6668 goto not_likely;
6669 case OPC_BLTZL:
e68dd28f 6670 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6671 goto likely;
e45a93e2
JL
6672 case OPC_BPOSGE32:
6673 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6674 goto not_likely;
6675#if defined(TARGET_MIPS64)
6676 case OPC_BPOSGE64:
6677 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6678 goto not_likely;
6679#endif
6af0bf9c 6680 case OPC_BLTZAL:
e68dd28f 6681 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6682 blink = 31;
6af0bf9c 6683 not_likely:
4ad40f36 6684 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6685 break;
6686 case OPC_BLTZALL:
e68dd28f 6687 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6688 blink = 31;
6af0bf9c 6689 likely:
4ad40f36 6690 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6691 break;
c53f4a62
TS
6692 default:
6693 MIPS_INVAL("conditional branch/jump");
9c708c7f 6694 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6695 goto out;
6af0bf9c 6696 }
6af0bf9c 6697 }
9b9e4393 6698
d077b6f7 6699 ctx->btarget = btgt;
b231c103
YK
6700
6701 switch (delayslot_size) {
6702 case 2:
6703 ctx->hflags |= MIPS_HFLAG_BDS16;
6704 break;
6705 case 4:
6706 ctx->hflags |= MIPS_HFLAG_BDS32;
6707 break;
6708 }
6709
6af0bf9c 6710 if (blink > 0) {
b231c103 6711 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6712 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6713
eeb3bba8
EC
6714 tcg_gen_movi_tl(cpu_gpr[blink],
6715 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6716 }
6c5c1e20
TS
6717
6718 out:
1f8929d2 6719 if (insn_bytes == 2) {
364d4831 6720 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 6721 }
6c5c1e20
TS
6722 tcg_temp_free(t0);
6723 tcg_temp_free(t1);
6af0bf9c
FB
6724}
6725
764371d2
SM
6726
6727/* nanoMIPS Branches */
6728static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6729 int insn_bytes,
6730 int rs, int rt, int32_t offset)
6731{
6732 target_ulong btgt = -1;
6733 int bcond_compute = 0;
6734 TCGv t0 = tcg_temp_new();
6735 TCGv t1 = tcg_temp_new();
6736
6737 /* Load needed operands */
6738 switch (opc) {
6739 case OPC_BEQ:
6740 case OPC_BNE:
6741 /* Compare two registers */
6742 if (rs != rt) {
6743 gen_load_gpr(t0, rs);
6744 gen_load_gpr(t1, rt);
6745 bcond_compute = 1;
6746 }
6747 btgt = ctx->base.pc_next + insn_bytes + offset;
6748 break;
6749 case OPC_BGEZAL:
6750 /* Compare to zero */
6751 if (rs != 0) {
6752 gen_load_gpr(t0, rs);
6753 bcond_compute = 1;
6754 }
6755 btgt = ctx->base.pc_next + insn_bytes + offset;
6756 break;
6757 case OPC_BPOSGE32:
6758 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6759 bcond_compute = 1;
6760 btgt = ctx->base.pc_next + insn_bytes + offset;
6761 break;
6762 case OPC_JR:
6763 case OPC_JALR:
6764 /* Jump to register */
6765 if (offset != 0 && offset != 16) {
7480515f
AM
6766 /*
6767 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6768 * others are reserved.
6769 */
764371d2
SM
6770 MIPS_INVAL("jump hint");
6771 generate_exception_end(ctx, EXCP_RI);
6772 goto out;
6773 }
6774 gen_load_gpr(btarget, rs);
6775 break;
6776 default:
6777 MIPS_INVAL("branch/jump");
6778 generate_exception_end(ctx, EXCP_RI);
6779 goto out;
6780 }
6781 if (bcond_compute == 0) {
6782 /* No condition to be computed */
6783 switch (opc) {
6784 case OPC_BEQ: /* rx == rx */
6785 /* Always take */
6786 ctx->hflags |= MIPS_HFLAG_B;
6787 break;
6788 case OPC_BGEZAL: /* 0 >= 0 */
6789 /* Always take and link */
6790 tcg_gen_movi_tl(cpu_gpr[31],
6791 ctx->base.pc_next + insn_bytes);
6792 ctx->hflags |= MIPS_HFLAG_B;
6793 break;
6794 case OPC_BNE: /* rx != rx */
6795 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6796 /* Skip the instruction in the delay slot */
6797 ctx->base.pc_next += 4;
6798 goto out;
6799 case OPC_JR:
6800 ctx->hflags |= MIPS_HFLAG_BR;
6801 break;
6802 case OPC_JALR:
6803 if (rt > 0) {
6804 tcg_gen_movi_tl(cpu_gpr[rt],
6805 ctx->base.pc_next + insn_bytes);
6806 }
6807 ctx->hflags |= MIPS_HFLAG_BR;
6808 break;
6809 default:
6810 MIPS_INVAL("branch/jump");
6811 generate_exception_end(ctx, EXCP_RI);
6812 goto out;
6813 }
6814 } else {
6815 switch (opc) {
6816 case OPC_BEQ:
6817 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6818 goto not_likely;
6819 case OPC_BNE:
6820 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6821 goto not_likely;
6822 case OPC_BGEZAL:
6823 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6824 tcg_gen_movi_tl(cpu_gpr[31],
6825 ctx->base.pc_next + insn_bytes);
6826 goto not_likely;
6827 case OPC_BPOSGE32:
6828 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6829 not_likely:
6830 ctx->hflags |= MIPS_HFLAG_BC;
6831 break;
6832 default:
6833 MIPS_INVAL("conditional branch/jump");
6834 generate_exception_end(ctx, EXCP_RI);
6835 goto out;
6836 }
6837 }
6838
6839 ctx->btarget = btgt;
6840
6841 out:
6842 if (insn_bytes == 2) {
6843 ctx->hflags |= MIPS_HFLAG_B16;
6844 }
6845 tcg_temp_free(t0);
6846 tcg_temp_free(t1);
6847}
6848
6849
7a387fff 6850/* special3 bitfield operations */
235785e8
AM
6851static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6852 int rs, int lsb, int msb)
7a387fff 6853{
a7812ae4
PB
6854 TCGv t0 = tcg_temp_new();
6855 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6856
6857 gen_load_gpr(t1, rs);
7a387fff
TS
6858 switch (opc) {
6859 case OPC_EXT:
b7f26e52 6860 if (lsb + msb > 31) {
7a387fff 6861 goto fail;
b7f26e52 6862 }
505ad7c2 6863 if (msb != 31) {
6eebb7a4 6864 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6865 } else {
7480515f
AM
6866 /*
6867 * The two checks together imply that lsb == 0,
6868 * so this is a simple sign-extension.
6869 */
6eebb7a4 6870 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6871 }
7a387fff 6872 break;
c6d6dd7c 6873#if defined(TARGET_MIPS64)
7a387fff 6874 case OPC_DEXTU:
b7f26e52
RH
6875 lsb += 32;
6876 goto do_dext;
6877 case OPC_DEXTM:
6878 msb += 32;
6879 goto do_dext;
7a387fff 6880 case OPC_DEXT:
b7f26e52
RH
6881 do_dext:
6882 if (lsb + msb > 63) {
6883 goto fail;
6884 }
6eebb7a4 6885 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6886 break;
c6d6dd7c 6887#endif
7a387fff 6888 case OPC_INS:
b7f26e52 6889 if (lsb > msb) {
7a387fff 6890 goto fail;
b7f26e52 6891 }
6c5c1e20 6892 gen_load_gpr(t0, rt);
e0d002f1 6893 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6894 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6895 break;
c6d6dd7c 6896#if defined(TARGET_MIPS64)
7a387fff 6897 case OPC_DINSU:
b7f26e52
RH
6898 lsb += 32;
6899 /* FALLTHRU */
6900 case OPC_DINSM:
6901 msb += 32;
6902 /* FALLTHRU */
7a387fff 6903 case OPC_DINS:
b7f26e52
RH
6904 if (lsb > msb) {
6905 goto fail;
6906 }
6c5c1e20 6907 gen_load_gpr(t0, rt);
e0d002f1 6908 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6909 break;
c6d6dd7c 6910#endif
7a387fff
TS
6911 default:
6912fail:
6913 MIPS_INVAL("bitops");
9c708c7f 6914 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6915 tcg_temp_free(t0);
6916 tcg_temp_free(t1);
7a387fff
TS
6917 return;
6918 }
6c5c1e20
TS
6919 gen_store_gpr(t0, rt);
6920 tcg_temp_free(t0);
6921 tcg_temp_free(t1);
7a387fff
TS
6922}
6923
235785e8 6924static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 6925{
3a55fa47 6926 TCGv t0;
49bcf33c 6927
3a55fa47
AJ
6928 if (rd == 0) {
6929 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6930 return;
6931 }
6932
6933 t0 = tcg_temp_new();
6934 gen_load_gpr(t0, rt);
49bcf33c
AJ
6935 switch (op2) {
6936 case OPC_WSBH:
3a55fa47
AJ
6937 {
6938 TCGv t1 = tcg_temp_new();
06a57e5c 6939 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6940
6941 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6942 tcg_gen_and_tl(t1, t1, t2);
6943 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6944 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6945 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6946 tcg_temp_free(t2);
3a55fa47
AJ
6947 tcg_temp_free(t1);
6948 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6949 }
49bcf33c
AJ
6950 break;
6951 case OPC_SEB:
3a55fa47 6952 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6953 break;
6954 case OPC_SEH:
3a55fa47 6955 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6956 break;
6957#if defined(TARGET_MIPS64)
6958 case OPC_DSBH:
3a55fa47
AJ
6959 {
6960 TCGv t1 = tcg_temp_new();
06a57e5c 6961 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6962
6963 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6964 tcg_gen_and_tl(t1, t1, t2);
6965 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6966 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6967 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6968 tcg_temp_free(t2);
3a55fa47
AJ
6969 tcg_temp_free(t1);
6970 }
49bcf33c
AJ
6971 break;
6972 case OPC_DSHD:
3a55fa47
AJ
6973 {
6974 TCGv t1 = tcg_temp_new();
06a57e5c 6975 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6976
6977 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6978 tcg_gen_and_tl(t1, t1, t2);
6979 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6980 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6981 tcg_gen_or_tl(t0, t0, t1);
6982 tcg_gen_shri_tl(t1, t0, 32);
6983 tcg_gen_shli_tl(t0, t0, 32);
6984 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6985 tcg_temp_free(t2);
3a55fa47
AJ
6986 tcg_temp_free(t1);
6987 }
49bcf33c
AJ
6988 break;
6989#endif
6990 default:
6991 MIPS_INVAL("bsfhl");
9c708c7f 6992 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6993 tcg_temp_free(t0);
49bcf33c
AJ
6994 return;
6995 }
49bcf33c 6996 tcg_temp_free(t0);
49bcf33c
AJ
6997}
6998
1f1b4c00
YK
6999static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
7000 int imm2)
7001{
7002 TCGv t0;
7003 TCGv t1;
7004 if (rd == 0) {
7005 /* Treat as NOP. */
7006 return;
7007 }
7008 t0 = tcg_temp_new();
7009 t1 = tcg_temp_new();
7010 gen_load_gpr(t0, rs);
7011 gen_load_gpr(t1, rt);
7012 tcg_gen_shli_tl(t0, t0, imm2 + 1);
7013 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
7014 if (opc == OPC_LSA) {
7015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
7016 }
7017
7018 tcg_temp_free(t1);
7019 tcg_temp_free(t0);
7020
7021 return;
7022}
7023
821f2008
JH
7024static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
7025 int rt, int bits)
284b731a 7026{
1f1b4c00
YK
7027 TCGv t0;
7028 if (rd == 0) {
7029 /* Treat as NOP. */
7030 return;
7031 }
7032 t0 = tcg_temp_new();
821f2008
JH
7033 if (bits == 0 || bits == wordsz) {
7034 if (bits == 0) {
7035 gen_load_gpr(t0, rt);
7036 } else {
7037 gen_load_gpr(t0, rs);
7038 }
7039 switch (wordsz) {
7040 case 32:
51243852
MD
7041 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
7042 break;
7043#if defined(TARGET_MIPS64)
821f2008 7044 case 64:
51243852
MD
7045 tcg_gen_mov_tl(cpu_gpr[rd], t0);
7046 break;
7047#endif
7048 }
1f1b4c00
YK
7049 } else {
7050 TCGv t1 = tcg_temp_new();
821f2008 7051 gen_load_gpr(t0, rt);
1f1b4c00 7052 gen_load_gpr(t1, rs);
821f2008
JH
7053 switch (wordsz) {
7054 case 32:
1f1b4c00
YK
7055 {
7056 TCGv_i64 t2 = tcg_temp_new_i64();
7057 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 7058 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
7059 gen_move_low32(cpu_gpr[rd], t2);
7060 tcg_temp_free_i64(t2);
7061 }
7062 break;
284b731a 7063#if defined(TARGET_MIPS64)
821f2008
JH
7064 case 64:
7065 tcg_gen_shli_tl(t0, t0, bits);
7066 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
7067 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
7068 break;
284b731a 7069#endif
1f1b4c00
YK
7070 }
7071 tcg_temp_free(t1);
7072 }
7073
7074 tcg_temp_free(t0);
7075}
7076
821f2008
JH
7077static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7078 int bp)
7079{
7080 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
7081}
7082
7083static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7084 int shift)
7085{
7086 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
7087}
7088
1f1b4c00
YK
7089static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
7090{
7091 TCGv t0;
7092 if (rd == 0) {
7093 /* Treat as NOP. */
7094 return;
7095 }
7096 t0 = tcg_temp_new();
7097 gen_load_gpr(t0, rt);
7098 switch (opc) {
7099 case OPC_BITSWAP:
7100 gen_helper_bitswap(cpu_gpr[rd], t0);
7101 break;
7102#if defined(TARGET_MIPS64)
7103 case OPC_DBITSWAP:
7104 gen_helper_dbitswap(cpu_gpr[rd], t0);
7105 break;
7106#endif
7107 }
7108 tcg_temp_free(t0);
284b731a
LA
7109}
7110
1f1b4c00
YK
7111#ifndef CONFIG_USER_ONLY
7112/* CP0 (MMU and control) */
5204ea79
LA
7113static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
7114{
7115 TCGv_i64 t0 = tcg_temp_new_i64();
7116 TCGv_i64 t1 = tcg_temp_new_i64();
7117
7118 tcg_gen_ext_tl_i64(t0, arg);
7119 tcg_gen_ld_i64(t1, cpu_env, off);
7120#if defined(TARGET_MIPS64)
7121 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
7122#else
7123 tcg_gen_concat32_i64(t1, t1, t0);
7124#endif
7125 tcg_gen_st_i64(t1, cpu_env, off);
7126 tcg_temp_free_i64(t1);
7127 tcg_temp_free_i64(t0);
7128}
7129
7130static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7131{
7132 TCGv_i64 t0 = tcg_temp_new_i64();
7133 TCGv_i64 t1 = tcg_temp_new_i64();
7134
7135 tcg_gen_ext_tl_i64(t0, arg);
7136 tcg_gen_ld_i64(t1, cpu_env, off);
7137 tcg_gen_concat32_i64(t1, t1, t0);
7138 tcg_gen_st_i64(t1, cpu_env, off);
7139 tcg_temp_free_i64(t1);
7140 tcg_temp_free_i64(t0);
7141}
7142
7143static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7144{
7145 TCGv_i64 t0 = tcg_temp_new_i64();
7146
7147 tcg_gen_ld_i64(t0, cpu_env, off);
7148#if defined(TARGET_MIPS64)
7149 tcg_gen_shri_i64(t0, t0, 30);
7150#else
7151 tcg_gen_shri_i64(t0, t0, 32);
7152#endif
7153 gen_move_low32(arg, t0);
7154 tcg_temp_free_i64(t0);
7155}
7156
7157static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7158{
7159 TCGv_i64 t0 = tcg_temp_new_i64();
7160
7161 tcg_gen_ld_i64(t0, cpu_env, off);
7162 tcg_gen_shri_i64(t0, t0, 32 + shift);
7163 gen_move_low32(arg, t0);
7164 tcg_temp_free_i64(t0);
7165}
7166
235785e8 7167static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 7168{
d9bea114 7169 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 7170
d9bea114
AJ
7171 tcg_gen_ld_i32(t0, cpu_env, off);
7172 tcg_gen_ext_i32_tl(arg, t0);
7173 tcg_temp_free_i32(t0);
4f57689a
TS
7174}
7175
235785e8 7176static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 7177{
d9bea114
AJ
7178 tcg_gen_ld_tl(arg, cpu_env, off);
7179 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
7180}
7181
235785e8 7182static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 7183{
d9bea114 7184 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 7185
d9bea114
AJ
7186 tcg_gen_trunc_tl_i32(t0, arg);
7187 tcg_gen_st_i32(t0, cpu_env, off);
7188 tcg_temp_free_i32(t0);
f1aa6320
TS
7189}
7190
c98d3d79
YK
7191#define CP0_CHECK(c) \
7192 do { \
7193 if (!(c)) { \
7194 goto cp0_unimplemented; \
7195 } \
7196 } while (0)
7197
5204ea79
LA
7198static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7199{
294fc2ea 7200 const char *register_name = "invalid";
5204ea79 7201
5204ea79 7202 switch (reg) {
04992c8c 7203 case CP0_REGISTER_02:
5204ea79
LA
7204 switch (sel) {
7205 case 0:
59488dda 7206 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 7207 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 7208 register_name = "EntryLo0";
5204ea79
LA
7209 break;
7210 default:
c98d3d79 7211 goto cp0_unimplemented;
5204ea79
LA
7212 }
7213 break;
04992c8c 7214 case CP0_REGISTER_03:
5204ea79 7215 switch (sel) {
acd37316 7216 case CP0_REG03__ENTRYLO1:
59488dda 7217 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 7218 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 7219 register_name = "EntryLo1";
5204ea79
LA
7220 break;
7221 default:
c98d3d79 7222 goto cp0_unimplemented;
5204ea79
LA
7223 }
7224 break;
04992c8c 7225 case CP0_REGISTER_09:
5fb2dcd1 7226 switch (sel) {
e5a98a72 7227 case CP0_REG09__SAAR:
5fb2dcd1
YK
7228 CP0_CHECK(ctx->saar);
7229 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 7230 register_name = "SAAR";
5fb2dcd1
YK
7231 break;
7232 default:
7233 goto cp0_unimplemented;
7234 }
7235 break;
04992c8c 7236 case CP0_REGISTER_17:
5204ea79 7237 switch (sel) {
706ce142 7238 case CP0_REG17__LLADDR:
c7c7e1e9 7239 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 7240 ctx->CP0_LLAddr_shift);
294fc2ea 7241 register_name = "LLAddr";
5204ea79 7242 break;
706ce142 7243 case CP0_REG17__MAAR:
f6d4dd81
YK
7244 CP0_CHECK(ctx->mrp);
7245 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 7246 register_name = "MAAR";
f6d4dd81 7247 break;
5204ea79 7248 default:
c98d3d79 7249 goto cp0_unimplemented;
5204ea79
LA
7250 }
7251 break;
feafe82c
YK
7252 case CP0_REGISTER_19:
7253 switch (sel) {
7254 case CP0_REG19__WATCHHI0:
7255 case CP0_REG19__WATCHHI1:
7256 case CP0_REG19__WATCHHI2:
7257 case CP0_REG19__WATCHHI3:
7258 case CP0_REG19__WATCHHI4:
7259 case CP0_REG19__WATCHHI5:
7260 case CP0_REG19__WATCHHI6:
7261 case CP0_REG19__WATCHHI7:
7262 /* upper 32 bits are only available when Config5MI != 0 */
7263 CP0_CHECK(ctx->mi);
7264 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7265 register_name = "WatchHi";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7269 }
7270 break;
04992c8c 7271 case CP0_REGISTER_28:
5204ea79
LA
7272 switch (sel) {
7273 case 0:
7274 case 2:
7275 case 4:
7276 case 6:
7277 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 7278 register_name = "TagLo";
5204ea79
LA
7279 break;
7280 default:
c98d3d79 7281 goto cp0_unimplemented;
5204ea79
LA
7282 }
7283 break;
7284 default:
c98d3d79 7285 goto cp0_unimplemented;
5204ea79 7286 }
294fc2ea 7287 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
7288 return;
7289
c98d3d79 7290cp0_unimplemented:
294fc2ea
AM
7291 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7292 register_name, reg, sel);
5204ea79
LA
7293 tcg_gen_movi_tl(arg, 0);
7294}
7295
7296static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7297{
294fc2ea 7298 const char *register_name = "invalid";
5204ea79
LA
7299 uint64_t mask = ctx->PAMask >> 36;
7300
5204ea79 7301 switch (reg) {
04992c8c 7302 case CP0_REGISTER_02:
5204ea79
LA
7303 switch (sel) {
7304 case 0:
59488dda 7305 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
7306 tcg_gen_andi_tl(arg, arg, mask);
7307 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 7308 register_name = "EntryLo0";
5204ea79
LA
7309 break;
7310 default:
c98d3d79 7311 goto cp0_unimplemented;
5204ea79
LA
7312 }
7313 break;
04992c8c 7314 case CP0_REGISTER_03:
5204ea79 7315 switch (sel) {
acd37316 7316 case CP0_REG03__ENTRYLO1:
59488dda 7317 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
7318 tcg_gen_andi_tl(arg, arg, mask);
7319 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 7320 register_name = "EntryLo1";
5204ea79
LA
7321 break;
7322 default:
c98d3d79 7323 goto cp0_unimplemented;
5204ea79
LA
7324 }
7325 break;
04992c8c 7326 case CP0_REGISTER_09:
5fb2dcd1 7327 switch (sel) {
e5a98a72 7328 case CP0_REG09__SAAR:
5fb2dcd1
YK
7329 CP0_CHECK(ctx->saar);
7330 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 7331 register_name = "SAAR";
5fb2dcd1
YK
7332 break;
7333 default:
7334 goto cp0_unimplemented;
7335 }
ab8c3410 7336 break;
04992c8c 7337 case CP0_REGISTER_17:
5204ea79 7338 switch (sel) {
706ce142 7339 case CP0_REG17__LLADDR:
7480515f
AM
7340 /*
7341 * LLAddr is read-only (the only exception is bit 0 if LLB is
7342 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7343 * relevant for modern MIPS cores supporting MTHC0, therefore
7344 * treating MTHC0 to LLAddr as NOP.
7345 */
294fc2ea 7346 register_name = "LLAddr";
5204ea79 7347 break;
706ce142 7348 case CP0_REG17__MAAR:
f6d4dd81
YK
7349 CP0_CHECK(ctx->mrp);
7350 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 7351 register_name = "MAAR";
f6d4dd81 7352 break;
5204ea79 7353 default:
c98d3d79 7354 goto cp0_unimplemented;
5204ea79
LA
7355 }
7356 break;
feafe82c
YK
7357 case CP0_REGISTER_19:
7358 switch (sel) {
7359 case CP0_REG19__WATCHHI0:
7360 case CP0_REG19__WATCHHI1:
7361 case CP0_REG19__WATCHHI2:
7362 case CP0_REG19__WATCHHI3:
7363 case CP0_REG19__WATCHHI4:
7364 case CP0_REG19__WATCHHI5:
7365 case CP0_REG19__WATCHHI6:
7366 case CP0_REG19__WATCHHI7:
7367 /* upper 32 bits are only available when Config5MI != 0 */
7368 CP0_CHECK(ctx->mi);
7369 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7370 register_name = "WatchHi";
7371 break;
7372 default:
7373 goto cp0_unimplemented;
7374 }
7375 break;
04992c8c 7376 case CP0_REGISTER_28:
5204ea79
LA
7377 switch (sel) {
7378 case 0:
7379 case 2:
7380 case 4:
7381 case 6:
7382 tcg_gen_andi_tl(arg, arg, mask);
7383 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 7384 register_name = "TagLo";
5204ea79
LA
7385 break;
7386 default:
c98d3d79 7387 goto cp0_unimplemented;
5204ea79
LA
7388 }
7389 break;
7390 default:
c98d3d79 7391 goto cp0_unimplemented;
5204ea79 7392 }
294fc2ea 7393 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 7394
c98d3d79 7395cp0_unimplemented:
294fc2ea
AM
7396 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7397 register_name, reg, sel);
5204ea79
LA
7398}
7399
e98c0d17
LA
7400static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7401{
2e211e0a 7402 if (ctx->insn_flags & ISA_MIPS_R6) {
e98c0d17
LA
7403 tcg_gen_movi_tl(arg, 0);
7404 } else {
7405 tcg_gen_movi_tl(arg, ~0);
7406 }
7407}
7408
d75c135e 7409static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 7410{
294fc2ea 7411 const char *register_name = "invalid";
873eb012 7412
1f8929d2 7413 if (sel != 0) {
bbd5e4a2 7414 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 7415 }
e189e748 7416
873eb012 7417 switch (reg) {
04992c8c 7418 case CP0_REGISTER_00:
7a387fff 7419 switch (sel) {
1b142da5 7420 case CP0_REG00__INDEX:
7db13fae 7421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 7422 register_name = "Index";
7a387fff 7423 break;
1b142da5 7424 case CP0_REG00__MVPCONTROL:
f31b035a 7425 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7426 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 7427 register_name = "MVPControl";
ead9360e 7428 break;
1b142da5 7429 case CP0_REG00__MVPCONF0:
f31b035a 7430 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7431 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 7432 register_name = "MVPConf0";
ead9360e 7433 break;
1b142da5 7434 case CP0_REG00__MVPCONF1:
f31b035a 7435 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7436 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 7437 register_name = "MVPConf1";
ead9360e 7438 break;
1b142da5 7439 case CP0_REG00__VPCONTROL:
01bc435b
YK
7440 CP0_CHECK(ctx->vp);
7441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 7442 register_name = "VPControl";
01bc435b 7443 break;
7a387fff 7444 default:
f31b035a 7445 goto cp0_unimplemented;
7a387fff 7446 }
873eb012 7447 break;
04992c8c 7448 case CP0_REGISTER_01:
7a387fff 7449 switch (sel) {
30deb460 7450 case CP0_REG01__RANDOM:
2e211e0a 7451 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 7452 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 7453 register_name = "Random";
2423f660 7454 break;
30deb460 7455 case CP0_REG01__VPECONTROL:
f31b035a 7456 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7457 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 7458 register_name = "VPEControl";
ead9360e 7459 break;
30deb460 7460 case CP0_REG01__VPECONF0:
f31b035a 7461 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7462 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 7463 register_name = "VPEConf0";
ead9360e 7464 break;
30deb460 7465 case CP0_REG01__VPECONF1:
f31b035a 7466 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 7468 register_name = "VPEConf1";
ead9360e 7469 break;
30deb460 7470 case CP0_REG01__YQMASK:
f31b035a 7471 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7472 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 7473 register_name = "YQMask";
ead9360e 7474 break;
30deb460 7475 case CP0_REG01__VPESCHEDULE:
f31b035a 7476 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7477 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7478 register_name = "VPESchedule";
ead9360e 7479 break;
30deb460 7480 case CP0_REG01__VPESCHEFBACK:
f31b035a 7481 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7482 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7483 register_name = "VPEScheFBack";
ead9360e 7484 break;
30deb460 7485 case CP0_REG01__VPEOPT:
f31b035a 7486 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 7488 register_name = "VPEOpt";
ead9360e 7489 break;
7a387fff 7490 default:
f31b035a 7491 goto cp0_unimplemented;
7a387fff 7492 }
873eb012 7493 break;
04992c8c 7494 case CP0_REGISTER_02:
7a387fff 7495 switch (sel) {
6d27d5bd 7496 case CP0_REG02__ENTRYLO0:
284b731a
LA
7497 {
7498 TCGv_i64 tmp = tcg_temp_new_i64();
7499 tcg_gen_ld_i64(tmp, cpu_env,
7500 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 7501#if defined(TARGET_MIPS64)
284b731a
LA
7502 if (ctx->rxi) {
7503 /* Move RI/XI fields to bits 31:30 */
7504 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7505 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7506 }
7207c7f9 7507#endif
284b731a
LA
7508 gen_move_low32(arg, tmp);
7509 tcg_temp_free_i64(tmp);
7510 }
294fc2ea 7511 register_name = "EntryLo0";
2423f660 7512 break;
6d27d5bd 7513 case CP0_REG02__TCSTATUS:
f31b035a 7514 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7515 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 7516 register_name = "TCStatus";
ead9360e 7517 break;
6d27d5bd 7518 case CP0_REG02__TCBIND:
f31b035a 7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7520 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 7521 register_name = "TCBind";
ead9360e 7522 break;
6d27d5bd 7523 case CP0_REG02__TCRESTART:
f31b035a 7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7525 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 7526 register_name = "TCRestart";
ead9360e 7527 break;
6d27d5bd 7528 case CP0_REG02__TCHALT:
f31b035a 7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7530 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 7531 register_name = "TCHalt";
ead9360e 7532 break;
6d27d5bd 7533 case CP0_REG02__TCCONTEXT:
f31b035a 7534 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7535 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 7536 register_name = "TCContext";
ead9360e 7537 break;
6d27d5bd 7538 case CP0_REG02__TCSCHEDULE:
f31b035a 7539 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7540 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 7541 register_name = "TCSchedule";
ead9360e 7542 break;
6d27d5bd 7543 case CP0_REG02__TCSCHEFBACK:
f31b035a 7544 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7545 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 7546 register_name = "TCScheFBack";
ead9360e 7547 break;
7a387fff 7548 default:
f31b035a 7549 goto cp0_unimplemented;
7a387fff 7550 }
873eb012 7551 break;
04992c8c 7552 case CP0_REGISTER_03:
7a387fff 7553 switch (sel) {
acd37316 7554 case CP0_REG03__ENTRYLO1:
284b731a
LA
7555 {
7556 TCGv_i64 tmp = tcg_temp_new_i64();
7557 tcg_gen_ld_i64(tmp, cpu_env,
7558 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 7559#if defined(TARGET_MIPS64)
284b731a
LA
7560 if (ctx->rxi) {
7561 /* Move RI/XI fields to bits 31:30 */
7562 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7563 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7564 }
7207c7f9 7565#endif
284b731a
LA
7566 gen_move_low32(arg, tmp);
7567 tcg_temp_free_i64(tmp);
7568 }
294fc2ea 7569 register_name = "EntryLo1";
2423f660 7570 break;
acd37316 7571 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7572 CP0_CHECK(ctx->vp);
7573 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7574 register_name = "GlobalNumber";
01bc435b 7575 break;
7a387fff 7576 default:
f31b035a 7577 goto cp0_unimplemented;
1579a72e 7578 }
873eb012 7579 break;
04992c8c 7580 case CP0_REGISTER_04:
7a387fff 7581 switch (sel) {
020fe379 7582 case CP0_REG04__CONTEXT:
7db13fae 7583 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 7584 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7585 register_name = "Context";
2423f660 7586 break;
020fe379
AM
7587 case CP0_REG04__CONTEXTCONFIG:
7588 /* SmartMIPS ASE */
7589 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 7590 register_name = "ContextConfig";
f31b035a 7591 goto cp0_unimplemented;
020fe379 7592 case CP0_REG04__USERLOCAL:
f31b035a 7593 CP0_CHECK(ctx->ulri);
e40df9a8
JH
7594 tcg_gen_ld_tl(arg, cpu_env,
7595 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7596 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7597 register_name = "UserLocal";
d279279e 7598 break;
99029be1
YK
7599 case CP0_REG04__MMID:
7600 CP0_CHECK(ctx->mi);
7601 gen_helper_mtc0_memorymapid(cpu_env, arg);
7602 register_name = "MMID";
7603 break;
7a387fff 7604 default:
f31b035a 7605 goto cp0_unimplemented;
1579a72e 7606 }
873eb012 7607 break;
04992c8c 7608 case CP0_REGISTER_05:
7a387fff 7609 switch (sel) {
a1e76353 7610 case CP0_REG05__PAGEMASK:
7db13fae 7611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7612 register_name = "PageMask";
2423f660 7613 break;
a1e76353 7614 case CP0_REG05__PAGEGRAIN:
7a47bae5 7615 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7617 register_name = "PageGrain";
2423f660 7618 break;
a1e76353 7619 case CP0_REG05__SEGCTL0:
cec56a73
JH
7620 CP0_CHECK(ctx->sc);
7621 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7622 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7623 register_name = "SegCtl0";
cec56a73 7624 break;
a1e76353 7625 case CP0_REG05__SEGCTL1:
cec56a73
JH
7626 CP0_CHECK(ctx->sc);
7627 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7628 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7629 register_name = "SegCtl1";
cec56a73 7630 break;
a1e76353 7631 case CP0_REG05__SEGCTL2:
cec56a73
JH
7632 CP0_CHECK(ctx->sc);
7633 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7634 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7635 register_name = "SegCtl2";
cec56a73 7636 break;
a1e76353 7637 case CP0_REG05__PWBASE:
5e31fdd5
YK
7638 check_pw(ctx);
7639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7640 register_name = "PWBase";
5e31fdd5 7641 break;
a1e76353 7642 case CP0_REG05__PWFIELD:
fa75ad14
YK
7643 check_pw(ctx);
7644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7645 register_name = "PWField";
fa75ad14 7646 break;
a1e76353 7647 case CP0_REG05__PWSIZE:
20b28ebc
YK
7648 check_pw(ctx);
7649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7650 register_name = "PWSize";
20b28ebc 7651 break;
7a387fff 7652 default:
f31b035a 7653 goto cp0_unimplemented;
1579a72e 7654 }
873eb012 7655 break;
04992c8c 7656 case CP0_REGISTER_06:
7a387fff 7657 switch (sel) {
9023594b 7658 case CP0_REG06__WIRED:
7db13fae 7659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7660 register_name = "Wired";
2423f660 7661 break;
9023594b 7662 case CP0_REG06__SRSCONF0:
7a47bae5 7663 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7665 register_name = "SRSConf0";
ead9360e 7666 break;
9023594b 7667 case CP0_REG06__SRSCONF1:
7a47bae5 7668 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7670 register_name = "SRSConf1";
ead9360e 7671 break;
9023594b 7672 case CP0_REG06__SRSCONF2:
7a47bae5 7673 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7675 register_name = "SRSConf2";
ead9360e 7676 break;
9023594b 7677 case CP0_REG06__SRSCONF3:
7a47bae5 7678 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7680 register_name = "SRSConf3";
ead9360e 7681 break;
9023594b 7682 case CP0_REG06__SRSCONF4:
7a47bae5 7683 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7685 register_name = "SRSConf4";
ead9360e 7686 break;
9023594b 7687 case CP0_REG06__PWCTL:
103be64c
YK
7688 check_pw(ctx);
7689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7690 register_name = "PWCtl";
103be64c 7691 break;
7a387fff 7692 default:
f31b035a 7693 goto cp0_unimplemented;
1579a72e 7694 }
873eb012 7695 break;
04992c8c 7696 case CP0_REGISTER_07:
7a387fff 7697 switch (sel) {
143a9875 7698 case CP0_REG07__HWRENA:
7a47bae5 7699 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7701 register_name = "HWREna";
2423f660 7702 break;
7a387fff 7703 default:
f31b035a 7704 goto cp0_unimplemented;
1579a72e 7705 }
8c0fdd85 7706 break;
04992c8c 7707 case CP0_REGISTER_08:
7a387fff 7708 switch (sel) {
67d167d2 7709 case CP0_REG08__BADVADDR:
7db13fae 7710 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7711 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7712 register_name = "BadVAddr";
2423f660 7713 break;
67d167d2 7714 case CP0_REG08__BADINSTR:
f31b035a
LA
7715 CP0_CHECK(ctx->bi);
7716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7717 register_name = "BadInstr";
aea14095 7718 break;
67d167d2 7719 case CP0_REG08__BADINSTRP:
f31b035a
LA
7720 CP0_CHECK(ctx->bp);
7721 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7722 register_name = "BadInstrP";
aea14095 7723 break;
67d167d2 7724 case CP0_REG08__BADINSTRX:
25beba9b
SM
7725 CP0_CHECK(ctx->bi);
7726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7727 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7728 register_name = "BadInstrX";
25beba9b 7729 break;
05aa7e93 7730 default:
f31b035a 7731 goto cp0_unimplemented;
aea14095 7732 }
873eb012 7733 break;
04992c8c 7734 case CP0_REGISTER_09:
7a387fff 7735 switch (sel) {
e5a98a72 7736 case CP0_REG09__COUNT:
2e70f6ef 7737 /* Mark as an IO operation because we read the time. */
eeb3bba8 7738 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7739 gen_io_start();
7d37435b 7740 }
895c2d04 7741 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7742 /*
7743 * Break the TB to be able to take timer interrupts immediately
7744 * after reading count. DISAS_STOP isn't sufficient, we need to
7745 * ensure we break completely out of translated code.
7746 */
eeb3bba8
EC
7747 gen_save_pc(ctx->base.pc_next + 4);
7748 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7749 register_name = "Count";
2423f660 7750 break;
e5a98a72 7751 case CP0_REG09__SAARI:
5fb2dcd1
YK
7752 CP0_CHECK(ctx->saar);
7753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7754 register_name = "SAARI";
5fb2dcd1 7755 break;
e5a98a72 7756 case CP0_REG09__SAAR:
5fb2dcd1
YK
7757 CP0_CHECK(ctx->saar);
7758 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7759 register_name = "SAAR";
5fb2dcd1 7760 break;
7a387fff 7761 default:
f31b035a 7762 goto cp0_unimplemented;
2423f660 7763 }
873eb012 7764 break;
04992c8c 7765 case CP0_REGISTER_10:
7a387fff 7766 switch (sel) {
860ffef0 7767 case CP0_REG10__ENTRYHI:
7db13fae 7768 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7769 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7770 register_name = "EntryHi";
2423f660 7771 break;
7a387fff 7772 default:
f31b035a 7773 goto cp0_unimplemented;
1579a72e 7774 }
873eb012 7775 break;
04992c8c 7776 case CP0_REGISTER_11:
7a387fff 7777 switch (sel) {
f5f3834f 7778 case CP0_REG11__COMPARE:
7db13fae 7779 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7780 register_name = "Compare";
2423f660
TS
7781 break;
7782 /* 6,7 are implementation dependent */
7a387fff 7783 default:
f31b035a 7784 goto cp0_unimplemented;
2423f660 7785 }
873eb012 7786 break;
04992c8c 7787 case CP0_REGISTER_12:
7a387fff 7788 switch (sel) {
2b084867 7789 case CP0_REG12__STATUS:
7db13fae 7790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7791 register_name = "Status";
2423f660 7792 break;
2b084867 7793 case CP0_REG12__INTCTL:
7a47bae5 7794 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7796 register_name = "IntCtl";
2423f660 7797 break;
2b084867 7798 case CP0_REG12__SRSCTL:
7a47bae5 7799 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7801 register_name = "SRSCtl";
2423f660 7802 break;
2b084867 7803 case CP0_REG12__SRSMAP:
7a47bae5 7804 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7806 register_name = "SRSMap";
fd88b6ab 7807 break;
7a387fff 7808 default:
f31b035a 7809 goto cp0_unimplemented;
7a387fff 7810 }
873eb012 7811 break;
04992c8c 7812 case CP0_REGISTER_13:
7a387fff 7813 switch (sel) {
e3c7559d 7814 case CP0_REG13__CAUSE:
7db13fae 7815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7816 register_name = "Cause";
2423f660 7817 break;
7a387fff 7818 default:
f31b035a 7819 goto cp0_unimplemented;
7a387fff 7820 }
873eb012 7821 break;
04992c8c 7822 case CP0_REGISTER_14:
7a387fff 7823 switch (sel) {
35e4b54d 7824 case CP0_REG14__EPC:
7db13fae 7825 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7826 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7827 register_name = "EPC";
2423f660 7828 break;
7a387fff 7829 default:
f31b035a 7830 goto cp0_unimplemented;
1579a72e 7831 }
873eb012 7832 break;
04992c8c 7833 case CP0_REGISTER_15:
7a387fff 7834 switch (sel) {
4466cd49 7835 case CP0_REG15__PRID:
7db13fae 7836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7837 register_name = "PRid";
2423f660 7838 break;
4466cd49 7839 case CP0_REG15__EBASE:
7a47bae5 7840 check_insn(ctx, ISA_MIPS_R2);
74dbf824
JH
7841 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7842 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7843 register_name = "EBase";
2423f660 7844 break;
4466cd49 7845 case CP0_REG15__CMGCRBASE:
7a47bae5 7846 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
7847 CP0_CHECK(ctx->cmgcr);
7848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7849 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7850 register_name = "CMGCRBase";
c870e3f5 7851 break;
7a387fff 7852 default:
f31b035a 7853 goto cp0_unimplemented;
7a387fff 7854 }
873eb012 7855 break;
04992c8c 7856 case CP0_REGISTER_16:
873eb012 7857 switch (sel) {
433efb4c 7858 case CP0_REG16__CONFIG:
7db13fae 7859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7860 register_name = "Config";
873eb012 7861 break;
433efb4c 7862 case CP0_REG16__CONFIG1:
7db13fae 7863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7864 register_name = "Config1";
873eb012 7865 break;
433efb4c 7866 case CP0_REG16__CONFIG2:
7db13fae 7867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7868 register_name = "Config2";
7a387fff 7869 break;
433efb4c 7870 case CP0_REG16__CONFIG3:
7db13fae 7871 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7872 register_name = "Config3";
7a387fff 7873 break;
433efb4c 7874 case CP0_REG16__CONFIG4:
b4160af1 7875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7876 register_name = "Config4";
b4160af1 7877 break;
433efb4c 7878 case CP0_REG16__CONFIG5:
b4dd99a3 7879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7880 register_name = "Config5";
b4dd99a3 7881 break;
e397ee33 7882 /* 6,7 are implementation dependent */
433efb4c 7883 case CP0_REG16__CONFIG6:
7db13fae 7884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7885 register_name = "Config6";
e397ee33 7886 break;
433efb4c 7887 case CP0_REG16__CONFIG7:
7db13fae 7888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7889 register_name = "Config7";
e397ee33 7890 break;
873eb012 7891 default:
f31b035a 7892 goto cp0_unimplemented;
873eb012
TS
7893 }
7894 break;
04992c8c 7895 case CP0_REGISTER_17:
7a387fff 7896 switch (sel) {
706ce142 7897 case CP0_REG17__LLADDR:
895c2d04 7898 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7899 register_name = "LLAddr";
2423f660 7900 break;
706ce142 7901 case CP0_REG17__MAAR:
f6d4dd81
YK
7902 CP0_CHECK(ctx->mrp);
7903 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7904 register_name = "MAAR";
f6d4dd81 7905 break;
706ce142 7906 case CP0_REG17__MAARI:
f6d4dd81
YK
7907 CP0_CHECK(ctx->mrp);
7908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7909 register_name = "MAARI";
f6d4dd81 7910 break;
7a387fff 7911 default:
f31b035a 7912 goto cp0_unimplemented;
7a387fff 7913 }
873eb012 7914 break;
04992c8c 7915 case CP0_REGISTER_18:
7a387fff 7916 switch (sel) {
e8dcfe82
AM
7917 case CP0_REG18__WATCHLO0:
7918 case CP0_REG18__WATCHLO1:
7919 case CP0_REG18__WATCHLO2:
7920 case CP0_REG18__WATCHLO3:
7921 case CP0_REG18__WATCHLO4:
7922 case CP0_REG18__WATCHLO5:
7923 case CP0_REG18__WATCHLO6:
7924 case CP0_REG18__WATCHLO7:
fa192d49 7925 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7926 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7927 register_name = "WatchLo";
2423f660 7928 break;
7a387fff 7929 default:
f31b035a 7930 goto cp0_unimplemented;
7a387fff 7931 }
873eb012 7932 break;
04992c8c 7933 case CP0_REGISTER_19:
7a387fff 7934 switch (sel) {
be274dc1
AM
7935 case CP0_REG19__WATCHHI0:
7936 case CP0_REG19__WATCHHI1:
7937 case CP0_REG19__WATCHHI2:
7938 case CP0_REG19__WATCHHI3:
7939 case CP0_REG19__WATCHHI4:
7940 case CP0_REG19__WATCHHI5:
7941 case CP0_REG19__WATCHHI6:
7942 case CP0_REG19__WATCHHI7:
fa192d49 7943 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7944 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7945 register_name = "WatchHi";
2423f660 7946 break;
7a387fff 7947 default:
f31b035a 7948 goto cp0_unimplemented;
7a387fff 7949 }
873eb012 7950 break;
04992c8c 7951 case CP0_REGISTER_20:
7a387fff 7952 switch (sel) {
14f92b0b 7953 case CP0_REG20__XCONTEXT:
d26bc211 7954#if defined(TARGET_MIPS64)
d75c135e 7955 check_insn(ctx, ISA_MIPS3);
7db13fae 7956 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7957 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7958 register_name = "XContext";
2423f660 7959 break;
703eaf37 7960#endif
7a387fff 7961 default:
f31b035a 7962 goto cp0_unimplemented;
7a387fff 7963 }
8c0fdd85 7964 break;
04992c8c 7965 case CP0_REGISTER_21:
7a387fff 7966 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 7967 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
7968 switch (sel) {
7969 case 0:
7db13fae 7970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7971 register_name = "Framemask";
2423f660 7972 break;
7a387fff 7973 default:
f31b035a 7974 goto cp0_unimplemented;
7a387fff 7975 }
8c0fdd85 7976 break;
04992c8c 7977 case CP0_REGISTER_22:
d9bea114 7978 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7979 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7980 break;
04992c8c 7981 case CP0_REGISTER_23:
7a387fff 7982 switch (sel) {
4cbf4b6d 7983 case CP0_REG23__DEBUG:
895c2d04 7984 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7985 register_name = "Debug";
2423f660 7986 break;
4cbf4b6d
AM
7987 case CP0_REG23__TRACECONTROL:
7988 /* PDtrace support */
7989 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 7990 register_name = "TraceControl";
3570d7f6 7991 goto cp0_unimplemented;
4cbf4b6d
AM
7992 case CP0_REG23__TRACECONTROL2:
7993 /* PDtrace support */
7994 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 7995 register_name = "TraceControl2";
3570d7f6 7996 goto cp0_unimplemented;
4cbf4b6d
AM
7997 case CP0_REG23__USERTRACEDATA1:
7998 /* PDtrace support */
7999 /* gen_helper_mfc0_usertracedata1(arg);*/
8000 register_name = "UserTraceData1";
3570d7f6 8001 goto cp0_unimplemented;
4cbf4b6d
AM
8002 case CP0_REG23__TRACEIBPC:
8003 /* PDtrace support */
8004 /* gen_helper_mfc0_traceibpc(arg); */
8005 register_name = "TraceIBPC";
8006 goto cp0_unimplemented;
8007 case CP0_REG23__TRACEDBPC:
8008 /* PDtrace support */
8009 /* gen_helper_mfc0_tracedbpc(arg); */
8010 register_name = "TraceDBPC";
3570d7f6 8011 goto cp0_unimplemented;
7a387fff 8012 default:
f31b035a 8013 goto cp0_unimplemented;
7a387fff 8014 }
873eb012 8015 break;
04992c8c 8016 case CP0_REGISTER_24:
7a387fff 8017 switch (sel) {
8d7b4b6e 8018 case CP0_REG24__DEPC:
f0b3f3ae 8019 /* EJTAG support */
7db13fae 8020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 8021 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 8022 register_name = "DEPC";
2423f660 8023 break;
7a387fff 8024 default:
f31b035a 8025 goto cp0_unimplemented;
7a387fff 8026 }
873eb012 8027 break;
04992c8c 8028 case CP0_REGISTER_25:
7a387fff 8029 switch (sel) {
1176b328 8030 case CP0_REG25__PERFCTL0:
7db13fae 8031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8032 register_name = "Performance0";
7a387fff 8033 break;
1176b328 8034 case CP0_REG25__PERFCNT0:
7480515f 8035 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 8036 register_name = "Performance1";
3570d7f6 8037 goto cp0_unimplemented;
1176b328 8038 case CP0_REG25__PERFCTL1:
7480515f 8039 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 8040 register_name = "Performance2";
3570d7f6 8041 goto cp0_unimplemented;
1176b328 8042 case CP0_REG25__PERFCNT1:
7480515f 8043 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 8044 register_name = "Performance3";
3570d7f6 8045 goto cp0_unimplemented;
1176b328 8046 case CP0_REG25__PERFCTL2:
7480515f 8047 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 8048 register_name = "Performance4";
3570d7f6 8049 goto cp0_unimplemented;
1176b328 8050 case CP0_REG25__PERFCNT2:
7480515f 8051 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 8052 register_name = "Performance5";
3570d7f6 8053 goto cp0_unimplemented;
1176b328 8054 case CP0_REG25__PERFCTL3:
7480515f 8055 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 8056 register_name = "Performance6";
3570d7f6 8057 goto cp0_unimplemented;
1176b328 8058 case CP0_REG25__PERFCNT3:
7480515f 8059 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 8060 register_name = "Performance7";
3570d7f6 8061 goto cp0_unimplemented;
7a387fff 8062 default:
f31b035a 8063 goto cp0_unimplemented;
7a387fff 8064 }
8c0fdd85 8065 break;
04992c8c 8066 case CP0_REGISTER_26:
0d74a222 8067 switch (sel) {
dbbf08b2 8068 case CP0_REG26__ERRCTL:
0d74a222 8069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8070 register_name = "ErrCtl";
0d74a222
LA
8071 break;
8072 default:
8073 goto cp0_unimplemented;
8074 }
da80682b 8075 break;
04992c8c 8076 case CP0_REGISTER_27:
7a387fff 8077 switch (sel) {
5a10873d 8078 case CP0_REG27__CACHERR:
d9bea114 8079 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8080 register_name = "CacheErr";
2423f660 8081 break;
7a387fff 8082 default:
f31b035a 8083 goto cp0_unimplemented;
7a387fff 8084 }
8c0fdd85 8085 break;
04992c8c 8086 case CP0_REGISTER_28:
873eb012 8087 switch (sel) {
a30e2f21
AM
8088 case CP0_REG28__TAGLO:
8089 case CP0_REG28__TAGLO1:
8090 case CP0_REG28__TAGLO2:
8091 case CP0_REG28__TAGLO3:
284b731a
LA
8092 {
8093 TCGv_i64 tmp = tcg_temp_new_i64();
8094 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
8095 gen_move_low32(arg, tmp);
8096 tcg_temp_free_i64(tmp);
8097 }
294fc2ea 8098 register_name = "TagLo";
873eb012 8099 break;
a30e2f21
AM
8100 case CP0_REG28__DATALO:
8101 case CP0_REG28__DATALO1:
8102 case CP0_REG28__DATALO2:
8103 case CP0_REG28__DATALO3:
7db13fae 8104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8105 register_name = "DataLo";
873eb012
TS
8106 break;
8107 default:
f31b035a 8108 goto cp0_unimplemented;
873eb012
TS
8109 }
8110 break;
04992c8c 8111 case CP0_REGISTER_29:
7a387fff 8112 switch (sel) {
af4bb6da
AM
8113 case CP0_REG29__TAGHI:
8114 case CP0_REG29__TAGHI1:
8115 case CP0_REG29__TAGHI2:
8116 case CP0_REG29__TAGHI3:
7db13fae 8117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8118 register_name = "TagHi";
7a387fff 8119 break;
af4bb6da
AM
8120 case CP0_REG29__DATAHI:
8121 case CP0_REG29__DATAHI1:
8122 case CP0_REG29__DATAHI2:
8123 case CP0_REG29__DATAHI3:
7db13fae 8124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8125 register_name = "DataHi";
7a387fff
TS
8126 break;
8127 default:
f31b035a 8128 goto cp0_unimplemented;
7a387fff 8129 }
8c0fdd85 8130 break;
04992c8c 8131 case CP0_REGISTER_30:
7a387fff 8132 switch (sel) {
4bcf121e 8133 case CP0_REG30__ERROREPC:
7db13fae 8134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 8135 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 8136 register_name = "ErrorEPC";
2423f660 8137 break;
7a387fff 8138 default:
f31b035a 8139 goto cp0_unimplemented;
7a387fff 8140 }
873eb012 8141 break;
04992c8c 8142 case CP0_REGISTER_31:
7a387fff 8143 switch (sel) {
14d92efd 8144 case CP0_REG31__DESAVE:
f0b3f3ae 8145 /* EJTAG support */
7db13fae 8146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8147 register_name = "DESAVE";
2423f660 8148 break;
14d92efd
AM
8149 case CP0_REG31__KSCRATCH1:
8150 case CP0_REG31__KSCRATCH2:
8151 case CP0_REG31__KSCRATCH3:
8152 case CP0_REG31__KSCRATCH4:
8153 case CP0_REG31__KSCRATCH5:
8154 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8155 CP0_CHECK(ctx->kscrexist & (1 << sel));
8156 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 8157 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 8158 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 8159 register_name = "KScratch";
e98c0d17 8160 break;
7a387fff 8161 default:
f31b035a 8162 goto cp0_unimplemented;
7a387fff 8163 }
873eb012
TS
8164 break;
8165 default:
f31b035a 8166 goto cp0_unimplemented;
873eb012 8167 }
294fc2ea 8168 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
8169 return;
8170
f31b035a 8171cp0_unimplemented:
294fc2ea
AM
8172 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8173 register_name, reg, sel);
f31b035a 8174 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
8175}
8176
d75c135e 8177static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 8178{
294fc2ea 8179 const char *register_name = "invalid";
7a387fff 8180
1f8929d2 8181 if (sel != 0) {
bbd5e4a2 8182 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 8183 }
e189e748 8184
eeb3bba8 8185 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8186 gen_io_start();
bd79255d 8187 }
2e70f6ef 8188
8c0fdd85 8189 switch (reg) {
04992c8c 8190 case CP0_REGISTER_00:
7a387fff 8191 switch (sel) {
1b142da5 8192 case CP0_REG00__INDEX:
895c2d04 8193 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 8194 register_name = "Index";
7a387fff 8195 break;
1b142da5 8196 case CP0_REG00__MVPCONTROL:
f31b035a 8197 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8198 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 8199 register_name = "MVPControl";
ead9360e 8200 break;
1b142da5 8201 case CP0_REG00__MVPCONF0:
f31b035a 8202 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8203 /* ignored */
294fc2ea 8204 register_name = "MVPConf0";
ead9360e 8205 break;
1b142da5 8206 case CP0_REG00__MVPCONF1:
f31b035a 8207 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8208 /* ignored */
294fc2ea 8209 register_name = "MVPConf1";
ead9360e 8210 break;
1b142da5 8211 case CP0_REG00__VPCONTROL:
01bc435b
YK
8212 CP0_CHECK(ctx->vp);
8213 /* ignored */
294fc2ea 8214 register_name = "VPControl";
01bc435b 8215 break;
7a387fff 8216 default:
f31b035a 8217 goto cp0_unimplemented;
7a387fff 8218 }
8c0fdd85 8219 break;
04992c8c 8220 case CP0_REGISTER_01:
7a387fff 8221 switch (sel) {
30deb460 8222 case CP0_REG01__RANDOM:
2423f660 8223 /* ignored */
294fc2ea 8224 register_name = "Random";
2423f660 8225 break;
30deb460 8226 case CP0_REG01__VPECONTROL:
f31b035a 8227 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8228 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 8229 register_name = "VPEControl";
ead9360e 8230 break;
30deb460 8231 case CP0_REG01__VPECONF0:
f31b035a 8232 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8233 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 8234 register_name = "VPEConf0";
ead9360e 8235 break;
30deb460 8236 case CP0_REG01__VPECONF1:
f31b035a 8237 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8238 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 8239 register_name = "VPEConf1";
ead9360e 8240 break;
30deb460 8241 case CP0_REG01__YQMASK:
f31b035a 8242 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8243 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 8244 register_name = "YQMask";
ead9360e 8245 break;
30deb460 8246 case CP0_REG01__VPESCHEDULE:
f31b035a 8247 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
8248 tcg_gen_st_tl(arg, cpu_env,
8249 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8250 register_name = "VPESchedule";
ead9360e 8251 break;
30deb460 8252 case CP0_REG01__VPESCHEFBACK:
f31b035a 8253 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
8254 tcg_gen_st_tl(arg, cpu_env,
8255 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8256 register_name = "VPEScheFBack";
ead9360e 8257 break;
30deb460 8258 case CP0_REG01__VPEOPT:
f31b035a 8259 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8260 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 8261 register_name = "VPEOpt";
ead9360e 8262 break;
7a387fff 8263 default:
f31b035a 8264 goto cp0_unimplemented;
7a387fff 8265 }
8c0fdd85 8266 break;
04992c8c 8267 case CP0_REGISTER_02:
7a387fff 8268 switch (sel) {
6d27d5bd 8269 case CP0_REG02__ENTRYLO0:
895c2d04 8270 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 8271 register_name = "EntryLo0";
2423f660 8272 break;
6d27d5bd 8273 case CP0_REG02__TCSTATUS:
f31b035a 8274 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8275 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 8276 register_name = "TCStatus";
ead9360e 8277 break;
6d27d5bd 8278 case CP0_REG02__TCBIND:
f31b035a 8279 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8280 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 8281 register_name = "TCBind";
ead9360e 8282 break;
6d27d5bd 8283 case CP0_REG02__TCRESTART:
f31b035a 8284 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8285 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 8286 register_name = "TCRestart";
ead9360e 8287 break;
6d27d5bd 8288 case CP0_REG02__TCHALT:
f31b035a 8289 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8290 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 8291 register_name = "TCHalt";
ead9360e 8292 break;
6d27d5bd 8293 case CP0_REG02__TCCONTEXT:
f31b035a 8294 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8295 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 8296 register_name = "TCContext";
ead9360e 8297 break;
6d27d5bd 8298 case CP0_REG02__TCSCHEDULE:
f31b035a 8299 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8300 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 8301 register_name = "TCSchedule";
ead9360e 8302 break;
6d27d5bd 8303 case CP0_REG02__TCSCHEFBACK:
f31b035a 8304 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8305 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 8306 register_name = "TCScheFBack";
ead9360e 8307 break;
7a387fff 8308 default:
f31b035a 8309 goto cp0_unimplemented;
7a387fff 8310 }
8c0fdd85 8311 break;
04992c8c 8312 case CP0_REGISTER_03:
7a387fff 8313 switch (sel) {
acd37316 8314 case CP0_REG03__ENTRYLO1:
895c2d04 8315 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 8316 register_name = "EntryLo1";
2423f660 8317 break;
acd37316 8318 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8319 CP0_CHECK(ctx->vp);
8320 /* ignored */
294fc2ea 8321 register_name = "GlobalNumber";
01bc435b 8322 break;
7a387fff 8323 default:
f31b035a 8324 goto cp0_unimplemented;
876d4b07 8325 }
8c0fdd85 8326 break;
04992c8c 8327 case CP0_REGISTER_04:
7a387fff 8328 switch (sel) {
020fe379 8329 case CP0_REG04__CONTEXT:
895c2d04 8330 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 8331 register_name = "Context";
2423f660 8332 break;
020fe379
AM
8333 case CP0_REG04__CONTEXTCONFIG:
8334 /* SmartMIPS ASE */
8335 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 8336 register_name = "ContextConfig";
f31b035a 8337 goto cp0_unimplemented;
020fe379 8338 case CP0_REG04__USERLOCAL:
f31b035a
LA
8339 CP0_CHECK(ctx->ulri);
8340 tcg_gen_st_tl(arg, cpu_env,
8341 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8342 register_name = "UserLocal";
d279279e 8343 break;
99029be1
YK
8344 case CP0_REG04__MMID:
8345 CP0_CHECK(ctx->mi);
8346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8347 register_name = "MMID";
8348 break;
7a387fff 8349 default:
f31b035a 8350 goto cp0_unimplemented;
876d4b07 8351 }
8c0fdd85 8352 break;
04992c8c 8353 case CP0_REGISTER_05:
7a387fff 8354 switch (sel) {
a1e76353 8355 case CP0_REG05__PAGEMASK:
895c2d04 8356 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 8357 register_name = "PageMask";
2423f660 8358 break;
a1e76353 8359 case CP0_REG05__PAGEGRAIN:
7a47bae5 8360 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8361 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 8362 register_name = "PageGrain";
eeb3bba8 8363 ctx->base.is_jmp = DISAS_STOP;
2423f660 8364 break;
a1e76353 8365 case CP0_REG05__SEGCTL0:
cec56a73
JH
8366 CP0_CHECK(ctx->sc);
8367 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 8368 register_name = "SegCtl0";
cec56a73 8369 break;
a1e76353 8370 case CP0_REG05__SEGCTL1:
cec56a73
JH
8371 CP0_CHECK(ctx->sc);
8372 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 8373 register_name = "SegCtl1";
cec56a73 8374 break;
a1e76353 8375 case CP0_REG05__SEGCTL2:
cec56a73
JH
8376 CP0_CHECK(ctx->sc);
8377 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 8378 register_name = "SegCtl2";
cec56a73 8379 break;
a1e76353 8380 case CP0_REG05__PWBASE:
5e31fdd5
YK
8381 check_pw(ctx);
8382 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8383 register_name = "PWBase";
5e31fdd5 8384 break;
a1e76353 8385 case CP0_REG05__PWFIELD:
fa75ad14
YK
8386 check_pw(ctx);
8387 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 8388 register_name = "PWField";
fa75ad14 8389 break;
a1e76353 8390 case CP0_REG05__PWSIZE:
20b28ebc
YK
8391 check_pw(ctx);
8392 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 8393 register_name = "PWSize";
20b28ebc 8394 break;
7a387fff 8395 default:
f31b035a 8396 goto cp0_unimplemented;
876d4b07 8397 }
8c0fdd85 8398 break;
04992c8c 8399 case CP0_REGISTER_06:
7a387fff 8400 switch (sel) {
9023594b 8401 case CP0_REG06__WIRED:
895c2d04 8402 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 8403 register_name = "Wired";
2423f660 8404 break;
9023594b 8405 case CP0_REG06__SRSCONF0:
7a47bae5 8406 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8407 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 8408 register_name = "SRSConf0";
ead9360e 8409 break;
9023594b 8410 case CP0_REG06__SRSCONF1:
7a47bae5 8411 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8412 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 8413 register_name = "SRSConf1";
ead9360e 8414 break;
9023594b 8415 case CP0_REG06__SRSCONF2:
7a47bae5 8416 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8417 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 8418 register_name = "SRSConf2";
ead9360e 8419 break;
9023594b 8420 case CP0_REG06__SRSCONF3:
7a47bae5 8421 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8422 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 8423 register_name = "SRSConf3";
ead9360e 8424 break;
9023594b 8425 case CP0_REG06__SRSCONF4:
7a47bae5 8426 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8427 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 8428 register_name = "SRSConf4";
ead9360e 8429 break;
9023594b 8430 case CP0_REG06__PWCTL:
103be64c
YK
8431 check_pw(ctx);
8432 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 8433 register_name = "PWCtl";
103be64c 8434 break;
7a387fff 8435 default:
f31b035a 8436 goto cp0_unimplemented;
876d4b07 8437 }
8c0fdd85 8438 break;
04992c8c 8439 case CP0_REGISTER_07:
7a387fff 8440 switch (sel) {
143a9875 8441 case CP0_REG07__HWRENA:
7a47bae5 8442 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8443 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 8444 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8445 register_name = "HWREna";
2423f660 8446 break;
7a387fff 8447 default:
f31b035a 8448 goto cp0_unimplemented;
876d4b07 8449 }
8c0fdd85 8450 break;
04992c8c 8451 case CP0_REGISTER_08:
aea14095 8452 switch (sel) {
67d167d2 8453 case CP0_REG08__BADVADDR:
aea14095 8454 /* ignored */
294fc2ea 8455 register_name = "BadVAddr";
aea14095 8456 break;
67d167d2 8457 case CP0_REG08__BADINSTR:
aea14095 8458 /* ignored */
294fc2ea 8459 register_name = "BadInstr";
aea14095 8460 break;
67d167d2 8461 case CP0_REG08__BADINSTRP:
aea14095 8462 /* ignored */
294fc2ea 8463 register_name = "BadInstrP";
aea14095 8464 break;
67d167d2 8465 case CP0_REG08__BADINSTRX:
25beba9b 8466 /* ignored */
294fc2ea 8467 register_name = "BadInstrX";
25beba9b 8468 break;
aea14095 8469 default:
f31b035a 8470 goto cp0_unimplemented;
aea14095 8471 }
8c0fdd85 8472 break;
04992c8c 8473 case CP0_REGISTER_09:
7a387fff 8474 switch (sel) {
e5a98a72 8475 case CP0_REG09__COUNT:
895c2d04 8476 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 8477 register_name = "Count";
2423f660 8478 break;
e5a98a72 8479 case CP0_REG09__SAARI:
5fb2dcd1
YK
8480 CP0_CHECK(ctx->saar);
8481 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 8482 register_name = "SAARI";
5fb2dcd1 8483 break;
e5a98a72 8484 case CP0_REG09__SAAR:
5fb2dcd1
YK
8485 CP0_CHECK(ctx->saar);
8486 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 8487 register_name = "SAAR";
5fb2dcd1 8488 break;
7a387fff 8489 default:
f31b035a 8490 goto cp0_unimplemented;
876d4b07 8491 }
8c0fdd85 8492 break;
04992c8c 8493 case CP0_REGISTER_10:
7a387fff 8494 switch (sel) {
860ffef0 8495 case CP0_REG10__ENTRYHI:
895c2d04 8496 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 8497 register_name = "EntryHi";
2423f660 8498 break;
7a387fff 8499 default:
f31b035a 8500 goto cp0_unimplemented;
876d4b07 8501 }
8c0fdd85 8502 break;
04992c8c 8503 case CP0_REGISTER_11:
7a387fff 8504 switch (sel) {
f5f3834f 8505 case CP0_REG11__COMPARE:
895c2d04 8506 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 8507 register_name = "Compare";
2423f660
TS
8508 break;
8509 /* 6,7 are implementation dependent */
7a387fff 8510 default:
f31b035a 8511 goto cp0_unimplemented;
876d4b07 8512 }
8c0fdd85 8513 break;
04992c8c 8514 case CP0_REGISTER_12:
7a387fff 8515 switch (sel) {
2b084867 8516 case CP0_REG12__STATUS:
867abc7e 8517 save_cpu_state(ctx, 1);
895c2d04 8518 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8519 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8520 gen_save_pc(ctx->base.pc_next + 4);
8521 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8522 register_name = "Status";
2423f660 8523 break;
2b084867 8524 case CP0_REG12__INTCTL:
7a47bae5 8525 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8526 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8527 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8528 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8529 register_name = "IntCtl";
2423f660 8530 break;
2b084867 8531 case CP0_REG12__SRSCTL:
7a47bae5 8532 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8533 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8534 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8535 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8536 register_name = "SRSCtl";
2423f660 8537 break;
2b084867 8538 case CP0_REG12__SRSMAP:
7a47bae5 8539 check_insn(ctx, ISA_MIPS_R2);
7db13fae 8540 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8541 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8542 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8543 register_name = "SRSMap";
fd88b6ab 8544 break;
7a387fff 8545 default:
f31b035a 8546 goto cp0_unimplemented;
876d4b07 8547 }
8c0fdd85 8548 break;
04992c8c 8549 case CP0_REGISTER_13:
7a387fff 8550 switch (sel) {
e3c7559d 8551 case CP0_REG13__CAUSE:
867abc7e 8552 save_cpu_state(ctx, 1);
895c2d04 8553 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
8554 /*
8555 * Stop translation as we may have triggered an interrupt.
b28425ba 8556 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
8557 * translated code to check for pending interrupts.
8558 */
eeb3bba8
EC
8559 gen_save_pc(ctx->base.pc_next + 4);
8560 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8561 register_name = "Cause";
2423f660 8562 break;
7a387fff 8563 default:
f31b035a 8564 goto cp0_unimplemented;
876d4b07 8565 }
8c0fdd85 8566 break;
04992c8c 8567 case CP0_REGISTER_14:
7a387fff 8568 switch (sel) {
35e4b54d 8569 case CP0_REG14__EPC:
d54a299b 8570 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8571 register_name = "EPC";
2423f660 8572 break;
7a387fff 8573 default:
f31b035a 8574 goto cp0_unimplemented;
876d4b07 8575 }
8c0fdd85 8576 break;
04992c8c 8577 case CP0_REGISTER_15:
7a387fff 8578 switch (sel) {
4466cd49 8579 case CP0_REG15__PRID:
2423f660 8580 /* ignored */
294fc2ea 8581 register_name = "PRid";
2423f660 8582 break;
4466cd49 8583 case CP0_REG15__EBASE:
7a47bae5 8584 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8585 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 8586 register_name = "EBase";
2423f660 8587 break;
7a387fff 8588 default:
f31b035a 8589 goto cp0_unimplemented;
1579a72e 8590 }
8c0fdd85 8591 break;
04992c8c 8592 case CP0_REGISTER_16:
8c0fdd85 8593 switch (sel) {
433efb4c 8594 case CP0_REG16__CONFIG:
895c2d04 8595 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 8596 register_name = "Config";
2423f660 8597 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8598 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8599 break;
433efb4c 8600 case CP0_REG16__CONFIG1:
e397ee33 8601 /* ignored, read only */
294fc2ea 8602 register_name = "Config1";
7a387fff 8603 break;
433efb4c 8604 case CP0_REG16__CONFIG2:
895c2d04 8605 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 8606 register_name = "Config2";
2423f660 8607 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8608 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 8609 break;
433efb4c 8610 case CP0_REG16__CONFIG3:
90f12d73 8611 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 8612 register_name = "Config3";
90f12d73 8613 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8614 ctx->base.is_jmp = DISAS_STOP;
7a387fff 8615 break;
433efb4c 8616 case CP0_REG16__CONFIG4:
b4160af1 8617 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 8618 register_name = "Config4";
eeb3bba8 8619 ctx->base.is_jmp = DISAS_STOP;
b4160af1 8620 break;
433efb4c 8621 case CP0_REG16__CONFIG5:
b4dd99a3 8622 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8623 register_name = "Config5";
b4dd99a3 8624 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8625 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 8626 break;
e397ee33 8627 /* 6,7 are implementation dependent */
433efb4c 8628 case CP0_REG16__CONFIG6:
e397ee33 8629 /* ignored */
294fc2ea 8630 register_name = "Config6";
e397ee33 8631 break;
433efb4c 8632 case CP0_REG16__CONFIG7:
e397ee33 8633 /* ignored */
294fc2ea 8634 register_name = "Config7";
e397ee33 8635 break;
8c0fdd85 8636 default:
294fc2ea 8637 register_name = "Invalid config selector";
f31b035a 8638 goto cp0_unimplemented;
8c0fdd85
TS
8639 }
8640 break;
04992c8c 8641 case CP0_REGISTER_17:
7a387fff 8642 switch (sel) {
706ce142 8643 case CP0_REG17__LLADDR:
895c2d04 8644 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8645 register_name = "LLAddr";
2423f660 8646 break;
706ce142 8647 case CP0_REG17__MAAR:
f6d4dd81
YK
8648 CP0_CHECK(ctx->mrp);
8649 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8650 register_name = "MAAR";
f6d4dd81 8651 break;
706ce142 8652 case CP0_REG17__MAARI:
f6d4dd81
YK
8653 CP0_CHECK(ctx->mrp);
8654 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8655 register_name = "MAARI";
f6d4dd81 8656 break;
7a387fff 8657 default:
f31b035a 8658 goto cp0_unimplemented;
7a387fff 8659 }
8c0fdd85 8660 break;
04992c8c 8661 case CP0_REGISTER_18:
7a387fff 8662 switch (sel) {
e8dcfe82
AM
8663 case CP0_REG18__WATCHLO0:
8664 case CP0_REG18__WATCHLO1:
8665 case CP0_REG18__WATCHLO2:
8666 case CP0_REG18__WATCHLO3:
8667 case CP0_REG18__WATCHLO4:
8668 case CP0_REG18__WATCHLO5:
8669 case CP0_REG18__WATCHLO6:
8670 case CP0_REG18__WATCHLO7:
fa192d49 8671 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8672 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8673 register_name = "WatchLo";
2423f660 8674 break;
7a387fff 8675 default:
f31b035a 8676 goto cp0_unimplemented;
7a387fff 8677 }
8c0fdd85 8678 break;
04992c8c 8679 case CP0_REGISTER_19:
7a387fff 8680 switch (sel) {
be274dc1
AM
8681 case CP0_REG19__WATCHHI0:
8682 case CP0_REG19__WATCHHI1:
8683 case CP0_REG19__WATCHHI2:
8684 case CP0_REG19__WATCHHI3:
8685 case CP0_REG19__WATCHHI4:
8686 case CP0_REG19__WATCHHI5:
8687 case CP0_REG19__WATCHHI6:
8688 case CP0_REG19__WATCHHI7:
fa192d49 8689 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8690 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8691 register_name = "WatchHi";
2423f660 8692 break;
7a387fff 8693 default:
f31b035a 8694 goto cp0_unimplemented;
7a387fff 8695 }
8c0fdd85 8696 break;
04992c8c 8697 case CP0_REGISTER_20:
7a387fff 8698 switch (sel) {
14f92b0b 8699 case CP0_REG20__XCONTEXT:
d26bc211 8700#if defined(TARGET_MIPS64)
d75c135e 8701 check_insn(ctx, ISA_MIPS3);
895c2d04 8702 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8703 register_name = "XContext";
2423f660 8704 break;
703eaf37 8705#endif
7a387fff 8706 default:
f31b035a 8707 goto cp0_unimplemented;
7a387fff 8708 }
8c0fdd85 8709 break;
04992c8c 8710 case CP0_REGISTER_21:
7a387fff 8711 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8712 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
8713 switch (sel) {
8714 case 0:
895c2d04 8715 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8716 register_name = "Framemask";
2423f660 8717 break;
7a387fff 8718 default:
f31b035a 8719 goto cp0_unimplemented;
7a387fff
TS
8720 }
8721 break;
04992c8c 8722 case CP0_REGISTER_22:
7a387fff 8723 /* ignored */
294fc2ea 8724 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8725 break;
04992c8c 8726 case CP0_REGISTER_23:
7a387fff 8727 switch (sel) {
4cbf4b6d 8728 case CP0_REG23__DEBUG:
895c2d04 8729 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8730 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8731 gen_save_pc(ctx->base.pc_next + 4);
8732 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8733 register_name = "Debug";
2423f660 8734 break;
4cbf4b6d
AM
8735 case CP0_REG23__TRACECONTROL:
8736 /* PDtrace support */
8737 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 8738 register_name = "TraceControl";
8487327a 8739 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8740 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8741 goto cp0_unimplemented;
4cbf4b6d
AM
8742 case CP0_REG23__TRACECONTROL2:
8743 /* PDtrace support */
8744 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 8745 register_name = "TraceControl2";
8487327a 8746 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8747 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8748 goto cp0_unimplemented;
4cbf4b6d 8749 case CP0_REG23__USERTRACEDATA1:
8487327a 8750 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8751 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8752 /* PDtrace support */
8753 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 8754 register_name = "UserTraceData";
8487327a 8755 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8756 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8757 goto cp0_unimplemented;
4cbf4b6d
AM
8758 case CP0_REG23__TRACEIBPC:
8759 /* PDtrace support */
8760 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 8761 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8762 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
8763 register_name = "TraceIBPC";
8764 goto cp0_unimplemented;
8765 case CP0_REG23__TRACEDBPC:
8766 /* PDtrace support */
8767 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8768 /* Stop translation as we may have switched the execution mode */
8769 ctx->base.is_jmp = DISAS_STOP;
8770 register_name = "TraceDBPC";
3570d7f6 8771 goto cp0_unimplemented;
7a387fff 8772 default:
f31b035a 8773 goto cp0_unimplemented;
7a387fff 8774 }
8c0fdd85 8775 break;
04992c8c 8776 case CP0_REGISTER_24:
7a387fff 8777 switch (sel) {
8d7b4b6e 8778 case CP0_REG24__DEPC:
f1aa6320 8779 /* EJTAG support */
d54a299b 8780 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8781 register_name = "DEPC";
2423f660 8782 break;
7a387fff 8783 default:
f31b035a 8784 goto cp0_unimplemented;
7a387fff 8785 }
8c0fdd85 8786 break;
04992c8c 8787 case CP0_REGISTER_25:
7a387fff 8788 switch (sel) {
1176b328 8789 case CP0_REG25__PERFCTL0:
895c2d04 8790 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8791 register_name = "Performance0";
2423f660 8792 break;
1176b328 8793 case CP0_REG25__PERFCNT0:
7480515f 8794 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 8795 register_name = "Performance1";
3570d7f6 8796 goto cp0_unimplemented;
1176b328 8797 case CP0_REG25__PERFCTL1:
7480515f 8798 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 8799 register_name = "Performance2";
3570d7f6 8800 goto cp0_unimplemented;
1176b328 8801 case CP0_REG25__PERFCNT1:
7480515f 8802 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 8803 register_name = "Performance3";
3570d7f6 8804 goto cp0_unimplemented;
1176b328 8805 case CP0_REG25__PERFCTL2:
7480515f 8806 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 8807 register_name = "Performance4";
3570d7f6 8808 goto cp0_unimplemented;
1176b328 8809 case CP0_REG25__PERFCNT2:
7480515f 8810 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 8811 register_name = "Performance5";
3570d7f6 8812 goto cp0_unimplemented;
1176b328 8813 case CP0_REG25__PERFCTL3:
7480515f 8814 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 8815 register_name = "Performance6";
3570d7f6 8816 goto cp0_unimplemented;
1176b328 8817 case CP0_REG25__PERFCNT3:
7480515f 8818 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 8819 register_name = "Performance7";
3570d7f6 8820 goto cp0_unimplemented;
7a387fff 8821 default:
f31b035a 8822 goto cp0_unimplemented;
7a387fff 8823 }
8c0fdd85 8824 break;
04992c8c 8825 case CP0_REGISTER_26:
0d74a222 8826 switch (sel) {
dbbf08b2 8827 case CP0_REG26__ERRCTL:
0d74a222 8828 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8829 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8830 register_name = "ErrCtl";
0d74a222
LA
8831 break;
8832 default:
8833 goto cp0_unimplemented;
8834 }
2423f660 8835 break;
04992c8c 8836 case CP0_REGISTER_27:
7a387fff 8837 switch (sel) {
5a10873d 8838 case CP0_REG27__CACHERR:
2423f660 8839 /* ignored */
294fc2ea 8840 register_name = "CacheErr";
2423f660 8841 break;
7a387fff 8842 default:
f31b035a 8843 goto cp0_unimplemented;
7a387fff 8844 }
8c0fdd85 8845 break;
04992c8c 8846 case CP0_REGISTER_28:
8c0fdd85 8847 switch (sel) {
a30e2f21
AM
8848 case CP0_REG28__TAGLO:
8849 case CP0_REG28__TAGLO1:
8850 case CP0_REG28__TAGLO2:
8851 case CP0_REG28__TAGLO3:
895c2d04 8852 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8853 register_name = "TagLo";
8c0fdd85 8854 break;
a30e2f21
AM
8855 case CP0_REG28__DATALO:
8856 case CP0_REG28__DATALO1:
8857 case CP0_REG28__DATALO2:
8858 case CP0_REG28__DATALO3:
895c2d04 8859 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8860 register_name = "DataLo";
7a387fff 8861 break;
8c0fdd85 8862 default:
f31b035a 8863 goto cp0_unimplemented;
8c0fdd85
TS
8864 }
8865 break;
04992c8c 8866 case CP0_REGISTER_29:
7a387fff 8867 switch (sel) {
af4bb6da
AM
8868 case CP0_REG29__TAGHI:
8869 case CP0_REG29__TAGHI1:
8870 case CP0_REG29__TAGHI2:
8871 case CP0_REG29__TAGHI3:
895c2d04 8872 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8873 register_name = "TagHi";
7a387fff 8874 break;
af4bb6da
AM
8875 case CP0_REG29__DATAHI:
8876 case CP0_REG29__DATAHI1:
8877 case CP0_REG29__DATAHI2:
8878 case CP0_REG29__DATAHI3:
895c2d04 8879 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8880 register_name = "DataHi";
7a387fff
TS
8881 break;
8882 default:
294fc2ea 8883 register_name = "invalid sel";
f31b035a 8884 goto cp0_unimplemented;
7a387fff 8885 }
8c0fdd85 8886 break;
04992c8c 8887 case CP0_REGISTER_30:
7a387fff 8888 switch (sel) {
4bcf121e 8889 case CP0_REG30__ERROREPC:
d54a299b 8890 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8891 register_name = "ErrorEPC";
2423f660 8892 break;
7a387fff 8893 default:
f31b035a 8894 goto cp0_unimplemented;
7a387fff 8895 }
8c0fdd85 8896 break;
04992c8c 8897 case CP0_REGISTER_31:
7a387fff 8898 switch (sel) {
14d92efd 8899 case CP0_REG31__DESAVE:
f1aa6320 8900 /* EJTAG support */
7db13fae 8901 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8902 register_name = "DESAVE";
2423f660 8903 break;
14d92efd
AM
8904 case CP0_REG31__KSCRATCH1:
8905 case CP0_REG31__KSCRATCH2:
8906 case CP0_REG31__KSCRATCH3:
8907 case CP0_REG31__KSCRATCH4:
8908 case CP0_REG31__KSCRATCH5:
8909 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8910 CP0_CHECK(ctx->kscrexist & (1 << sel));
8911 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 8912 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8913 register_name = "KScratch";
e98c0d17 8914 break;
7a387fff 8915 default:
f31b035a 8916 goto cp0_unimplemented;
7a387fff 8917 }
8c0fdd85
TS
8918 break;
8919 default:
f31b035a 8920 goto cp0_unimplemented;
8c0fdd85 8921 }
294fc2ea 8922 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8923
bf20dc07 8924 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8925 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8926 /*
8927 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8928 * translated code to check for pending interrupts.
8929 */
eeb3bba8
EC
8930 gen_save_pc(ctx->base.pc_next + 4);
8931 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8932 }
8c0fdd85
TS
8933 return;
8934
f31b035a 8935cp0_unimplemented:
294fc2ea
AM
8936 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8937 register_name, reg, sel);
8c0fdd85
TS
8938}
8939
d26bc211 8940#if defined(TARGET_MIPS64)
d75c135e 8941static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8942{
294fc2ea 8943 const char *register_name = "invalid";
9c2149c8 8944
1f8929d2 8945 if (sel != 0) {
bbd5e4a2 8946 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 8947 }
e189e748 8948
9c2149c8 8949 switch (reg) {
04992c8c 8950 case CP0_REGISTER_00:
9c2149c8 8951 switch (sel) {
1b142da5 8952 case CP0_REG00__INDEX:
7db13fae 8953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8954 register_name = "Index";
9c2149c8 8955 break;
1b142da5 8956 case CP0_REG00__MVPCONTROL:
f31b035a 8957 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8958 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8959 register_name = "MVPControl";
ead9360e 8960 break;
1b142da5 8961 case CP0_REG00__MVPCONF0:
f31b035a 8962 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8963 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8964 register_name = "MVPConf0";
ead9360e 8965 break;
1b142da5 8966 case CP0_REG00__MVPCONF1:
f31b035a 8967 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8968 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8969 register_name = "MVPConf1";
ead9360e 8970 break;
1b142da5 8971 case CP0_REG00__VPCONTROL:
01bc435b
YK
8972 CP0_CHECK(ctx->vp);
8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8974 register_name = "VPControl";
01bc435b 8975 break;
9c2149c8 8976 default:
f31b035a 8977 goto cp0_unimplemented;
9c2149c8
TS
8978 }
8979 break;
04992c8c 8980 case CP0_REGISTER_01:
9c2149c8 8981 switch (sel) {
30deb460 8982 case CP0_REG01__RANDOM:
2e211e0a 8983 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 8984 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8985 register_name = "Random";
2423f660 8986 break;
30deb460 8987 case CP0_REG01__VPECONTROL:
f31b035a 8988 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8989 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8990 register_name = "VPEControl";
ead9360e 8991 break;
30deb460 8992 case CP0_REG01__VPECONF0:
f31b035a 8993 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8995 register_name = "VPEConf0";
ead9360e 8996 break;
30deb460 8997 case CP0_REG01__VPECONF1:
f31b035a 8998 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8999 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 9000 register_name = "VPEConf1";
ead9360e 9001 break;
30deb460 9002 case CP0_REG01__YQMASK:
f31b035a 9003 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9004 tcg_gen_ld_tl(arg, cpu_env,
9005 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 9006 register_name = "YQMask";
ead9360e 9007 break;
30deb460 9008 case CP0_REG01__VPESCHEDULE:
f31b035a 9009 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9010 tcg_gen_ld_tl(arg, cpu_env,
9011 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9012 register_name = "VPESchedule";
ead9360e 9013 break;
30deb460 9014 case CP0_REG01__VPESCHEFBACK:
f31b035a 9015 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9016 tcg_gen_ld_tl(arg, cpu_env,
9017 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9018 register_name = "VPEScheFBack";
ead9360e 9019 break;
30deb460 9020 case CP0_REG01__VPEOPT:
f31b035a 9021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 9022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 9023 register_name = "VPEOpt";
ead9360e 9024 break;
9c2149c8 9025 default:
f31b035a 9026 goto cp0_unimplemented;
9c2149c8
TS
9027 }
9028 break;
04992c8c 9029 case CP0_REGISTER_02:
9c2149c8 9030 switch (sel) {
6d27d5bd 9031 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
9032 tcg_gen_ld_tl(arg, cpu_env,
9033 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 9034 register_name = "EntryLo0";
2423f660 9035 break;
6d27d5bd 9036 case CP0_REG02__TCSTATUS:
f31b035a 9037 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9038 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 9039 register_name = "TCStatus";
ead9360e 9040 break;
6d27d5bd 9041 case CP0_REG02__TCBIND:
f31b035a 9042 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9043 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 9044 register_name = "TCBind";
ead9360e 9045 break;
6d27d5bd 9046 case CP0_REG02__TCRESTART:
f31b035a 9047 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9048 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 9049 register_name = "TCRestart";
ead9360e 9050 break;
6d27d5bd 9051 case CP0_REG02__TCHALT:
f31b035a 9052 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9053 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 9054 register_name = "TCHalt";
ead9360e 9055 break;
6d27d5bd 9056 case CP0_REG02__TCCONTEXT:
f31b035a 9057 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9058 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 9059 register_name = "TCContext";
ead9360e 9060 break;
6d27d5bd 9061 case CP0_REG02__TCSCHEDULE:
f31b035a 9062 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9063 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 9064 register_name = "TCSchedule";
ead9360e 9065 break;
6d27d5bd 9066 case CP0_REG02__TCSCHEFBACK:
f31b035a 9067 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9068 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 9069 register_name = "TCScheFBack";
ead9360e 9070 break;
9c2149c8 9071 default:
f31b035a 9072 goto cp0_unimplemented;
9c2149c8
TS
9073 }
9074 break;
04992c8c 9075 case CP0_REGISTER_03:
9c2149c8 9076 switch (sel) {
acd37316 9077 case CP0_REG03__ENTRYLO1:
7db13fae 9078 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 9079 register_name = "EntryLo1";
2423f660 9080 break;
acd37316 9081 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9082 CP0_CHECK(ctx->vp);
9083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 9084 register_name = "GlobalNumber";
01bc435b 9085 break;
9c2149c8 9086 default:
f31b035a 9087 goto cp0_unimplemented;
1579a72e 9088 }
9c2149c8 9089 break;
04992c8c 9090 case CP0_REGISTER_04:
9c2149c8 9091 switch (sel) {
020fe379 9092 case CP0_REG04__CONTEXT:
7db13fae 9093 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 9094 register_name = "Context";
2423f660 9095 break;
020fe379
AM
9096 case CP0_REG04__CONTEXTCONFIG:
9097 /* SmartMIPS ASE */
9098 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 9099 register_name = "ContextConfig";
f31b035a 9100 goto cp0_unimplemented;
020fe379 9101 case CP0_REG04__USERLOCAL:
f31b035a
LA
9102 CP0_CHECK(ctx->ulri);
9103 tcg_gen_ld_tl(arg, cpu_env,
9104 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9105 register_name = "UserLocal";
d279279e 9106 break;
99029be1
YK
9107 case CP0_REG04__MMID:
9108 CP0_CHECK(ctx->mi);
9109 gen_helper_mtc0_memorymapid(cpu_env, arg);
9110 register_name = "MMID";
9111 break;
9c2149c8 9112 default:
f31b035a 9113 goto cp0_unimplemented;
876d4b07 9114 }
9c2149c8 9115 break;
04992c8c 9116 case CP0_REGISTER_05:
9c2149c8 9117 switch (sel) {
a1e76353 9118 case CP0_REG05__PAGEMASK:
7db13fae 9119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 9120 register_name = "PageMask";
2423f660 9121 break;
a1e76353 9122 case CP0_REG05__PAGEGRAIN:
7a47bae5 9123 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 9125 register_name = "PageGrain";
2423f660 9126 break;
a1e76353 9127 case CP0_REG05__SEGCTL0:
cec56a73
JH
9128 CP0_CHECK(ctx->sc);
9129 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 9130 register_name = "SegCtl0";
cec56a73 9131 break;
a1e76353 9132 case CP0_REG05__SEGCTL1:
cec56a73
JH
9133 CP0_CHECK(ctx->sc);
9134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 9135 register_name = "SegCtl1";
cec56a73 9136 break;
a1e76353 9137 case CP0_REG05__SEGCTL2:
cec56a73
JH
9138 CP0_CHECK(ctx->sc);
9139 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 9140 register_name = "SegCtl2";
cec56a73 9141 break;
a1e76353 9142 case CP0_REG05__PWBASE:
5e31fdd5
YK
9143 check_pw(ctx);
9144 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9145 register_name = "PWBase";
5e31fdd5 9146 break;
a1e76353 9147 case CP0_REG05__PWFIELD:
fa75ad14
YK
9148 check_pw(ctx);
9149 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 9150 register_name = "PWField";
fa75ad14 9151 break;
a1e76353 9152 case CP0_REG05__PWSIZE:
20b28ebc
YK
9153 check_pw(ctx);
9154 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 9155 register_name = "PWSize";
20b28ebc 9156 break;
9c2149c8 9157 default:
f31b035a 9158 goto cp0_unimplemented;
876d4b07 9159 }
9c2149c8 9160 break;
04992c8c 9161 case CP0_REGISTER_06:
9c2149c8 9162 switch (sel) {
9023594b 9163 case CP0_REG06__WIRED:
7db13fae 9164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 9165 register_name = "Wired";
2423f660 9166 break;
9023594b 9167 case CP0_REG06__SRSCONF0:
7a47bae5 9168 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 9170 register_name = "SRSConf0";
ead9360e 9171 break;
9023594b 9172 case CP0_REG06__SRSCONF1:
7a47bae5 9173 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 9175 register_name = "SRSConf1";
ead9360e 9176 break;
9023594b 9177 case CP0_REG06__SRSCONF2:
7a47bae5 9178 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 9180 register_name = "SRSConf2";
ead9360e 9181 break;
9023594b 9182 case CP0_REG06__SRSCONF3:
7a47bae5 9183 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 9185 register_name = "SRSConf3";
ead9360e 9186 break;
9023594b 9187 case CP0_REG06__SRSCONF4:
7a47bae5 9188 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 9190 register_name = "SRSConf4";
ead9360e 9191 break;
9023594b 9192 case CP0_REG06__PWCTL:
103be64c
YK
9193 check_pw(ctx);
9194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 9195 register_name = "PWCtl";
103be64c 9196 break;
9c2149c8 9197 default:
f31b035a 9198 goto cp0_unimplemented;
876d4b07 9199 }
9c2149c8 9200 break;
04992c8c 9201 case CP0_REGISTER_07:
9c2149c8 9202 switch (sel) {
143a9875 9203 case CP0_REG07__HWRENA:
7a47bae5 9204 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 9206 register_name = "HWREna";
2423f660 9207 break;
9c2149c8 9208 default:
f31b035a 9209 goto cp0_unimplemented;
876d4b07 9210 }
9c2149c8 9211 break;
04992c8c 9212 case CP0_REGISTER_08:
9c2149c8 9213 switch (sel) {
67d167d2 9214 case CP0_REG08__BADVADDR:
7db13fae 9215 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 9216 register_name = "BadVAddr";
2423f660 9217 break;
67d167d2 9218 case CP0_REG08__BADINSTR:
f31b035a
LA
9219 CP0_CHECK(ctx->bi);
9220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 9221 register_name = "BadInstr";
aea14095 9222 break;
67d167d2 9223 case CP0_REG08__BADINSTRP:
f31b035a
LA
9224 CP0_CHECK(ctx->bp);
9225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 9226 register_name = "BadInstrP";
aea14095 9227 break;
67d167d2 9228 case CP0_REG08__BADINSTRX:
25beba9b
SM
9229 CP0_CHECK(ctx->bi);
9230 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9231 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 9232 register_name = "BadInstrX";
25beba9b 9233 break;
9c2149c8 9234 default:
f31b035a 9235 goto cp0_unimplemented;
876d4b07 9236 }
9c2149c8 9237 break;
04992c8c 9238 case CP0_REGISTER_09:
9c2149c8 9239 switch (sel) {
e5a98a72 9240 case CP0_REG09__COUNT:
2e70f6ef 9241 /* Mark as an IO operation because we read the time. */
eeb3bba8 9242 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9243 gen_io_start();
bd79255d 9244 }
895c2d04 9245 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
9246 /*
9247 * Break the TB to be able to take timer interrupts immediately
9248 * after reading count. DISAS_STOP isn't sufficient, we need to
9249 * ensure we break completely out of translated code.
9250 */
eeb3bba8
EC
9251 gen_save_pc(ctx->base.pc_next + 4);
9252 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9253 register_name = "Count";
2423f660 9254 break;
e5a98a72 9255 case CP0_REG09__SAARI:
5fb2dcd1
YK
9256 CP0_CHECK(ctx->saar);
9257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 9258 register_name = "SAARI";
5fb2dcd1 9259 break;
e5a98a72 9260 case CP0_REG09__SAAR:
5fb2dcd1
YK
9261 CP0_CHECK(ctx->saar);
9262 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 9263 register_name = "SAAR";
5fb2dcd1 9264 break;
9c2149c8 9265 default:
f31b035a 9266 goto cp0_unimplemented;
876d4b07 9267 }
9c2149c8 9268 break;
04992c8c 9269 case CP0_REGISTER_10:
9c2149c8 9270 switch (sel) {
860ffef0 9271 case CP0_REG10__ENTRYHI:
7db13fae 9272 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 9273 register_name = "EntryHi";
2423f660 9274 break;
9c2149c8 9275 default:
f31b035a 9276 goto cp0_unimplemented;
876d4b07 9277 }
9c2149c8 9278 break;
04992c8c 9279 case CP0_REGISTER_11:
9c2149c8 9280 switch (sel) {
f5f3834f 9281 case CP0_REG11__COMPARE:
7db13fae 9282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 9283 register_name = "Compare";
2423f660 9284 break;
876d4b07 9285 /* 6,7 are implementation dependent */
9c2149c8 9286 default:
f31b035a 9287 goto cp0_unimplemented;
876d4b07 9288 }
9c2149c8 9289 break;
04992c8c 9290 case CP0_REGISTER_12:
9c2149c8 9291 switch (sel) {
2b084867 9292 case CP0_REG12__STATUS:
7db13fae 9293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 9294 register_name = "Status";
2423f660 9295 break;
2b084867 9296 case CP0_REG12__INTCTL:
7a47bae5 9297 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 9299 register_name = "IntCtl";
2423f660 9300 break;
2b084867 9301 case CP0_REG12__SRSCTL:
7a47bae5 9302 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 9304 register_name = "SRSCtl";
2423f660 9305 break;
2b084867 9306 case CP0_REG12__SRSMAP:
7a47bae5 9307 check_insn(ctx, ISA_MIPS_R2);
7db13fae 9308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 9309 register_name = "SRSMap";
2423f660 9310 break;
9c2149c8 9311 default:
f31b035a 9312 goto cp0_unimplemented;
876d4b07 9313 }
9c2149c8 9314 break;
04992c8c 9315 case CP0_REGISTER_13:
9c2149c8 9316 switch (sel) {
e3c7559d 9317 case CP0_REG13__CAUSE:
7db13fae 9318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 9319 register_name = "Cause";
2423f660 9320 break;
9c2149c8 9321 default:
f31b035a 9322 goto cp0_unimplemented;
876d4b07 9323 }
9c2149c8 9324 break;
04992c8c 9325 case CP0_REGISTER_14:
9c2149c8 9326 switch (sel) {
35e4b54d 9327 case CP0_REG14__EPC:
7db13fae 9328 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9329 register_name = "EPC";
2423f660 9330 break;
9c2149c8 9331 default:
f31b035a 9332 goto cp0_unimplemented;
876d4b07 9333 }
9c2149c8 9334 break;
04992c8c 9335 case CP0_REGISTER_15:
9c2149c8 9336 switch (sel) {
4466cd49 9337 case CP0_REG15__PRID:
7db13fae 9338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 9339 register_name = "PRid";
2423f660 9340 break;
4466cd49 9341 case CP0_REG15__EBASE:
7a47bae5 9342 check_insn(ctx, ISA_MIPS_R2);
74dbf824 9343 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 9344 register_name = "EBase";
2423f660 9345 break;
4466cd49 9346 case CP0_REG15__CMGCRBASE:
7a47bae5 9347 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
9348 CP0_CHECK(ctx->cmgcr);
9349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 9350 register_name = "CMGCRBase";
c870e3f5 9351 break;
9c2149c8 9352 default:
f31b035a 9353 goto cp0_unimplemented;
876d4b07 9354 }
9c2149c8 9355 break;
04992c8c 9356 case CP0_REGISTER_16:
9c2149c8 9357 switch (sel) {
433efb4c 9358 case CP0_REG16__CONFIG:
7db13fae 9359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 9360 register_name = "Config";
9c2149c8 9361 break;
433efb4c 9362 case CP0_REG16__CONFIG1:
7db13fae 9363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 9364 register_name = "Config1";
9c2149c8 9365 break;
433efb4c 9366 case CP0_REG16__CONFIG2:
7db13fae 9367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 9368 register_name = "Config2";
9c2149c8 9369 break;
433efb4c 9370 case CP0_REG16__CONFIG3:
7db13fae 9371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 9372 register_name = "Config3";
9c2149c8 9373 break;
433efb4c 9374 case CP0_REG16__CONFIG4:
faf1f68b 9375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 9376 register_name = "Config4";
faf1f68b 9377 break;
433efb4c 9378 case CP0_REG16__CONFIG5:
faf1f68b 9379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 9380 register_name = "Config5";
faf1f68b 9381 break;
05aa7e93 9382 /* 6,7 are implementation dependent */
433efb4c 9383 case CP0_REG16__CONFIG6:
7db13fae 9384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 9385 register_name = "Config6";
f0b3f3ae 9386 break;
433efb4c 9387 case CP0_REG16__CONFIG7:
7db13fae 9388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 9389 register_name = "Config7";
f0b3f3ae 9390 break;
9c2149c8 9391 default:
f31b035a 9392 goto cp0_unimplemented;
9c2149c8
TS
9393 }
9394 break;
04992c8c 9395 case CP0_REGISTER_17:
9c2149c8 9396 switch (sel) {
706ce142 9397 case CP0_REG17__LLADDR:
895c2d04 9398 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 9399 register_name = "LLAddr";
2423f660 9400 break;
706ce142 9401 case CP0_REG17__MAAR:
f6d4dd81
YK
9402 CP0_CHECK(ctx->mrp);
9403 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 9404 register_name = "MAAR";
f6d4dd81 9405 break;
706ce142 9406 case CP0_REG17__MAARI:
f6d4dd81
YK
9407 CP0_CHECK(ctx->mrp);
9408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 9409 register_name = "MAARI";
f6d4dd81 9410 break;
9c2149c8 9411 default:
f31b035a 9412 goto cp0_unimplemented;
9c2149c8
TS
9413 }
9414 break;
04992c8c 9415 case CP0_REGISTER_18:
9c2149c8 9416 switch (sel) {
e8dcfe82
AM
9417 case CP0_REG18__WATCHLO0:
9418 case CP0_REG18__WATCHLO1:
9419 case CP0_REG18__WATCHLO2:
9420 case CP0_REG18__WATCHLO3:
9421 case CP0_REG18__WATCHLO4:
9422 case CP0_REG18__WATCHLO5:
9423 case CP0_REG18__WATCHLO6:
9424 case CP0_REG18__WATCHLO7:
fa192d49 9425 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9426 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 9427 register_name = "WatchLo";
2423f660 9428 break;
9c2149c8 9429 default:
f31b035a 9430 goto cp0_unimplemented;
9c2149c8
TS
9431 }
9432 break;
04992c8c 9433 case CP0_REGISTER_19:
9c2149c8 9434 switch (sel) {
be274dc1
AM
9435 case CP0_REG19__WATCHHI0:
9436 case CP0_REG19__WATCHHI1:
9437 case CP0_REG19__WATCHHI2:
9438 case CP0_REG19__WATCHHI3:
9439 case CP0_REG19__WATCHHI4:
9440 case CP0_REG19__WATCHHI5:
9441 case CP0_REG19__WATCHHI6:
9442 case CP0_REG19__WATCHHI7:
fa192d49 9443 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 9444 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 9445 register_name = "WatchHi";
2423f660 9446 break;
9c2149c8 9447 default:
f31b035a 9448 goto cp0_unimplemented;
9c2149c8
TS
9449 }
9450 break;
04992c8c 9451 case CP0_REGISTER_20:
9c2149c8 9452 switch (sel) {
14f92b0b 9453 case CP0_REG20__XCONTEXT:
d75c135e 9454 check_insn(ctx, ISA_MIPS3);
7db13fae 9455 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 9456 register_name = "XContext";
2423f660 9457 break;
9c2149c8 9458 default:
f31b035a 9459 goto cp0_unimplemented;
9c2149c8
TS
9460 }
9461 break;
04992c8c 9462 case CP0_REGISTER_21:
05aa7e93 9463 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 9464 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
9465 switch (sel) {
9466 case 0:
7db13fae 9467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 9468 register_name = "Framemask";
2423f660 9469 break;
9c2149c8 9470 default:
f31b035a 9471 goto cp0_unimplemented;
9c2149c8
TS
9472 }
9473 break;
04992c8c 9474 case CP0_REGISTER_22:
d9bea114 9475 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 9476 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 9477 break;
04992c8c 9478 case CP0_REGISTER_23:
9c2149c8 9479 switch (sel) {
4cbf4b6d 9480 case CP0_REG23__DEBUG:
895c2d04 9481 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 9482 register_name = "Debug";
2423f660 9483 break;
4cbf4b6d
AM
9484 case CP0_REG23__TRACECONTROL:
9485 /* PDtrace support */
9486 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 9487 register_name = "TraceControl";
3570d7f6 9488 goto cp0_unimplemented;
4cbf4b6d
AM
9489 case CP0_REG23__TRACECONTROL2:
9490 /* PDtrace support */
9491 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 9492 register_name = "TraceControl2";
3570d7f6 9493 goto cp0_unimplemented;
4cbf4b6d
AM
9494 case CP0_REG23__USERTRACEDATA1:
9495 /* PDtrace support */
9496 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9497 register_name = "UserTraceData1";
3570d7f6 9498 goto cp0_unimplemented;
4cbf4b6d
AM
9499 case CP0_REG23__TRACEIBPC:
9500 /* PDtrace support */
9501 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9502 register_name = "TraceIBPC";
9503 goto cp0_unimplemented;
9504 case CP0_REG23__TRACEDBPC:
9505 /* PDtrace support */
9506 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9507 register_name = "TraceDBPC";
3570d7f6 9508 goto cp0_unimplemented;
9c2149c8 9509 default:
f31b035a 9510 goto cp0_unimplemented;
9c2149c8
TS
9511 }
9512 break;
04992c8c 9513 case CP0_REGISTER_24:
9c2149c8 9514 switch (sel) {
8d7b4b6e 9515 case CP0_REG24__DEPC:
f0b3f3ae 9516 /* EJTAG support */
7db13fae 9517 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9518 register_name = "DEPC";
2423f660 9519 break;
9c2149c8 9520 default:
f31b035a 9521 goto cp0_unimplemented;
9c2149c8
TS
9522 }
9523 break;
04992c8c 9524 case CP0_REGISTER_25:
9c2149c8 9525 switch (sel) {
1176b328 9526 case CP0_REG25__PERFCTL0:
7db13fae 9527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 9528 register_name = "Performance0";
9c2149c8 9529 break;
1176b328 9530 case CP0_REG25__PERFCNT0:
7480515f 9531 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 9532 register_name = "Performance1";
3570d7f6 9533 goto cp0_unimplemented;
1176b328 9534 case CP0_REG25__PERFCTL1:
7480515f 9535 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 9536 register_name = "Performance2";
3570d7f6 9537 goto cp0_unimplemented;
1176b328 9538 case CP0_REG25__PERFCNT1:
7480515f 9539 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 9540 register_name = "Performance3";
3570d7f6 9541 goto cp0_unimplemented;
1176b328 9542 case CP0_REG25__PERFCTL2:
7480515f 9543 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 9544 register_name = "Performance4";
3570d7f6 9545 goto cp0_unimplemented;
1176b328 9546 case CP0_REG25__PERFCNT2:
7480515f 9547 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 9548 register_name = "Performance5";
3570d7f6 9549 goto cp0_unimplemented;
1176b328 9550 case CP0_REG25__PERFCTL3:
7480515f 9551 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 9552 register_name = "Performance6";
3570d7f6 9553 goto cp0_unimplemented;
1176b328 9554 case CP0_REG25__PERFCNT3:
7480515f 9555 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 9556 register_name = "Performance7";
3570d7f6 9557 goto cp0_unimplemented;
9c2149c8 9558 default:
f31b035a 9559 goto cp0_unimplemented;
9c2149c8
TS
9560 }
9561 break;
04992c8c 9562 case CP0_REGISTER_26:
0d74a222 9563 switch (sel) {
dbbf08b2 9564 case CP0_REG26__ERRCTL:
0d74a222 9565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 9566 register_name = "ErrCtl";
0d74a222
LA
9567 break;
9568 default:
9569 goto cp0_unimplemented;
9570 }
da80682b 9571 break;
04992c8c 9572 case CP0_REGISTER_27:
9c2149c8
TS
9573 switch (sel) {
9574 /* ignored */
5a10873d 9575 case CP0_REG27__CACHERR:
d9bea114 9576 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 9577 register_name = "CacheErr";
2423f660 9578 break;
9c2149c8 9579 default:
f31b035a 9580 goto cp0_unimplemented;
9c2149c8
TS
9581 }
9582 break;
04992c8c 9583 case CP0_REGISTER_28:
9c2149c8 9584 switch (sel) {
a30e2f21
AM
9585 case CP0_REG28__TAGLO:
9586 case CP0_REG28__TAGLO1:
9587 case CP0_REG28__TAGLO2:
9588 case CP0_REG28__TAGLO3:
7db13fae 9589 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 9590 register_name = "TagLo";
9c2149c8 9591 break;
a30e2f21
AM
9592 case CP0_REG28__DATALO:
9593 case CP0_REG28__DATALO1:
9594 case CP0_REG28__DATALO2:
9595 case CP0_REG28__DATALO3:
7db13fae 9596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 9597 register_name = "DataLo";
9c2149c8
TS
9598 break;
9599 default:
f31b035a 9600 goto cp0_unimplemented;
9c2149c8
TS
9601 }
9602 break;
04992c8c 9603 case CP0_REGISTER_29:
9c2149c8 9604 switch (sel) {
af4bb6da
AM
9605 case CP0_REG29__TAGHI:
9606 case CP0_REG29__TAGHI1:
9607 case CP0_REG29__TAGHI2:
9608 case CP0_REG29__TAGHI3:
7db13fae 9609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 9610 register_name = "TagHi";
9c2149c8 9611 break;
af4bb6da
AM
9612 case CP0_REG29__DATAHI:
9613 case CP0_REG29__DATAHI1:
9614 case CP0_REG29__DATAHI2:
9615 case CP0_REG29__DATAHI3:
7db13fae 9616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 9617 register_name = "DataHi";
9c2149c8
TS
9618 break;
9619 default:
f31b035a 9620 goto cp0_unimplemented;
9c2149c8
TS
9621 }
9622 break;
04992c8c 9623 case CP0_REGISTER_30:
9c2149c8 9624 switch (sel) {
4bcf121e 9625 case CP0_REG30__ERROREPC:
7db13fae 9626 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9627 register_name = "ErrorEPC";
2423f660 9628 break;
9c2149c8 9629 default:
f31b035a 9630 goto cp0_unimplemented;
9c2149c8
TS
9631 }
9632 break;
04992c8c 9633 case CP0_REGISTER_31:
9c2149c8 9634 switch (sel) {
14d92efd 9635 case CP0_REG31__DESAVE:
f0b3f3ae 9636 /* EJTAG support */
7db13fae 9637 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9638 register_name = "DESAVE";
2423f660 9639 break;
14d92efd
AM
9640 case CP0_REG31__KSCRATCH1:
9641 case CP0_REG31__KSCRATCH2:
9642 case CP0_REG31__KSCRATCH3:
9643 case CP0_REG31__KSCRATCH4:
9644 case CP0_REG31__KSCRATCH5:
9645 case CP0_REG31__KSCRATCH6:
f31b035a
LA
9646 CP0_CHECK(ctx->kscrexist & (1 << sel));
9647 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 9648 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 9649 register_name = "KScratch";
e98c0d17 9650 break;
9c2149c8 9651 default:
f31b035a 9652 goto cp0_unimplemented;
9c2149c8
TS
9653 }
9654 break;
9655 default:
f31b035a 9656 goto cp0_unimplemented;
9c2149c8 9657 }
294fc2ea 9658 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
9659 return;
9660
f31b035a 9661cp0_unimplemented:
294fc2ea
AM
9662 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9663 register_name, reg, sel);
f31b035a 9664 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
9665}
9666
d75c135e 9667static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 9668{
294fc2ea 9669 const char *register_name = "invalid";
9c2149c8 9670
1f8929d2 9671 if (sel != 0) {
bbd5e4a2 9672 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 9673 }
e189e748 9674
eeb3bba8 9675 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9676 gen_io_start();
bd79255d 9677 }
2e70f6ef 9678
9c2149c8 9679 switch (reg) {
04992c8c 9680 case CP0_REGISTER_00:
9c2149c8 9681 switch (sel) {
1b142da5 9682 case CP0_REG00__INDEX:
895c2d04 9683 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 9684 register_name = "Index";
9c2149c8 9685 break;
1b142da5 9686 case CP0_REG00__MVPCONTROL:
f31b035a 9687 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9688 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 9689 register_name = "MVPControl";
ead9360e 9690 break;
1b142da5 9691 case CP0_REG00__MVPCONF0:
f31b035a 9692 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9693 /* ignored */
294fc2ea 9694 register_name = "MVPConf0";
ead9360e 9695 break;
1b142da5 9696 case CP0_REG00__MVPCONF1:
f31b035a 9697 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 9698 /* ignored */
294fc2ea 9699 register_name = "MVPConf1";
ead9360e 9700 break;
1b142da5 9701 case CP0_REG00__VPCONTROL:
01bc435b
YK
9702 CP0_CHECK(ctx->vp);
9703 /* ignored */
294fc2ea 9704 register_name = "VPControl";
01bc435b 9705 break;
9c2149c8 9706 default:
f31b035a 9707 goto cp0_unimplemented;
9c2149c8
TS
9708 }
9709 break;
04992c8c 9710 case CP0_REGISTER_01:
9c2149c8 9711 switch (sel) {
30deb460 9712 case CP0_REG01__RANDOM:
2423f660 9713 /* ignored */
294fc2ea 9714 register_name = "Random";
2423f660 9715 break;
30deb460 9716 case CP0_REG01__VPECONTROL:
f31b035a 9717 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9718 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9719 register_name = "VPEControl";
ead9360e 9720 break;
30deb460 9721 case CP0_REG01__VPECONF0:
f31b035a 9722 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9723 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9724 register_name = "VPEConf0";
ead9360e 9725 break;
30deb460 9726 case CP0_REG01__VPECONF1:
f31b035a 9727 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9728 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9729 register_name = "VPEConf1";
ead9360e 9730 break;
30deb460 9731 case CP0_REG01__YQMASK:
f31b035a 9732 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9733 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9734 register_name = "YQMask";
ead9360e 9735 break;
30deb460 9736 case CP0_REG01__VPESCHEDULE:
f31b035a 9737 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9738 tcg_gen_st_tl(arg, cpu_env,
9739 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9740 register_name = "VPESchedule";
ead9360e 9741 break;
30deb460 9742 case CP0_REG01__VPESCHEFBACK:
f31b035a 9743 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
9744 tcg_gen_st_tl(arg, cpu_env,
9745 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9746 register_name = "VPEScheFBack";
ead9360e 9747 break;
30deb460 9748 case CP0_REG01__VPEOPT:
f31b035a 9749 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9750 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9751 register_name = "VPEOpt";
ead9360e 9752 break;
9c2149c8 9753 default:
f31b035a 9754 goto cp0_unimplemented;
9c2149c8
TS
9755 }
9756 break;
04992c8c 9757 case CP0_REGISTER_02:
9c2149c8 9758 switch (sel) {
6d27d5bd 9759 case CP0_REG02__ENTRYLO0:
7207c7f9 9760 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9761 register_name = "EntryLo0";
2423f660 9762 break;
6d27d5bd 9763 case CP0_REG02__TCSTATUS:
f31b035a 9764 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9765 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9766 register_name = "TCStatus";
ead9360e 9767 break;
6d27d5bd 9768 case CP0_REG02__TCBIND:
f31b035a 9769 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9770 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9771 register_name = "TCBind";
ead9360e 9772 break;
6d27d5bd 9773 case CP0_REG02__TCRESTART:
f31b035a 9774 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9775 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9776 register_name = "TCRestart";
ead9360e 9777 break;
6d27d5bd 9778 case CP0_REG02__TCHALT:
f31b035a 9779 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9780 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9781 register_name = "TCHalt";
ead9360e 9782 break;
6d27d5bd 9783 case CP0_REG02__TCCONTEXT:
f31b035a 9784 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9785 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9786 register_name = "TCContext";
ead9360e 9787 break;
6d27d5bd 9788 case CP0_REG02__TCSCHEDULE:
f31b035a 9789 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9790 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9791 register_name = "TCSchedule";
ead9360e 9792 break;
6d27d5bd 9793 case CP0_REG02__TCSCHEFBACK:
f31b035a 9794 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9795 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9796 register_name = "TCScheFBack";
ead9360e 9797 break;
9c2149c8 9798 default:
f31b035a 9799 goto cp0_unimplemented;
9c2149c8
TS
9800 }
9801 break;
04992c8c 9802 case CP0_REGISTER_03:
9c2149c8 9803 switch (sel) {
acd37316 9804 case CP0_REG03__ENTRYLO1:
7207c7f9 9805 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9806 register_name = "EntryLo1";
2423f660 9807 break;
acd37316 9808 case CP0_REG03__GLOBALNUM:
01bc435b
YK
9809 CP0_CHECK(ctx->vp);
9810 /* ignored */
294fc2ea 9811 register_name = "GlobalNumber";
01bc435b 9812 break;
9c2149c8 9813 default:
f31b035a 9814 goto cp0_unimplemented;
876d4b07 9815 }
9c2149c8 9816 break;
04992c8c 9817 case CP0_REGISTER_04:
9c2149c8 9818 switch (sel) {
020fe379 9819 case CP0_REG04__CONTEXT:
895c2d04 9820 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9821 register_name = "Context";
2423f660 9822 break;
020fe379
AM
9823 case CP0_REG04__CONTEXTCONFIG:
9824 /* SmartMIPS ASE */
9825 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 9826 register_name = "ContextConfig";
f31b035a 9827 goto cp0_unimplemented;
020fe379 9828 case CP0_REG04__USERLOCAL:
f31b035a
LA
9829 CP0_CHECK(ctx->ulri);
9830 tcg_gen_st_tl(arg, cpu_env,
9831 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9832 register_name = "UserLocal";
d279279e 9833 break;
99029be1
YK
9834 case CP0_REG04__MMID:
9835 CP0_CHECK(ctx->mi);
9836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9837 register_name = "MMID";
9838 break;
9c2149c8 9839 default:
f31b035a 9840 goto cp0_unimplemented;
876d4b07 9841 }
9c2149c8 9842 break;
04992c8c 9843 case CP0_REGISTER_05:
9c2149c8 9844 switch (sel) {
a1e76353 9845 case CP0_REG05__PAGEMASK:
895c2d04 9846 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9847 register_name = "PageMask";
2423f660 9848 break;
a1e76353 9849 case CP0_REG05__PAGEGRAIN:
7a47bae5 9850 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9851 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9852 register_name = "PageGrain";
2423f660 9853 break;
a1e76353 9854 case CP0_REG05__SEGCTL0:
cec56a73
JH
9855 CP0_CHECK(ctx->sc);
9856 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9857 register_name = "SegCtl0";
cec56a73 9858 break;
a1e76353 9859 case CP0_REG05__SEGCTL1:
cec56a73
JH
9860 CP0_CHECK(ctx->sc);
9861 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9862 register_name = "SegCtl1";
cec56a73 9863 break;
a1e76353 9864 case CP0_REG05__SEGCTL2:
cec56a73
JH
9865 CP0_CHECK(ctx->sc);
9866 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9867 register_name = "SegCtl2";
cec56a73 9868 break;
a1e76353 9869 case CP0_REG05__PWBASE:
5e31fdd5
YK
9870 check_pw(ctx);
9871 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9872 register_name = "PWBase";
5e31fdd5 9873 break;
a1e76353 9874 case CP0_REG05__PWFIELD:
fa75ad14
YK
9875 check_pw(ctx);
9876 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9877 register_name = "PWField";
fa75ad14 9878 break;
a1e76353 9879 case CP0_REG05__PWSIZE:
20b28ebc
YK
9880 check_pw(ctx);
9881 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9882 register_name = "PWSize";
20b28ebc 9883 break;
9c2149c8 9884 default:
f31b035a 9885 goto cp0_unimplemented;
876d4b07 9886 }
9c2149c8 9887 break;
04992c8c 9888 case CP0_REGISTER_06:
9c2149c8 9889 switch (sel) {
9023594b 9890 case CP0_REG06__WIRED:
895c2d04 9891 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9892 register_name = "Wired";
2423f660 9893 break;
9023594b 9894 case CP0_REG06__SRSCONF0:
7a47bae5 9895 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9896 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9897 register_name = "SRSConf0";
ead9360e 9898 break;
9023594b 9899 case CP0_REG06__SRSCONF1:
7a47bae5 9900 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9901 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9902 register_name = "SRSConf1";
ead9360e 9903 break;
9023594b 9904 case CP0_REG06__SRSCONF2:
7a47bae5 9905 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9906 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9907 register_name = "SRSConf2";
ead9360e 9908 break;
9023594b 9909 case CP0_REG06__SRSCONF3:
7a47bae5 9910 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9911 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9912 register_name = "SRSConf3";
ead9360e 9913 break;
9023594b 9914 case CP0_REG06__SRSCONF4:
7a47bae5 9915 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9916 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9917 register_name = "SRSConf4";
ead9360e 9918 break;
9023594b 9919 case CP0_REG06__PWCTL:
103be64c
YK
9920 check_pw(ctx);
9921 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9922 register_name = "PWCtl";
103be64c 9923 break;
9c2149c8 9924 default:
f31b035a 9925 goto cp0_unimplemented;
876d4b07 9926 }
9c2149c8 9927 break;
04992c8c 9928 case CP0_REGISTER_07:
9c2149c8 9929 switch (sel) {
143a9875 9930 case CP0_REG07__HWRENA:
7a47bae5 9931 check_insn(ctx, ISA_MIPS_R2);
895c2d04 9932 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9933 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9934 register_name = "HWREna";
2423f660 9935 break;
9c2149c8 9936 default:
f31b035a 9937 goto cp0_unimplemented;
876d4b07 9938 }
9c2149c8 9939 break;
04992c8c 9940 case CP0_REGISTER_08:
aea14095 9941 switch (sel) {
67d167d2 9942 case CP0_REG08__BADVADDR:
aea14095 9943 /* ignored */
294fc2ea 9944 register_name = "BadVAddr";
aea14095 9945 break;
67d167d2 9946 case CP0_REG08__BADINSTR:
aea14095 9947 /* ignored */
294fc2ea 9948 register_name = "BadInstr";
aea14095 9949 break;
67d167d2 9950 case CP0_REG08__BADINSTRP:
aea14095 9951 /* ignored */
294fc2ea 9952 register_name = "BadInstrP";
aea14095 9953 break;
67d167d2 9954 case CP0_REG08__BADINSTRX:
25beba9b 9955 /* ignored */
294fc2ea 9956 register_name = "BadInstrX";
25beba9b 9957 break;
aea14095 9958 default:
f31b035a 9959 goto cp0_unimplemented;
aea14095 9960 }
9c2149c8 9961 break;
04992c8c 9962 case CP0_REGISTER_09:
9c2149c8 9963 switch (sel) {
e5a98a72 9964 case CP0_REG09__COUNT:
895c2d04 9965 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9966 register_name = "Count";
2423f660 9967 break;
e5a98a72 9968 case CP0_REG09__SAARI:
5fb2dcd1
YK
9969 CP0_CHECK(ctx->saar);
9970 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9971 register_name = "SAARI";
5fb2dcd1 9972 break;
e5a98a72 9973 case CP0_REG09__SAAR:
5fb2dcd1
YK
9974 CP0_CHECK(ctx->saar);
9975 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9976 register_name = "SAAR";
5fb2dcd1 9977 break;
9c2149c8 9978 default:
f31b035a 9979 goto cp0_unimplemented;
876d4b07
TS
9980 }
9981 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9982 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9983 break;
04992c8c 9984 case CP0_REGISTER_10:
9c2149c8 9985 switch (sel) {
860ffef0 9986 case CP0_REG10__ENTRYHI:
895c2d04 9987 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9988 register_name = "EntryHi";
2423f660 9989 break;
9c2149c8 9990 default:
f31b035a 9991 goto cp0_unimplemented;
876d4b07 9992 }
9c2149c8 9993 break;
04992c8c 9994 case CP0_REGISTER_11:
9c2149c8 9995 switch (sel) {
f5f3834f 9996 case CP0_REG11__COMPARE:
895c2d04 9997 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9998 register_name = "Compare";
2423f660 9999 break;
876d4b07 10000 /* 6,7 are implementation dependent */
9c2149c8 10001 default:
f31b035a 10002 goto cp0_unimplemented;
876d4b07 10003 }
de9a95f0 10004 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10005 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 10006 break;
04992c8c 10007 case CP0_REGISTER_12:
9c2149c8 10008 switch (sel) {
2b084867 10009 case CP0_REG12__STATUS:
867abc7e 10010 save_cpu_state(ctx, 1);
895c2d04 10011 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 10012 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
10013 gen_save_pc(ctx->base.pc_next + 4);
10014 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 10015 register_name = "Status";
2423f660 10016 break;
2b084867 10017 case CP0_REG12__INTCTL:
7a47bae5 10018 check_insn(ctx, ISA_MIPS_R2);
895c2d04 10019 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 10020 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10021 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10022 register_name = "IntCtl";
2423f660 10023 break;
2b084867 10024 case CP0_REG12__SRSCTL:
7a47bae5 10025 check_insn(ctx, ISA_MIPS_R2);
895c2d04 10026 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 10027 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10028 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10029 register_name = "SRSCtl";
2423f660 10030 break;
2b084867 10031 case CP0_REG12__SRSMAP:
7a47bae5 10032 check_insn(ctx, ISA_MIPS_R2);
7db13fae 10033 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 10034 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10035 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10036 register_name = "SRSMap";
2423f660
TS
10037 break;
10038 default:
f31b035a 10039 goto cp0_unimplemented;
876d4b07 10040 }
9c2149c8 10041 break;
04992c8c 10042 case CP0_REGISTER_13:
9c2149c8 10043 switch (sel) {
e3c7559d 10044 case CP0_REG13__CAUSE:
867abc7e 10045 save_cpu_state(ctx, 1);
895c2d04 10046 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
10047 /*
10048 * Stop translation as we may have triggered an interrupt.
b28425ba 10049 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
10050 * translated code to check for pending interrupts.
10051 */
eeb3bba8
EC
10052 gen_save_pc(ctx->base.pc_next + 4);
10053 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 10054 register_name = "Cause";
2423f660 10055 break;
9c2149c8 10056 default:
f31b035a 10057 goto cp0_unimplemented;
876d4b07 10058 }
9c2149c8 10059 break;
04992c8c 10060 case CP0_REGISTER_14:
9c2149c8 10061 switch (sel) {
35e4b54d 10062 case CP0_REG14__EPC:
7db13fae 10063 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 10064 register_name = "EPC";
2423f660 10065 break;
9c2149c8 10066 default:
f31b035a 10067 goto cp0_unimplemented;
876d4b07 10068 }
9c2149c8 10069 break;
04992c8c 10070 case CP0_REGISTER_15:
9c2149c8 10071 switch (sel) {
4466cd49 10072 case CP0_REG15__PRID:
2423f660 10073 /* ignored */
294fc2ea 10074 register_name = "PRid";
2423f660 10075 break;
4466cd49 10076 case CP0_REG15__EBASE:
7a47bae5 10077 check_insn(ctx, ISA_MIPS_R2);
895c2d04 10078 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 10079 register_name = "EBase";
2423f660 10080 break;
9c2149c8 10081 default:
f31b035a 10082 goto cp0_unimplemented;
876d4b07 10083 }
9c2149c8 10084 break;
04992c8c 10085 case CP0_REGISTER_16:
9c2149c8 10086 switch (sel) {
433efb4c 10087 case CP0_REG16__CONFIG:
895c2d04 10088 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 10089 register_name = "Config";
2423f660 10090 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10091 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 10092 break;
433efb4c 10093 case CP0_REG16__CONFIG1:
1fc7bf6e 10094 /* ignored, read only */
294fc2ea 10095 register_name = "Config1";
9c2149c8 10096 break;
433efb4c 10097 case CP0_REG16__CONFIG2:
895c2d04 10098 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 10099 register_name = "Config2";
2423f660 10100 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10101 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 10102 break;
433efb4c 10103 case CP0_REG16__CONFIG3:
90f12d73 10104 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 10105 register_name = "Config3";
90f12d73 10106 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10107 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 10108 break;
433efb4c 10109 case CP0_REG16__CONFIG4:
faf1f68b 10110 /* currently ignored */
294fc2ea 10111 register_name = "Config4";
faf1f68b 10112 break;
433efb4c 10113 case CP0_REG16__CONFIG5:
faf1f68b 10114 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 10115 register_name = "Config5";
faf1f68b 10116 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10117 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 10118 break;
9c2149c8
TS
10119 /* 6,7 are implementation dependent */
10120 default:
294fc2ea 10121 register_name = "Invalid config selector";
f31b035a 10122 goto cp0_unimplemented;
9c2149c8 10123 }
9c2149c8 10124 break;
04992c8c 10125 case CP0_REGISTER_17:
9c2149c8 10126 switch (sel) {
706ce142 10127 case CP0_REG17__LLADDR:
895c2d04 10128 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 10129 register_name = "LLAddr";
2423f660 10130 break;
706ce142 10131 case CP0_REG17__MAAR:
f6d4dd81
YK
10132 CP0_CHECK(ctx->mrp);
10133 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 10134 register_name = "MAAR";
f6d4dd81 10135 break;
706ce142 10136 case CP0_REG17__MAARI:
f6d4dd81
YK
10137 CP0_CHECK(ctx->mrp);
10138 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 10139 register_name = "MAARI";
f6d4dd81 10140 break;
9c2149c8 10141 default:
f31b035a 10142 goto cp0_unimplemented;
9c2149c8
TS
10143 }
10144 break;
04992c8c 10145 case CP0_REGISTER_18:
9c2149c8 10146 switch (sel) {
e8dcfe82
AM
10147 case CP0_REG18__WATCHLO0:
10148 case CP0_REG18__WATCHLO1:
10149 case CP0_REG18__WATCHLO2:
10150 case CP0_REG18__WATCHLO3:
10151 case CP0_REG18__WATCHLO4:
10152 case CP0_REG18__WATCHLO5:
10153 case CP0_REG18__WATCHLO6:
10154 case CP0_REG18__WATCHLO7:
fa192d49 10155 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 10156 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 10157 register_name = "WatchLo";
2423f660 10158 break;
9c2149c8 10159 default:
f31b035a 10160 goto cp0_unimplemented;
9c2149c8
TS
10161 }
10162 break;
04992c8c 10163 case CP0_REGISTER_19:
9c2149c8 10164 switch (sel) {
be274dc1
AM
10165 case CP0_REG19__WATCHHI0:
10166 case CP0_REG19__WATCHHI1:
10167 case CP0_REG19__WATCHHI2:
10168 case CP0_REG19__WATCHHI3:
10169 case CP0_REG19__WATCHHI4:
10170 case CP0_REG19__WATCHHI5:
10171 case CP0_REG19__WATCHHI6:
10172 case CP0_REG19__WATCHHI7:
fa192d49 10173 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 10174 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 10175 register_name = "WatchHi";
2423f660 10176 break;
9c2149c8 10177 default:
f31b035a 10178 goto cp0_unimplemented;
9c2149c8
TS
10179 }
10180 break;
04992c8c 10181 case CP0_REGISTER_20:
9c2149c8 10182 switch (sel) {
14f92b0b 10183 case CP0_REG20__XCONTEXT:
d75c135e 10184 check_insn(ctx, ISA_MIPS3);
895c2d04 10185 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 10186 register_name = "XContext";
2423f660 10187 break;
9c2149c8 10188 default:
f31b035a 10189 goto cp0_unimplemented;
9c2149c8
TS
10190 }
10191 break;
04992c8c 10192 case CP0_REGISTER_21:
9c2149c8 10193 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 10194 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
10195 switch (sel) {
10196 case 0:
895c2d04 10197 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 10198 register_name = "Framemask";
2423f660 10199 break;
9c2149c8 10200 default:
f31b035a 10201 goto cp0_unimplemented;
9c2149c8
TS
10202 }
10203 break;
04992c8c 10204 case CP0_REGISTER_22:
9c2149c8 10205 /* ignored */
294fc2ea 10206 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 10207 break;
04992c8c 10208 case CP0_REGISTER_23:
9c2149c8 10209 switch (sel) {
4cbf4b6d 10210 case CP0_REG23__DEBUG:
895c2d04 10211 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 10212 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
10213 gen_save_pc(ctx->base.pc_next + 4);
10214 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 10215 register_name = "Debug";
2423f660 10216 break;
4cbf4b6d
AM
10217 case CP0_REG23__TRACECONTROL:
10218 /* PDtrace support */
10219 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 10220 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10221 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10222 register_name = "TraceControl";
3570d7f6 10223 goto cp0_unimplemented;
4cbf4b6d
AM
10224 case CP0_REG23__TRACECONTROL2:
10225 /* PDtrace support */
10226 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 10227 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10228 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10229 register_name = "TraceControl2";
3570d7f6 10230 goto cp0_unimplemented;
4cbf4b6d
AM
10231 case CP0_REG23__USERTRACEDATA1:
10232 /* PDtrace support */
10233 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 10234 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10235 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 10236 register_name = "UserTraceData1";
3570d7f6 10237 goto cp0_unimplemented;
4cbf4b6d
AM
10238 case CP0_REG23__TRACEIBPC:
10239 /* PDtrace support */
10240 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10241 /* Stop translation as we may have switched the execution mode */
10242 ctx->base.is_jmp = DISAS_STOP;
10243 register_name = "TraceIBPC";
10244 goto cp0_unimplemented;
10245 case CP0_REG23__TRACEDBPC:
10246 /* PDtrace support */
10247 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 10248 /* Stop translation as we may have switched the execution mode */
eeb3bba8 10249 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 10250 register_name = "TraceDBPC";
3570d7f6 10251 goto cp0_unimplemented;
9c2149c8 10252 default:
f31b035a 10253 goto cp0_unimplemented;
9c2149c8 10254 }
9c2149c8 10255 break;
04992c8c 10256 case CP0_REGISTER_24:
9c2149c8 10257 switch (sel) {
8d7b4b6e 10258 case CP0_REG24__DEPC:
f1aa6320 10259 /* EJTAG support */
7db13fae 10260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 10261 register_name = "DEPC";
2423f660 10262 break;
9c2149c8 10263 default:
f31b035a 10264 goto cp0_unimplemented;
9c2149c8
TS
10265 }
10266 break;
04992c8c 10267 case CP0_REGISTER_25:
9c2149c8 10268 switch (sel) {
1176b328 10269 case CP0_REG25__PERFCTL0:
895c2d04 10270 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 10271 register_name = "Performance0";
2423f660 10272 break;
1176b328 10273 case CP0_REG25__PERFCNT0:
7480515f 10274 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 10275 register_name = "Performance1";
3570d7f6 10276 goto cp0_unimplemented;
1176b328 10277 case CP0_REG25__PERFCTL1:
7480515f 10278 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 10279 register_name = "Performance2";
3570d7f6 10280 goto cp0_unimplemented;
1176b328 10281 case CP0_REG25__PERFCNT1:
7480515f 10282 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 10283 register_name = "Performance3";
3570d7f6 10284 goto cp0_unimplemented;
1176b328 10285 case CP0_REG25__PERFCTL2:
7480515f 10286 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 10287 register_name = "Performance4";
3570d7f6 10288 goto cp0_unimplemented;
1176b328 10289 case CP0_REG25__PERFCNT2:
7480515f 10290 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 10291 register_name = "Performance5";
3570d7f6 10292 goto cp0_unimplemented;
1176b328 10293 case CP0_REG25__PERFCTL3:
7480515f 10294 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 10295 register_name = "Performance6";
3570d7f6 10296 goto cp0_unimplemented;
1176b328 10297 case CP0_REG25__PERFCNT3:
7480515f 10298 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 10299 register_name = "Performance7";
3570d7f6 10300 goto cp0_unimplemented;
9c2149c8 10301 default:
f31b035a 10302 goto cp0_unimplemented;
9c2149c8 10303 }
876d4b07 10304 break;
04992c8c 10305 case CP0_REGISTER_26:
0d74a222 10306 switch (sel) {
dbbf08b2 10307 case CP0_REG26__ERRCTL:
0d74a222 10308 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 10309 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 10310 register_name = "ErrCtl";
0d74a222
LA
10311 break;
10312 default:
10313 goto cp0_unimplemented;
10314 }
876d4b07 10315 break;
04992c8c 10316 case CP0_REGISTER_27:
9c2149c8 10317 switch (sel) {
5a10873d 10318 case CP0_REG27__CACHERR:
2423f660 10319 /* ignored */
294fc2ea 10320 register_name = "CacheErr";
2423f660 10321 break;
9c2149c8 10322 default:
f31b035a 10323 goto cp0_unimplemented;
9c2149c8 10324 }
876d4b07 10325 break;
04992c8c 10326 case CP0_REGISTER_28:
9c2149c8 10327 switch (sel) {
a30e2f21
AM
10328 case CP0_REG28__TAGLO:
10329 case CP0_REG28__TAGLO1:
10330 case CP0_REG28__TAGLO2:
10331 case CP0_REG28__TAGLO3:
895c2d04 10332 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 10333 register_name = "TagLo";
9c2149c8 10334 break;
a30e2f21
AM
10335 case CP0_REG28__DATALO:
10336 case CP0_REG28__DATALO1:
10337 case CP0_REG28__DATALO2:
10338 case CP0_REG28__DATALO3:
895c2d04 10339 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 10340 register_name = "DataLo";
9c2149c8
TS
10341 break;
10342 default:
f31b035a 10343 goto cp0_unimplemented;
9c2149c8
TS
10344 }
10345 break;
04992c8c 10346 case CP0_REGISTER_29:
9c2149c8 10347 switch (sel) {
af4bb6da
AM
10348 case CP0_REG29__TAGHI:
10349 case CP0_REG29__TAGHI1:
10350 case CP0_REG29__TAGHI2:
10351 case CP0_REG29__TAGHI3:
895c2d04 10352 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 10353 register_name = "TagHi";
9c2149c8 10354 break;
af4bb6da
AM
10355 case CP0_REG29__DATAHI:
10356 case CP0_REG29__DATAHI1:
10357 case CP0_REG29__DATAHI2:
10358 case CP0_REG29__DATAHI3:
895c2d04 10359 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 10360 register_name = "DataHi";
9c2149c8
TS
10361 break;
10362 default:
294fc2ea 10363 register_name = "invalid sel";
f31b035a 10364 goto cp0_unimplemented;
9c2149c8 10365 }
876d4b07 10366 break;
04992c8c 10367 case CP0_REGISTER_30:
9c2149c8 10368 switch (sel) {
4bcf121e 10369 case CP0_REG30__ERROREPC:
7db13fae 10370 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 10371 register_name = "ErrorEPC";
2423f660 10372 break;
9c2149c8 10373 default:
f31b035a 10374 goto cp0_unimplemented;
9c2149c8
TS
10375 }
10376 break;
04992c8c 10377 case CP0_REGISTER_31:
9c2149c8 10378 switch (sel) {
14d92efd 10379 case CP0_REG31__DESAVE:
f1aa6320 10380 /* EJTAG support */
7db13fae 10381 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 10382 register_name = "DESAVE";
2423f660 10383 break;
14d92efd
AM
10384 case CP0_REG31__KSCRATCH1:
10385 case CP0_REG31__KSCRATCH2:
10386 case CP0_REG31__KSCRATCH3:
10387 case CP0_REG31__KSCRATCH4:
10388 case CP0_REG31__KSCRATCH5:
10389 case CP0_REG31__KSCRATCH6:
f31b035a
LA
10390 CP0_CHECK(ctx->kscrexist & (1 << sel));
10391 tcg_gen_st_tl(arg, cpu_env,
71375b59 10392 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 10393 register_name = "KScratch";
e98c0d17 10394 break;
9c2149c8 10395 default:
f31b035a 10396 goto cp0_unimplemented;
9c2149c8 10397 }
9c2149c8
TS
10398 break;
10399 default:
f31b035a 10400 goto cp0_unimplemented;
9c2149c8 10401 }
294fc2ea 10402 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 10403
bf20dc07 10404 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 10405 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
10406 /*
10407 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10408 * translated code to check for pending interrupts.
10409 */
eeb3bba8
EC
10410 gen_save_pc(ctx->base.pc_next + 4);
10411 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 10412 }
9c2149c8
TS
10413 return;
10414
f31b035a 10415cp0_unimplemented:
294fc2ea
AM
10416 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10417 register_name, reg, sel);
9c2149c8 10418}
d26bc211 10419#endif /* TARGET_MIPS64 */
9c2149c8 10420
7db13fae 10421static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
10422 int u, int sel, int h)
10423{
10424 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10425 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
10426
10427 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10428 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10429 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 10430 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
10431 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10432 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 10433 tcg_gen_movi_tl(t0, -1);
1f8929d2 10434 } else if (u == 0) {
ead9360e 10435 switch (rt) {
5a25ce94
EI
10436 case 1:
10437 switch (sel) {
10438 case 1:
895c2d04 10439 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
10440 break;
10441 case 2:
895c2d04 10442 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
10443 break;
10444 default:
10445 goto die;
10446 break;
10447 }
10448 break;
ead9360e
TS
10449 case 2:
10450 switch (sel) {
10451 case 1:
895c2d04 10452 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
10453 break;
10454 case 2:
895c2d04 10455 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
10456 break;
10457 case 3:
895c2d04 10458 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
10459 break;
10460 case 4:
895c2d04 10461 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
10462 break;
10463 case 5:
895c2d04 10464 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
10465 break;
10466 case 6:
895c2d04 10467 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
10468 break;
10469 case 7:
895c2d04 10470 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
10471 break;
10472 default:
d75c135e 10473 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10474 break;
10475 }
10476 break;
10477 case 10:
10478 switch (sel) {
10479 case 0:
895c2d04 10480 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
10481 break;
10482 default:
d75c135e 10483 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10484 break;
10485 }
f1fadbb2 10486 break;
ead9360e
TS
10487 case 12:
10488 switch (sel) {
10489 case 0:
895c2d04 10490 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
10491 break;
10492 default:
d75c135e 10493 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10494 break;
10495 }
f1fadbb2 10496 break;
5a25ce94
EI
10497 case 13:
10498 switch (sel) {
10499 case 0:
895c2d04 10500 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
10501 break;
10502 default:
10503 goto die;
10504 break;
10505 }
10506 break;
10507 case 14:
10508 switch (sel) {
10509 case 0:
895c2d04 10510 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
10511 break;
10512 default:
10513 goto die;
10514 break;
10515 }
10516 break;
10517 case 15:
10518 switch (sel) {
10519 case 1:
895c2d04 10520 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
10521 break;
10522 default:
10523 goto die;
10524 break;
10525 }
10526 break;
10527 case 16:
10528 switch (sel) {
c2e19f3c
AM
10529 case 0:
10530 case 1:
10531 case 2:
10532 case 3:
10533 case 4:
10534 case 5:
10535 case 6:
10536 case 7:
895c2d04 10537 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
10538 break;
10539 default:
10540 goto die;
10541 break;
10542 }
10543 break;
ead9360e
TS
10544 case 23:
10545 switch (sel) {
10546 case 0:
895c2d04 10547 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
10548 break;
10549 default:
d75c135e 10550 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
10551 break;
10552 }
10553 break;
10554 default:
d75c135e 10555 gen_mfc0(ctx, t0, rt, sel);
ead9360e 10556 }
71375b59
AM
10557 } else {
10558 switch (sel) {
10559 /* GPR registers. */
ead9360e 10560 case 0:
71375b59 10561 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 10562 break;
71375b59 10563 /* Auxiliary CPU registers */
ead9360e 10564 case 1:
71375b59
AM
10565 switch (rt) {
10566 case 0:
10567 gen_helper_1e0i(mftlo, t0, 0);
10568 break;
10569 case 1:
10570 gen_helper_1e0i(mfthi, t0, 0);
10571 break;
10572 case 2:
10573 gen_helper_1e0i(mftacx, t0, 0);
10574 break;
10575 case 4:
10576 gen_helper_1e0i(mftlo, t0, 1);
10577 break;
10578 case 5:
10579 gen_helper_1e0i(mfthi, t0, 1);
10580 break;
10581 case 6:
10582 gen_helper_1e0i(mftacx, t0, 1);
10583 break;
10584 case 8:
10585 gen_helper_1e0i(mftlo, t0, 2);
10586 break;
10587 case 9:
10588 gen_helper_1e0i(mfthi, t0, 2);
10589 break;
10590 case 10:
10591 gen_helper_1e0i(mftacx, t0, 2);
10592 break;
10593 case 12:
10594 gen_helper_1e0i(mftlo, t0, 3);
10595 break;
10596 case 13:
10597 gen_helper_1e0i(mfthi, t0, 3);
10598 break;
10599 case 14:
10600 gen_helper_1e0i(mftacx, t0, 3);
10601 break;
10602 case 16:
10603 gen_helper_mftdsp(t0, cpu_env);
10604 break;
10605 default:
10606 goto die;
10607 }
ead9360e 10608 break;
71375b59 10609 /* Floating point (COP1). */
ead9360e 10610 case 2:
71375b59
AM
10611 /* XXX: For now we support only a single FPU context. */
10612 if (h == 0) {
10613 TCGv_i32 fp0 = tcg_temp_new_i32();
10614
10615 gen_load_fpr32(ctx, fp0, rt);
10616 tcg_gen_ext_i32_tl(t0, fp0);
10617 tcg_temp_free_i32(fp0);
10618 } else {
10619 TCGv_i32 fp0 = tcg_temp_new_i32();
10620
10621 gen_load_fpr32h(ctx, fp0, rt);
10622 tcg_gen_ext_i32_tl(t0, fp0);
10623 tcg_temp_free_i32(fp0);
10624 }
ead9360e 10625 break;
71375b59
AM
10626 case 3:
10627 /* XXX: For now we support only a single FPU context. */
10628 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 10629 break;
71375b59
AM
10630 /* COP2: Not implemented. */
10631 case 4:
ead9360e 10632 case 5:
71375b59 10633 /* fall through */
ead9360e
TS
10634 default:
10635 goto die;
10636 }
ead9360e 10637 }
b44a7fb1 10638 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
10639 gen_store_gpr(t0, rd);
10640 tcg_temp_free(t0);
ead9360e
TS
10641 return;
10642
10643die:
1a3fd9c3 10644 tcg_temp_free(t0);
d12d51d5 10645 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 10646 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10647}
10648
7db13fae 10649static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
10650 int u, int sel, int h)
10651{
10652 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 10653 TCGv t0 = tcg_temp_local_new();
ead9360e 10654
1a3fd9c3 10655 gen_load_gpr(t0, rt);
ead9360e 10656 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 10657 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 10658 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
10659 /* NOP */
10660 ;
1f8929d2
AM
10661 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10662 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
10663 /* NOP */
10664 ;
1f8929d2 10665 } else if (u == 0) {
ead9360e 10666 switch (rd) {
5a25ce94
EI
10667 case 1:
10668 switch (sel) {
10669 case 1:
895c2d04 10670 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
10671 break;
10672 case 2:
895c2d04 10673 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
10674 break;
10675 default:
10676 goto die;
10677 break;
10678 }
10679 break;
ead9360e
TS
10680 case 2:
10681 switch (sel) {
10682 case 1:
895c2d04 10683 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
10684 break;
10685 case 2:
895c2d04 10686 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
10687 break;
10688 case 3:
895c2d04 10689 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
10690 break;
10691 case 4:
895c2d04 10692 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
10693 break;
10694 case 5:
895c2d04 10695 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
10696 break;
10697 case 6:
895c2d04 10698 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
10699 break;
10700 case 7:
895c2d04 10701 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
10702 break;
10703 default:
d75c135e 10704 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10705 break;
10706 }
10707 break;
10708 case 10:
10709 switch (sel) {
10710 case 0:
895c2d04 10711 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
10712 break;
10713 default:
d75c135e 10714 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10715 break;
10716 }
0d0304f2 10717 break;
ead9360e
TS
10718 case 12:
10719 switch (sel) {
10720 case 0:
895c2d04 10721 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
10722 break;
10723 default:
d75c135e 10724 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10725 break;
10726 }
0d0304f2 10727 break;
5a25ce94
EI
10728 case 13:
10729 switch (sel) {
10730 case 0:
895c2d04 10731 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
10732 break;
10733 default:
10734 goto die;
10735 break;
10736 }
10737 break;
10738 case 15:
10739 switch (sel) {
10740 case 1:
895c2d04 10741 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10742 break;
10743 default:
10744 goto die;
10745 break;
10746 }
10747 break;
ead9360e
TS
10748 case 23:
10749 switch (sel) {
10750 case 0:
895c2d04 10751 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10752 break;
10753 default:
d75c135e 10754 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10755 break;
10756 }
10757 break;
10758 default:
d75c135e 10759 gen_mtc0(ctx, t0, rd, sel);
ead9360e 10760 }
71375b59
AM
10761 } else {
10762 switch (sel) {
10763 /* GPR registers. */
ead9360e 10764 case 0:
71375b59 10765 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 10766 break;
71375b59 10767 /* Auxiliary CPU registers */
ead9360e 10768 case 1:
71375b59
AM
10769 switch (rd) {
10770 case 0:
10771 gen_helper_0e1i(mttlo, t0, 0);
10772 break;
10773 case 1:
10774 gen_helper_0e1i(mtthi, t0, 0);
10775 break;
10776 case 2:
10777 gen_helper_0e1i(mttacx, t0, 0);
10778 break;
10779 case 4:
10780 gen_helper_0e1i(mttlo, t0, 1);
10781 break;
10782 case 5:
10783 gen_helper_0e1i(mtthi, t0, 1);
10784 break;
10785 case 6:
10786 gen_helper_0e1i(mttacx, t0, 1);
10787 break;
10788 case 8:
10789 gen_helper_0e1i(mttlo, t0, 2);
10790 break;
10791 case 9:
10792 gen_helper_0e1i(mtthi, t0, 2);
10793 break;
10794 case 10:
10795 gen_helper_0e1i(mttacx, t0, 2);
10796 break;
10797 case 12:
10798 gen_helper_0e1i(mttlo, t0, 3);
10799 break;
10800 case 13:
10801 gen_helper_0e1i(mtthi, t0, 3);
10802 break;
10803 case 14:
10804 gen_helper_0e1i(mttacx, t0, 3);
10805 break;
10806 case 16:
10807 gen_helper_mttdsp(cpu_env, t0);
10808 break;
10809 default:
10810 goto die;
10811 }
ead9360e 10812 break;
71375b59 10813 /* Floating point (COP1). */
ead9360e 10814 case 2:
71375b59
AM
10815 /* XXX: For now we support only a single FPU context. */
10816 if (h == 0) {
10817 TCGv_i32 fp0 = tcg_temp_new_i32();
10818
10819 tcg_gen_trunc_tl_i32(fp0, t0);
10820 gen_store_fpr32(ctx, fp0, rd);
10821 tcg_temp_free_i32(fp0);
10822 } else {
10823 TCGv_i32 fp0 = tcg_temp_new_i32();
10824
10825 tcg_gen_trunc_tl_i32(fp0, t0);
10826 gen_store_fpr32h(ctx, fp0, rd);
10827 tcg_temp_free_i32(fp0);
10828 }
ead9360e 10829 break;
71375b59
AM
10830 case 3:
10831 /* XXX: For now we support only a single FPU context. */
10832 {
10833 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10834
10835 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10836 tcg_temp_free_i32(fs_tmp);
10837 }
10838 /* Stop translation as we may have changed hflags */
10839 ctx->base.is_jmp = DISAS_STOP;
ead9360e 10840 break;
71375b59
AM
10841 /* COP2: Not implemented. */
10842 case 4:
ead9360e 10843 case 5:
71375b59 10844 /* fall through */
ead9360e
TS
10845 default:
10846 goto die;
10847 }
ead9360e 10848 }
b44a7fb1 10849 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10850 tcg_temp_free(t0);
ead9360e
TS
10851 return;
10852
10853die:
1a3fd9c3 10854 tcg_temp_free(t0);
d12d51d5 10855 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10856 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10857}
10858
235785e8
AM
10859static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10860 int rt, int rd)
6af0bf9c 10861{
287c4b84 10862 const char *opn = "ldst";
6af0bf9c 10863
2e15497c 10864 check_cp0_enabled(ctx);
6af0bf9c
FB
10865 switch (opc) {
10866 case OPC_MFC0:
10867 if (rt == 0) {
ead9360e 10868 /* Treat as NOP. */
6af0bf9c
FB
10869 return;
10870 }
d75c135e 10871 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10872 opn = "mfc0";
10873 break;
10874 case OPC_MTC0:
1a3fd9c3 10875 {
1fc7bf6e 10876 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10877
10878 gen_load_gpr(t0, rt);
d75c135e 10879 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10880 tcg_temp_free(t0);
10881 }
6af0bf9c
FB
10882 opn = "mtc0";
10883 break;
d26bc211 10884#if defined(TARGET_MIPS64)
9c2149c8 10885 case OPC_DMFC0:
d75c135e 10886 check_insn(ctx, ISA_MIPS3);
9c2149c8 10887 if (rt == 0) {
ead9360e 10888 /* Treat as NOP. */
9c2149c8
TS
10889 return;
10890 }
d75c135e 10891 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10892 opn = "dmfc0";
10893 break;
10894 case OPC_DMTC0:
d75c135e 10895 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10896 {
1fc7bf6e 10897 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10898
10899 gen_load_gpr(t0, rt);
d75c135e 10900 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10901 tcg_temp_free(t0);
10902 }
9c2149c8
TS
10903 opn = "dmtc0";
10904 break;
534ce69f 10905#endif
5204ea79
LA
10906 case OPC_MFHC0:
10907 check_mvh(ctx);
10908 if (rt == 0) {
10909 /* Treat as NOP. */
10910 return;
10911 }
10912 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10913 opn = "mfhc0";
10914 break;
10915 case OPC_MTHC0:
10916 check_mvh(ctx);
10917 {
10918 TCGv t0 = tcg_temp_new();
10919 gen_load_gpr(t0, rt);
10920 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10921 tcg_temp_free(t0);
10922 }
10923 opn = "mthc0";
10924 break;
ead9360e 10925 case OPC_MFTR:
9affc1c5 10926 check_cp0_enabled(ctx);
ead9360e
TS
10927 if (rd == 0) {
10928 /* Treat as NOP. */
10929 return;
10930 }
6c5c1e20 10931 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10932 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10933 opn = "mftr";
10934 break;
10935 case OPC_MTTR:
9affc1c5 10936 check_cp0_enabled(ctx);
6c5c1e20 10937 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10938 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10939 opn = "mttr";
10940 break;
6af0bf9c 10941 case OPC_TLBWI:
6af0bf9c 10942 opn = "tlbwi";
1f8929d2 10943 if (!env->tlb->helper_tlbwi) {
29929e34 10944 goto die;
1f8929d2 10945 }
895c2d04 10946 gen_helper_tlbwi(cpu_env);
6af0bf9c 10947 break;
9456c2fb
LA
10948 case OPC_TLBINV:
10949 opn = "tlbinv";
10950 if (ctx->ie >= 2) {
10951 if (!env->tlb->helper_tlbinv) {
10952 goto die;
10953 }
10954 gen_helper_tlbinv(cpu_env);
10955 } /* treat as nop if TLBINV not supported */
10956 break;
10957 case OPC_TLBINVF:
10958 opn = "tlbinvf";
10959 if (ctx->ie >= 2) {
10960 if (!env->tlb->helper_tlbinvf) {
10961 goto die;
10962 }
10963 gen_helper_tlbinvf(cpu_env);
10964 } /* treat as nop if TLBINV not supported */
10965 break;
6af0bf9c 10966 case OPC_TLBWR:
6af0bf9c 10967 opn = "tlbwr";
1f8929d2 10968 if (!env->tlb->helper_tlbwr) {
29929e34 10969 goto die;
1f8929d2 10970 }
895c2d04 10971 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10972 break;
10973 case OPC_TLBP:
6af0bf9c 10974 opn = "tlbp";
1f8929d2 10975 if (!env->tlb->helper_tlbp) {
29929e34 10976 goto die;
1f8929d2 10977 }
895c2d04 10978 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10979 break;
10980 case OPC_TLBR:
6af0bf9c 10981 opn = "tlbr";
1f8929d2 10982 if (!env->tlb->helper_tlbr) {
29929e34 10983 goto die;
1f8929d2 10984 }
895c2d04 10985 gen_helper_tlbr(cpu_env);
6af0bf9c 10986 break;
ce9782f4 10987 case OPC_ERET: /* OPC_ERETNC */
2e211e0a 10988 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 10989 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10990 goto die;
ce9782f4
LA
10991 } else {
10992 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10993 if (ctx->opcode & (1 << bit_shift)) {
10994 /* OPC_ERETNC */
10995 opn = "eretnc";
5f89ce4f 10996 check_insn(ctx, ISA_MIPS_R5);
ce9782f4
LA
10997 gen_helper_eretnc(cpu_env);
10998 } else {
10999 /* OPC_ERET */
11000 opn = "eret";
11001 check_insn(ctx, ISA_MIPS2);
11002 gen_helper_eret(cpu_env);
11003 }
eeb3bba8 11004 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 11005 }
6af0bf9c
FB
11006 break;
11007 case OPC_DERET:
11008 opn = "deret";
bbd5e4a2 11009 check_insn(ctx, ISA_MIPS_R1);
2e211e0a 11010 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 11011 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
11012 goto die;
11013 }
6af0bf9c 11014 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 11015 MIPS_INVAL(opn);
9c708c7f 11016 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 11017 } else {
895c2d04 11018 gen_helper_deret(cpu_env);
eeb3bba8 11019 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
11020 }
11021 break;
4ad40f36
FB
11022 case OPC_WAIT:
11023 opn = "wait";
bbd5e4a2 11024 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
2e211e0a 11025 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 11026 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
11027 goto die;
11028 }
4ad40f36 11029 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 11030 ctx->base.pc_next += 4;
4ad40f36 11031 save_cpu_state(ctx, 1);
eeb3bba8 11032 ctx->base.pc_next -= 4;
895c2d04 11033 gen_helper_wait(cpu_env);
eeb3bba8 11034 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 11035 break;
6af0bf9c 11036 default:
29929e34 11037 die:
923617a3 11038 MIPS_INVAL(opn);
9c708c7f 11039 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
11040 return;
11041 }
2abf314d 11042 (void)opn; /* avoid a compiler warning */
6af0bf9c 11043}
f1aa6320 11044#endif /* !CONFIG_USER_ONLY */
6af0bf9c 11045
6ea83fed 11046/* CP1 Branches (before delay slot) */
d75c135e
AJ
11047static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
11048 int32_t cc, int32_t offset)
6ea83fed
FB
11049{
11050 target_ulong btarget;
a7812ae4 11051 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 11052
2e211e0a 11053 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 11054 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
11055 goto out;
11056 }
11057
1f8929d2 11058 if (cc != 0) {
bbd5e4a2 11059 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
1f8929d2 11060 }
e189e748 11061
eeb3bba8 11062 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 11063
7a387fff
TS
11064 switch (op) {
11065 case OPC_BC1F:
d94536f4
AJ
11066 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11067 tcg_gen_not_i32(t0, t0);
11068 tcg_gen_andi_i32(t0, t0, 1);
11069 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 11070 goto not_likely;
7a387fff 11071 case OPC_BC1FL:
d94536f4
AJ
11072 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11073 tcg_gen_not_i32(t0, t0);
11074 tcg_gen_andi_i32(t0, t0, 1);
11075 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 11076 goto likely;
7a387fff 11077 case OPC_BC1T:
d94536f4
AJ
11078 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11079 tcg_gen_andi_i32(t0, t0, 1);
11080 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 11081 goto not_likely;
7a387fff 11082 case OPC_BC1TL:
d94536f4
AJ
11083 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11084 tcg_gen_andi_i32(t0, t0, 1);
11085 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
11086 likely:
11087 ctx->hflags |= MIPS_HFLAG_BL;
11088 break;
5a5012ec 11089 case OPC_BC1FANY2:
a16336e4 11090 {
d94536f4
AJ
11091 TCGv_i32 t1 = tcg_temp_new_i32();
11092 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 11093 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 11094 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 11095 tcg_temp_free_i32(t1);
d94536f4
AJ
11096 tcg_gen_andi_i32(t0, t0, 1);
11097 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 11098 }
5a5012ec
TS
11099 goto not_likely;
11100 case OPC_BC1TANY2:
a16336e4 11101 {
d94536f4
AJ
11102 TCGv_i32 t1 = tcg_temp_new_i32();
11103 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 11104 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
11105 tcg_gen_or_i32(t0, t0, t1);
11106 tcg_temp_free_i32(t1);
11107 tcg_gen_andi_i32(t0, t0, 1);
11108 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 11109 }
5a5012ec
TS
11110 goto not_likely;
11111 case OPC_BC1FANY4:
a16336e4 11112 {
d94536f4
AJ
11113 TCGv_i32 t1 = tcg_temp_new_i32();
11114 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 11115 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 11116 tcg_gen_and_i32(t0, t0, t1);
71375b59 11117 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 11118 tcg_gen_and_i32(t0, t0, t1);
71375b59 11119 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 11120 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 11121 tcg_temp_free_i32(t1);
d94536f4
AJ
11122 tcg_gen_andi_i32(t0, t0, 1);
11123 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 11124 }
5a5012ec
TS
11125 goto not_likely;
11126 case OPC_BC1TANY4:
a16336e4 11127 {
d94536f4
AJ
11128 TCGv_i32 t1 = tcg_temp_new_i32();
11129 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 11130 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 11131 tcg_gen_or_i32(t0, t0, t1);
71375b59 11132 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 11133 tcg_gen_or_i32(t0, t0, t1);
71375b59 11134 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
11135 tcg_gen_or_i32(t0, t0, t1);
11136 tcg_temp_free_i32(t1);
11137 tcg_gen_andi_i32(t0, t0, 1);
11138 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 11139 }
5a5012ec
TS
11140 not_likely:
11141 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
11142 break;
11143 default:
9d68ac14 11144 MIPS_INVAL("cp1 cond branch");
9c708c7f 11145 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 11146 goto out;
6ea83fed 11147 }
6ea83fed 11148 ctx->btarget = btarget;
b231c103 11149 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 11150 out:
a7812ae4 11151 tcg_temp_free_i32(t0);
6ea83fed
FB
11152}
11153
31837be3
YK
11154/* R6 CP1 Branches */
11155static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
11156 int32_t ft, int32_t offset,
11157 int delayslot_size)
31837be3
YK
11158{
11159 target_ulong btarget;
31837be3
YK
11160 TCGv_i64 t0 = tcg_temp_new_i64();
11161
11162 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11163#ifdef MIPS_DEBUG_DISAS
339cd2a8 11164 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 11165 "\n", ctx->base.pc_next);
31837be3 11166#endif
9c708c7f 11167 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
11168 goto out;
11169 }
11170
11171 gen_load_fpr64(ctx, t0, ft);
11172 tcg_gen_andi_i64(t0, t0, 1);
11173
eeb3bba8 11174 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
11175
11176 switch (op) {
11177 case OPC_BC1EQZ:
11178 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
11179 ctx->hflags |= MIPS_HFLAG_BC;
11180 break;
11181 case OPC_BC1NEZ:
11182 /* t0 already set */
31837be3
YK
11183 ctx->hflags |= MIPS_HFLAG_BC;
11184 break;
11185 default:
9d68ac14 11186 MIPS_INVAL("cp1 cond branch");
9c708c7f 11187 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
11188 goto out;
11189 }
11190
11191 tcg_gen_trunc_i64_tl(bcond, t0);
11192
31837be3 11193 ctx->btarget = btarget;
65935f07
YK
11194
11195 switch (delayslot_size) {
11196 case 2:
11197 ctx->hflags |= MIPS_HFLAG_BDS16;
11198 break;
11199 case 4:
11200 ctx->hflags |= MIPS_HFLAG_BDS32;
11201 break;
11202 }
31837be3
YK
11203
11204out:
11205 tcg_temp_free_i64(t0);
11206}
11207
6af0bf9c 11208/* Coprocessor 1 (FPU) */
5a5012ec 11209
5a5012ec
TS
11210#define FOP(func, fmt) (((fmt) << 21) | (func))
11211
bf4120ad
NF
11212enum fopcode {
11213 OPC_ADD_S = FOP(0, FMT_S),
11214 OPC_SUB_S = FOP(1, FMT_S),
11215 OPC_MUL_S = FOP(2, FMT_S),
11216 OPC_DIV_S = FOP(3, FMT_S),
11217 OPC_SQRT_S = FOP(4, FMT_S),
11218 OPC_ABS_S = FOP(5, FMT_S),
11219 OPC_MOV_S = FOP(6, FMT_S),
11220 OPC_NEG_S = FOP(7, FMT_S),
11221 OPC_ROUND_L_S = FOP(8, FMT_S),
11222 OPC_TRUNC_L_S = FOP(9, FMT_S),
11223 OPC_CEIL_L_S = FOP(10, FMT_S),
11224 OPC_FLOOR_L_S = FOP(11, FMT_S),
11225 OPC_ROUND_W_S = FOP(12, FMT_S),
11226 OPC_TRUNC_W_S = FOP(13, FMT_S),
11227 OPC_CEIL_W_S = FOP(14, FMT_S),
11228 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 11229 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
11230 OPC_MOVCF_S = FOP(17, FMT_S),
11231 OPC_MOVZ_S = FOP(18, FMT_S),
11232 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 11233 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
11234 OPC_RECIP_S = FOP(21, FMT_S),
11235 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
11236 OPC_SELNEZ_S = FOP(23, FMT_S),
11237 OPC_MADDF_S = FOP(24, FMT_S),
11238 OPC_MSUBF_S = FOP(25, FMT_S),
11239 OPC_RINT_S = FOP(26, FMT_S),
11240 OPC_CLASS_S = FOP(27, FMT_S),
11241 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 11242 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 11243 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 11244 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 11245 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 11246 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 11247 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
11248 OPC_RSQRT2_S = FOP(31, FMT_S),
11249 OPC_CVT_D_S = FOP(33, FMT_S),
11250 OPC_CVT_W_S = FOP(36, FMT_S),
11251 OPC_CVT_L_S = FOP(37, FMT_S),
11252 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
11253 OPC_CMP_F_S = FOP(48, FMT_S),
11254 OPC_CMP_UN_S = FOP(49, FMT_S),
11255 OPC_CMP_EQ_S = FOP(50, FMT_S),
11256 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11257 OPC_CMP_OLT_S = FOP(52, FMT_S),
11258 OPC_CMP_ULT_S = FOP(53, FMT_S),
11259 OPC_CMP_OLE_S = FOP(54, FMT_S),
11260 OPC_CMP_ULE_S = FOP(55, FMT_S),
11261 OPC_CMP_SF_S = FOP(56, FMT_S),
11262 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11263 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11264 OPC_CMP_NGL_S = FOP(59, FMT_S),
11265 OPC_CMP_LT_S = FOP(60, FMT_S),
11266 OPC_CMP_NGE_S = FOP(61, FMT_S),
11267 OPC_CMP_LE_S = FOP(62, FMT_S),
11268 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
11269
11270 OPC_ADD_D = FOP(0, FMT_D),
11271 OPC_SUB_D = FOP(1, FMT_D),
11272 OPC_MUL_D = FOP(2, FMT_D),
11273 OPC_DIV_D = FOP(3, FMT_D),
11274 OPC_SQRT_D = FOP(4, FMT_D),
11275 OPC_ABS_D = FOP(5, FMT_D),
11276 OPC_MOV_D = FOP(6, FMT_D),
11277 OPC_NEG_D = FOP(7, FMT_D),
11278 OPC_ROUND_L_D = FOP(8, FMT_D),
11279 OPC_TRUNC_L_D = FOP(9, FMT_D),
11280 OPC_CEIL_L_D = FOP(10, FMT_D),
11281 OPC_FLOOR_L_D = FOP(11, FMT_D),
11282 OPC_ROUND_W_D = FOP(12, FMT_D),
11283 OPC_TRUNC_W_D = FOP(13, FMT_D),
11284 OPC_CEIL_W_D = FOP(14, FMT_D),
11285 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 11286 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
11287 OPC_MOVCF_D = FOP(17, FMT_D),
11288 OPC_MOVZ_D = FOP(18, FMT_D),
11289 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 11290 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
11291 OPC_RECIP_D = FOP(21, FMT_D),
11292 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
11293 OPC_SELNEZ_D = FOP(23, FMT_D),
11294 OPC_MADDF_D = FOP(24, FMT_D),
11295 OPC_MSUBF_D = FOP(25, FMT_D),
11296 OPC_RINT_D = FOP(26, FMT_D),
11297 OPC_CLASS_D = FOP(27, FMT_D),
11298 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 11299 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 11300 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 11301 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 11302 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 11303 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 11304 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
11305 OPC_RSQRT2_D = FOP(31, FMT_D),
11306 OPC_CVT_S_D = FOP(32, FMT_D),
11307 OPC_CVT_W_D = FOP(36, FMT_D),
11308 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
11309 OPC_CMP_F_D = FOP(48, FMT_D),
11310 OPC_CMP_UN_D = FOP(49, FMT_D),
11311 OPC_CMP_EQ_D = FOP(50, FMT_D),
11312 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11313 OPC_CMP_OLT_D = FOP(52, FMT_D),
11314 OPC_CMP_ULT_D = FOP(53, FMT_D),
11315 OPC_CMP_OLE_D = FOP(54, FMT_D),
11316 OPC_CMP_ULE_D = FOP(55, FMT_D),
11317 OPC_CMP_SF_D = FOP(56, FMT_D),
11318 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11319 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11320 OPC_CMP_NGL_D = FOP(59, FMT_D),
11321 OPC_CMP_LT_D = FOP(60, FMT_D),
11322 OPC_CMP_NGE_D = FOP(61, FMT_D),
11323 OPC_CMP_LE_D = FOP(62, FMT_D),
11324 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
11325
11326 OPC_CVT_S_W = FOP(32, FMT_W),
11327 OPC_CVT_D_W = FOP(33, FMT_W),
11328 OPC_CVT_S_L = FOP(32, FMT_L),
11329 OPC_CVT_D_L = FOP(33, FMT_L),
11330 OPC_CVT_PS_PW = FOP(38, FMT_W),
11331
11332 OPC_ADD_PS = FOP(0, FMT_PS),
11333 OPC_SUB_PS = FOP(1, FMT_PS),
11334 OPC_MUL_PS = FOP(2, FMT_PS),
11335 OPC_DIV_PS = FOP(3, FMT_PS),
11336 OPC_ABS_PS = FOP(5, FMT_PS),
11337 OPC_MOV_PS = FOP(6, FMT_PS),
11338 OPC_NEG_PS = FOP(7, FMT_PS),
11339 OPC_MOVCF_PS = FOP(17, FMT_PS),
11340 OPC_MOVZ_PS = FOP(18, FMT_PS),
11341 OPC_MOVN_PS = FOP(19, FMT_PS),
11342 OPC_ADDR_PS = FOP(24, FMT_PS),
11343 OPC_MULR_PS = FOP(26, FMT_PS),
11344 OPC_RECIP2_PS = FOP(28, FMT_PS),
11345 OPC_RECIP1_PS = FOP(29, FMT_PS),
11346 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11347 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11348
11349 OPC_CVT_S_PU = FOP(32, FMT_PS),
11350 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11351 OPC_CVT_S_PL = FOP(40, FMT_PS),
11352 OPC_PLL_PS = FOP(44, FMT_PS),
11353 OPC_PLU_PS = FOP(45, FMT_PS),
11354 OPC_PUL_PS = FOP(46, FMT_PS),
11355 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
11356 OPC_CMP_F_PS = FOP(48, FMT_PS),
11357 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11358 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11359 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11360 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11361 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11362 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11363 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11364 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11365 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11366 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11367 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11368 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11369 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11370 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11371 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
11372};
11373
3f493883
YK
11374enum r6_f_cmp_op {
11375 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11376 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11377 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11378 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11379 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11380 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11381 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11382 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11383 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11384 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11385 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11386 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11387 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11388 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11389 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11390 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11391 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11392 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11393 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11394 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11395 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11396 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11397
11398 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11399 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11400 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11401 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11402 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11403 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11404 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11405 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11406 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11407 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11408 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11409 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11410 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11411 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11412 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11413 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11414 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11415 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11416 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11417 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11418 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11419 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11420};
235785e8
AM
11421
11422static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 11423{
72c3a3ee 11424 TCGv t0 = tcg_temp_new();
6ea83fed
FB
11425
11426 switch (opc) {
11427 case OPC_MFC1:
b6d96bed 11428 {
a7812ae4 11429 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11430
7c979afd 11431 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 11432 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 11433 tcg_temp_free_i32(fp0);
6958549d 11434 }
6c5c1e20 11435 gen_store_gpr(t0, rt);
6ea83fed
FB
11436 break;
11437 case OPC_MTC1:
6c5c1e20 11438 gen_load_gpr(t0, rt);
b6d96bed 11439 {
a7812ae4 11440 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
11441
11442 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 11443 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 11444 tcg_temp_free_i32(fp0);
6958549d 11445 }
6ea83fed
FB
11446 break;
11447 case OPC_CFC1:
895c2d04 11448 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 11449 gen_store_gpr(t0, rt);
6ea83fed
FB
11450 break;
11451 case OPC_CTC1:
6c5c1e20 11452 gen_load_gpr(t0, rt);
9c708c7f 11453 save_cpu_state(ctx, 0);
736d120a
PJ
11454 {
11455 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11456
11457 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11458 tcg_temp_free_i32(fs_tmp);
11459 }
4cf8a45f 11460 /* Stop translation as we may have changed hflags */
eeb3bba8 11461 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 11462 break;
72c3a3ee 11463#if defined(TARGET_MIPS64)
9c2149c8 11464 case OPC_DMFC1:
72c3a3ee 11465 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 11466 gen_store_gpr(t0, rt);
5a5012ec 11467 break;
9c2149c8 11468 case OPC_DMTC1:
6c5c1e20 11469 gen_load_gpr(t0, rt);
72c3a3ee 11470 gen_store_fpr64(ctx, t0, fs);
5a5012ec 11471 break;
72c3a3ee 11472#endif
5a5012ec 11473 case OPC_MFHC1:
b6d96bed 11474 {
a7812ae4 11475 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11476
7f6613ce 11477 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 11478 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 11479 tcg_temp_free_i32(fp0);
6958549d 11480 }
6c5c1e20 11481 gen_store_gpr(t0, rt);
5a5012ec
TS
11482 break;
11483 case OPC_MTHC1:
6c5c1e20 11484 gen_load_gpr(t0, rt);
b6d96bed 11485 {
a7812ae4 11486 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
11487
11488 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 11489 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 11490 tcg_temp_free_i32(fp0);
6958549d 11491 }
5a5012ec 11492 break;
6ea83fed 11493 default:
9d68ac14 11494 MIPS_INVAL("cp1 move");
9c708c7f 11495 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 11496 goto out;
6ea83fed 11497 }
6c5c1e20
TS
11498
11499 out:
11500 tcg_temp_free(t0);
6ea83fed
FB
11501}
11502
235785e8 11503static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 11504{
42a268c2 11505 TCGLabel *l1;
e214b9bb 11506 TCGCond cond;
af58f9ca
AJ
11507 TCGv_i32 t0;
11508
11509 if (rd == 0) {
11510 /* Treat as NOP. */
11511 return;
11512 }
6ea83fed 11513
1f8929d2 11514 if (tf) {
e214b9bb 11515 cond = TCG_COND_EQ;
1f8929d2 11516 } else {
27848470 11517 cond = TCG_COND_NE;
1f8929d2 11518 }
27848470 11519
af58f9ca
AJ
11520 l1 = gen_new_label();
11521 t0 = tcg_temp_new_i32();
fa31af0e 11522 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 11523 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11524 tcg_temp_free_i32(t0);
af58f9ca
AJ
11525 if (rs == 0) {
11526 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11527 } else {
11528 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11529 }
e214b9bb 11530 gen_set_label(l1);
5a5012ec
TS
11531}
11532
7c979afd
LA
11533static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11534 int tf)
a16336e4 11535{
a16336e4 11536 int cond;
cbc37b28 11537 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 11538 TCGLabel *l1 = gen_new_label();
a16336e4 11539
1f8929d2 11540 if (tf) {
a16336e4 11541 cond = TCG_COND_EQ;
1f8929d2 11542 } else {
a16336e4 11543 cond = TCG_COND_NE;
1f8929d2 11544 }
a16336e4 11545
fa31af0e 11546 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11547 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11548 gen_load_fpr32(ctx, t0, fs);
11549 gen_store_fpr32(ctx, t0, fd);
a16336e4 11550 gen_set_label(l1);
cbc37b28 11551 tcg_temp_free_i32(t0);
5a5012ec 11552}
a16336e4 11553
235785e8
AM
11554static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11555 int tf)
a16336e4 11556{
a16336e4 11557 int cond;
cbc37b28
AJ
11558 TCGv_i32 t0 = tcg_temp_new_i32();
11559 TCGv_i64 fp0;
42a268c2 11560 TCGLabel *l1 = gen_new_label();
a16336e4 11561
1f8929d2 11562 if (tf) {
a16336e4 11563 cond = TCG_COND_EQ;
1f8929d2 11564 } else {
a16336e4 11565 cond = TCG_COND_NE;
1f8929d2 11566 }
a16336e4 11567
fa31af0e 11568 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11569 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 11570 tcg_temp_free_i32(t0);
11f94258 11571 fp0 = tcg_temp_new_i64();
9bf3eb2c 11572 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 11573 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11574 tcg_temp_free_i64(fp0);
cbc37b28 11575 gen_set_label(l1);
a16336e4
TS
11576}
11577
7f6613ce
PJ
11578static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11579 int cc, int tf)
a16336e4
TS
11580{
11581 int cond;
cbc37b28 11582 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
11583 TCGLabel *l1 = gen_new_label();
11584 TCGLabel *l2 = gen_new_label();
a16336e4 11585
1f8929d2 11586 if (tf) {
a16336e4 11587 cond = TCG_COND_EQ;
1f8929d2 11588 } else {
a16336e4 11589 cond = TCG_COND_NE;
1f8929d2 11590 }
a16336e4 11591
fa31af0e 11592 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 11593 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
11594 gen_load_fpr32(ctx, t0, fs);
11595 gen_store_fpr32(ctx, t0, fd);
a16336e4 11596 gen_set_label(l1);
9bf3eb2c 11597
71375b59 11598 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 11599 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
11600 gen_load_fpr32h(ctx, t0, fs);
11601 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 11602 tcg_temp_free_i32(t0);
a16336e4 11603 gen_set_label(l2);
a16336e4
TS
11604}
11605
e7f16abb
LA
11606static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11607 int fs)
11608{
11609 TCGv_i32 t1 = tcg_const_i32(0);
11610 TCGv_i32 fp0 = tcg_temp_new_i32();
11611 TCGv_i32 fp1 = tcg_temp_new_i32();
11612 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11613 gen_load_fpr32(ctx, fp0, fd);
11614 gen_load_fpr32(ctx, fp1, ft);
11615 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
11616
11617 switch (op1) {
11618 case OPC_SEL_S:
11619 tcg_gen_andi_i32(fp0, fp0, 1);
11620 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11621 break;
11622 case OPC_SELEQZ_S:
11623 tcg_gen_andi_i32(fp1, fp1, 1);
11624 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11625 break;
11626 case OPC_SELNEZ_S:
11627 tcg_gen_andi_i32(fp1, fp1, 1);
11628 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11629 break;
11630 default:
11631 MIPS_INVAL("gen_sel_s");
9c708c7f 11632 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11633 break;
11634 }
11635
7c979afd 11636 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11637 tcg_temp_free_i32(fp2);
11638 tcg_temp_free_i32(fp1);
11639 tcg_temp_free_i32(fp0);
11640 tcg_temp_free_i32(t1);
11641}
11642
11643static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11644 int fs)
11645{
11646 TCGv_i64 t1 = tcg_const_i64(0);
11647 TCGv_i64 fp0 = tcg_temp_new_i64();
11648 TCGv_i64 fp1 = tcg_temp_new_i64();
11649 TCGv_i64 fp2 = tcg_temp_new_i64();
11650 gen_load_fpr64(ctx, fp0, fd);
11651 gen_load_fpr64(ctx, fp1, ft);
11652 gen_load_fpr64(ctx, fp2, fs);
11653
11654 switch (op1) {
11655 case OPC_SEL_D:
11656 tcg_gen_andi_i64(fp0, fp0, 1);
11657 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11658 break;
11659 case OPC_SELEQZ_D:
11660 tcg_gen_andi_i64(fp1, fp1, 1);
11661 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11662 break;
11663 case OPC_SELNEZ_D:
11664 tcg_gen_andi_i64(fp1, fp1, 1);
11665 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11666 break;
11667 default:
11668 MIPS_INVAL("gen_sel_d");
9c708c7f 11669 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
11670 break;
11671 }
11672
11673 gen_store_fpr64(ctx, fp0, fd);
11674 tcg_temp_free_i64(fp2);
11675 tcg_temp_free_i64(fp1);
11676 tcg_temp_free_i64(fp0);
11677 tcg_temp_free_i64(t1);
11678}
6ea83fed 11679
235785e8
AM
11680static void gen_farith(DisasContext *ctx, enum fopcode op1,
11681 int ft, int fs, int fd, int cc)
6ea83fed 11682{
7a387fff 11683 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
11684 switch (op1) {
11685 case OPC_ADD_S:
b6d96bed 11686 {
a7812ae4
PB
11687 TCGv_i32 fp0 = tcg_temp_new_i32();
11688 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11689
7c979afd
LA
11690 gen_load_fpr32(ctx, fp0, fs);
11691 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11692 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11693 tcg_temp_free_i32(fp1);
7c979afd 11694 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11695 tcg_temp_free_i32(fp0);
b6d96bed 11696 }
5a5012ec 11697 break;
bf4120ad 11698 case OPC_SUB_S:
b6d96bed 11699 {
a7812ae4
PB
11700 TCGv_i32 fp0 = tcg_temp_new_i32();
11701 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11702
7c979afd
LA
11703 gen_load_fpr32(ctx, fp0, fs);
11704 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11705 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11706 tcg_temp_free_i32(fp1);
7c979afd 11707 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11708 tcg_temp_free_i32(fp0);
b6d96bed 11709 }
5a5012ec 11710 break;
bf4120ad 11711 case OPC_MUL_S:
b6d96bed 11712 {
a7812ae4
PB
11713 TCGv_i32 fp0 = tcg_temp_new_i32();
11714 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11715
7c979afd
LA
11716 gen_load_fpr32(ctx, fp0, fs);
11717 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11718 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11719 tcg_temp_free_i32(fp1);
7c979afd 11720 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11721 tcg_temp_free_i32(fp0);
b6d96bed 11722 }
5a5012ec 11723 break;
bf4120ad 11724 case OPC_DIV_S:
b6d96bed 11725 {
a7812ae4
PB
11726 TCGv_i32 fp0 = tcg_temp_new_i32();
11727 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11728
7c979afd
LA
11729 gen_load_fpr32(ctx, fp0, fs);
11730 gen_load_fpr32(ctx, fp1, ft);
895c2d04 11731 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 11732 tcg_temp_free_i32(fp1);
7c979afd 11733 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11734 tcg_temp_free_i32(fp0);
b6d96bed 11735 }
5a5012ec 11736 break;
bf4120ad 11737 case OPC_SQRT_S:
b6d96bed 11738 {
a7812ae4 11739 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11740
7c979afd 11741 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11742 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 11743 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11744 tcg_temp_free_i32(fp0);
b6d96bed 11745 }
5a5012ec 11746 break;
bf4120ad 11747 case OPC_ABS_S:
b6d96bed 11748 {
a7812ae4 11749 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11750
7c979afd 11751 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11752 if (ctx->abs2008) {
11753 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11754 } else {
11755 gen_helper_float_abs_s(fp0, fp0);
11756 }
7c979afd 11757 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11758 tcg_temp_free_i32(fp0);
b6d96bed 11759 }
5a5012ec 11760 break;
bf4120ad 11761 case OPC_MOV_S:
b6d96bed 11762 {
a7812ae4 11763 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11764
7c979afd
LA
11765 gen_load_fpr32(ctx, fp0, fs);
11766 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11767 tcg_temp_free_i32(fp0);
b6d96bed 11768 }
5a5012ec 11769 break;
bf4120ad 11770 case OPC_NEG_S:
b6d96bed 11771 {
a7812ae4 11772 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11773
7c979afd 11774 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11775 if (ctx->abs2008) {
11776 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11777 } else {
11778 gen_helper_float_chs_s(fp0, fp0);
11779 }
7c979afd 11780 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11781 tcg_temp_free_i32(fp0);
b6d96bed 11782 }
5a5012ec 11783 break;
bf4120ad 11784 case OPC_ROUND_L_S:
5e755519 11785 check_cp1_64bitmode(ctx);
b6d96bed 11786 {
a7812ae4
PB
11787 TCGv_i32 fp32 = tcg_temp_new_i32();
11788 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11789
7c979afd 11790 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11791 if (ctx->nan2008) {
11792 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11793 } else {
11794 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11795 }
a7812ae4 11796 tcg_temp_free_i32(fp32);
b6d96bed 11797 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11798 tcg_temp_free_i64(fp64);
b6d96bed 11799 }
5a5012ec 11800 break;
bf4120ad 11801 case OPC_TRUNC_L_S:
5e755519 11802 check_cp1_64bitmode(ctx);
b6d96bed 11803 {
a7812ae4
PB
11804 TCGv_i32 fp32 = tcg_temp_new_i32();
11805 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11806
7c979afd 11807 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11808 if (ctx->nan2008) {
11809 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11810 } else {
11811 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11812 }
a7812ae4 11813 tcg_temp_free_i32(fp32);
b6d96bed 11814 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11815 tcg_temp_free_i64(fp64);
b6d96bed 11816 }
5a5012ec 11817 break;
bf4120ad 11818 case OPC_CEIL_L_S:
5e755519 11819 check_cp1_64bitmode(ctx);
b6d96bed 11820 {
a7812ae4
PB
11821 TCGv_i32 fp32 = tcg_temp_new_i32();
11822 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11823
7c979afd 11824 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11825 if (ctx->nan2008) {
11826 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11827 } else {
11828 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11829 }
a7812ae4 11830 tcg_temp_free_i32(fp32);
b6d96bed 11831 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11832 tcg_temp_free_i64(fp64);
b6d96bed 11833 }
5a5012ec 11834 break;
bf4120ad 11835 case OPC_FLOOR_L_S:
5e755519 11836 check_cp1_64bitmode(ctx);
b6d96bed 11837 {
a7812ae4
PB
11838 TCGv_i32 fp32 = tcg_temp_new_i32();
11839 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11840
7c979afd 11841 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11842 if (ctx->nan2008) {
11843 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11844 } else {
11845 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11846 }
a7812ae4 11847 tcg_temp_free_i32(fp32);
b6d96bed 11848 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11849 tcg_temp_free_i64(fp64);
b6d96bed 11850 }
5a5012ec 11851 break;
bf4120ad 11852 case OPC_ROUND_W_S:
b6d96bed 11853 {
a7812ae4 11854 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11855
7c979afd 11856 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11857 if (ctx->nan2008) {
11858 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11859 } else {
11860 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11861 }
7c979afd 11862 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11863 tcg_temp_free_i32(fp0);
b6d96bed 11864 }
5a5012ec 11865 break;
bf4120ad 11866 case OPC_TRUNC_W_S:
b6d96bed 11867 {
a7812ae4 11868 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11869
7c979afd 11870 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11871 if (ctx->nan2008) {
11872 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11873 } else {
11874 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11875 }
7c979afd 11876 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11877 tcg_temp_free_i32(fp0);
b6d96bed 11878 }
5a5012ec 11879 break;
bf4120ad 11880 case OPC_CEIL_W_S:
b6d96bed 11881 {
a7812ae4 11882 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11883
7c979afd 11884 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11885 if (ctx->nan2008) {
11886 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11887 } else {
11888 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11889 }
7c979afd 11890 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11891 tcg_temp_free_i32(fp0);
b6d96bed 11892 }
5a5012ec 11893 break;
bf4120ad 11894 case OPC_FLOOR_W_S:
b6d96bed 11895 {
a7812ae4 11896 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11897
7c979afd 11898 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11899 if (ctx->nan2008) {
11900 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11901 } else {
11902 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11903 }
7c979afd 11904 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11905 tcg_temp_free_i32(fp0);
b6d96bed 11906 }
5a5012ec 11907 break;
e7f16abb 11908 case OPC_SEL_S:
2e211e0a 11909 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11910 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11911 break;
11912 case OPC_SELEQZ_S:
2e211e0a 11913 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11914 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11915 break;
11916 case OPC_SELNEZ_S:
2e211e0a 11917 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11918 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11919 break;
bf4120ad 11920 case OPC_MOVCF_S:
2e211e0a 11921 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7c979afd 11922 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11923 break;
bf4120ad 11924 case OPC_MOVZ_S:
2e211e0a 11925 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11926 {
42a268c2 11927 TCGLabel *l1 = gen_new_label();
c9297f4d 11928 TCGv_i32 fp0;
a16336e4 11929
c9297f4d
AJ
11930 if (ft != 0) {
11931 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11932 }
11933 fp0 = tcg_temp_new_i32();
7c979afd
LA
11934 gen_load_fpr32(ctx, fp0, fs);
11935 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11936 tcg_temp_free_i32(fp0);
a16336e4
TS
11937 gen_set_label(l1);
11938 }
5a5012ec 11939 break;
bf4120ad 11940 case OPC_MOVN_S:
2e211e0a 11941 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11942 {
42a268c2 11943 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11944 TCGv_i32 fp0;
11945
11946 if (ft != 0) {
11947 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11948 fp0 = tcg_temp_new_i32();
7c979afd
LA
11949 gen_load_fpr32(ctx, fp0, fs);
11950 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11951 tcg_temp_free_i32(fp0);
11952 gen_set_label(l1);
11953 }
a16336e4 11954 }
5a5012ec 11955 break;
bf4120ad 11956 case OPC_RECIP_S:
b6d96bed 11957 {
a7812ae4 11958 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11959
7c979afd 11960 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11961 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11962 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11963 tcg_temp_free_i32(fp0);
b6d96bed 11964 }
57fa1fb3 11965 break;
bf4120ad 11966 case OPC_RSQRT_S:
b6d96bed 11967 {
a7812ae4 11968 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11969
7c979afd 11970 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11971 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11972 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11973 tcg_temp_free_i32(fp0);
b6d96bed 11974 }
57fa1fb3 11975 break;
e7f16abb 11976 case OPC_MADDF_S:
2e211e0a 11977 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11978 {
a7812ae4
PB
11979 TCGv_i32 fp0 = tcg_temp_new_i32();
11980 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11981 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11982 gen_load_fpr32(ctx, fp0, fs);
11983 gen_load_fpr32(ctx, fp1, ft);
11984 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11985 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11986 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11987 tcg_temp_free_i32(fp2);
a7812ae4 11988 tcg_temp_free_i32(fp1);
a7812ae4 11989 tcg_temp_free_i32(fp0);
b6d96bed 11990 }
57fa1fb3 11991 break;
e7f16abb 11992 case OPC_MSUBF_S:
2e211e0a 11993 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11994 {
a7812ae4 11995 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11996 TCGv_i32 fp1 = tcg_temp_new_i32();
11997 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11998 gen_load_fpr32(ctx, fp0, fs);
11999 gen_load_fpr32(ctx, fp1, ft);
12000 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 12001 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 12002 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
12003 tcg_temp_free_i32(fp2);
12004 tcg_temp_free_i32(fp1);
a7812ae4 12005 tcg_temp_free_i32(fp0);
b6d96bed 12006 }
57fa1fb3 12007 break;
e7f16abb 12008 case OPC_RINT_S:
2e211e0a 12009 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12010 {
a7812ae4 12011 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12012 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 12013 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 12014 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12015 tcg_temp_free_i32(fp0);
b6d96bed 12016 }
57fa1fb3 12017 break;
e7f16abb 12018 case OPC_CLASS_S:
2e211e0a 12019 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12020 {
e7f16abb 12021 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12022 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 12023 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 12024 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 12025 tcg_temp_free_i32(fp0);
e7f16abb
LA
12026 }
12027 break;
12028 case OPC_MIN_S: /* OPC_RECIP2_S */
2e211e0a 12029 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 12030 /* OPC_MIN_S */
a7812ae4
PB
12031 TCGv_i32 fp0 = tcg_temp_new_i32();
12032 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 12033 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
12034 gen_load_fpr32(ctx, fp0, fs);
12035 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 12036 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 12037 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
12038 tcg_temp_free_i32(fp2);
12039 tcg_temp_free_i32(fp1);
12040 tcg_temp_free_i32(fp0);
e7f16abb
LA
12041 } else {
12042 /* OPC_RECIP2_S */
12043 check_cp1_64bitmode(ctx);
12044 {
12045 TCGv_i32 fp0 = tcg_temp_new_i32();
12046 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12047
7c979afd
LA
12048 gen_load_fpr32(ctx, fp0, fs);
12049 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
12050 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
12051 tcg_temp_free_i32(fp1);
7c979afd 12052 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
12053 tcg_temp_free_i32(fp0);
12054 }
e7f16abb
LA
12055 }
12056 break;
12057 case OPC_MINA_S: /* OPC_RECIP1_S */
2e211e0a 12058 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12059 /* OPC_MINA_S */
12060 TCGv_i32 fp0 = tcg_temp_new_i32();
12061 TCGv_i32 fp1 = tcg_temp_new_i32();
12062 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
12063 gen_load_fpr32(ctx, fp0, fs);
12064 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 12065 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 12066 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
12067 tcg_temp_free_i32(fp2);
12068 tcg_temp_free_i32(fp1);
12069 tcg_temp_free_i32(fp0);
e7f16abb
LA
12070 } else {
12071 /* OPC_RECIP1_S */
12072 check_cp1_64bitmode(ctx);
12073 {
12074 TCGv_i32 fp0 = tcg_temp_new_i32();
12075
7c979afd 12076 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 12077 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 12078 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
12079 tcg_temp_free_i32(fp0);
12080 }
e7f16abb
LA
12081 }
12082 break;
12083 case OPC_MAX_S: /* OPC_RSQRT1_S */
2e211e0a 12084 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12085 /* OPC_MAX_S */
12086 TCGv_i32 fp0 = tcg_temp_new_i32();
12087 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
12088 gen_load_fpr32(ctx, fp0, fs);
12089 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 12090 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 12091 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
12092 tcg_temp_free_i32(fp1);
12093 tcg_temp_free_i32(fp0);
e7f16abb
LA
12094 } else {
12095 /* OPC_RSQRT1_S */
12096 check_cp1_64bitmode(ctx);
12097 {
12098 TCGv_i32 fp0 = tcg_temp_new_i32();
12099
7c979afd 12100 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 12101 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 12102 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
12103 tcg_temp_free_i32(fp0);
12104 }
e7f16abb
LA
12105 }
12106 break;
12107 case OPC_MAXA_S: /* OPC_RSQRT2_S */
2e211e0a 12108 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12109 /* OPC_MAXA_S */
12110 TCGv_i32 fp0 = tcg_temp_new_i32();
12111 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
12112 gen_load_fpr32(ctx, fp0, fs);
12113 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 12114 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 12115 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 12116 tcg_temp_free_i32(fp1);
a7812ae4 12117 tcg_temp_free_i32(fp0);
e7f16abb
LA
12118 } else {
12119 /* OPC_RSQRT2_S */
12120 check_cp1_64bitmode(ctx);
12121 {
12122 TCGv_i32 fp0 = tcg_temp_new_i32();
12123 TCGv_i32 fp1 = tcg_temp_new_i32();
12124
7c979afd
LA
12125 gen_load_fpr32(ctx, fp0, fs);
12126 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
12127 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12128 tcg_temp_free_i32(fp1);
7c979afd 12129 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
12130 tcg_temp_free_i32(fp0);
12131 }
b6d96bed 12132 }
57fa1fb3 12133 break;
bf4120ad 12134 case OPC_CVT_D_S:
5e755519 12135 check_cp1_registers(ctx, fd);
b6d96bed 12136 {
a7812ae4
PB
12137 TCGv_i32 fp32 = tcg_temp_new_i32();
12138 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12139
7c979afd 12140 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12141 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 12142 tcg_temp_free_i32(fp32);
b6d96bed 12143 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12144 tcg_temp_free_i64(fp64);
b6d96bed 12145 }
5a5012ec 12146 break;
bf4120ad 12147 case OPC_CVT_W_S:
b6d96bed 12148 {
a7812ae4 12149 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12150
7c979afd 12151 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
12152 if (ctx->nan2008) {
12153 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12154 } else {
12155 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12156 }
7c979afd 12157 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12158 tcg_temp_free_i32(fp0);
b6d96bed 12159 }
5a5012ec 12160 break;
bf4120ad 12161 case OPC_CVT_L_S:
5e755519 12162 check_cp1_64bitmode(ctx);
b6d96bed 12163 {
a7812ae4
PB
12164 TCGv_i32 fp32 = tcg_temp_new_i32();
12165 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12166
7c979afd 12167 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
12168 if (ctx->nan2008) {
12169 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12170 } else {
12171 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12172 }
a7812ae4 12173 tcg_temp_free_i32(fp32);
b6d96bed 12174 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12175 tcg_temp_free_i64(fp64);
b6d96bed 12176 }
5a5012ec 12177 break;
bf4120ad 12178 case OPC_CVT_PS_S:
e29c9628 12179 check_ps(ctx);
b6d96bed 12180 {
a7812ae4
PB
12181 TCGv_i64 fp64 = tcg_temp_new_i64();
12182 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12183 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 12184
7c979afd
LA
12185 gen_load_fpr32(ctx, fp32_0, fs);
12186 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 12187 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
12188 tcg_temp_free_i32(fp32_1);
12189 tcg_temp_free_i32(fp32_0);
36aa55dc 12190 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12191 tcg_temp_free_i64(fp64);
b6d96bed 12192 }
5a5012ec 12193 break;
bf4120ad
NF
12194 case OPC_CMP_F_S:
12195 case OPC_CMP_UN_S:
12196 case OPC_CMP_EQ_S:
12197 case OPC_CMP_UEQ_S:
12198 case OPC_CMP_OLT_S:
12199 case OPC_CMP_ULT_S:
12200 case OPC_CMP_OLE_S:
12201 case OPC_CMP_ULE_S:
12202 case OPC_CMP_SF_S:
12203 case OPC_CMP_NGLE_S:
12204 case OPC_CMP_SEQ_S:
12205 case OPC_CMP_NGL_S:
12206 case OPC_CMP_LT_S:
12207 case OPC_CMP_NGE_S:
12208 case OPC_CMP_LE_S:
12209 case OPC_CMP_NGT_S:
2e211e0a 12210 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 12211 if (ctx->opcode & (1 << 6)) {
71375b59 12212 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 12213 } else {
71375b59 12214 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12215 }
5a5012ec 12216 break;
bf4120ad 12217 case OPC_ADD_D:
5e755519 12218 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 12219 {
a7812ae4
PB
12220 TCGv_i64 fp0 = tcg_temp_new_i64();
12221 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12222
12223 gen_load_fpr64(ctx, fp0, fs);
12224 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12225 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 12226 tcg_temp_free_i64(fp1);
b6d96bed 12227 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12228 tcg_temp_free_i64(fp0);
b6d96bed 12229 }
6ea83fed 12230 break;
bf4120ad 12231 case OPC_SUB_D:
5e755519 12232 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 12233 {
a7812ae4
PB
12234 TCGv_i64 fp0 = tcg_temp_new_i64();
12235 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12236
12237 gen_load_fpr64(ctx, fp0, fs);
12238 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12239 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 12240 tcg_temp_free_i64(fp1);
b6d96bed 12241 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12242 tcg_temp_free_i64(fp0);
b6d96bed 12243 }
6ea83fed 12244 break;
bf4120ad 12245 case OPC_MUL_D:
5e755519 12246 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 12247 {
a7812ae4
PB
12248 TCGv_i64 fp0 = tcg_temp_new_i64();
12249 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12250
12251 gen_load_fpr64(ctx, fp0, fs);
12252 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12253 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 12254 tcg_temp_free_i64(fp1);
b6d96bed 12255 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12256 tcg_temp_free_i64(fp0);
b6d96bed 12257 }
6ea83fed 12258 break;
bf4120ad 12259 case OPC_DIV_D:
5e755519 12260 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 12261 {
a7812ae4
PB
12262 TCGv_i64 fp0 = tcg_temp_new_i64();
12263 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12264
12265 gen_load_fpr64(ctx, fp0, fs);
12266 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12267 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 12268 tcg_temp_free_i64(fp1);
b6d96bed 12269 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12270 tcg_temp_free_i64(fp0);
b6d96bed 12271 }
6ea83fed 12272 break;
bf4120ad 12273 case OPC_SQRT_D:
5e755519 12274 check_cp1_registers(ctx, fs | fd);
b6d96bed 12275 {
a7812ae4 12276 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12277
12278 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12279 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 12280 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12281 tcg_temp_free_i64(fp0);
b6d96bed 12282 }
6ea83fed 12283 break;
bf4120ad 12284 case OPC_ABS_D:
5e755519 12285 check_cp1_registers(ctx, fs | fd);
b6d96bed 12286 {
a7812ae4 12287 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12288
12289 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
12290 if (ctx->abs2008) {
12291 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12292 } else {
12293 gen_helper_float_abs_d(fp0, fp0);
12294 }
b6d96bed 12295 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12296 tcg_temp_free_i64(fp0);
b6d96bed 12297 }
6ea83fed 12298 break;
bf4120ad 12299 case OPC_MOV_D:
5e755519 12300 check_cp1_registers(ctx, fs | fd);
b6d96bed 12301 {
a7812ae4 12302 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12303
12304 gen_load_fpr64(ctx, fp0, fs);
12305 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12306 tcg_temp_free_i64(fp0);
b6d96bed 12307 }
6ea83fed 12308 break;
bf4120ad 12309 case OPC_NEG_D:
5e755519 12310 check_cp1_registers(ctx, fs | fd);
b6d96bed 12311 {
a7812ae4 12312 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12313
12314 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
12315 if (ctx->abs2008) {
12316 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12317 } else {
12318 gen_helper_float_chs_d(fp0, fp0);
12319 }
b6d96bed 12320 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12321 tcg_temp_free_i64(fp0);
b6d96bed 12322 }
6ea83fed 12323 break;
bf4120ad 12324 case OPC_ROUND_L_D:
5e755519 12325 check_cp1_64bitmode(ctx);
b6d96bed 12326 {
a7812ae4 12327 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12328
12329 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12330 if (ctx->nan2008) {
12331 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12332 } else {
12333 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12334 }
b6d96bed 12335 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12336 tcg_temp_free_i64(fp0);
b6d96bed 12337 }
5a5012ec 12338 break;
bf4120ad 12339 case OPC_TRUNC_L_D:
5e755519 12340 check_cp1_64bitmode(ctx);
b6d96bed 12341 {
a7812ae4 12342 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12343
12344 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12345 if (ctx->nan2008) {
12346 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12347 } else {
12348 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12349 }
b6d96bed 12350 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12351 tcg_temp_free_i64(fp0);
b6d96bed 12352 }
5a5012ec 12353 break;
bf4120ad 12354 case OPC_CEIL_L_D:
5e755519 12355 check_cp1_64bitmode(ctx);
b6d96bed 12356 {
a7812ae4 12357 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12358
12359 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12360 if (ctx->nan2008) {
12361 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12362 } else {
12363 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12364 }
b6d96bed 12365 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12366 tcg_temp_free_i64(fp0);
b6d96bed 12367 }
5a5012ec 12368 break;
bf4120ad 12369 case OPC_FLOOR_L_D:
5e755519 12370 check_cp1_64bitmode(ctx);
b6d96bed 12371 {
a7812ae4 12372 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12373
12374 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12375 if (ctx->nan2008) {
12376 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12377 } else {
12378 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12379 }
b6d96bed 12380 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12381 tcg_temp_free_i64(fp0);
b6d96bed 12382 }
5a5012ec 12383 break;
bf4120ad 12384 case OPC_ROUND_W_D:
5e755519 12385 check_cp1_registers(ctx, fs);
b6d96bed 12386 {
a7812ae4
PB
12387 TCGv_i32 fp32 = tcg_temp_new_i32();
12388 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12389
12390 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12391 if (ctx->nan2008) {
12392 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12393 } else {
12394 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12395 }
a7812ae4 12396 tcg_temp_free_i64(fp64);
7c979afd 12397 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12398 tcg_temp_free_i32(fp32);
b6d96bed 12399 }
6ea83fed 12400 break;
bf4120ad 12401 case OPC_TRUNC_W_D:
5e755519 12402 check_cp1_registers(ctx, fs);
b6d96bed 12403 {
a7812ae4
PB
12404 TCGv_i32 fp32 = tcg_temp_new_i32();
12405 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12406
12407 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12408 if (ctx->nan2008) {
12409 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12410 } else {
12411 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12412 }
a7812ae4 12413 tcg_temp_free_i64(fp64);
7c979afd 12414 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12415 tcg_temp_free_i32(fp32);
b6d96bed 12416 }
6ea83fed 12417 break;
bf4120ad 12418 case OPC_CEIL_W_D:
5e755519 12419 check_cp1_registers(ctx, fs);
b6d96bed 12420 {
a7812ae4
PB
12421 TCGv_i32 fp32 = tcg_temp_new_i32();
12422 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12423
12424 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12425 if (ctx->nan2008) {
12426 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12427 } else {
12428 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12429 }
a7812ae4 12430 tcg_temp_free_i64(fp64);
7c979afd 12431 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12432 tcg_temp_free_i32(fp32);
b6d96bed 12433 }
6ea83fed 12434 break;
bf4120ad 12435 case OPC_FLOOR_W_D:
5e755519 12436 check_cp1_registers(ctx, fs);
b6d96bed 12437 {
a7812ae4
PB
12438 TCGv_i32 fp32 = tcg_temp_new_i32();
12439 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12440
12441 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12442 if (ctx->nan2008) {
12443 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12444 } else {
12445 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12446 }
a7812ae4 12447 tcg_temp_free_i64(fp64);
7c979afd 12448 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12449 tcg_temp_free_i32(fp32);
b6d96bed 12450 }
6ea83fed 12451 break;
e7f16abb 12452 case OPC_SEL_D:
2e211e0a 12453 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 12454 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
12455 break;
12456 case OPC_SELEQZ_D:
2e211e0a 12457 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 12458 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
12459 break;
12460 case OPC_SELNEZ_D:
2e211e0a 12461 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 12462 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 12463 break;
bf4120ad 12464 case OPC_MOVCF_D:
2e211e0a 12465 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6d96bed 12466 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 12467 break;
bf4120ad 12468 case OPC_MOVZ_D:
2e211e0a 12469 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 12470 {
42a268c2 12471 TCGLabel *l1 = gen_new_label();
c9297f4d 12472 TCGv_i64 fp0;
a16336e4 12473
c9297f4d
AJ
12474 if (ft != 0) {
12475 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12476 }
12477 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12478 gen_load_fpr64(ctx, fp0, fs);
12479 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12480 tcg_temp_free_i64(fp0);
a16336e4
TS
12481 gen_set_label(l1);
12482 }
5a5012ec 12483 break;
bf4120ad 12484 case OPC_MOVN_D:
2e211e0a 12485 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 12486 {
42a268c2 12487 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
12488 TCGv_i64 fp0;
12489
12490 if (ft != 0) {
12491 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12492 fp0 = tcg_temp_new_i64();
12493 gen_load_fpr64(ctx, fp0, fs);
12494 gen_store_fpr64(ctx, fp0, fd);
12495 tcg_temp_free_i64(fp0);
12496 gen_set_label(l1);
12497 }
a16336e4 12498 }
6ea83fed 12499 break;
bf4120ad 12500 case OPC_RECIP_D:
ca6c7803 12501 check_cp1_registers(ctx, fs | fd);
b6d96bed 12502 {
a7812ae4 12503 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12504
12505 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12506 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 12507 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12508 tcg_temp_free_i64(fp0);
b6d96bed 12509 }
57fa1fb3 12510 break;
bf4120ad 12511 case OPC_RSQRT_D:
ca6c7803 12512 check_cp1_registers(ctx, fs | fd);
b6d96bed 12513 {
a7812ae4 12514 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12515
12516 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12517 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 12518 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12519 tcg_temp_free_i64(fp0);
b6d96bed 12520 }
57fa1fb3 12521 break;
e7f16abb 12522 case OPC_MADDF_D:
2e211e0a 12523 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12524 {
a7812ae4
PB
12525 TCGv_i64 fp0 = tcg_temp_new_i64();
12526 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 12527 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12528 gen_load_fpr64(ctx, fp0, fs);
12529 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12530 gen_load_fpr64(ctx, fp2, fd);
12531 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12532 gen_store_fpr64(ctx, fp2, fd);
12533 tcg_temp_free_i64(fp2);
a7812ae4 12534 tcg_temp_free_i64(fp1);
a7812ae4 12535 tcg_temp_free_i64(fp0);
b6d96bed 12536 }
57fa1fb3 12537 break;
e7f16abb 12538 case OPC_MSUBF_D:
2e211e0a 12539 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12540 {
a7812ae4 12541 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
12542 TCGv_i64 fp1 = tcg_temp_new_i64();
12543 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 12544 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
12545 gen_load_fpr64(ctx, fp1, ft);
12546 gen_load_fpr64(ctx, fp2, fd);
12547 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12548 gen_store_fpr64(ctx, fp2, fd);
12549 tcg_temp_free_i64(fp2);
12550 tcg_temp_free_i64(fp1);
a7812ae4 12551 tcg_temp_free_i64(fp0);
b6d96bed 12552 }
57fa1fb3 12553 break;
e7f16abb 12554 case OPC_RINT_D:
2e211e0a 12555 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12556 {
a7812ae4 12557 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12558 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 12559 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 12560 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12561 tcg_temp_free_i64(fp0);
b6d96bed 12562 }
57fa1fb3 12563 break;
e7f16abb 12564 case OPC_CLASS_D:
2e211e0a 12565 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 12566 {
e7f16abb
LA
12567 TCGv_i64 fp0 = tcg_temp_new_i64();
12568 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 12569 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
12570 gen_store_fpr64(ctx, fp0, fd);
12571 tcg_temp_free_i64(fp0);
e7f16abb
LA
12572 }
12573 break;
12574 case OPC_MIN_D: /* OPC_RECIP2_D */
2e211e0a 12575 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 12576 /* OPC_MIN_D */
a7812ae4
PB
12577 TCGv_i64 fp0 = tcg_temp_new_i64();
12578 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
12579 gen_load_fpr64(ctx, fp0, fs);
12580 gen_load_fpr64(ctx, fp1, ft);
12581 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12582 gen_store_fpr64(ctx, fp1, fd);
12583 tcg_temp_free_i64(fp1);
12584 tcg_temp_free_i64(fp0);
e7f16abb
LA
12585 } else {
12586 /* OPC_RECIP2_D */
12587 check_cp1_64bitmode(ctx);
12588 {
12589 TCGv_i64 fp0 = tcg_temp_new_i64();
12590 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 12591
e7f16abb
LA
12592 gen_load_fpr64(ctx, fp0, fs);
12593 gen_load_fpr64(ctx, fp1, ft);
12594 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12595 tcg_temp_free_i64(fp1);
12596 gen_store_fpr64(ctx, fp0, fd);
12597 tcg_temp_free_i64(fp0);
12598 }
e7f16abb
LA
12599 }
12600 break;
12601 case OPC_MINA_D: /* OPC_RECIP1_D */
2e211e0a 12602 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12603 /* OPC_MINA_D */
12604 TCGv_i64 fp0 = tcg_temp_new_i64();
12605 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12606 gen_load_fpr64(ctx, fp0, fs);
12607 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
12608 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12609 gen_store_fpr64(ctx, fp1, fd);
12610 tcg_temp_free_i64(fp1);
12611 tcg_temp_free_i64(fp0);
e7f16abb
LA
12612 } else {
12613 /* OPC_RECIP1_D */
12614 check_cp1_64bitmode(ctx);
12615 {
12616 TCGv_i64 fp0 = tcg_temp_new_i64();
12617
12618 gen_load_fpr64(ctx, fp0, fs);
12619 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12620 gen_store_fpr64(ctx, fp0, fd);
12621 tcg_temp_free_i64(fp0);
12622 }
e7f16abb
LA
12623 }
12624 break;
12625 case OPC_MAX_D: /* OPC_RSQRT1_D */
2e211e0a 12626 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12627 /* OPC_MAX_D */
12628 TCGv_i64 fp0 = tcg_temp_new_i64();
12629 TCGv_i64 fp1 = tcg_temp_new_i64();
12630 gen_load_fpr64(ctx, fp0, fs);
12631 gen_load_fpr64(ctx, fp1, ft);
12632 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12633 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 12634 tcg_temp_free_i64(fp1);
a7812ae4 12635 tcg_temp_free_i64(fp0);
e7f16abb
LA
12636 } else {
12637 /* OPC_RSQRT1_D */
12638 check_cp1_64bitmode(ctx);
12639 {
12640 TCGv_i64 fp0 = tcg_temp_new_i64();
12641
12642 gen_load_fpr64(ctx, fp0, fs);
12643 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12644 gen_store_fpr64(ctx, fp0, fd);
12645 tcg_temp_free_i64(fp0);
12646 }
e7f16abb
LA
12647 }
12648 break;
12649 case OPC_MAXA_D: /* OPC_RSQRT2_D */
2e211e0a 12650 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
12651 /* OPC_MAXA_D */
12652 TCGv_i64 fp0 = tcg_temp_new_i64();
12653 TCGv_i64 fp1 = tcg_temp_new_i64();
12654 gen_load_fpr64(ctx, fp0, fs);
12655 gen_load_fpr64(ctx, fp1, ft);
12656 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12657 gen_store_fpr64(ctx, fp1, fd);
12658 tcg_temp_free_i64(fp1);
12659 tcg_temp_free_i64(fp0);
e7f16abb
LA
12660 } else {
12661 /* OPC_RSQRT2_D */
12662 check_cp1_64bitmode(ctx);
12663 {
12664 TCGv_i64 fp0 = tcg_temp_new_i64();
12665 TCGv_i64 fp1 = tcg_temp_new_i64();
12666
12667 gen_load_fpr64(ctx, fp0, fs);
12668 gen_load_fpr64(ctx, fp1, ft);
12669 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12670 tcg_temp_free_i64(fp1);
12671 gen_store_fpr64(ctx, fp0, fd);
12672 tcg_temp_free_i64(fp0);
12673 }
b6d96bed 12674 }
57fa1fb3 12675 break;
bf4120ad
NF
12676 case OPC_CMP_F_D:
12677 case OPC_CMP_UN_D:
12678 case OPC_CMP_EQ_D:
12679 case OPC_CMP_UEQ_D:
12680 case OPC_CMP_OLT_D:
12681 case OPC_CMP_ULT_D:
12682 case OPC_CMP_OLE_D:
12683 case OPC_CMP_ULE_D:
12684 case OPC_CMP_SF_D:
12685 case OPC_CMP_NGLE_D:
12686 case OPC_CMP_SEQ_D:
12687 case OPC_CMP_NGL_D:
12688 case OPC_CMP_LT_D:
12689 case OPC_CMP_NGE_D:
12690 case OPC_CMP_LE_D:
12691 case OPC_CMP_NGT_D:
2e211e0a 12692 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 12693 if (ctx->opcode & (1 << 6)) {
71375b59 12694 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 12695 } else {
71375b59 12696 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 12697 }
6ea83fed 12698 break;
bf4120ad 12699 case OPC_CVT_S_D:
5e755519 12700 check_cp1_registers(ctx, fs);
b6d96bed 12701 {
a7812ae4
PB
12702 TCGv_i32 fp32 = tcg_temp_new_i32();
12703 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12704
12705 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12706 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 12707 tcg_temp_free_i64(fp64);
7c979afd 12708 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12709 tcg_temp_free_i32(fp32);
b6d96bed 12710 }
5a5012ec 12711 break;
bf4120ad 12712 case OPC_CVT_W_D:
5e755519 12713 check_cp1_registers(ctx, fs);
b6d96bed 12714 {
a7812ae4
PB
12715 TCGv_i32 fp32 = tcg_temp_new_i32();
12716 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12717
12718 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
12719 if (ctx->nan2008) {
12720 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12721 } else {
12722 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12723 }
a7812ae4 12724 tcg_temp_free_i64(fp64);
7c979afd 12725 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12726 tcg_temp_free_i32(fp32);
b6d96bed 12727 }
5a5012ec 12728 break;
bf4120ad 12729 case OPC_CVT_L_D:
5e755519 12730 check_cp1_64bitmode(ctx);
b6d96bed 12731 {
a7812ae4 12732 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12733
12734 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
12735 if (ctx->nan2008) {
12736 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12737 } else {
12738 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12739 }
b6d96bed 12740 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12741 tcg_temp_free_i64(fp0);
b6d96bed 12742 }
5a5012ec 12743 break;
bf4120ad 12744 case OPC_CVT_S_W:
b6d96bed 12745 {
a7812ae4 12746 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12747
7c979afd 12748 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12749 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 12750 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12751 tcg_temp_free_i32(fp0);
b6d96bed 12752 }
6ea83fed 12753 break;
bf4120ad 12754 case OPC_CVT_D_W:
5e755519 12755 check_cp1_registers(ctx, fd);
b6d96bed 12756 {
a7812ae4
PB
12757 TCGv_i32 fp32 = tcg_temp_new_i32();
12758 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12759
7c979afd 12760 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12761 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12762 tcg_temp_free_i32(fp32);
b6d96bed 12763 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12764 tcg_temp_free_i64(fp64);
b6d96bed 12765 }
5a5012ec 12766 break;
bf4120ad 12767 case OPC_CVT_S_L:
5e755519 12768 check_cp1_64bitmode(ctx);
b6d96bed 12769 {
a7812ae4
PB
12770 TCGv_i32 fp32 = tcg_temp_new_i32();
12771 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12772
12773 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12774 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12775 tcg_temp_free_i64(fp64);
7c979afd 12776 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12777 tcg_temp_free_i32(fp32);
b6d96bed 12778 }
5a5012ec 12779 break;
bf4120ad 12780 case OPC_CVT_D_L:
5e755519 12781 check_cp1_64bitmode(ctx);
b6d96bed 12782 {
a7812ae4 12783 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12784
12785 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12786 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12787 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12788 tcg_temp_free_i64(fp0);
b6d96bed 12789 }
5a5012ec 12790 break;
bf4120ad 12791 case OPC_CVT_PS_PW:
e29c9628 12792 check_ps(ctx);
b6d96bed 12793 {
a7812ae4 12794 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12795
12796 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12797 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12798 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12799 tcg_temp_free_i64(fp0);
b6d96bed 12800 }
5a5012ec 12801 break;
bf4120ad 12802 case OPC_ADD_PS:
e29c9628 12803 check_ps(ctx);
b6d96bed 12804 {
a7812ae4
PB
12805 TCGv_i64 fp0 = tcg_temp_new_i64();
12806 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12807
12808 gen_load_fpr64(ctx, fp0, fs);
12809 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12810 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12811 tcg_temp_free_i64(fp1);
b6d96bed 12812 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12813 tcg_temp_free_i64(fp0);
b6d96bed 12814 }
6ea83fed 12815 break;
bf4120ad 12816 case OPC_SUB_PS:
e29c9628 12817 check_ps(ctx);
b6d96bed 12818 {
a7812ae4
PB
12819 TCGv_i64 fp0 = tcg_temp_new_i64();
12820 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12821
12822 gen_load_fpr64(ctx, fp0, fs);
12823 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12824 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12825 tcg_temp_free_i64(fp1);
b6d96bed 12826 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12827 tcg_temp_free_i64(fp0);
b6d96bed 12828 }
6ea83fed 12829 break;
bf4120ad 12830 case OPC_MUL_PS:
e29c9628 12831 check_ps(ctx);
b6d96bed 12832 {
a7812ae4
PB
12833 TCGv_i64 fp0 = tcg_temp_new_i64();
12834 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12835
12836 gen_load_fpr64(ctx, fp0, fs);
12837 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12838 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12839 tcg_temp_free_i64(fp1);
b6d96bed 12840 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12841 tcg_temp_free_i64(fp0);
b6d96bed 12842 }
6ea83fed 12843 break;
bf4120ad 12844 case OPC_ABS_PS:
e29c9628 12845 check_ps(ctx);
b6d96bed 12846 {
a7812ae4 12847 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12848
12849 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12850 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12851 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12852 tcg_temp_free_i64(fp0);
b6d96bed 12853 }
6ea83fed 12854 break;
bf4120ad 12855 case OPC_MOV_PS:
e29c9628 12856 check_ps(ctx);
b6d96bed 12857 {
a7812ae4 12858 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12859
12860 gen_load_fpr64(ctx, fp0, fs);
12861 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12862 tcg_temp_free_i64(fp0);
b6d96bed 12863 }
6ea83fed 12864 break;
bf4120ad 12865 case OPC_NEG_PS:
e29c9628 12866 check_ps(ctx);
b6d96bed 12867 {
a7812ae4 12868 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12869
12870 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12871 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12872 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12873 tcg_temp_free_i64(fp0);
b6d96bed 12874 }
6ea83fed 12875 break;
bf4120ad 12876 case OPC_MOVCF_PS:
e29c9628 12877 check_ps(ctx);
7f6613ce 12878 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12879 break;
bf4120ad 12880 case OPC_MOVZ_PS:
e29c9628 12881 check_ps(ctx);
a16336e4 12882 {
42a268c2 12883 TCGLabel *l1 = gen_new_label();
30a3848b 12884 TCGv_i64 fp0;
a16336e4 12885
1f8929d2 12886 if (ft != 0) {
c9297f4d 12887 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 12888 }
c9297f4d
AJ
12889 fp0 = tcg_temp_new_i64();
12890 gen_load_fpr64(ctx, fp0, fs);
12891 gen_store_fpr64(ctx, fp0, fd);
12892 tcg_temp_free_i64(fp0);
a16336e4
TS
12893 gen_set_label(l1);
12894 }
6ea83fed 12895 break;
bf4120ad 12896 case OPC_MOVN_PS:
e29c9628 12897 check_ps(ctx);
a16336e4 12898 {
42a268c2 12899 TCGLabel *l1 = gen_new_label();
30a3848b 12900 TCGv_i64 fp0;
c9297f4d
AJ
12901
12902 if (ft != 0) {
12903 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12904 fp0 = tcg_temp_new_i64();
12905 gen_load_fpr64(ctx, fp0, fs);
12906 gen_store_fpr64(ctx, fp0, fd);
12907 tcg_temp_free_i64(fp0);
12908 gen_set_label(l1);
12909 }
a16336e4 12910 }
6ea83fed 12911 break;
bf4120ad 12912 case OPC_ADDR_PS:
e29c9628 12913 check_ps(ctx);
b6d96bed 12914 {
a7812ae4
PB
12915 TCGv_i64 fp0 = tcg_temp_new_i64();
12916 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12917
12918 gen_load_fpr64(ctx, fp0, ft);
12919 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12920 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12921 tcg_temp_free_i64(fp1);
b6d96bed 12922 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12923 tcg_temp_free_i64(fp0);
b6d96bed 12924 }
fbcc6828 12925 break;
bf4120ad 12926 case OPC_MULR_PS:
e29c9628 12927 check_ps(ctx);
b6d96bed 12928 {
a7812ae4
PB
12929 TCGv_i64 fp0 = tcg_temp_new_i64();
12930 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12931
12932 gen_load_fpr64(ctx, fp0, ft);
12933 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12934 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12935 tcg_temp_free_i64(fp1);
b6d96bed 12936 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12937 tcg_temp_free_i64(fp0);
b6d96bed 12938 }
57fa1fb3 12939 break;
bf4120ad 12940 case OPC_RECIP2_PS:
e29c9628 12941 check_ps(ctx);
b6d96bed 12942 {
a7812ae4
PB
12943 TCGv_i64 fp0 = tcg_temp_new_i64();
12944 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12945
12946 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12947 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12948 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12949 tcg_temp_free_i64(fp1);
b6d96bed 12950 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12951 tcg_temp_free_i64(fp0);
b6d96bed 12952 }
57fa1fb3 12953 break;
bf4120ad 12954 case OPC_RECIP1_PS:
e29c9628 12955 check_ps(ctx);
b6d96bed 12956 {
a7812ae4 12957 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12958
12959 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12960 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12961 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12962 tcg_temp_free_i64(fp0);
b6d96bed 12963 }
57fa1fb3 12964 break;
bf4120ad 12965 case OPC_RSQRT1_PS:
e29c9628 12966 check_ps(ctx);
b6d96bed 12967 {
a7812ae4 12968 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12969
12970 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12971 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12972 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12973 tcg_temp_free_i64(fp0);
b6d96bed 12974 }
57fa1fb3 12975 break;
bf4120ad 12976 case OPC_RSQRT2_PS:
e29c9628 12977 check_ps(ctx);
b6d96bed 12978 {
a7812ae4
PB
12979 TCGv_i64 fp0 = tcg_temp_new_i64();
12980 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12981
12982 gen_load_fpr64(ctx, fp0, fs);
12983 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12984 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12985 tcg_temp_free_i64(fp1);
b6d96bed 12986 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12987 tcg_temp_free_i64(fp0);
b6d96bed 12988 }
57fa1fb3 12989 break;
bf4120ad 12990 case OPC_CVT_S_PU:
5e755519 12991 check_cp1_64bitmode(ctx);
b6d96bed 12992 {
a7812ae4 12993 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12994
7f6613ce 12995 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12996 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12997 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12998 tcg_temp_free_i32(fp0);
b6d96bed 12999 }
dd016883 13000 break;
bf4120ad 13001 case OPC_CVT_PW_PS:
e29c9628 13002 check_ps(ctx);
b6d96bed 13003 {
a7812ae4 13004 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
13005
13006 gen_load_fpr64(ctx, fp0, fs);
895c2d04 13007 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 13008 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 13009 tcg_temp_free_i64(fp0);
b6d96bed 13010 }
6ea83fed 13011 break;
bf4120ad 13012 case OPC_CVT_S_PL:
5e755519 13013 check_cp1_64bitmode(ctx);
b6d96bed 13014 {
a7812ae4 13015 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 13016
7c979afd 13017 gen_load_fpr32(ctx, fp0, fs);
895c2d04 13018 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 13019 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 13020 tcg_temp_free_i32(fp0);
b6d96bed 13021 }
6ea83fed 13022 break;
bf4120ad 13023 case OPC_PLL_PS:
e29c9628 13024 check_ps(ctx);
b6d96bed 13025 {
a7812ae4
PB
13026 TCGv_i32 fp0 = tcg_temp_new_i32();
13027 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 13028
7c979afd
LA
13029 gen_load_fpr32(ctx, fp0, fs);
13030 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 13031 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 13032 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
13033 tcg_temp_free_i32(fp0);
13034 tcg_temp_free_i32(fp1);
b6d96bed 13035 }
6ea83fed 13036 break;
bf4120ad 13037 case OPC_PLU_PS:
e29c9628 13038 check_ps(ctx);
b6d96bed 13039 {
a7812ae4
PB
13040 TCGv_i32 fp0 = tcg_temp_new_i32();
13041 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 13042
7c979afd 13043 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 13044 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 13045 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 13046 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
13047 tcg_temp_free_i32(fp0);
13048 tcg_temp_free_i32(fp1);
b6d96bed 13049 }
5a5012ec 13050 break;
bf4120ad 13051 case OPC_PUL_PS:
e29c9628 13052 check_ps(ctx);
b6d96bed 13053 {
a7812ae4
PB
13054 TCGv_i32 fp0 = tcg_temp_new_i32();
13055 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 13056
7f6613ce 13057 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
13058 gen_load_fpr32(ctx, fp1, ft);
13059 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 13060 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
13061 tcg_temp_free_i32(fp0);
13062 tcg_temp_free_i32(fp1);
b6d96bed 13063 }
5a5012ec 13064 break;
bf4120ad 13065 case OPC_PUU_PS:
e29c9628 13066 check_ps(ctx);
b6d96bed 13067 {
a7812ae4
PB
13068 TCGv_i32 fp0 = tcg_temp_new_i32();
13069 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 13070
7f6613ce
PJ
13071 gen_load_fpr32h(ctx, fp0, fs);
13072 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 13073 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 13074 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
13075 tcg_temp_free_i32(fp0);
13076 tcg_temp_free_i32(fp1);
b6d96bed 13077 }
5a5012ec 13078 break;
bf4120ad
NF
13079 case OPC_CMP_F_PS:
13080 case OPC_CMP_UN_PS:
13081 case OPC_CMP_EQ_PS:
13082 case OPC_CMP_UEQ_PS:
13083 case OPC_CMP_OLT_PS:
13084 case OPC_CMP_ULT_PS:
13085 case OPC_CMP_OLE_PS:
13086 case OPC_CMP_ULE_PS:
13087 case OPC_CMP_SF_PS:
13088 case OPC_CMP_NGLE_PS:
13089 case OPC_CMP_SEQ_PS:
13090 case OPC_CMP_NGL_PS:
13091 case OPC_CMP_LT_PS:
13092 case OPC_CMP_NGE_PS:
13093 case OPC_CMP_LE_PS:
13094 case OPC_CMP_NGT_PS:
8153667c 13095 if (ctx->opcode & (1 << 6)) {
71375b59 13096 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 13097 } else {
71375b59 13098 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 13099 }
6ea83fed 13100 break;
5a5012ec 13101 default:
9d68ac14 13102 MIPS_INVAL("farith");
9c708c7f 13103 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
13104 return;
13105 }
6ea83fed 13106}
6af0bf9c 13107
5a5012ec 13108/* Coprocessor 3 (FPU) */
235785e8
AM
13109static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
13110 int fd, int fs, int base, int index)
7a387fff 13111{
4e2474d6 13112 TCGv t0 = tcg_temp_new();
7a387fff 13113
93b12ccc 13114 if (base == 0) {
6c5c1e20 13115 gen_load_gpr(t0, index);
93b12ccc 13116 } else if (index == 0) {
6c5c1e20 13117 gen_load_gpr(t0, base);
93b12ccc 13118 } else {
05168674 13119 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 13120 }
7480515f
AM
13121 /*
13122 * Don't do NOP if destination is zero: we must perform the actual
13123 * memory access.
13124 */
5a5012ec
TS
13125 switch (opc) {
13126 case OPC_LWXC1:
8c0ab41f 13127 check_cop1x(ctx);
b6d96bed 13128 {
a7812ae4 13129 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 13130
5f68f5ae 13131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 13132 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 13133 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 13134 tcg_temp_free_i32(fp0);
b6d96bed 13135 }
5a5012ec
TS
13136 break;
13137 case OPC_LDXC1:
8c0ab41f
AJ
13138 check_cop1x(ctx);
13139 check_cp1_registers(ctx, fd);
b6d96bed 13140 {
a7812ae4 13141 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 13142 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 13143 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 13144 tcg_temp_free_i64(fp0);
b6d96bed 13145 }
5a5012ec
TS
13146 break;
13147 case OPC_LUXC1:
8c0ab41f 13148 check_cp1_64bitmode(ctx);
6c5c1e20 13149 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 13150 {
a7812ae4 13151 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 13152
5f68f5ae 13153 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 13154 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 13155 tcg_temp_free_i64(fp0);
b6d96bed 13156 }
5a5012ec
TS
13157 break;
13158 case OPC_SWXC1:
8c0ab41f 13159 check_cop1x(ctx);
b6d96bed 13160 {
a7812ae4 13161 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 13162 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 13163 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 13164 tcg_temp_free_i32(fp0);
b6d96bed 13165 }
5a5012ec
TS
13166 break;
13167 case OPC_SDXC1:
8c0ab41f
AJ
13168 check_cop1x(ctx);
13169 check_cp1_registers(ctx, fs);
b6d96bed 13170 {
a7812ae4 13171 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 13172 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 13173 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 13174 tcg_temp_free_i64(fp0);
b6d96bed 13175 }
5a5012ec
TS
13176 break;
13177 case OPC_SUXC1:
8c0ab41f 13178 check_cp1_64bitmode(ctx);
6c5c1e20 13179 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 13180 {
a7812ae4 13181 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 13182 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 13183 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 13184 tcg_temp_free_i64(fp0);
b6d96bed 13185 }
5a5012ec 13186 break;
5a5012ec 13187 }
6c5c1e20 13188 tcg_temp_free(t0);
5a5012ec
TS
13189}
13190
235785e8
AM
13191static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13192 int fd, int fr, int fs, int ft)
5a5012ec 13193{
5a5012ec
TS
13194 switch (opc) {
13195 case OPC_ALNV_PS:
e29c9628 13196 check_ps(ctx);
a16336e4 13197 {
a7812ae4 13198 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
13199 TCGv_i32 fp = tcg_temp_new_i32();
13200 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
13201 TCGLabel *l1 = gen_new_label();
13202 TCGLabel *l2 = gen_new_label();
a16336e4 13203
6c5c1e20
TS
13204 gen_load_gpr(t0, fr);
13205 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
13206
13207 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 13208 gen_load_fpr32(ctx, fp, fs);
7f6613ce 13209 gen_load_fpr32h(ctx, fph, fs);
7c979afd 13210 gen_store_fpr32(ctx, fp, fd);
7f6613ce 13211 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
13212 tcg_gen_br(l2);
13213 gen_set_label(l1);
6c5c1e20
TS
13214 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13215 tcg_temp_free(t0);
a16336e4 13216#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 13217 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
13218 gen_load_fpr32h(ctx, fph, ft);
13219 gen_store_fpr32h(ctx, fp, fd);
7c979afd 13220 gen_store_fpr32(ctx, fph, fd);
a16336e4 13221#else
7f6613ce 13222 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
13223 gen_load_fpr32(ctx, fp, ft);
13224 gen_store_fpr32(ctx, fph, fd);
7f6613ce 13225 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
13226#endif
13227 gen_set_label(l2);
c905fdac
AJ
13228 tcg_temp_free_i32(fp);
13229 tcg_temp_free_i32(fph);
a16336e4 13230 }
5a5012ec
TS
13231 break;
13232 case OPC_MADD_S:
b8aa4598 13233 check_cop1x(ctx);
b6d96bed 13234 {
a7812ae4
PB
13235 TCGv_i32 fp0 = tcg_temp_new_i32();
13236 TCGv_i32 fp1 = tcg_temp_new_i32();
13237 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 13238
7c979afd
LA
13239 gen_load_fpr32(ctx, fp0, fs);
13240 gen_load_fpr32(ctx, fp1, ft);
13241 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 13242 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13243 tcg_temp_free_i32(fp0);
13244 tcg_temp_free_i32(fp1);
7c979afd 13245 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 13246 tcg_temp_free_i32(fp2);
b6d96bed 13247 }
5a5012ec
TS
13248 break;
13249 case OPC_MADD_D:
b8aa4598
TS
13250 check_cop1x(ctx);
13251 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 13252 {
a7812ae4
PB
13253 TCGv_i64 fp0 = tcg_temp_new_i64();
13254 TCGv_i64 fp1 = tcg_temp_new_i64();
13255 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13256
13257 gen_load_fpr64(ctx, fp0, fs);
13258 gen_load_fpr64(ctx, fp1, ft);
13259 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13260 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13261 tcg_temp_free_i64(fp0);
13262 tcg_temp_free_i64(fp1);
b6d96bed 13263 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13264 tcg_temp_free_i64(fp2);
b6d96bed 13265 }
5a5012ec
TS
13266 break;
13267 case OPC_MADD_PS:
e29c9628 13268 check_ps(ctx);
b6d96bed 13269 {
a7812ae4
PB
13270 TCGv_i64 fp0 = tcg_temp_new_i64();
13271 TCGv_i64 fp1 = tcg_temp_new_i64();
13272 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13273
13274 gen_load_fpr64(ctx, fp0, fs);
13275 gen_load_fpr64(ctx, fp1, ft);
13276 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13277 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13278 tcg_temp_free_i64(fp0);
13279 tcg_temp_free_i64(fp1);
b6d96bed 13280 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13281 tcg_temp_free_i64(fp2);
b6d96bed 13282 }
5a5012ec
TS
13283 break;
13284 case OPC_MSUB_S:
b8aa4598 13285 check_cop1x(ctx);
b6d96bed 13286 {
a7812ae4
PB
13287 TCGv_i32 fp0 = tcg_temp_new_i32();
13288 TCGv_i32 fp1 = tcg_temp_new_i32();
13289 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 13290
7c979afd
LA
13291 gen_load_fpr32(ctx, fp0, fs);
13292 gen_load_fpr32(ctx, fp1, ft);
13293 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 13294 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13295 tcg_temp_free_i32(fp0);
13296 tcg_temp_free_i32(fp1);
7c979afd 13297 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 13298 tcg_temp_free_i32(fp2);
b6d96bed 13299 }
5a5012ec
TS
13300 break;
13301 case OPC_MSUB_D:
b8aa4598
TS
13302 check_cop1x(ctx);
13303 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 13304 {
a7812ae4
PB
13305 TCGv_i64 fp0 = tcg_temp_new_i64();
13306 TCGv_i64 fp1 = tcg_temp_new_i64();
13307 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13308
13309 gen_load_fpr64(ctx, fp0, fs);
13310 gen_load_fpr64(ctx, fp1, ft);
13311 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13312 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13313 tcg_temp_free_i64(fp0);
13314 tcg_temp_free_i64(fp1);
b6d96bed 13315 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13316 tcg_temp_free_i64(fp2);
b6d96bed 13317 }
5a5012ec
TS
13318 break;
13319 case OPC_MSUB_PS:
e29c9628 13320 check_ps(ctx);
b6d96bed 13321 {
a7812ae4
PB
13322 TCGv_i64 fp0 = tcg_temp_new_i64();
13323 TCGv_i64 fp1 = tcg_temp_new_i64();
13324 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13325
13326 gen_load_fpr64(ctx, fp0, fs);
13327 gen_load_fpr64(ctx, fp1, ft);
13328 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13329 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13330 tcg_temp_free_i64(fp0);
13331 tcg_temp_free_i64(fp1);
b6d96bed 13332 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13333 tcg_temp_free_i64(fp2);
b6d96bed 13334 }
5a5012ec
TS
13335 break;
13336 case OPC_NMADD_S:
b8aa4598 13337 check_cop1x(ctx);
b6d96bed 13338 {
a7812ae4
PB
13339 TCGv_i32 fp0 = tcg_temp_new_i32();
13340 TCGv_i32 fp1 = tcg_temp_new_i32();
13341 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 13342
7c979afd
LA
13343 gen_load_fpr32(ctx, fp0, fs);
13344 gen_load_fpr32(ctx, fp1, ft);
13345 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 13346 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13347 tcg_temp_free_i32(fp0);
13348 tcg_temp_free_i32(fp1);
7c979afd 13349 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 13350 tcg_temp_free_i32(fp2);
b6d96bed 13351 }
5a5012ec
TS
13352 break;
13353 case OPC_NMADD_D:
b8aa4598
TS
13354 check_cop1x(ctx);
13355 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 13356 {
a7812ae4
PB
13357 TCGv_i64 fp0 = tcg_temp_new_i64();
13358 TCGv_i64 fp1 = tcg_temp_new_i64();
13359 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13360
13361 gen_load_fpr64(ctx, fp0, fs);
13362 gen_load_fpr64(ctx, fp1, ft);
13363 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13364 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13365 tcg_temp_free_i64(fp0);
13366 tcg_temp_free_i64(fp1);
b6d96bed 13367 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13368 tcg_temp_free_i64(fp2);
b6d96bed 13369 }
5a5012ec
TS
13370 break;
13371 case OPC_NMADD_PS:
e29c9628 13372 check_ps(ctx);
b6d96bed 13373 {
a7812ae4
PB
13374 TCGv_i64 fp0 = tcg_temp_new_i64();
13375 TCGv_i64 fp1 = tcg_temp_new_i64();
13376 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13377
13378 gen_load_fpr64(ctx, fp0, fs);
13379 gen_load_fpr64(ctx, fp1, ft);
13380 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13381 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13382 tcg_temp_free_i64(fp0);
13383 tcg_temp_free_i64(fp1);
b6d96bed 13384 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13385 tcg_temp_free_i64(fp2);
b6d96bed 13386 }
5a5012ec
TS
13387 break;
13388 case OPC_NMSUB_S:
b8aa4598 13389 check_cop1x(ctx);
b6d96bed 13390 {
a7812ae4
PB
13391 TCGv_i32 fp0 = tcg_temp_new_i32();
13392 TCGv_i32 fp1 = tcg_temp_new_i32();
13393 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 13394
7c979afd
LA
13395 gen_load_fpr32(ctx, fp0, fs);
13396 gen_load_fpr32(ctx, fp1, ft);
13397 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 13398 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13399 tcg_temp_free_i32(fp0);
13400 tcg_temp_free_i32(fp1);
7c979afd 13401 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 13402 tcg_temp_free_i32(fp2);
b6d96bed 13403 }
5a5012ec
TS
13404 break;
13405 case OPC_NMSUB_D:
b8aa4598
TS
13406 check_cop1x(ctx);
13407 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 13408 {
a7812ae4
PB
13409 TCGv_i64 fp0 = tcg_temp_new_i64();
13410 TCGv_i64 fp1 = tcg_temp_new_i64();
13411 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13412
13413 gen_load_fpr64(ctx, fp0, fs);
13414 gen_load_fpr64(ctx, fp1, ft);
13415 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13416 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13417 tcg_temp_free_i64(fp0);
13418 tcg_temp_free_i64(fp1);
b6d96bed 13419 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13420 tcg_temp_free_i64(fp2);
b6d96bed 13421 }
5a5012ec
TS
13422 break;
13423 case OPC_NMSUB_PS:
e29c9628 13424 check_ps(ctx);
b6d96bed 13425 {
a7812ae4
PB
13426 TCGv_i64 fp0 = tcg_temp_new_i64();
13427 TCGv_i64 fp1 = tcg_temp_new_i64();
13428 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
13429
13430 gen_load_fpr64(ctx, fp0, fs);
13431 gen_load_fpr64(ctx, fp1, ft);
13432 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 13433 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
13434 tcg_temp_free_i64(fp0);
13435 tcg_temp_free_i64(fp1);
b6d96bed 13436 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 13437 tcg_temp_free_i64(fp2);
b6d96bed 13438 }
5a5012ec 13439 break;
923617a3 13440 default:
9d68ac14 13441 MIPS_INVAL("flt3_arith");
9c708c7f 13442 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
13443 return;
13444 }
7a387fff
TS
13445}
13446
b00c7218 13447static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
13448{
13449 TCGv t0;
13450
b3167288 13451#if !defined(CONFIG_USER_ONLY)
7480515f
AM
13452 /*
13453 * The Linux kernel will emulate rdhwr if it's not supported natively.
13454 * Therefore only check the ISA in system mode.
13455 */
7a47bae5 13456 check_insn(ctx, ISA_MIPS_R2);
b3167288 13457#endif
26ebe468
NF
13458 t0 = tcg_temp_new();
13459
13460 switch (rd) {
13461 case 0:
895c2d04 13462 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
13463 gen_store_gpr(t0, rt);
13464 break;
13465 case 1:
895c2d04 13466 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
13467 gen_store_gpr(t0, rt);
13468 break;
13469 case 2:
eeb3bba8 13470 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
13471 gen_io_start();
13472 }
895c2d04 13473 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 13474 gen_store_gpr(t0, rt);
7480515f
AM
13475 /*
13476 * Break the TB to be able to take timer interrupts immediately
13477 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13478 * we break completely out of translated code.
13479 */
eeb3bba8
EC
13480 gen_save_pc(ctx->base.pc_next + 4);
13481 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
13482 break;
13483 case 3:
895c2d04 13484 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
13485 gen_store_gpr(t0, rt);
13486 break;
b00c7218 13487 case 4:
2e211e0a 13488 check_insn(ctx, ISA_MIPS_R6);
b00c7218 13489 if (sel != 0) {
7480515f
AM
13490 /*
13491 * Performance counter registers are not implemented other than
b00c7218
YK
13492 * control register 0.
13493 */
13494 generate_exception(ctx, EXCP_RI);
13495 }
13496 gen_helper_rdhwr_performance(t0, cpu_env);
13497 gen_store_gpr(t0, rt);
13498 break;
13499 case 5:
2e211e0a 13500 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
13501 gen_helper_rdhwr_xnp(t0, cpu_env);
13502 gen_store_gpr(t0, rt);
13503 break;
26ebe468
NF
13504 case 29:
13505#if defined(CONFIG_USER_ONLY)
d279279e
PJ
13506 tcg_gen_ld_tl(t0, cpu_env,
13507 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
13508 gen_store_gpr(t0, rt);
13509 break;
13510#else
d279279e
PJ
13511 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13512 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13513 tcg_gen_ld_tl(t0, cpu_env,
13514 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13515 gen_store_gpr(t0, rt);
13516 } else {
9c708c7f 13517 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
13518 }
13519 break;
26ebe468
NF
13520#endif
13521 default: /* Invalid */
13522 MIPS_INVAL("rdhwr");
9c708c7f 13523 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
13524 break;
13525 }
13526 tcg_temp_free(t0);
13527}
13528
a5f53390
LA
13529static inline void clear_branch_hflags(DisasContext *ctx)
13530{
13531 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 13532 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
13533 save_cpu_state(ctx, 0);
13534 } else {
7480515f
AM
13535 /*
13536 * It is not safe to save ctx->hflags as hflags may be changed
13537 * in execution time by the instruction in delay / forbidden slot.
13538 */
a5f53390
LA
13539 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13540 }
13541}
13542
31837be3 13543static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
13544{
13545 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 13546 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 13547 /* Branches completion */
a5f53390 13548 clear_branch_hflags(ctx);
eeb3bba8 13549 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 13550 /* FIXME: Need to clear can_do_io. */
364d4831 13551 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 13552 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 13553 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 13554 break;
c9602061
NF
13555 case MIPS_HFLAG_B:
13556 /* unconditional branch */
364d4831
NF
13557 if (proc_hflags & MIPS_HFLAG_BX) {
13558 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13559 }
c9602061
NF
13560 gen_goto_tb(ctx, 0, ctx->btarget);
13561 break;
13562 case MIPS_HFLAG_BL:
13563 /* blikely taken case */
c9602061
NF
13564 gen_goto_tb(ctx, 0, ctx->btarget);
13565 break;
13566 case MIPS_HFLAG_BC:
13567 /* Conditional branch */
c9602061 13568 {
42a268c2 13569 TCGLabel *l1 = gen_new_label();
c9602061
NF
13570
13571 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 13572 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
13573 gen_set_label(l1);
13574 gen_goto_tb(ctx, 0, ctx->btarget);
13575 }
13576 break;
13577 case MIPS_HFLAG_BR:
13578 /* unconditional branch to register */
d75c135e 13579 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
13580 TCGv t0 = tcg_temp_new();
13581 TCGv_i32 t1 = tcg_temp_new_i32();
13582
13583 tcg_gen_andi_tl(t0, btarget, 0x1);
13584 tcg_gen_trunc_tl_i32(t1, t0);
13585 tcg_temp_free(t0);
13586 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13587 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13588 tcg_gen_or_i32(hflags, hflags, t1);
13589 tcg_temp_free_i32(t1);
13590
13591 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13592 } else {
13593 tcg_gen_mov_tl(cpu_PC, btarget);
13594 }
eeb3bba8 13595 if (ctx->base.singlestep_enabled) {
c9602061 13596 save_cpu_state(ctx, 0);
9c708c7f 13597 gen_helper_raise_exception_debug(cpu_env);
c9602061 13598 }
7f11636d 13599 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
13600 break;
13601 default:
a5f53390
LA
13602 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13603 abort();
c9602061
NF
13604 }
13605 }
13606}
13607
6893f074
YK
13608/* Compact Branches */
13609static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13610 int rs, int rt, int32_t offset)
13611{
13612 int bcond_compute = 0;
13613 TCGv t0 = tcg_temp_new();
13614 TCGv t1 = tcg_temp_new();
65935f07 13615 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
13616
13617 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13618#ifdef MIPS_DEBUG_DISAS
13619 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 13620 "\n", ctx->base.pc_next);
6893f074 13621#endif
9c708c7f 13622 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13623 goto out;
13624 }
13625
13626 /* Load needed operands and calculate btarget */
13627 switch (opc) {
13628 /* compact branch */
13629 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13630 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13631 gen_load_gpr(t0, rs);
13632 gen_load_gpr(t1, rt);
13633 bcond_compute = 1;
eeb3bba8 13634 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13635 if (rs <= rt && rs == 0) {
13636 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 13637 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13638 }
13639 break;
13640 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13641 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13642 gen_load_gpr(t0, rs);
13643 gen_load_gpr(t1, rt);
13644 bcond_compute = 1;
eeb3bba8 13645 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13646 break;
13647 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13648 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13649 if (rs == 0 || rs == rt) {
13650 /* OPC_BLEZALC, OPC_BGEZALC */
13651 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 13652 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13653 }
13654 gen_load_gpr(t0, rs);
13655 gen_load_gpr(t1, rt);
13656 bcond_compute = 1;
eeb3bba8 13657 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13658 break;
13659 case OPC_BC:
13660 case OPC_BALC:
eeb3bba8 13661 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13662 break;
13663 case OPC_BEQZC:
13664 case OPC_BNEZC:
13665 if (rs != 0) {
13666 /* OPC_BEQZC, OPC_BNEZC */
13667 gen_load_gpr(t0, rs);
13668 bcond_compute = 1;
eeb3bba8 13669 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
13670 } else {
13671 /* OPC_JIC, OPC_JIALC */
13672 TCGv tbase = tcg_temp_new();
13673 TCGv toffset = tcg_temp_new();
13674
13675 gen_load_gpr(tbase, rt);
13676 tcg_gen_movi_tl(toffset, offset);
13677 gen_op_addr_add(ctx, btarget, tbase, toffset);
13678 tcg_temp_free(tbase);
13679 tcg_temp_free(toffset);
13680 }
13681 break;
13682 default:
13683 MIPS_INVAL("Compact branch/jump");
9c708c7f 13684 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13685 goto out;
13686 }
13687
13688 if (bcond_compute == 0) {
13689 /* Uncoditional compact branch */
13690 switch (opc) {
13691 case OPC_JIALC:
eeb3bba8 13692 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13693 /* Fallthrough */
13694 case OPC_JIC:
13695 ctx->hflags |= MIPS_HFLAG_BR;
13696 break;
13697 case OPC_BALC:
eeb3bba8 13698 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
13699 /* Fallthrough */
13700 case OPC_BC:
13701 ctx->hflags |= MIPS_HFLAG_B;
13702 break;
13703 default:
13704 MIPS_INVAL("Compact branch/jump");
9c708c7f 13705 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13706 goto out;
13707 }
13708
13709 /* Generating branch here as compact branches don't have delay slot */
13710 gen_branch(ctx, 4);
13711 } else {
13712 /* Conditional compact branch */
13713 TCGLabel *fs = gen_new_label();
13714 save_cpu_state(ctx, 0);
13715
13716 switch (opc) {
13717 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13718 if (rs == 0 && rt != 0) {
13719 /* OPC_BLEZALC */
13720 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13721 } else if (rs != 0 && rt != 0 && rs == rt) {
13722 /* OPC_BGEZALC */
13723 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13724 } else {
13725 /* OPC_BGEUC */
13726 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13727 }
13728 break;
13729 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13730 if (rs == 0 && rt != 0) {
13731 /* OPC_BGTZALC */
13732 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13733 } else if (rs != 0 && rt != 0 && rs == rt) {
13734 /* OPC_BLTZALC */
13735 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13736 } else {
13737 /* OPC_BLTUC */
13738 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13739 }
13740 break;
13741 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13742 if (rs == 0 && rt != 0) {
13743 /* OPC_BLEZC */
13744 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13745 } else if (rs != 0 && rt != 0 && rs == rt) {
13746 /* OPC_BGEZC */
13747 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13748 } else {
13749 /* OPC_BGEC */
13750 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13751 }
13752 break;
13753 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13754 if (rs == 0 && rt != 0) {
13755 /* OPC_BGTZC */
13756 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13757 } else if (rs != 0 && rt != 0 && rs == rt) {
13758 /* OPC_BLTZC */
13759 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13760 } else {
13761 /* OPC_BLTC */
13762 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13763 }
13764 break;
13765 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13766 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13767 if (rs >= rt) {
13768 /* OPC_BOVC, OPC_BNVC */
13769 TCGv t2 = tcg_temp_new();
13770 TCGv t3 = tcg_temp_new();
13771 TCGv t4 = tcg_temp_new();
13772 TCGv input_overflow = tcg_temp_new();
13773
13774 gen_load_gpr(t0, rs);
13775 gen_load_gpr(t1, rt);
13776 tcg_gen_ext32s_tl(t2, t0);
13777 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13778 tcg_gen_ext32s_tl(t3, t1);
13779 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13780 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13781
13782 tcg_gen_add_tl(t4, t2, t3);
13783 tcg_gen_ext32s_tl(t4, t4);
13784 tcg_gen_xor_tl(t2, t2, t3);
13785 tcg_gen_xor_tl(t3, t4, t3);
13786 tcg_gen_andc_tl(t2, t3, t2);
13787 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13788 tcg_gen_or_tl(t4, t4, input_overflow);
13789 if (opc == OPC_BOVC) {
13790 /* OPC_BOVC */
13791 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13792 } else {
13793 /* OPC_BNVC */
13794 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13795 }
13796 tcg_temp_free(input_overflow);
13797 tcg_temp_free(t4);
13798 tcg_temp_free(t3);
13799 tcg_temp_free(t2);
13800 } else if (rs < rt && rs == 0) {
13801 /* OPC_BEQZALC, OPC_BNEZALC */
13802 if (opc == OPC_BEQZALC) {
13803 /* OPC_BEQZALC */
13804 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13805 } else {
13806 /* OPC_BNEZALC */
13807 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13808 }
13809 } else {
13810 /* OPC_BEQC, OPC_BNEC */
13811 if (opc == OPC_BEQC) {
13812 /* OPC_BEQC */
13813 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13814 } else {
13815 /* OPC_BNEC */
13816 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13817 }
13818 }
13819 break;
13820 case OPC_BEQZC:
13821 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13822 break;
13823 case OPC_BNEZC:
13824 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13825 break;
13826 default:
13827 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13828 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13829 goto out;
13830 }
13831
13832 /* Generating branch here as compact branches don't have delay slot */
13833 gen_goto_tb(ctx, 1, ctx->btarget);
13834 gen_set_label(fs);
13835
13836 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13837 }
13838
13839out:
13840 tcg_temp_free(t0);
13841 tcg_temp_free(t1);
13842}
13843
7a387fff 13844/* ISA extensions (ASEs) */
6af0bf9c 13845/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13846
13847/* MIPS16 major opcodes */
13848enum {
13849 M16_OPC_ADDIUSP = 0x00,
13850 M16_OPC_ADDIUPC = 0x01,
13851 M16_OPC_B = 0x02,
13852 M16_OPC_JAL = 0x03,
13853 M16_OPC_BEQZ = 0x04,
13854 M16_OPC_BNEQZ = 0x05,
13855 M16_OPC_SHIFT = 0x06,
13856 M16_OPC_LD = 0x07,
13857 M16_OPC_RRIA = 0x08,
13858 M16_OPC_ADDIU8 = 0x09,
13859 M16_OPC_SLTI = 0x0a,
13860 M16_OPC_SLTIU = 0x0b,
13861 M16_OPC_I8 = 0x0c,
13862 M16_OPC_LI = 0x0d,
13863 M16_OPC_CMPI = 0x0e,
13864 M16_OPC_SD = 0x0f,
13865 M16_OPC_LB = 0x10,
13866 M16_OPC_LH = 0x11,
13867 M16_OPC_LWSP = 0x12,
13868 M16_OPC_LW = 0x13,
13869 M16_OPC_LBU = 0x14,
13870 M16_OPC_LHU = 0x15,
13871 M16_OPC_LWPC = 0x16,
13872 M16_OPC_LWU = 0x17,
13873 M16_OPC_SB = 0x18,
13874 M16_OPC_SH = 0x19,
13875 M16_OPC_SWSP = 0x1a,
13876 M16_OPC_SW = 0x1b,
13877 M16_OPC_RRR = 0x1c,
13878 M16_OPC_RR = 0x1d,
13879 M16_OPC_EXTEND = 0x1e,
13880 M16_OPC_I64 = 0x1f
13881};
13882
13883/* I8 funct field */
13884enum {
13885 I8_BTEQZ = 0x0,
13886 I8_BTNEZ = 0x1,
13887 I8_SWRASP = 0x2,
13888 I8_ADJSP = 0x3,
13889 I8_SVRS = 0x4,
13890 I8_MOV32R = 0x5,
13891 I8_MOVR32 = 0x7
13892};
13893
13894/* RRR f field */
13895enum {
13896 RRR_DADDU = 0x0,
13897 RRR_ADDU = 0x1,
13898 RRR_DSUBU = 0x2,
13899 RRR_SUBU = 0x3
13900};
13901
13902/* RR funct field */
13903enum {
13904 RR_JR = 0x00,
13905 RR_SDBBP = 0x01,
13906 RR_SLT = 0x02,
13907 RR_SLTU = 0x03,
13908 RR_SLLV = 0x04,
13909 RR_BREAK = 0x05,
13910 RR_SRLV = 0x06,
13911 RR_SRAV = 0x07,
13912 RR_DSRL = 0x08,
13913 RR_CMP = 0x0a,
13914 RR_NEG = 0x0b,
13915 RR_AND = 0x0c,
13916 RR_OR = 0x0d,
13917 RR_XOR = 0x0e,
13918 RR_NOT = 0x0f,
13919 RR_MFHI = 0x10,
13920 RR_CNVT = 0x11,
13921 RR_MFLO = 0x12,
13922 RR_DSRA = 0x13,
13923 RR_DSLLV = 0x14,
13924 RR_DSRLV = 0x16,
13925 RR_DSRAV = 0x17,
13926 RR_MULT = 0x18,
13927 RR_MULTU = 0x19,
13928 RR_DIV = 0x1a,
13929 RR_DIVU = 0x1b,
13930 RR_DMULT = 0x1c,
13931 RR_DMULTU = 0x1d,
13932 RR_DDIV = 0x1e,
13933 RR_DDIVU = 0x1f
13934};
13935
13936/* I64 funct field */
13937enum {
13938 I64_LDSP = 0x0,
13939 I64_SDSP = 0x1,
13940 I64_SDRASP = 0x2,
13941 I64_DADJSP = 0x3,
13942 I64_LDPC = 0x4,
364d4831 13943 I64_DADDIU5 = 0x5,
6ea219d0
NF
13944 I64_DADDIUPC = 0x6,
13945 I64_DADDIUSP = 0x7
13946};
13947
13948/* RR ry field for CNVT */
13949enum {
13950 RR_RY_CNVT_ZEB = 0x0,
13951 RR_RY_CNVT_ZEH = 0x1,
13952 RR_RY_CNVT_ZEW = 0x2,
13953 RR_RY_CNVT_SEB = 0x4,
13954 RR_RY_CNVT_SEH = 0x5,
13955 RR_RY_CNVT_SEW = 0x6,
13956};
13957
235785e8 13958static int xlat(int r)
364d4831
NF
13959{
13960 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13961
13962 return map[r];
13963}
13964
235785e8
AM
13965static void gen_mips16_save(DisasContext *ctx,
13966 int xsregs, int aregs,
13967 int do_ra, int do_s0, int do_s1,
13968 int framesize)
364d4831
NF
13969{
13970 TCGv t0 = tcg_temp_new();
13971 TCGv t1 = tcg_temp_new();
c48245f0 13972 TCGv t2 = tcg_temp_new();
364d4831
NF
13973 int args, astatic;
13974
13975 switch (aregs) {
13976 case 0:
13977 case 1:
13978 case 2:
13979 case 3:
13980 case 11:
13981 args = 0;
13982 break;
13983 case 4:
13984 case 5:
13985 case 6:
13986 case 7:
13987 args = 1;
13988 break;
13989 case 8:
13990 case 9:
13991 case 10:
13992 args = 2;
13993 break;
13994 case 12:
13995 case 13:
13996 args = 3;
13997 break;
13998 case 14:
13999 args = 4;
14000 break;
14001 default:
9c708c7f 14002 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14003 return;
14004 }
14005
14006 switch (args) {
14007 case 4:
14008 gen_base_offset_addr(ctx, t0, 29, 12);
14009 gen_load_gpr(t1, 7);
5f68f5ae 14010 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
14011 /* Fall through */
14012 case 3:
14013 gen_base_offset_addr(ctx, t0, 29, 8);
14014 gen_load_gpr(t1, 6);
5f68f5ae 14015 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
14016 /* Fall through */
14017 case 2:
14018 gen_base_offset_addr(ctx, t0, 29, 4);
14019 gen_load_gpr(t1, 5);
5f68f5ae 14020 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
14021 /* Fall through */
14022 case 1:
14023 gen_base_offset_addr(ctx, t0, 29, 0);
14024 gen_load_gpr(t1, 4);
5f68f5ae 14025 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
14026 }
14027
14028 gen_load_gpr(t0, 29);
14029
5f68f5ae 14030#define DECR_AND_STORE(reg) do { \
c48245f0
MR
14031 tcg_gen_movi_tl(t2, -4); \
14032 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
14033 gen_load_gpr(t1, reg); \
14034 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
14035 } while (0)
14036
14037 if (do_ra) {
14038 DECR_AND_STORE(31);
14039 }
14040
14041 switch (xsregs) {
14042 case 7:
14043 DECR_AND_STORE(30);
14044 /* Fall through */
14045 case 6:
14046 DECR_AND_STORE(23);
14047 /* Fall through */
14048 case 5:
14049 DECR_AND_STORE(22);
14050 /* Fall through */
14051 case 4:
14052 DECR_AND_STORE(21);
14053 /* Fall through */
14054 case 3:
14055 DECR_AND_STORE(20);
14056 /* Fall through */
14057 case 2:
14058 DECR_AND_STORE(19);
14059 /* Fall through */
14060 case 1:
14061 DECR_AND_STORE(18);
14062 }
14063
14064 if (do_s1) {
14065 DECR_AND_STORE(17);
14066 }
14067 if (do_s0) {
14068 DECR_AND_STORE(16);
14069 }
14070
14071 switch (aregs) {
14072 case 0:
14073 case 4:
14074 case 8:
14075 case 12:
14076 case 14:
14077 astatic = 0;
14078 break;
14079 case 1:
14080 case 5:
14081 case 9:
14082 case 13:
14083 astatic = 1;
14084 break;
14085 case 2:
14086 case 6:
14087 case 10:
14088 astatic = 2;
14089 break;
14090 case 3:
14091 case 7:
14092 astatic = 3;
14093 break;
14094 case 11:
14095 astatic = 4;
14096 break;
14097 default:
9c708c7f 14098 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14099 return;
14100 }
14101
14102 if (astatic > 0) {
14103 DECR_AND_STORE(7);
14104 if (astatic > 1) {
14105 DECR_AND_STORE(6);
14106 if (astatic > 2) {
14107 DECR_AND_STORE(5);
14108 if (astatic > 3) {
14109 DECR_AND_STORE(4);
14110 }
14111 }
14112 }
14113 }
14114#undef DECR_AND_STORE
14115
c48245f0
MR
14116 tcg_gen_movi_tl(t2, -framesize);
14117 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
14118 tcg_temp_free(t0);
14119 tcg_temp_free(t1);
c48245f0 14120 tcg_temp_free(t2);
364d4831
NF
14121}
14122
235785e8
AM
14123static void gen_mips16_restore(DisasContext *ctx,
14124 int xsregs, int aregs,
14125 int do_ra, int do_s0, int do_s1,
14126 int framesize)
364d4831
NF
14127{
14128 int astatic;
14129 TCGv t0 = tcg_temp_new();
14130 TCGv t1 = tcg_temp_new();
c48245f0 14131 TCGv t2 = tcg_temp_new();
364d4831 14132
c48245f0
MR
14133 tcg_gen_movi_tl(t2, framesize);
14134 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 14135
5f68f5ae 14136#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
14137 tcg_gen_movi_tl(t2, -4); \
14138 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
14139 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14140 gen_store_gpr(t1, reg); \
364d4831
NF
14141 } while (0)
14142
14143 if (do_ra) {
14144 DECR_AND_LOAD(31);
14145 }
14146
14147 switch (xsregs) {
14148 case 7:
14149 DECR_AND_LOAD(30);
14150 /* Fall through */
14151 case 6:
14152 DECR_AND_LOAD(23);
14153 /* Fall through */
14154 case 5:
14155 DECR_AND_LOAD(22);
14156 /* Fall through */
14157 case 4:
14158 DECR_AND_LOAD(21);
14159 /* Fall through */
14160 case 3:
14161 DECR_AND_LOAD(20);
14162 /* Fall through */
14163 case 2:
14164 DECR_AND_LOAD(19);
14165 /* Fall through */
14166 case 1:
14167 DECR_AND_LOAD(18);
14168 }
14169
14170 if (do_s1) {
14171 DECR_AND_LOAD(17);
14172 }
14173 if (do_s0) {
14174 DECR_AND_LOAD(16);
14175 }
14176
14177 switch (aregs) {
14178 case 0:
14179 case 4:
14180 case 8:
14181 case 12:
14182 case 14:
14183 astatic = 0;
14184 break;
14185 case 1:
14186 case 5:
14187 case 9:
14188 case 13:
14189 astatic = 1;
14190 break;
14191 case 2:
14192 case 6:
14193 case 10:
14194 astatic = 2;
14195 break;
14196 case 3:
14197 case 7:
14198 astatic = 3;
14199 break;
14200 case 11:
14201 astatic = 4;
14202 break;
14203 default:
9c708c7f 14204 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14205 return;
14206 }
14207
14208 if (astatic > 0) {
14209 DECR_AND_LOAD(7);
14210 if (astatic > 1) {
14211 DECR_AND_LOAD(6);
14212 if (astatic > 2) {
14213 DECR_AND_LOAD(5);
14214 if (astatic > 3) {
14215 DECR_AND_LOAD(4);
14216 }
14217 }
14218 }
14219 }
14220#undef DECR_AND_LOAD
14221
c48245f0
MR
14222 tcg_gen_movi_tl(t2, framesize);
14223 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
14224 tcg_temp_free(t0);
14225 tcg_temp_free(t1);
c48245f0 14226 tcg_temp_free(t2);
364d4831
NF
14227}
14228
235785e8
AM
14229static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14230 int is_64_bit, int extended)
364d4831
NF
14231{
14232 TCGv t0;
14233
14234 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 14235 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14236 return;
14237 }
14238
14239 t0 = tcg_temp_new();
14240
14241 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14242 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14243 if (!is_64_bit) {
14244 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14245 }
14246
14247 tcg_temp_free(t0);
14248}
14249
0d74a222
LA
14250static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14251 int16_t offset)
14252{
14253 TCGv_i32 t0 = tcg_const_i32(op);
14254 TCGv t1 = tcg_temp_new();
14255 gen_base_offset_addr(ctx, t1, base, offset);
14256 gen_helper_cache(cpu_env, t1, t0);
14257}
14258
364d4831 14259#if defined(TARGET_MIPS64)
235785e8
AM
14260static void decode_i64_mips16(DisasContext *ctx,
14261 int ry, int funct, int16_t offset,
14262 int extended)
364d4831
NF
14263{
14264 switch (funct) {
14265 case I64_LDSP:
d9224450 14266 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14267 check_mips_64(ctx);
14268 offset = extended ? offset : offset << 3;
d75c135e 14269 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
14270 break;
14271 case I64_SDSP:
d9224450 14272 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14273 check_mips_64(ctx);
14274 offset = extended ? offset : offset << 3;
5c13fdfd 14275 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
14276 break;
14277 case I64_SDRASP:
d9224450 14278 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14279 check_mips_64(ctx);
14280 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 14281 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
14282 break;
14283 case I64_DADJSP:
d9224450 14284 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14285 check_mips_64(ctx);
14286 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 14287 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
14288 break;
14289 case I64_LDPC:
d9224450
MR
14290 check_insn(ctx, ISA_MIPS3);
14291 check_mips_64(ctx);
364d4831 14292 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 14293 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14294 } else {
14295 offset = extended ? offset : offset << 3;
d75c135e 14296 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
14297 }
14298 break;
14299 case I64_DADDIU5:
d9224450 14300 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14301 check_mips_64(ctx);
14302 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 14303 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
14304 break;
14305 case I64_DADDIUPC:
d9224450 14306 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14307 check_mips_64(ctx);
14308 offset = extended ? offset : offset << 2;
14309 gen_addiupc(ctx, ry, offset, 1, extended);
14310 break;
14311 case I64_DADDIUSP:
d9224450 14312 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14313 check_mips_64(ctx);
14314 offset = extended ? offset : offset << 2;
d75c135e 14315 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
14316 break;
14317 }
14318}
14319#endif
14320
235785e8 14321static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 14322{
eeb3bba8 14323 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
14324 int op, rx, ry, funct, sa;
14325 int16_t imm, offset;
14326
14327 ctx->opcode = (ctx->opcode << 16) | extend;
14328 op = (ctx->opcode >> 11) & 0x1f;
14329 sa = (ctx->opcode >> 22) & 0x1f;
14330 funct = (ctx->opcode >> 8) & 0x7;
14331 rx = xlat((ctx->opcode >> 8) & 0x7);
14332 ry = xlat((ctx->opcode >> 5) & 0x7);
14333 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14334 | ((ctx->opcode >> 21) & 0x3f) << 5
14335 | (ctx->opcode & 0x1f));
14336
7480515f
AM
14337 /*
14338 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14339 * counterparts.
14340 */
364d4831
NF
14341 switch (op) {
14342 case M16_OPC_ADDIUSP:
d75c135e 14343 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
14344 break;
14345 case M16_OPC_ADDIUPC:
14346 gen_addiupc(ctx, rx, imm, 0, 1);
14347 break;
14348 case M16_OPC_B:
b231c103 14349 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
14350 /* No delay slot, so just process as a normal instruction */
14351 break;
14352 case M16_OPC_BEQZ:
b231c103 14353 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
14354 /* No delay slot, so just process as a normal instruction */
14355 break;
14356 case M16_OPC_BNEQZ:
b231c103 14357 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
14358 /* No delay slot, so just process as a normal instruction */
14359 break;
14360 case M16_OPC_SHIFT:
14361 switch (ctx->opcode & 0x3) {
14362 case 0x0:
d75c135e 14363 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
14364 break;
14365 case 0x1:
14366#if defined(TARGET_MIPS64)
14367 check_mips_64(ctx);
d75c135e 14368 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 14369#else
9c708c7f 14370 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14371#endif
14372 break;
14373 case 0x2:
d75c135e 14374 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
14375 break;
14376 case 0x3:
d75c135e 14377 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
14378 break;
14379 }
14380 break;
14381#if defined(TARGET_MIPS64)
14382 case M16_OPC_LD:
d9224450 14383 check_insn(ctx, ISA_MIPS3);
d75de749 14384 check_mips_64(ctx);
d75c135e 14385 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
14386 break;
14387#endif
14388 case M16_OPC_RRIA:
14389 imm = ctx->opcode & 0xf;
14390 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14391 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14392 imm = (int16_t) (imm << 1) >> 1;
14393 if ((ctx->opcode >> 4) & 0x1) {
14394#if defined(TARGET_MIPS64)
14395 check_mips_64(ctx);
d75c135e 14396 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 14397#else
9c708c7f 14398 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14399#endif
14400 } else {
d75c135e 14401 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14402 }
14403 break;
14404 case M16_OPC_ADDIU8:
d75c135e 14405 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14406 break;
14407 case M16_OPC_SLTI:
d75c135e 14408 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14409 break;
14410 case M16_OPC_SLTIU:
d75c135e 14411 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14412 break;
14413 case M16_OPC_I8:
14414 switch (funct) {
14415 case I8_BTEQZ:
b231c103 14416 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
14417 break;
14418 case I8_BTNEZ:
b231c103 14419 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
14420 break;
14421 case I8_SWRASP:
5c13fdfd 14422 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
14423 break;
14424 case I8_ADJSP:
d75c135e 14425 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
14426 break;
14427 case I8_SVRS:
bbd5e4a2 14428 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
14429 {
14430 int xsregs = (ctx->opcode >> 24) & 0x7;
14431 int aregs = (ctx->opcode >> 16) & 0xf;
14432 int do_ra = (ctx->opcode >> 6) & 0x1;
14433 int do_s0 = (ctx->opcode >> 5) & 0x1;
14434 int do_s1 = (ctx->opcode >> 4) & 0x1;
14435 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14436 | (ctx->opcode & 0xf)) << 3;
14437
14438 if (ctx->opcode & (1 << 7)) {
14439 gen_mips16_save(ctx, xsregs, aregs,
14440 do_ra, do_s0, do_s1,
14441 framesize);
14442 } else {
14443 gen_mips16_restore(ctx, xsregs, aregs,
14444 do_ra, do_s0, do_s1,
14445 framesize);
14446 }
14447 }
14448 break;
14449 default:
9c708c7f 14450 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14451 break;
14452 }
14453 break;
14454 case M16_OPC_LI:
14455 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14456 break;
14457 case M16_OPC_CMPI:
14458 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14459 break;
14460#if defined(TARGET_MIPS64)
14461 case M16_OPC_SD:
d9224450
MR
14462 check_insn(ctx, ISA_MIPS3);
14463 check_mips_64(ctx);
5c13fdfd 14464 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
14465 break;
14466#endif
14467 case M16_OPC_LB:
d75c135e 14468 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14469 break;
14470 case M16_OPC_LH:
d75c135e 14471 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
14472 break;
14473 case M16_OPC_LWSP:
d75c135e 14474 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
14475 break;
14476 case M16_OPC_LW:
d75c135e 14477 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
14478 break;
14479 case M16_OPC_LBU:
d75c135e 14480 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14481 break;
14482 case M16_OPC_LHU:
d75c135e 14483 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
14484 break;
14485 case M16_OPC_LWPC:
d75c135e 14486 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
14487 break;
14488#if defined(TARGET_MIPS64)
14489 case M16_OPC_LWU:
d9224450
MR
14490 check_insn(ctx, ISA_MIPS3);
14491 check_mips_64(ctx);
d75c135e 14492 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
14493 break;
14494#endif
14495 case M16_OPC_SB:
5c13fdfd 14496 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14497 break;
14498 case M16_OPC_SH:
5c13fdfd 14499 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
14500 break;
14501 case M16_OPC_SWSP:
5c13fdfd 14502 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
14503 break;
14504 case M16_OPC_SW:
5c13fdfd 14505 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
14506 break;
14507#if defined(TARGET_MIPS64)
14508 case M16_OPC_I64:
d75c135e 14509 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
14510 break;
14511#endif
14512 default:
9c708c7f 14513 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14514 break;
14515 }
14516
14517 return 4;
14518}
14519
3b3c1694
LA
14520static inline bool is_uhi(int sdbbp_code)
14521{
14522#ifdef CONFIG_USER_ONLY
14523 return false;
14524#else
14525 return semihosting_enabled() && sdbbp_code == 1;
14526#endif
14527}
14528
82ba4266
AB
14529#ifdef CONFIG_USER_ONLY
14530/* The above should dead-code away any calls to this..*/
14531static inline void gen_helper_do_semihosting(void *env)
14532{
14533 g_assert_not_reached();
14534}
14535#endif
14536
235785e8 14537static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
14538{
14539 int rx, ry;
14540 int sa;
14541 int op, cnvt_op, op1, offset;
14542 int funct;
14543 int n_bytes;
14544
14545 op = (ctx->opcode >> 11) & 0x1f;
14546 sa = (ctx->opcode >> 2) & 0x7;
14547 sa = sa == 0 ? 8 : sa;
14548 rx = xlat((ctx->opcode >> 8) & 0x7);
14549 cnvt_op = (ctx->opcode >> 5) & 0x7;
14550 ry = xlat((ctx->opcode >> 5) & 0x7);
14551 op1 = offset = ctx->opcode & 0x1f;
14552
14553 n_bytes = 2;
14554
14555 switch (op) {
14556 case M16_OPC_ADDIUSP:
14557 {
14558 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14559
d75c135e 14560 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
14561 }
14562 break;
14563 case M16_OPC_ADDIUPC:
14564 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14565 break;
14566 case M16_OPC_B:
14567 offset = (ctx->opcode & 0x7ff) << 1;
14568 offset = (int16_t)(offset << 4) >> 4;
b231c103 14569 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
14570 /* No delay slot, so just process as a normal instruction */
14571 break;
14572 case M16_OPC_JAL:
eeb3bba8 14573 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
14574 offset = (((ctx->opcode & 0x1f) << 21)
14575 | ((ctx->opcode >> 5) & 0x1f) << 16
14576 | offset) << 2;
b231c103
YK
14577 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14578 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 14579 n_bytes = 4;
364d4831
NF
14580 break;
14581 case M16_OPC_BEQZ:
b231c103
YK
14582 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14583 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14584 /* No delay slot, so just process as a normal instruction */
14585 break;
14586 case M16_OPC_BNEQZ:
b231c103
YK
14587 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14588 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14589 /* No delay slot, so just process as a normal instruction */
14590 break;
14591 case M16_OPC_SHIFT:
14592 switch (ctx->opcode & 0x3) {
14593 case 0x0:
d75c135e 14594 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
14595 break;
14596 case 0x1:
14597#if defined(TARGET_MIPS64)
d9224450 14598 check_insn(ctx, ISA_MIPS3);
364d4831 14599 check_mips_64(ctx);
d75c135e 14600 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 14601#else
9c708c7f 14602 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14603#endif
14604 break;
14605 case 0x2:
d75c135e 14606 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
14607 break;
14608 case 0x3:
d75c135e 14609 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
14610 break;
14611 }
14612 break;
14613#if defined(TARGET_MIPS64)
14614 case M16_OPC_LD:
d9224450 14615 check_insn(ctx, ISA_MIPS3);
364d4831 14616 check_mips_64(ctx);
d75c135e 14617 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
14618 break;
14619#endif
14620 case M16_OPC_RRIA:
14621 {
14622 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14623
14624 if ((ctx->opcode >> 4) & 1) {
14625#if defined(TARGET_MIPS64)
d9224450 14626 check_insn(ctx, ISA_MIPS3);
364d4831 14627 check_mips_64(ctx);
d75c135e 14628 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 14629#else
9c708c7f 14630 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14631#endif
14632 } else {
d75c135e 14633 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
14634 }
14635 }
14636 break;
14637 case M16_OPC_ADDIU8:
14638 {
14639 int16_t imm = (int8_t) ctx->opcode;
14640
d75c135e 14641 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
14642 }
14643 break;
14644 case M16_OPC_SLTI:
14645 {
14646 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14647 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
14648 }
14649 break;
14650 case M16_OPC_SLTIU:
14651 {
14652 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14653 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
14654 }
14655 break;
14656 case M16_OPC_I8:
14657 {
14658 int reg32;
14659
14660 funct = (ctx->opcode >> 8) & 0x7;
14661 switch (funct) {
14662 case I8_BTEQZ:
14663 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 14664 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14665 break;
14666 case I8_BTNEZ:
14667 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 14668 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
14669 break;
14670 case I8_SWRASP:
5c13fdfd 14671 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
14672 break;
14673 case I8_ADJSP:
d75c135e 14674 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
14675 ((int8_t)ctx->opcode) << 3);
14676 break;
14677 case I8_SVRS:
bbd5e4a2 14678 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
14679 {
14680 int do_ra = ctx->opcode & (1 << 6);
14681 int do_s0 = ctx->opcode & (1 << 5);
14682 int do_s1 = ctx->opcode & (1 << 4);
14683 int framesize = ctx->opcode & 0xf;
14684
14685 if (framesize == 0) {
14686 framesize = 128;
14687 } else {
14688 framesize = framesize << 3;
14689 }
14690
14691 if (ctx->opcode & (1 << 7)) {
14692 gen_mips16_save(ctx, 0, 0,
14693 do_ra, do_s0, do_s1, framesize);
14694 } else {
14695 gen_mips16_restore(ctx, 0, 0,
14696 do_ra, do_s0, do_s1, framesize);
14697 }
14698 }
14699 break;
14700 case I8_MOV32R:
14701 {
14702 int rz = xlat(ctx->opcode & 0x7);
14703
14704 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14705 ((ctx->opcode >> 5) & 0x7);
d75c135e 14706 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
14707 }
14708 break;
14709 case I8_MOVR32:
14710 reg32 = ctx->opcode & 0x1f;
d75c135e 14711 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
14712 break;
14713 default:
9c708c7f 14714 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14715 break;
14716 }
14717 }
14718 break;
14719 case M16_OPC_LI:
14720 {
14721 int16_t imm = (uint8_t) ctx->opcode;
14722
d75c135e 14723 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
14724 }
14725 break;
14726 case M16_OPC_CMPI:
14727 {
14728 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 14729 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
14730 }
14731 break;
14732#if defined(TARGET_MIPS64)
14733 case M16_OPC_SD:
d9224450 14734 check_insn(ctx, ISA_MIPS3);
364d4831 14735 check_mips_64(ctx);
5c13fdfd 14736 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
14737 break;
14738#endif
14739 case M16_OPC_LB:
d75c135e 14740 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
14741 break;
14742 case M16_OPC_LH:
d75c135e 14743 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
14744 break;
14745 case M16_OPC_LWSP:
d75c135e 14746 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14747 break;
14748 case M16_OPC_LW:
d75c135e 14749 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
14750 break;
14751 case M16_OPC_LBU:
d75c135e 14752 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
14753 break;
14754 case M16_OPC_LHU:
d75c135e 14755 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
14756 break;
14757 case M16_OPC_LWPC:
d75c135e 14758 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 14759 break;
235785e8 14760#if defined(TARGET_MIPS64)
364d4831 14761 case M16_OPC_LWU:
d9224450 14762 check_insn(ctx, ISA_MIPS3);
364d4831 14763 check_mips_64(ctx);
d75c135e 14764 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
14765 break;
14766#endif
14767 case M16_OPC_SB:
5c13fdfd 14768 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
14769 break;
14770 case M16_OPC_SH:
5c13fdfd 14771 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14772 break;
14773 case M16_OPC_SWSP:
5c13fdfd 14774 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14775 break;
14776 case M16_OPC_SW:
5c13fdfd 14777 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14778 break;
14779 case M16_OPC_RRR:
14780 {
14781 int rz = xlat((ctx->opcode >> 2) & 0x7);
14782 int mips32_op;
14783
14784 switch (ctx->opcode & 0x3) {
14785 case RRR_ADDU:
14786 mips32_op = OPC_ADDU;
14787 break;
14788 case RRR_SUBU:
14789 mips32_op = OPC_SUBU;
14790 break;
14791#if defined(TARGET_MIPS64)
14792 case RRR_DADDU:
14793 mips32_op = OPC_DADDU;
d9224450 14794 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14795 check_mips_64(ctx);
14796 break;
14797 case RRR_DSUBU:
14798 mips32_op = OPC_DSUBU;
d9224450 14799 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14800 check_mips_64(ctx);
14801 break;
14802#endif
14803 default:
9c708c7f 14804 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14805 goto done;
14806 }
14807
d75c135e 14808 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14809 done:
14810 ;
14811 }
14812 break;
14813 case M16_OPC_RR:
14814 switch (op1) {
14815 case RR_JR:
14816 {
14817 int nd = (ctx->opcode >> 7) & 0x1;
14818 int link = (ctx->opcode >> 6) & 0x1;
14819 int ra = (ctx->opcode >> 5) & 0x1;
14820
d9224450 14821 if (nd) {
bbd5e4a2 14822 check_insn(ctx, ISA_MIPS_R1);
d9224450
MR
14823 }
14824
364d4831 14825 if (link) {
b231c103 14826 op = OPC_JALR;
364d4831
NF
14827 } else {
14828 op = OPC_JR;
14829 }
14830
b231c103
YK
14831 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14832 (nd ? 0 : 2));
364d4831
NF
14833 }
14834 break;
14835 case RR_SDBBP:
3b3c1694
LA
14836 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14837 gen_helper_do_semihosting(cpu_env);
14838 } else {
7480515f
AM
14839 /*
14840 * XXX: not clear which exception should be raised
3b3c1694
LA
14841 * when in debug mode...
14842 */
bbd5e4a2 14843 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 14844 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14845 }
364d4831
NF
14846 break;
14847 case RR_SLT:
d75c135e 14848 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14849 break;
14850 case RR_SLTU:
d75c135e 14851 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14852 break;
14853 case RR_BREAK:
9c708c7f 14854 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14855 break;
14856 case RR_SLLV:
d75c135e 14857 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14858 break;
14859 case RR_SRLV:
d75c135e 14860 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14861 break;
14862 case RR_SRAV:
d75c135e 14863 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 14864 break;
235785e8 14865#if defined(TARGET_MIPS64)
364d4831 14866 case RR_DSRL:
d9224450 14867 check_insn(ctx, ISA_MIPS3);
364d4831 14868 check_mips_64(ctx);
d75c135e 14869 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14870 break;
14871#endif
14872 case RR_CMP:
d75c135e 14873 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14874 break;
14875 case RR_NEG:
d75c135e 14876 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14877 break;
14878 case RR_AND:
d75c135e 14879 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14880 break;
14881 case RR_OR:
d75c135e 14882 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14883 break;
14884 case RR_XOR:
d75c135e 14885 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14886 break;
14887 case RR_NOT:
d75c135e 14888 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14889 break;
14890 case RR_MFHI:
26135ead 14891 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14892 break;
14893 case RR_CNVT:
bbd5e4a2 14894 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
14895 switch (cnvt_op) {
14896 case RR_RY_CNVT_ZEB:
14897 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14898 break;
14899 case RR_RY_CNVT_ZEH:
14900 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14901 break;
14902 case RR_RY_CNVT_SEB:
14903 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14904 break;
14905 case RR_RY_CNVT_SEH:
14906 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14907 break;
71375b59 14908#if defined(TARGET_MIPS64)
364d4831 14909 case RR_RY_CNVT_ZEW:
bbd5e4a2 14910 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
14911 check_mips_64(ctx);
14912 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14913 break;
14914 case RR_RY_CNVT_SEW:
bbd5e4a2 14915 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
14916 check_mips_64(ctx);
14917 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14918 break;
14919#endif
14920 default:
9c708c7f 14921 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14922 break;
14923 }
14924 break;
14925 case RR_MFLO:
26135ead 14926 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 14927 break;
235785e8 14928#if defined(TARGET_MIPS64)
364d4831 14929 case RR_DSRA:
d9224450 14930 check_insn(ctx, ISA_MIPS3);
364d4831 14931 check_mips_64(ctx);
d75c135e 14932 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14933 break;
14934 case RR_DSLLV:
d9224450 14935 check_insn(ctx, ISA_MIPS3);
364d4831 14936 check_mips_64(ctx);
d75c135e 14937 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14938 break;
14939 case RR_DSRLV:
d9224450 14940 check_insn(ctx, ISA_MIPS3);
364d4831 14941 check_mips_64(ctx);
d75c135e 14942 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14943 break;
14944 case RR_DSRAV:
d9224450 14945 check_insn(ctx, ISA_MIPS3);
364d4831 14946 check_mips_64(ctx);
d75c135e 14947 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14948 break;
14949#endif
14950 case RR_MULT:
26135ead 14951 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14952 break;
14953 case RR_MULTU:
26135ead 14954 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14955 break;
14956 case RR_DIV:
26135ead 14957 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14958 break;
14959 case RR_DIVU:
26135ead 14960 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 14961 break;
235785e8 14962#if defined(TARGET_MIPS64)
364d4831 14963 case RR_DMULT:
d9224450 14964 check_insn(ctx, ISA_MIPS3);
364d4831 14965 check_mips_64(ctx);
26135ead 14966 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14967 break;
14968 case RR_DMULTU:
d9224450 14969 check_insn(ctx, ISA_MIPS3);
364d4831 14970 check_mips_64(ctx);
26135ead 14971 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14972 break;
14973 case RR_DDIV:
d9224450 14974 check_insn(ctx, ISA_MIPS3);
364d4831 14975 check_mips_64(ctx);
26135ead 14976 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14977 break;
14978 case RR_DDIVU:
d9224450 14979 check_insn(ctx, ISA_MIPS3);
364d4831 14980 check_mips_64(ctx);
26135ead 14981 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14982 break;
14983#endif
14984 default:
9c708c7f 14985 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14986 break;
14987 }
14988 break;
14989 case M16_OPC_EXTEND:
240ce26a 14990 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14991 n_bytes = 4;
14992 break;
14993#if defined(TARGET_MIPS64)
14994 case M16_OPC_I64:
14995 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14996 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14997 break;
14998#endif
14999 default:
9c708c7f 15000 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
15001 break;
15002 }
15003
15004 return n_bytes;
15005}
15006
211da992 15007/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 15008
211da992
CWR
15009/*
15010 * microMIPS32/microMIPS64 major opcodes
15011 *
15012 * 1. MIPS Architecture for Programmers Volume II-B:
15013 * The microMIPS32 Instruction Set (Revision 3.05)
15014 *
15015 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
15016 *
15017 * 2. MIPS Architecture For Programmers Volume II-A:
15018 * The MIPS64 Instruction Set (Revision 3.51)
15019 */
6af0bf9c 15020
3c824109
NF
15021enum {
15022 POOL32A = 0x00,
15023 POOL16A = 0x01,
15024 LBU16 = 0x02,
15025 MOVE16 = 0x03,
15026 ADDI32 = 0x04,
3a1f4268
YK
15027 R6_LUI = 0x04,
15028 AUI = 0x04,
3c824109
NF
15029 LBU32 = 0x05,
15030 SB32 = 0x06,
15031 LB32 = 0x07,
15032
15033 POOL32B = 0x08,
15034 POOL16B = 0x09,
15035 LHU16 = 0x0a,
15036 ANDI16 = 0x0b,
15037 ADDIU32 = 0x0c,
15038 LHU32 = 0x0d,
15039 SH32 = 0x0e,
15040 LH32 = 0x0f,
15041
15042 POOL32I = 0x10,
15043 POOL16C = 0x11,
15044 LWSP16 = 0x12,
15045 POOL16D = 0x13,
15046 ORI32 = 0x14,
15047 POOL32F = 0x15,
211da992
CWR
15048 POOL32S = 0x16, /* MIPS64 */
15049 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
15050
15051 POOL32C = 0x18,
15052 LWGP16 = 0x19,
15053 LW16 = 0x1a,
15054 POOL16E = 0x1b,
15055 XORI32 = 0x1c,
15056 JALS32 = 0x1d,
3a1f4268
YK
15057 BOVC = 0x1d,
15058 BEQC = 0x1d,
15059 BEQZALC = 0x1d,
3c824109 15060 ADDIUPC = 0x1e,
3a1f4268
YK
15061 PCREL = 0x1e,
15062 BNVC = 0x1f,
15063 BNEC = 0x1f,
15064 BNEZALC = 0x1f,
3c824109 15065
3a1f4268
YK
15066 R6_BEQZC = 0x20,
15067 JIC = 0x20,
3c824109
NF
15068 POOL16F = 0x21,
15069 SB16 = 0x22,
15070 BEQZ16 = 0x23,
3a1f4268 15071 BEQZC16 = 0x23,
3c824109
NF
15072 SLTI32 = 0x24,
15073 BEQ32 = 0x25,
3a1f4268 15074 BC = 0x25,
3c824109
NF
15075 SWC132 = 0x26,
15076 LWC132 = 0x27,
15077
3a1f4268 15078 /* 0x29 is reserved */
3c824109 15079 RES_29 = 0x29,
3a1f4268
YK
15080 R6_BNEZC = 0x28,
15081 JIALC = 0x28,
3c824109
NF
15082 SH16 = 0x2a,
15083 BNEZ16 = 0x2b,
3a1f4268 15084 BNEZC16 = 0x2b,
3c824109
NF
15085 SLTIU32 = 0x2c,
15086 BNE32 = 0x2d,
3a1f4268 15087 BALC = 0x2d,
3c824109
NF
15088 SDC132 = 0x2e,
15089 LDC132 = 0x2f,
15090
3a1f4268 15091 /* 0x31 is reserved */
3c824109 15092 RES_31 = 0x31,
3a1f4268
YK
15093 BLEZALC = 0x30,
15094 BGEZALC = 0x30,
15095 BGEUC = 0x30,
3c824109
NF
15096 SWSP16 = 0x32,
15097 B16 = 0x33,
3a1f4268 15098 BC16 = 0x33,
3c824109
NF
15099 ANDI32 = 0x34,
15100 J32 = 0x35,
3a1f4268
YK
15101 BGTZC = 0x35,
15102 BLTZC = 0x35,
15103 BLTC = 0x35,
211da992
CWR
15104 SD32 = 0x36, /* MIPS64 */
15105 LD32 = 0x37, /* MIPS64 */
3c824109 15106
3a1f4268 15107 /* 0x39 is reserved */
3c824109 15108 RES_39 = 0x39,
3a1f4268
YK
15109 BGTZALC = 0x38,
15110 BLTZALC = 0x38,
15111 BLTUC = 0x38,
3c824109
NF
15112 SW16 = 0x3a,
15113 LI16 = 0x3b,
15114 JALX32 = 0x3c,
15115 JAL32 = 0x3d,
3a1f4268
YK
15116 BLEZC = 0x3d,
15117 BGEZC = 0x3d,
15118 BGEC = 0x3d,
3c824109
NF
15119 SW32 = 0x3e,
15120 LW32 = 0x3f
15121};
15122
3a1f4268
YK
15123/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
15124enum {
15125 ADDIUPC_00 = 0x00,
c38a1d52
AR
15126 ADDIUPC_01 = 0x01,
15127 ADDIUPC_02 = 0x02,
15128 ADDIUPC_03 = 0x03,
15129 ADDIUPC_04 = 0x04,
15130 ADDIUPC_05 = 0x05,
15131 ADDIUPC_06 = 0x06,
3a1f4268
YK
15132 ADDIUPC_07 = 0x07,
15133 AUIPC = 0x1e,
15134 ALUIPC = 0x1f,
15135 LWPC_08 = 0x08,
c38a1d52
AR
15136 LWPC_09 = 0x09,
15137 LWPC_0A = 0x0A,
15138 LWPC_0B = 0x0B,
15139 LWPC_0C = 0x0C,
15140 LWPC_0D = 0x0D,
15141 LWPC_0E = 0x0E,
3a1f4268
YK
15142 LWPC_0F = 0x0F,
15143};
15144
3c824109
NF
15145/* POOL32A encoding of minor opcode field */
15146
15147enum {
7480515f
AM
15148 /*
15149 * These opcodes are distinguished only by bits 9..6; those bits are
15150 * what are recorded below.
15151 */
3c824109
NF
15152 SLL32 = 0x0,
15153 SRL32 = 0x1,
15154 SRA = 0x2,
15155 ROTR = 0x3,
3a1f4268
YK
15156 SELEQZ = 0x5,
15157 SELNEZ = 0x6,
b00c7218 15158 R6_RDHWR = 0x7,
3c824109
NF
15159
15160 SLLV = 0x0,
15161 SRLV = 0x1,
15162 SRAV = 0x2,
15163 ROTRV = 0x3,
15164 ADD = 0x4,
15165 ADDU32 = 0x5,
15166 SUB = 0x6,
15167 SUBU32 = 0x7,
15168 MUL = 0x8,
15169 AND = 0x9,
15170 OR32 = 0xa,
15171 NOR = 0xb,
15172 XOR32 = 0xc,
15173 SLT = 0xd,
15174 SLTU = 0xe,
15175
15176 MOVN = 0x0,
3a1f4268 15177 R6_MUL = 0x0,
3c824109 15178 MOVZ = 0x1,
3a1f4268
YK
15179 MUH = 0x1,
15180 MULU = 0x2,
15181 MUHU = 0x3,
3c824109 15182 LWXS = 0x4,
3a1f4268
YK
15183 R6_DIV = 0x4,
15184 MOD = 0x5,
15185 R6_DIVU = 0x6,
15186 MODU = 0x7,
3c824109
NF
15187
15188 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 15189 BREAK32 = 0x07,
3c824109 15190 INS = 0x0c,
3a1f4268
YK
15191 LSA = 0x0f,
15192 ALIGN = 0x1f,
3c824109 15193 EXT = 0x2c,
bb238210
YK
15194 POOL32AXF = 0x3c,
15195 SIGRIE = 0x3f
3c824109
NF
15196};
15197
15198/* POOL32AXF encoding of minor opcode field extension */
15199
d132c79f
CWR
15200/*
15201 * 1. MIPS Architecture for Programmers Volume II-B:
15202 * The microMIPS32 Instruction Set (Revision 3.05)
15203 *
15204 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15205 *
15206 * 2. MIPS Architecture for Programmers VolumeIV-e:
15207 * The MIPS DSP Application-Specific Extension
15208 * to the microMIPS32 Architecture (Revision 2.34)
15209 *
15210 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15211 */
15212
3c824109
NF
15213enum {
15214 /* bits 11..6 */
15215 TEQ = 0x00,
15216 TGE = 0x08,
15217 TGEU = 0x10,
15218 TLT = 0x20,
15219 TLTU = 0x28,
15220 TNE = 0x30,
15221
15222 MFC0 = 0x03,
15223 MTC0 = 0x0b,
15224
d132c79f
CWR
15225 /* begin of microMIPS32 DSP */
15226
3c824109
NF
15227 /* bits 13..12 for 0x01 */
15228 MFHI_ACC = 0x0,
15229 MFLO_ACC = 0x1,
15230 MTHI_ACC = 0x2,
15231 MTLO_ACC = 0x3,
15232
15233 /* bits 13..12 for 0x2a */
15234 MADD_ACC = 0x0,
15235 MADDU_ACC = 0x1,
15236 MSUB_ACC = 0x2,
15237 MSUBU_ACC = 0x3,
15238
15239 /* bits 13..12 for 0x32 */
15240 MULT_ACC = 0x0,
6801038b 15241 MULTU_ACC = 0x1,
3c824109 15242
d132c79f
CWR
15243 /* end of microMIPS32 DSP */
15244
3c824109 15245 /* bits 15..12 for 0x2c */
3a1f4268 15246 BITSWAP = 0x0,
3c824109
NF
15247 SEB = 0x2,
15248 SEH = 0x3,
15249 CLO = 0x4,
15250 CLZ = 0x5,
15251 RDHWR = 0x6,
15252 WSBH = 0x7,
15253 MULT = 0x8,
15254 MULTU = 0x9,
15255 DIV = 0xa,
15256 DIVU = 0xb,
15257 MADD = 0xc,
15258 MADDU = 0xd,
15259 MSUB = 0xe,
15260 MSUBU = 0xf,
15261
15262 /* bits 15..12 for 0x34 */
15263 MFC2 = 0x4,
15264 MTC2 = 0x5,
15265 MFHC2 = 0x8,
15266 MTHC2 = 0x9,
15267 CFC2 = 0xc,
15268 CTC2 = 0xd,
15269
15270 /* bits 15..12 for 0x3c */
15271 JALR = 0x0,
15272 JR = 0x0, /* alias */
3a1f4268
YK
15273 JALRC = 0x0,
15274 JRC = 0x0,
3c824109 15275 JALR_HB = 0x1,
3a1f4268 15276 JALRC_HB = 0x1,
3c824109
NF
15277 JALRS = 0x4,
15278 JALRS_HB = 0x5,
15279
15280 /* bits 15..12 for 0x05 */
15281 RDPGPR = 0xe,
15282 WRPGPR = 0xf,
15283
15284 /* bits 15..12 for 0x0d */
15285 TLBP = 0x0,
15286 TLBR = 0x1,
15287 TLBWI = 0x2,
15288 TLBWR = 0x3,
e60ec063
YK
15289 TLBINV = 0x4,
15290 TLBINVF = 0x5,
3c824109
NF
15291 WAIT = 0x9,
15292 IRET = 0xd,
15293 DERET = 0xe,
15294 ERET = 0xf,
15295
15296 /* bits 15..12 for 0x15 */
15297 DMT = 0x0,
15298 DVPE = 0x1,
15299 EMT = 0x2,
15300 EVPE = 0x3,
15301
15302 /* bits 15..12 for 0x1d */
15303 DI = 0x4,
15304 EI = 0x5,
15305
15306 /* bits 15..12 for 0x2d */
15307 SYNC = 0x6,
15308 SYSCALL = 0x8,
15309 SDBBP = 0xd,
15310
15311 /* bits 15..12 for 0x35 */
15312 MFHI32 = 0x0,
15313 MFLO32 = 0x1,
15314 MTHI32 = 0x2,
15315 MTLO32 = 0x3,
15316};
15317
15318/* POOL32B encoding of minor opcode field (bits 15..12) */
15319
15320enum {
15321 LWC2 = 0x0,
15322 LWP = 0x1,
15323 LDP = 0x4,
15324 LWM32 = 0x5,
15325 CACHE = 0x6,
15326 LDM = 0x7,
15327 SWC2 = 0x8,
15328 SWP = 0x9,
15329 SDP = 0xc,
15330 SWM32 = 0xd,
15331 SDM = 0xf
15332};
15333
15334/* POOL32C encoding of minor opcode field (bits 15..12) */
15335
15336enum {
15337 LWL = 0x0,
15338 SWL = 0x8,
15339 LWR = 0x1,
15340 SWR = 0x9,
15341 PREF = 0x2,
8fffc646 15342 ST_EVA = 0xa,
3c824109
NF
15343 LL = 0x3,
15344 SC = 0xb,
15345 LDL = 0x4,
15346 SDL = 0xc,
15347 LDR = 0x5,
15348 SDR = 0xd,
8fffc646 15349 LD_EVA = 0x6,
3c824109
NF
15350 LWU = 0xe,
15351 LLD = 0x7,
15352 SCD = 0xf
15353};
15354
8fffc646
JH
15355/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15356
15357enum {
15358 LBUE = 0x0,
15359 LHUE = 0x1,
15360 LWLE = 0x2,
15361 LWRE = 0x3,
15362 LBE = 0x4,
15363 LHE = 0x5,
15364 LLE = 0x6,
15365 LWE = 0x7,
15366};
15367
15368/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15369
15370enum {
15371 SWLE = 0x0,
15372 SWRE = 0x1,
15373 PREFE = 0x2,
15374 CACHEE = 0x3,
15375 SBE = 0x4,
15376 SHE = 0x5,
15377 SCE = 0x6,
15378 SWE = 0x7,
15379};
15380
3c824109
NF
15381/* POOL32F encoding of minor opcode field (bits 5..0) */
15382
15383enum {
15384 /* These are the bit 7..6 values */
15385 ADD_FMT = 0x0,
3c824109
NF
15386
15387 SUB_FMT = 0x1,
3c824109
NF
15388
15389 MUL_FMT = 0x2,
15390
15391 DIV_FMT = 0x3,
15392
15393 /* These are the bit 8..6 values */
3a1f4268 15394 MOVN_FMT = 0x0,
3c824109
NF
15395 RSQRT2_FMT = 0x0,
15396 MOVF_FMT = 0x0,
3a1f4268
YK
15397 RINT_FMT = 0x0,
15398 SELNEZ_FMT = 0x0,
3c824109 15399
3a1f4268 15400 MOVZ_FMT = 0x1,
3c824109
NF
15401 LWXC1 = 0x1,
15402 MOVT_FMT = 0x1,
3a1f4268
YK
15403 CLASS_FMT = 0x1,
15404 SELEQZ_FMT = 0x1,
3c824109
NF
15405
15406 PLL_PS = 0x2,
15407 SWXC1 = 0x2,
3a1f4268 15408 SEL_FMT = 0x2,
3c824109
NF
15409
15410 PLU_PS = 0x3,
15411 LDXC1 = 0x3,
15412
3a1f4268 15413 MOVN_FMT_04 = 0x4,
3c824109
NF
15414 PUL_PS = 0x4,
15415 SDXC1 = 0x4,
15416 RECIP2_FMT = 0x4,
15417
3a1f4268 15418 MOVZ_FMT_05 = 0x05,
3c824109
NF
15419 PUU_PS = 0x5,
15420 LUXC1 = 0x5,
15421
15422 CVT_PS_S = 0x6,
15423 SUXC1 = 0x6,
15424 ADDR_PS = 0x6,
15425 PREFX = 0x6,
3a1f4268 15426 MADDF_FMT = 0x6,
3c824109
NF
15427
15428 MULR_PS = 0x7,
3a1f4268 15429 MSUBF_FMT = 0x7,
3c824109
NF
15430
15431 MADD_S = 0x01,
15432 MADD_D = 0x09,
15433 MADD_PS = 0x11,
15434 ALNV_PS = 0x19,
15435 MSUB_S = 0x21,
15436 MSUB_D = 0x29,
15437 MSUB_PS = 0x31,
15438
15439 NMADD_S = 0x02,
15440 NMADD_D = 0x0a,
15441 NMADD_PS = 0x12,
15442 NMSUB_S = 0x22,
15443 NMSUB_D = 0x2a,
15444 NMSUB_PS = 0x32,
15445
3a1f4268
YK
15446 MIN_FMT = 0x3,
15447 MAX_FMT = 0xb,
15448 MINA_FMT = 0x23,
15449 MAXA_FMT = 0x2b,
3c824109
NF
15450 POOL32FXF = 0x3b,
15451
15452 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
15453 C_COND_FMT = 0x3c,
15454
15455 CMP_CONDN_S = 0x5,
15456 CMP_CONDN_D = 0x15
3c824109
NF
15457};
15458
15459/* POOL32Fxf encoding of minor opcode extension field */
15460
15461enum {
15462 CVT_L = 0x04,
15463 RSQRT_FMT = 0x08,
15464 FLOOR_L = 0x0c,
15465 CVT_PW_PS = 0x1c,
15466 CVT_W = 0x24,
15467 SQRT_FMT = 0x28,
15468 FLOOR_W = 0x2c,
15469 CVT_PS_PW = 0x3c,
15470 CFC1 = 0x40,
15471 RECIP_FMT = 0x48,
15472 CEIL_L = 0x4c,
15473 CTC1 = 0x60,
15474 CEIL_W = 0x6c,
15475 MFC1 = 0x80,
15476 CVT_S_PL = 0x84,
15477 TRUNC_L = 0x8c,
15478 MTC1 = 0xa0,
15479 CVT_S_PU = 0xa4,
15480 TRUNC_W = 0xac,
15481 MFHC1 = 0xc0,
15482 ROUND_L = 0xcc,
15483 MTHC1 = 0xe0,
15484 ROUND_W = 0xec,
15485
15486 MOV_FMT = 0x01,
15487 MOVF = 0x05,
15488 ABS_FMT = 0x0d,
15489 RSQRT1_FMT = 0x1d,
15490 MOVT = 0x25,
15491 NEG_FMT = 0x2d,
15492 CVT_D = 0x4d,
15493 RECIP1_FMT = 0x5d,
15494 CVT_S = 0x6d
15495};
15496
15497/* POOL32I encoding of minor opcode field (bits 25..21) */
15498
15499enum {
15500 BLTZ = 0x00,
15501 BLTZAL = 0x01,
15502 BGEZ = 0x02,
15503 BGEZAL = 0x03,
15504 BLEZ = 0x04,
15505 BNEZC = 0x05,
15506 BGTZ = 0x06,
15507 BEQZC = 0x07,
15508 TLTI = 0x08,
3a1f4268 15509 BC1EQZC = 0x08,
3c824109 15510 TGEI = 0x09,
3a1f4268 15511 BC1NEZC = 0x09,
3c824109 15512 TLTIU = 0x0a,
3a1f4268 15513 BC2EQZC = 0x0a,
3c824109 15514 TGEIU = 0x0b,
3a1f4268 15515 BC2NEZC = 0x0a,
3c824109 15516 TNEI = 0x0c,
3a1f4268 15517 R6_SYNCI = 0x0c,
3c824109
NF
15518 LUI = 0x0d,
15519 TEQI = 0x0e,
15520 SYNCI = 0x10,
15521 BLTZALS = 0x11,
15522 BGEZALS = 0x13,
15523 BC2F = 0x14,
15524 BC2T = 0x15,
15525 BPOSGE64 = 0x1a,
15526 BPOSGE32 = 0x1b,
15527 /* These overlap and are distinguished by bit16 of the instruction */
15528 BC1F = 0x1c,
15529 BC1T = 0x1d,
15530 BC1ANY2F = 0x1c,
15531 BC1ANY2T = 0x1d,
15532 BC1ANY4F = 0x1e,
15533 BC1ANY4T = 0x1f
15534};
15535
15536/* POOL16A encoding of minor opcode field */
15537
15538enum {
15539 ADDU16 = 0x0,
15540 SUBU16 = 0x1
15541};
15542
15543/* POOL16B encoding of minor opcode field */
15544
15545enum {
15546 SLL16 = 0x0,
15547 SRL16 = 0x1
15548};
15549
15550/* POOL16C encoding of minor opcode field */
15551
15552enum {
15553 NOT16 = 0x00,
15554 XOR16 = 0x04,
15555 AND16 = 0x08,
15556 OR16 = 0x0c,
15557 LWM16 = 0x10,
15558 SWM16 = 0x14,
15559 JR16 = 0x18,
15560 JRC16 = 0x1a,
15561 JALR16 = 0x1c,
15562 JALR16S = 0x1e,
15563 MFHI16 = 0x20,
15564 MFLO16 = 0x24,
15565 BREAK16 = 0x28,
15566 SDBBP16 = 0x2c,
15567 JRADDIUSP = 0x30
15568};
15569
3a1f4268
YK
15570/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15571
15572enum {
15573 R6_NOT16 = 0x00,
15574 R6_AND16 = 0x01,
15575 R6_LWM16 = 0x02,
15576 R6_JRC16 = 0x03,
15577 MOVEP = 0x04,
c38a1d52
AR
15578 MOVEP_05 = 0x05,
15579 MOVEP_06 = 0x06,
3a1f4268
YK
15580 MOVEP_07 = 0x07,
15581 R6_XOR16 = 0x08,
15582 R6_OR16 = 0x09,
15583 R6_SWM16 = 0x0a,
15584 JALRC16 = 0x0b,
15585 MOVEP_0C = 0x0c,
c38a1d52
AR
15586 MOVEP_0D = 0x0d,
15587 MOVEP_0E = 0x0e,
3a1f4268
YK
15588 MOVEP_0F = 0x0f,
15589 JRCADDIUSP = 0x13,
15590 R6_BREAK16 = 0x1b,
15591 R6_SDBBP16 = 0x3b
15592};
15593
3c824109
NF
15594/* POOL16D encoding of minor opcode field */
15595
15596enum {
15597 ADDIUS5 = 0x0,
15598 ADDIUSP = 0x1
15599};
15600
15601/* POOL16E encoding of minor opcode field */
15602
15603enum {
15604 ADDIUR2 = 0x0,
15605 ADDIUR1SP = 0x1
15606};
15607
235785e8 15608static int mmreg(int r)
3c824109
NF
15609{
15610 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15611
15612 return map[r];
15613}
15614
15615/* Used for 16-bit store instructions. */
235785e8 15616static int mmreg2(int r)
3c824109
NF
15617{
15618 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15619
15620 return map[r];
15621}
15622
15623#define uMIPS_RD(op) ((op >> 7) & 0x7)
15624#define uMIPS_RS(op) ((op >> 4) & 0x7)
15625#define uMIPS_RS2(op) uMIPS_RS(op)
15626#define uMIPS_RS1(op) ((op >> 1) & 0x7)
15627#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15628#define uMIPS_RS5(op) (op & 0x1f)
15629
15630/* Signed immediate */
15631#define SIMM(op, start, width) \
71375b59
AM
15632 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15633 << (32 - width)) \
15634 >> (32 - width))
3c824109 15635/* Zero-extended immediate */
71375b59 15636#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 15637
d75c135e 15638static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
15639{
15640 int rd = mmreg(uMIPS_RD(ctx->opcode));
15641
d75c135e 15642 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
15643}
15644
d75c135e 15645static void gen_addiur2(DisasContext *ctx)
3c824109
NF
15646{
15647 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15648 int rd = mmreg(uMIPS_RD(ctx->opcode));
15649 int rs = mmreg(uMIPS_RS(ctx->opcode));
15650
d75c135e 15651 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
15652}
15653
d75c135e 15654static void gen_addiusp(DisasContext *ctx)
3c824109
NF
15655{
15656 int encoded = ZIMM(ctx->opcode, 1, 9);
15657 int decoded;
15658
15659 if (encoded <= 1) {
15660 decoded = 256 + encoded;
15661 } else if (encoded <= 255) {
15662 decoded = encoded;
15663 } else if (encoded <= 509) {
15664 decoded = encoded - 512;
15665 } else {
15666 decoded = encoded - 768;
15667 }
15668
d75c135e 15669 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
15670}
15671
d75c135e 15672static void gen_addius5(DisasContext *ctx)
3c824109
NF
15673{
15674 int imm = SIMM(ctx->opcode, 1, 4);
15675 int rd = (ctx->opcode >> 5) & 0x1f;
15676
d75c135e 15677 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
15678}
15679
d75c135e 15680static void gen_andi16(DisasContext *ctx)
3c824109
NF
15681{
15682 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15683 31, 32, 63, 64, 255, 32768, 65535 };
15684 int rd = mmreg(uMIPS_RD(ctx->opcode));
15685 int rs = mmreg(uMIPS_RS(ctx->opcode));
15686 int encoded = ZIMM(ctx->opcode, 0, 4);
15687
d75c135e 15688 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
15689}
15690
235785e8
AM
15691static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15692 int base, int16_t offset)
3c824109
NF
15693{
15694 TCGv t0, t1;
15695 TCGv_i32 t2;
15696
15697 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 15698 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15699 return;
15700 }
15701
15702 t0 = tcg_temp_new();
15703
15704 gen_base_offset_addr(ctx, t0, base, offset);
15705
15706 t1 = tcg_const_tl(reglist);
15707 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 15708
3c824109
NF
15709 save_cpu_state(ctx, 1);
15710 switch (opc) {
15711 case LWM32:
895c2d04 15712 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
15713 break;
15714 case SWM32:
895c2d04 15715 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
15716 break;
15717#ifdef TARGET_MIPS64
15718 case LDM:
895c2d04 15719 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
15720 break;
15721 case SDM:
895c2d04 15722 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 15723 break;
6af0bf9c 15724#endif
3c824109 15725 }
3c824109 15726 tcg_temp_free(t0);
33087598 15727 tcg_temp_free(t1);
3c824109
NF
15728 tcg_temp_free_i32(t2);
15729}
6af0bf9c 15730
3c824109 15731
240ce26a 15732static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 15733{
3c824109
NF
15734 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15735 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 15736
3c824109
NF
15737 switch (((ctx->opcode) >> 4) & 0x3f) {
15738 case NOT16 + 0:
15739 case NOT16 + 1:
15740 case NOT16 + 2:
15741 case NOT16 + 3:
d75c135e 15742 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
15743 break;
15744 case XOR16 + 0:
15745 case XOR16 + 1:
15746 case XOR16 + 2:
15747 case XOR16 + 3:
d75c135e 15748 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
15749 break;
15750 case AND16 + 0:
15751 case AND16 + 1:
15752 case AND16 + 2:
15753 case AND16 + 3:
d75c135e 15754 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
15755 break;
15756 case OR16 + 0:
15757 case OR16 + 1:
15758 case OR16 + 2:
15759 case OR16 + 3:
d75c135e 15760 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
15761 break;
15762 case LWM16 + 0:
15763 case LWM16 + 1:
15764 case LWM16 + 2:
15765 case LWM16 + 3:
15766 {
15767 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15768 int offset = ZIMM(ctx->opcode, 0, 4);
15769
15770 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15771 29, offset << 2);
15772 }
15773 break;
15774 case SWM16 + 0:
15775 case SWM16 + 1:
15776 case SWM16 + 2:
15777 case SWM16 + 3:
15778 {
15779 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15780 int offset = ZIMM(ctx->opcode, 0, 4);
15781
15782 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15783 29, offset << 2);
15784 }
15785 break;
15786 case JR16 + 0:
15787 case JR16 + 1:
15788 {
15789 int reg = ctx->opcode & 0x1f;
15790
b231c103 15791 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15792 }
3c824109
NF
15793 break;
15794 case JRC16 + 0:
15795 case JRC16 + 1:
15796 {
15797 int reg = ctx->opcode & 0x1f;
b231c103 15798 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
15799 /*
15800 * Let normal delay slot handling in our caller take us
15801 * to the branch target.
15802 */
3c824109
NF
15803 }
15804 break;
15805 case JALR16 + 0:
15806 case JALR16 + 1:
b231c103
YK
15807 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15808 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15809 break;
3c824109
NF
15810 case JALR16S + 0:
15811 case JALR16S + 1:
b231c103
YK
15812 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15813 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15814 break;
15815 case MFHI16 + 0:
15816 case MFHI16 + 1:
26135ead 15817 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15818 break;
15819 case MFLO16 + 0:
15820 case MFLO16 + 1:
26135ead 15821 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15822 break;
15823 case BREAK16:
9c708c7f 15824 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15825 break;
15826 case SDBBP16:
3b3c1694
LA
15827 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15828 gen_helper_do_semihosting(cpu_env);
15829 } else {
7480515f
AM
15830 /*
15831 * XXX: not clear which exception should be raised
3b3c1694
LA
15832 * when in debug mode...
15833 */
bbd5e4a2 15834 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 15835 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15836 }
3c824109
NF
15837 break;
15838 case JRADDIUSP + 0:
15839 case JRADDIUSP + 1:
15840 {
15841 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15842 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15843 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
15844 /*
15845 * Let normal delay slot handling in our caller take us
15846 * to the branch target.
15847 */
3c824109
NF
15848 }
15849 break;
15850 default:
9c708c7f 15851 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15852 break;
15853 }
15854}
15855
ed7ce6c0
YK
15856static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15857 int enc_rs)
15858{
15859 int rd, rs, re, rt;
15860 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15861 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15862 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15863 rd = rd_enc[enc_dest];
15864 re = re_enc[enc_dest];
15865 rs = rs_rt_enc[enc_rs];
15866 rt = rs_rt_enc[enc_rt];
15867 if (rs) {
15868 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15869 } else {
15870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15871 }
15872 if (rt) {
15873 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15874 } else {
15875 tcg_gen_movi_tl(cpu_gpr[re], 0);
15876 }
15877}
15878
15879static void gen_pool16c_r6_insn(DisasContext *ctx)
15880{
15881 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15882 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15883
15884 switch (ctx->opcode & 0xf) {
15885 case R6_NOT16:
15886 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15887 break;
15888 case R6_AND16:
15889 gen_logic(ctx, OPC_AND, rt, rt, rs);
15890 break;
15891 case R6_LWM16:
15892 {
15893 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15894 int offset = extract32(ctx->opcode, 4, 4);
15895 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15896 }
15897 break;
15898 case R6_JRC16: /* JRCADDIUSP */
15899 if ((ctx->opcode >> 4) & 1) {
15900 /* JRCADDIUSP */
15901 int imm = extract32(ctx->opcode, 5, 5);
15902 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15903 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15904 } else {
15905 /* JRC16 */
e1555d7d 15906 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15907 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15908 }
15909 break;
c38a1d52
AR
15910 case MOVEP:
15911 case MOVEP_05:
15912 case MOVEP_06:
15913 case MOVEP_07:
15914 case MOVEP_0C:
15915 case MOVEP_0D:
15916 case MOVEP_0E:
15917 case MOVEP_0F:
ed7ce6c0
YK
15918 {
15919 int enc_dest = uMIPS_RD(ctx->opcode);
15920 int enc_rt = uMIPS_RS2(ctx->opcode);
15921 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15922 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15923 }
15924 break;
15925 case R6_XOR16:
15926 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15927 break;
15928 case R6_OR16:
15929 gen_logic(ctx, OPC_OR, rt, rt, rs);
15930 break;
15931 case R6_SWM16:
15932 {
15933 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15934 int offset = extract32(ctx->opcode, 4, 4);
15935 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15936 }
15937 break;
15938 case JALRC16: /* BREAK16, SDBBP16 */
15939 switch (ctx->opcode & 0x3f) {
15940 case JALRC16:
15941 case JALRC16 + 0x20:
15942 /* JALRC16 */
15943 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15944 31, 0, 0);
15945 break;
15946 case R6_BREAK16:
15947 /* BREAK16 */
15948 generate_exception(ctx, EXCP_BREAK);
15949 break;
15950 case R6_SDBBP16:
15951 /* SDBBP16 */
060ebfef
LA
15952 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15953 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15954 } else {
060ebfef
LA
15955 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15956 generate_exception(ctx, EXCP_RI);
15957 } else {
15958 generate_exception(ctx, EXCP_DBp);
15959 }
ed7ce6c0
YK
15960 }
15961 break;
15962 }
15963 break;
15964 default:
15965 generate_exception(ctx, EXCP_RI);
15966 break;
15967 }
15968}
15969
235785e8 15970static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
15971{
15972 TCGv t0 = tcg_temp_new();
15973 TCGv t1 = tcg_temp_new();
15974
15975 gen_load_gpr(t0, base);
15976
15977 if (index != 0) {
15978 gen_load_gpr(t1, index);
15979 tcg_gen_shli_tl(t1, t1, 2);
15980 gen_op_addr_add(ctx, t0, t1, t0);
15981 }
15982
5f68f5ae 15983 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15984 gen_store_gpr(t1, rd);
15985
15986 tcg_temp_free(t0);
15987 tcg_temp_free(t1);
15988}
15989
235785e8
AM
15990static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15991 int base, int16_t offset)
3c824109 15992{
3c824109
NF
15993 TCGv t0, t1;
15994
36c6711b 15995 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15996 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15997 return;
15998 }
15999
3c824109
NF
16000 t0 = tcg_temp_new();
16001 t1 = tcg_temp_new();
8e9ade68 16002
3c824109
NF
16003 gen_base_offset_addr(ctx, t0, base, offset);
16004
16005 switch (opc) {
16006 case LWP:
36c6711b 16007 if (rd == base) {
9c708c7f 16008 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
16009 return;
16010 }
5f68f5ae 16011 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
16012 gen_store_gpr(t1, rd);
16013 tcg_gen_movi_tl(t1, 4);
16014 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 16015 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 16016 gen_store_gpr(t1, rd + 1);
3c824109
NF
16017 break;
16018 case SWP:
3c824109 16019 gen_load_gpr(t1, rd);
5f68f5ae 16020 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
16021 tcg_gen_movi_tl(t1, 4);
16022 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 16023 gen_load_gpr(t1, rd + 1);
5f68f5ae 16024 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
16025 break;
16026#ifdef TARGET_MIPS64
16027 case LDP:
36c6711b 16028 if (rd == base) {
9c708c7f 16029 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
16030 return;
16031 }
5f68f5ae 16032 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
16033 gen_store_gpr(t1, rd);
16034 tcg_gen_movi_tl(t1, 8);
16035 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 16036 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 16037 gen_store_gpr(t1, rd + 1);
3c824109
NF
16038 break;
16039 case SDP:
3c824109 16040 gen_load_gpr(t1, rd);
5f68f5ae 16041 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
16042 tcg_gen_movi_tl(t1, 8);
16043 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 16044 gen_load_gpr(t1, rd + 1);
5f68f5ae 16045 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
16046 break;
16047#endif
6af0bf9c 16048 }
3c824109
NF
16049 tcg_temp_free(t0);
16050 tcg_temp_free(t1);
16051}
618b0fe9 16052
d208ac0c
LA
16053static void gen_sync(int stype)
16054{
16055 TCGBar tcg_mo = TCG_BAR_SC;
16056
16057 switch (stype) {
16058 case 0x4: /* SYNC_WMB */
16059 tcg_mo |= TCG_MO_ST_ST;
16060 break;
16061 case 0x10: /* SYNC_MB */
16062 tcg_mo |= TCG_MO_ALL;
16063 break;
16064 case 0x11: /* SYNC_ACQUIRE */
16065 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
16066 break;
16067 case 0x12: /* SYNC_RELEASE */
16068 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
16069 break;
16070 case 0x13: /* SYNC_RMB */
16071 tcg_mo |= TCG_MO_LD_LD;
16072 break;
16073 default:
16074 tcg_mo |= TCG_MO_ALL;
16075 break;
16076 }
16077
16078 tcg_gen_mb(tcg_mo);
16079}
16080
235785e8 16081static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
16082{
16083 int extension = (ctx->opcode >> 6) & 0x3f;
16084 int minor = (ctx->opcode >> 12) & 0xf;
16085 uint32_t mips32_op;
16086
16087 switch (extension) {
16088 case TEQ:
16089 mips32_op = OPC_TEQ;
16090 goto do_trap;
16091 case TGE:
16092 mips32_op = OPC_TGE;
16093 goto do_trap;
16094 case TGEU:
16095 mips32_op = OPC_TGEU;
16096 goto do_trap;
16097 case TLT:
16098 mips32_op = OPC_TLT;
16099 goto do_trap;
16100 case TLTU:
16101 mips32_op = OPC_TLTU;
16102 goto do_trap;
16103 case TNE:
16104 mips32_op = OPC_TNE;
16105 do_trap:
16106 gen_trap(ctx, mips32_op, rs, rt, -1);
16107 break;
16108#ifndef CONFIG_USER_ONLY
16109 case MFC0:
16110 case MFC0 + 32:
2e15497c 16111 check_cp0_enabled(ctx);
3c824109
NF
16112 if (rt == 0) {
16113 /* Treat as NOP. */
16114 break;
16115 }
d75c135e 16116 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
16117 break;
16118 case MTC0:
16119 case MTC0 + 32:
2e15497c 16120 check_cp0_enabled(ctx);
3c824109
NF
16121 {
16122 TCGv t0 = tcg_temp_new();
618b0fe9 16123
3c824109 16124 gen_load_gpr(t0, rt);
d75c135e 16125 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
16126 tcg_temp_free(t0);
16127 }
16128 break;
16129#endif
a1fc6246
LA
16130 case 0x2a:
16131 switch (minor & 3) {
16132 case MADD_ACC:
16133 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16134 break;
16135 case MADDU_ACC:
16136 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16137 break;
16138 case MSUB_ACC:
16139 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16140 break;
16141 case MSUBU_ACC:
16142 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16143 break;
16144 default:
16145 goto pool32axf_invalid;
16146 }
16147 break;
16148 case 0x32:
16149 switch (minor & 3) {
16150 case MULT_ACC:
16151 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16152 break;
16153 case MULTU_ACC:
16154 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16155 break;
16156 default:
16157 goto pool32axf_invalid;
16158 }
16159 break;
3c824109
NF
16160 case 0x2c:
16161 switch (minor) {
e0332095 16162 case BITSWAP:
2e211e0a 16163 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16164 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16165 break;
3c824109
NF
16166 case SEB:
16167 gen_bshfl(ctx, OPC_SEB, rs, rt);
16168 break;
16169 case SEH:
16170 gen_bshfl(ctx, OPC_SEH, rs, rt);
16171 break;
16172 case CLO:
16173 mips32_op = OPC_CLO;
16174 goto do_cl;
16175 case CLZ:
16176 mips32_op = OPC_CLZ;
16177 do_cl:
bbd5e4a2 16178 check_insn(ctx, ISA_MIPS_R1);
3c824109
NF
16179 gen_cl(ctx, mips32_op, rt, rs);
16180 break;
16181 case RDHWR:
2e211e0a 16182 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b00c7218 16183 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
16184 break;
16185 case WSBH:
16186 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16187 break;
16188 case MULT:
2e211e0a 16189 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16190 mips32_op = OPC_MULT;
26135ead 16191 goto do_mul;
3c824109 16192 case MULTU:
2e211e0a 16193 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16194 mips32_op = OPC_MULTU;
26135ead 16195 goto do_mul;
3c824109 16196 case DIV:
2e211e0a 16197 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16198 mips32_op = OPC_DIV;
26135ead 16199 goto do_div;
3c824109 16200 case DIVU:
2e211e0a 16201 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16202 mips32_op = OPC_DIVU;
26135ead
RS
16203 goto do_div;
16204 do_div:
bbd5e4a2 16205 check_insn(ctx, ISA_MIPS_R1);
26135ead
RS
16206 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16207 break;
3c824109 16208 case MADD:
2e211e0a 16209 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16210 mips32_op = OPC_MADD;
26135ead 16211 goto do_mul;
3c824109 16212 case MADDU:
2e211e0a 16213 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16214 mips32_op = OPC_MADDU;
26135ead 16215 goto do_mul;
3c824109 16216 case MSUB:
2e211e0a 16217 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16218 mips32_op = OPC_MSUB;
26135ead 16219 goto do_mul;
3c824109 16220 case MSUBU:
2e211e0a 16221 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16222 mips32_op = OPC_MSUBU;
26135ead 16223 do_mul:
bbd5e4a2 16224 check_insn(ctx, ISA_MIPS_R1);
a1fc6246 16225 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
16226 break;
16227 default:
16228 goto pool32axf_invalid;
16229 }
16230 break;
16231 case 0x34:
16232 switch (minor) {
16233 case MFC2:
16234 case MTC2:
16235 case MFHC2:
16236 case MTHC2:
16237 case CFC2:
16238 case CTC2:
16239 generate_exception_err(ctx, EXCP_CpU, 2);
16240 break;
16241 default:
16242 goto pool32axf_invalid;
16243 }
16244 break;
16245 case 0x3c:
16246 switch (minor) {
65935f07
YK
16247 case JALR: /* JALRC */
16248 case JALR_HB: /* JALRC_HB */
2e211e0a 16249 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16250 /* JALRC, JALRC_HB */
16251 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16252 } else {
16253 /* JALR, JALR_HB */
16254 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16255 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16256 }
3c824109
NF
16257 break;
16258 case JALRS:
16259 case JALRS_HB:
2e211e0a 16260 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
16261 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16262 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
16263 break;
16264 default:
16265 goto pool32axf_invalid;
16266 }
16267 break;
16268 case 0x05:
16269 switch (minor) {
16270 case RDPGPR:
2e15497c 16271 check_cp0_enabled(ctx);
7a47bae5 16272 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 16273 gen_load_srsgpr(rs, rt);
3c824109
NF
16274 break;
16275 case WRPGPR:
2e15497c 16276 check_cp0_enabled(ctx);
7a47bae5 16277 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 16278 gen_store_srsgpr(rs, rt);
3c824109
NF
16279 break;
16280 default:
16281 goto pool32axf_invalid;
16282 }
16283 break;
16284#ifndef CONFIG_USER_ONLY
16285 case 0x0d:
16286 switch (minor) {
16287 case TLBP:
16288 mips32_op = OPC_TLBP;
16289 goto do_cp0;
16290 case TLBR:
16291 mips32_op = OPC_TLBR;
16292 goto do_cp0;
16293 case TLBWI:
16294 mips32_op = OPC_TLBWI;
16295 goto do_cp0;
16296 case TLBWR:
16297 mips32_op = OPC_TLBWR;
16298 goto do_cp0;
e60ec063
YK
16299 case TLBINV:
16300 mips32_op = OPC_TLBINV;
16301 goto do_cp0;
16302 case TLBINVF:
16303 mips32_op = OPC_TLBINVF;
16304 goto do_cp0;
3c824109
NF
16305 case WAIT:
16306 mips32_op = OPC_WAIT;
16307 goto do_cp0;
16308 case DERET:
16309 mips32_op = OPC_DERET;
16310 goto do_cp0;
16311 case ERET:
16312 mips32_op = OPC_ERET;
16313 do_cp0:
16314 gen_cp0(env, ctx, mips32_op, rt, rs);
16315 break;
16316 default:
16317 goto pool32axf_invalid;
16318 }
16319 break;
16320 case 0x1d:
16321 switch (minor) {
16322 case DI:
2e15497c 16323 check_cp0_enabled(ctx);
3c824109
NF
16324 {
16325 TCGv t0 = tcg_temp_new();
16326
16327 save_cpu_state(ctx, 1);
895c2d04 16328 gen_helper_di(t0, cpu_env);
3c824109 16329 gen_store_gpr(t0, rs);
71375b59
AM
16330 /*
16331 * Stop translation as we may have switched the execution
16332 * mode.
16333 */
eeb3bba8 16334 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16335 tcg_temp_free(t0);
16336 }
16337 break;
16338 case EI:
2e15497c 16339 check_cp0_enabled(ctx);
3c824109
NF
16340 {
16341 TCGv t0 = tcg_temp_new();
16342
16343 save_cpu_state(ctx, 1);
895c2d04 16344 gen_helper_ei(t0, cpu_env);
3c824109 16345 gen_store_gpr(t0, rs);
7480515f
AM
16346 /*
16347 * DISAS_STOP isn't sufficient, we need to ensure we break out
16348 * of translated code to check for pending interrupts.
16349 */
eeb3bba8
EC
16350 gen_save_pc(ctx->base.pc_next + 4);
16351 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
16352 tcg_temp_free(t0);
16353 }
16354 break;
16355 default:
16356 goto pool32axf_invalid;
16357 }
16358 break;
16359#endif
16360 case 0x2d:
16361 switch (minor) {
16362 case SYNC:
d208ac0c 16363 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
16364 break;
16365 case SYSCALL:
9c708c7f 16366 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
16367 break;
16368 case SDBBP:
3b3c1694
LA
16369 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16370 gen_helper_do_semihosting(cpu_env);
16371 } else {
bbd5e4a2 16372 check_insn(ctx, ISA_MIPS_R1);
e0332095 16373 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 16374 generate_exception_end(ctx, EXCP_RI);
e0332095 16375 } else {
9c708c7f 16376 generate_exception_end(ctx, EXCP_DBp);
e0332095 16377 }
3b3c1694 16378 }
3c824109
NF
16379 break;
16380 default:
16381 goto pool32axf_invalid;
16382 }
16383 break;
a1fc6246 16384 case 0x01:
26135ead 16385 switch (minor & 3) {
a1fc6246 16386 case MFHI_ACC:
26135ead 16387 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 16388 break;
a1fc6246 16389 case MFLO_ACC:
26135ead 16390 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 16391 break;
a1fc6246 16392 case MTHI_ACC:
26135ead 16393 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 16394 break;
a1fc6246 16395 case MTLO_ACC:
26135ead 16396 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
16397 break;
16398 default:
16399 goto pool32axf_invalid;
16400 }
16401 break;
a1fc6246 16402 case 0x35:
2e211e0a 16403 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a1fc6246
LA
16404 switch (minor) {
16405 case MFHI32:
16406 gen_HILO(ctx, OPC_MFHI, 0, rs);
16407 break;
16408 case MFLO32:
16409 gen_HILO(ctx, OPC_MFLO, 0, rs);
16410 break;
16411 case MTHI32:
16412 gen_HILO(ctx, OPC_MTHI, 0, rs);
16413 break;
16414 case MTLO32:
16415 gen_HILO(ctx, OPC_MTLO, 0, rs);
16416 break;
16417 default:
16418 goto pool32axf_invalid;
16419 }
16420 break;
3c824109
NF
16421 default:
16422 pool32axf_invalid:
16423 MIPS_INVAL("pool32axf");
9c708c7f 16424 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16425 break;
16426 }
16427}
16428
7480515f
AM
16429/*
16430 * Values for microMIPS fmt field. Variable-width, depending on which
16431 * formats the instruction supports.
16432 */
3c824109
NF
16433enum {
16434 FMT_SD_S = 0,
16435 FMT_SD_D = 1,
16436
16437 FMT_SDPS_S = 0,
16438 FMT_SDPS_D = 1,
16439 FMT_SDPS_PS = 2,
16440
16441 FMT_SWL_S = 0,
16442 FMT_SWL_W = 1,
16443 FMT_SWL_L = 2,
16444
16445 FMT_DWL_D = 0,
16446 FMT_DWL_W = 1,
16447 FMT_DWL_L = 2
16448};
16449
d75c135e 16450static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
16451{
16452 int extension = (ctx->opcode >> 6) & 0x3ff;
16453 uint32_t mips32_op;
16454
71375b59
AM
16455#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16456#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16457#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
16458
16459 switch (extension) {
16460 case FLOAT_1BIT_FMT(CFC1, 0):
16461 mips32_op = OPC_CFC1;
16462 goto do_cp1;
16463 case FLOAT_1BIT_FMT(CTC1, 0):
16464 mips32_op = OPC_CTC1;
16465 goto do_cp1;
16466 case FLOAT_1BIT_FMT(MFC1, 0):
16467 mips32_op = OPC_MFC1;
16468 goto do_cp1;
16469 case FLOAT_1BIT_FMT(MTC1, 0):
16470 mips32_op = OPC_MTC1;
16471 goto do_cp1;
16472 case FLOAT_1BIT_FMT(MFHC1, 0):
16473 mips32_op = OPC_MFHC1;
16474 goto do_cp1;
16475 case FLOAT_1BIT_FMT(MTHC1, 0):
16476 mips32_op = OPC_MTHC1;
16477 do_cp1:
16478 gen_cp1(ctx, mips32_op, rt, rs);
16479 break;
16480
16481 /* Reciprocal square root */
16482 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16483 mips32_op = OPC_RSQRT_S;
16484 goto do_unaryfp;
16485 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16486 mips32_op = OPC_RSQRT_D;
16487 goto do_unaryfp;
16488
16489 /* Square root */
16490 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16491 mips32_op = OPC_SQRT_S;
16492 goto do_unaryfp;
16493 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16494 mips32_op = OPC_SQRT_D;
16495 goto do_unaryfp;
16496
16497 /* Reciprocal */
16498 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16499 mips32_op = OPC_RECIP_S;
16500 goto do_unaryfp;
16501 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16502 mips32_op = OPC_RECIP_D;
16503 goto do_unaryfp;
16504
16505 /* Floor */
16506 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16507 mips32_op = OPC_FLOOR_L_S;
16508 goto do_unaryfp;
16509 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16510 mips32_op = OPC_FLOOR_L_D;
16511 goto do_unaryfp;
16512 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16513 mips32_op = OPC_FLOOR_W_S;
16514 goto do_unaryfp;
16515 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16516 mips32_op = OPC_FLOOR_W_D;
16517 goto do_unaryfp;
16518
16519 /* Ceiling */
16520 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16521 mips32_op = OPC_CEIL_L_S;
16522 goto do_unaryfp;
16523 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16524 mips32_op = OPC_CEIL_L_D;
16525 goto do_unaryfp;
16526 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16527 mips32_op = OPC_CEIL_W_S;
16528 goto do_unaryfp;
16529 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16530 mips32_op = OPC_CEIL_W_D;
16531 goto do_unaryfp;
16532
16533 /* Truncation */
16534 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16535 mips32_op = OPC_TRUNC_L_S;
16536 goto do_unaryfp;
16537 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16538 mips32_op = OPC_TRUNC_L_D;
16539 goto do_unaryfp;
16540 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16541 mips32_op = OPC_TRUNC_W_S;
16542 goto do_unaryfp;
16543 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16544 mips32_op = OPC_TRUNC_W_D;
16545 goto do_unaryfp;
16546
16547 /* Round */
16548 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16549 mips32_op = OPC_ROUND_L_S;
16550 goto do_unaryfp;
16551 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16552 mips32_op = OPC_ROUND_L_D;
16553 goto do_unaryfp;
16554 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16555 mips32_op = OPC_ROUND_W_S;
16556 goto do_unaryfp;
16557 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16558 mips32_op = OPC_ROUND_W_D;
16559 goto do_unaryfp;
16560
16561 /* Integer to floating-point conversion */
16562 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16563 mips32_op = OPC_CVT_L_S;
16564 goto do_unaryfp;
16565 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16566 mips32_op = OPC_CVT_L_D;
16567 goto do_unaryfp;
16568 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16569 mips32_op = OPC_CVT_W_S;
16570 goto do_unaryfp;
16571 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16572 mips32_op = OPC_CVT_W_D;
16573 goto do_unaryfp;
16574
16575 /* Paired-foo conversions */
16576 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16577 mips32_op = OPC_CVT_S_PL;
16578 goto do_unaryfp;
16579 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16580 mips32_op = OPC_CVT_S_PU;
16581 goto do_unaryfp;
16582 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16583 mips32_op = OPC_CVT_PW_PS;
16584 goto do_unaryfp;
16585 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16586 mips32_op = OPC_CVT_PS_PW;
16587 goto do_unaryfp;
16588
16589 /* Floating-point moves */
16590 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16591 mips32_op = OPC_MOV_S;
16592 goto do_unaryfp;
16593 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16594 mips32_op = OPC_MOV_D;
16595 goto do_unaryfp;
16596 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16597 mips32_op = OPC_MOV_PS;
16598 goto do_unaryfp;
16599
16600 /* Absolute value */
16601 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16602 mips32_op = OPC_ABS_S;
16603 goto do_unaryfp;
16604 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16605 mips32_op = OPC_ABS_D;
16606 goto do_unaryfp;
16607 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16608 mips32_op = OPC_ABS_PS;
16609 goto do_unaryfp;
16610
16611 /* Negation */
16612 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16613 mips32_op = OPC_NEG_S;
16614 goto do_unaryfp;
16615 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16616 mips32_op = OPC_NEG_D;
16617 goto do_unaryfp;
16618 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16619 mips32_op = OPC_NEG_PS;
16620 goto do_unaryfp;
16621
16622 /* Reciprocal square root step */
16623 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16624 mips32_op = OPC_RSQRT1_S;
16625 goto do_unaryfp;
16626 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16627 mips32_op = OPC_RSQRT1_D;
16628 goto do_unaryfp;
16629 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16630 mips32_op = OPC_RSQRT1_PS;
16631 goto do_unaryfp;
16632
16633 /* Reciprocal step */
16634 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16635 mips32_op = OPC_RECIP1_S;
16636 goto do_unaryfp;
16637 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16638 mips32_op = OPC_RECIP1_S;
16639 goto do_unaryfp;
16640 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16641 mips32_op = OPC_RECIP1_PS;
16642 goto do_unaryfp;
16643
16644 /* Conversions from double */
16645 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16646 mips32_op = OPC_CVT_D_S;
16647 goto do_unaryfp;
16648 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16649 mips32_op = OPC_CVT_D_W;
16650 goto do_unaryfp;
16651 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16652 mips32_op = OPC_CVT_D_L;
16653 goto do_unaryfp;
16654
16655 /* Conversions from single */
16656 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16657 mips32_op = OPC_CVT_S_D;
16658 goto do_unaryfp;
16659 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16660 mips32_op = OPC_CVT_S_W;
16661 goto do_unaryfp;
16662 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16663 mips32_op = OPC_CVT_S_L;
16664 do_unaryfp:
16665 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16666 break;
16667
16668 /* Conditional moves on floating-point codes */
16669 case COND_FLOAT_MOV(MOVT, 0):
16670 case COND_FLOAT_MOV(MOVT, 1):
16671 case COND_FLOAT_MOV(MOVT, 2):
16672 case COND_FLOAT_MOV(MOVT, 3):
16673 case COND_FLOAT_MOV(MOVT, 4):
16674 case COND_FLOAT_MOV(MOVT, 5):
16675 case COND_FLOAT_MOV(MOVT, 6):
16676 case COND_FLOAT_MOV(MOVT, 7):
2e211e0a 16677 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16678 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16679 break;
16680 case COND_FLOAT_MOV(MOVF, 0):
16681 case COND_FLOAT_MOV(MOVF, 1):
16682 case COND_FLOAT_MOV(MOVF, 2):
16683 case COND_FLOAT_MOV(MOVF, 3):
16684 case COND_FLOAT_MOV(MOVF, 4):
16685 case COND_FLOAT_MOV(MOVF, 5):
16686 case COND_FLOAT_MOV(MOVF, 6):
16687 case COND_FLOAT_MOV(MOVF, 7):
2e211e0a 16688 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16689 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16690 break;
16691 default:
16692 MIPS_INVAL("pool32fxf");
9c708c7f 16693 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16694 break;
16695 }
16696}
16697
f60eeb0c 16698static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16699{
16700 int32_t offset;
16701 uint16_t insn;
16702 int rt, rs, rd, rr;
16703 int16_t imm;
8fffc646 16704 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
16705 uint32_t cond, fmt, cc;
16706
eeb3bba8 16707 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
16708 ctx->opcode = (ctx->opcode << 16) | insn;
16709
16710 rt = (ctx->opcode >> 21) & 0x1f;
16711 rs = (ctx->opcode >> 16) & 0x1f;
16712 rd = (ctx->opcode >> 11) & 0x1f;
16713 rr = (ctx->opcode >> 6) & 0x1f;
16714 imm = (int16_t) ctx->opcode;
16715
16716 op = (ctx->opcode >> 26) & 0x3f;
16717 switch (op) {
16718 case POOL32A:
16719 minor = ctx->opcode & 0x3f;
16720 switch (minor) {
16721 case 0x00:
16722 minor = (ctx->opcode >> 6) & 0xf;
16723 switch (minor) {
16724 case SLL32:
16725 mips32_op = OPC_SLL;
16726 goto do_shifti;
16727 case SRA:
16728 mips32_op = OPC_SRA;
16729 goto do_shifti;
16730 case SRL32:
16731 mips32_op = OPC_SRL;
16732 goto do_shifti;
16733 case ROTR:
16734 mips32_op = OPC_ROTR;
16735 do_shifti:
d75c135e 16736 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 16737 break;
e0332095 16738 case SELEQZ:
2e211e0a 16739 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16740 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16741 break;
16742 case SELNEZ:
2e211e0a 16743 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16744 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16745 break;
b00c7218 16746 case R6_RDHWR:
2e211e0a 16747 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
16748 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16749 break;
3c824109
NF
16750 default:
16751 goto pool32a_invalid;
16752 }
16753 break;
16754 case 0x10:
16755 minor = (ctx->opcode >> 6) & 0xf;
16756 switch (minor) {
16757 /* Arithmetic */
16758 case ADD:
16759 mips32_op = OPC_ADD;
16760 goto do_arith;
16761 case ADDU32:
16762 mips32_op = OPC_ADDU;
16763 goto do_arith;
16764 case SUB:
16765 mips32_op = OPC_SUB;
16766 goto do_arith;
16767 case SUBU32:
16768 mips32_op = OPC_SUBU;
16769 goto do_arith;
16770 case MUL:
2e211e0a 16771 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16772 mips32_op = OPC_MUL;
16773 do_arith:
d75c135e 16774 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16775 break;
16776 /* Shifts */
16777 case SLLV:
16778 mips32_op = OPC_SLLV;
16779 goto do_shift;
16780 case SRLV:
16781 mips32_op = OPC_SRLV;
16782 goto do_shift;
16783 case SRAV:
16784 mips32_op = OPC_SRAV;
16785 goto do_shift;
16786 case ROTRV:
16787 mips32_op = OPC_ROTRV;
16788 do_shift:
d75c135e 16789 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16790 break;
16791 /* Logical operations */
16792 case AND:
16793 mips32_op = OPC_AND;
16794 goto do_logic;
16795 case OR32:
16796 mips32_op = OPC_OR;
16797 goto do_logic;
16798 case NOR:
16799 mips32_op = OPC_NOR;
16800 goto do_logic;
16801 case XOR32:
16802 mips32_op = OPC_XOR;
16803 do_logic:
d75c135e 16804 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16805 break;
16806 /* Set less than */
16807 case SLT:
16808 mips32_op = OPC_SLT;
16809 goto do_slt;
16810 case SLTU:
16811 mips32_op = OPC_SLTU;
16812 do_slt:
d75c135e 16813 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16814 break;
16815 default:
16816 goto pool32a_invalid;
16817 }
16818 break;
16819 case 0x18:
16820 minor = (ctx->opcode >> 6) & 0xf;
16821 switch (minor) {
16822 /* Conditional moves */
e0332095 16823 case MOVN: /* MUL */
2e211e0a 16824 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
16825 /* MUL */
16826 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16827 } else {
16828 /* MOVN */
16829 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16830 }
16831 break;
16832 case MOVZ: /* MUH */
2e211e0a 16833 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
16834 /* MUH */
16835 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16836 } else {
16837 /* MOVZ */
16838 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16839 }
16840 break;
16841 case MULU:
2e211e0a 16842 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16843 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16844 break;
16845 case MUHU:
2e211e0a 16846 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16847 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16848 break;
16849 case LWXS: /* DIV */
2e211e0a 16850 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
16851 /* DIV */
16852 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16853 } else {
16854 /* LWXS */
16855 gen_ldxs(ctx, rs, rt, rd);
16856 }
16857 break;
16858 case MOD:
2e211e0a 16859 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16860 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16861 break;
16862 case R6_DIVU:
2e211e0a 16863 check_insn(ctx, ISA_MIPS_R6);
e0332095 16864 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16865 break;
e0332095 16866 case MODU:
2e211e0a 16867 check_insn(ctx, ISA_MIPS_R6);
e0332095 16868 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16869 break;
16870 default:
16871 goto pool32a_invalid;
16872 }
16873 break;
16874 case INS:
16875 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16876 return;
e0332095 16877 case LSA:
2e211e0a 16878 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
16879 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16880 extract32(ctx->opcode, 9, 2));
16881 break;
16882 case ALIGN:
2e211e0a 16883 check_insn(ctx, ISA_MIPS_R6);
821f2008 16884 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16885 break;
3c824109
NF
16886 case EXT:
16887 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16888 return;
16889 case POOL32AXF:
240ce26a 16890 gen_pool32axf(env, ctx, rt, rs);
3c824109 16891 break;
dbd8af98 16892 case BREAK32:
9c708c7f 16893 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16894 break;
bb238210 16895 case SIGRIE:
2e211e0a 16896 check_insn(ctx, ISA_MIPS_R6);
bb238210
YK
16897 generate_exception_end(ctx, EXCP_RI);
16898 break;
3c824109
NF
16899 default:
16900 pool32a_invalid:
16901 MIPS_INVAL("pool32a");
9c708c7f 16902 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16903 break;
16904 }
16905 break;
16906 case POOL32B:
16907 minor = (ctx->opcode >> 12) & 0xf;
16908 switch (minor) {
16909 case CACHE:
2e15497c 16910 check_cp0_enabled(ctx);
0d74a222
LA
16911 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16912 gen_cache_operation(ctx, rt, rs, imm);
16913 }
3c824109
NF
16914 break;
16915 case LWC2:
16916 case SWC2:
16917 /* COP2: Not implemented. */
16918 generate_exception_err(ctx, EXCP_CpU, 2);
16919 break;
3c824109
NF
16920#ifdef TARGET_MIPS64
16921 case LDP:
16922 case SDP:
d9224450
MR
16923 check_insn(ctx, ISA_MIPS3);
16924 check_mips_64(ctx);
3c824109 16925#endif
146dd620 16926 /* fall through */
d9224450
MR
16927 case LWP:
16928 case SWP:
3c824109
NF
16929 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16930 break;
3c824109
NF
16931#ifdef TARGET_MIPS64
16932 case LDM:
16933 case SDM:
d9224450
MR
16934 check_insn(ctx, ISA_MIPS3);
16935 check_mips_64(ctx);
3c824109 16936#endif
146dd620 16937 /* fall through */
d9224450
MR
16938 case LWM32:
16939 case SWM32:
3c824109
NF
16940 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16941 break;
16942 default:
16943 MIPS_INVAL("pool32b");
9c708c7f 16944 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16945 break;
16946 }
16947 break;
16948 case POOL32F:
5ab5c041 16949 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16950 minor = ctx->opcode & 0x3f;
16951 check_cp1_enabled(ctx);
16952 switch (minor) {
16953 case ALNV_PS:
2e211e0a 16954 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16955 mips32_op = OPC_ALNV_PS;
16956 goto do_madd;
16957 case MADD_S:
2e211e0a 16958 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16959 mips32_op = OPC_MADD_S;
16960 goto do_madd;
16961 case MADD_D:
2e211e0a 16962 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16963 mips32_op = OPC_MADD_D;
16964 goto do_madd;
16965 case MADD_PS:
2e211e0a 16966 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16967 mips32_op = OPC_MADD_PS;
16968 goto do_madd;
16969 case MSUB_S:
2e211e0a 16970 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16971 mips32_op = OPC_MSUB_S;
16972 goto do_madd;
16973 case MSUB_D:
2e211e0a 16974 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16975 mips32_op = OPC_MSUB_D;
16976 goto do_madd;
16977 case MSUB_PS:
2e211e0a 16978 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16979 mips32_op = OPC_MSUB_PS;
16980 goto do_madd;
16981 case NMADD_S:
2e211e0a 16982 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16983 mips32_op = OPC_NMADD_S;
16984 goto do_madd;
16985 case NMADD_D:
2e211e0a 16986 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16987 mips32_op = OPC_NMADD_D;
16988 goto do_madd;
16989 case NMADD_PS:
2e211e0a 16990 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16991 mips32_op = OPC_NMADD_PS;
16992 goto do_madd;
16993 case NMSUB_S:
2e211e0a 16994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16995 mips32_op = OPC_NMSUB_S;
16996 goto do_madd;
16997 case NMSUB_D:
2e211e0a 16998 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16999 mips32_op = OPC_NMSUB_D;
17000 goto do_madd;
17001 case NMSUB_PS:
2e211e0a 17002 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17003 mips32_op = OPC_NMSUB_PS;
17004 do_madd:
17005 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
17006 break;
17007 case CABS_COND_FMT:
2e211e0a 17008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17009 cond = (ctx->opcode >> 6) & 0xf;
17010 cc = (ctx->opcode >> 13) & 0x7;
17011 fmt = (ctx->opcode >> 10) & 0x3;
17012 switch (fmt) {
17013 case 0x0:
17014 gen_cmpabs_s(ctx, cond, rt, rs, cc);
17015 break;
17016 case 0x1:
17017 gen_cmpabs_d(ctx, cond, rt, rs, cc);
17018 break;
17019 case 0x2:
17020 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
17021 break;
17022 default:
17023 goto pool32f_invalid;
17024 }
17025 break;
17026 case C_COND_FMT:
2e211e0a 17027 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17028 cond = (ctx->opcode >> 6) & 0xf;
17029 cc = (ctx->opcode >> 13) & 0x7;
17030 fmt = (ctx->opcode >> 10) & 0x3;
17031 switch (fmt) {
17032 case 0x0:
17033 gen_cmp_s(ctx, cond, rt, rs, cc);
17034 break;
17035 case 0x1:
17036 gen_cmp_d(ctx, cond, rt, rs, cc);
17037 break;
17038 case 0x2:
17039 gen_cmp_ps(ctx, cond, rt, rs, cc);
17040 break;
17041 default:
17042 goto pool32f_invalid;
17043 }
17044 break;
2a24a7ba 17045 case CMP_CONDN_S:
2e211e0a 17046 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17047 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17048 break;
17049 case CMP_CONDN_D:
2e211e0a 17050 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17051 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17052 break;
3c824109 17053 case POOL32FXF:
d75c135e 17054 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
17055 break;
17056 case 0x00:
17057 /* PLL foo */
17058 switch ((ctx->opcode >> 6) & 0x7) {
17059 case PLL_PS:
17060 mips32_op = OPC_PLL_PS;
17061 goto do_ps;
17062 case PLU_PS:
17063 mips32_op = OPC_PLU_PS;
17064 goto do_ps;
17065 case PUL_PS:
17066 mips32_op = OPC_PUL_PS;
17067 goto do_ps;
17068 case PUU_PS:
17069 mips32_op = OPC_PUU_PS;
17070 goto do_ps;
17071 case CVT_PS_S:
2e211e0a 17072 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17073 mips32_op = OPC_CVT_PS_S;
17074 do_ps:
17075 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17076 break;
17077 default:
17078 goto pool32f_invalid;
17079 }
17080 break;
2a24a7ba 17081 case MIN_FMT:
2e211e0a 17082 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17083 switch ((ctx->opcode >> 9) & 0x3) {
17084 case FMT_SDPS_S:
17085 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
17086 break;
17087 case FMT_SDPS_D:
17088 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
17089 break;
17090 default:
17091 goto pool32f_invalid;
17092 }
17093 break;
3c824109
NF
17094 case 0x08:
17095 /* [LS][WDU]XC1 */
17096 switch ((ctx->opcode >> 6) & 0x7) {
17097 case LWXC1:
2e211e0a 17098 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17099 mips32_op = OPC_LWXC1;
17100 goto do_ldst_cp1;
17101 case SWXC1:
2e211e0a 17102 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17103 mips32_op = OPC_SWXC1;
17104 goto do_ldst_cp1;
17105 case LDXC1:
2e211e0a 17106 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17107 mips32_op = OPC_LDXC1;
17108 goto do_ldst_cp1;
17109 case SDXC1:
2e211e0a 17110 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17111 mips32_op = OPC_SDXC1;
17112 goto do_ldst_cp1;
17113 case LUXC1:
2e211e0a 17114 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17115 mips32_op = OPC_LUXC1;
17116 goto do_ldst_cp1;
17117 case SUXC1:
2e211e0a 17118 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17119 mips32_op = OPC_SUXC1;
17120 do_ldst_cp1:
17121 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
17122 break;
17123 default:
17124 goto pool32f_invalid;
17125 }
17126 break;
2a24a7ba 17127 case MAX_FMT:
2e211e0a 17128 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17129 switch ((ctx->opcode >> 9) & 0x3) {
17130 case FMT_SDPS_S:
17131 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17132 break;
17133 case FMT_SDPS_D:
17134 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17135 break;
17136 default:
17137 goto pool32f_invalid;
17138 }
17139 break;
3c824109
NF
17140 case 0x18:
17141 /* 3D insns */
2e211e0a 17142 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17143 fmt = (ctx->opcode >> 9) & 0x3;
17144 switch ((ctx->opcode >> 6) & 0x7) {
17145 case RSQRT2_FMT:
17146 switch (fmt) {
17147 case FMT_SDPS_S:
17148 mips32_op = OPC_RSQRT2_S;
17149 goto do_3d;
17150 case FMT_SDPS_D:
17151 mips32_op = OPC_RSQRT2_D;
17152 goto do_3d;
17153 case FMT_SDPS_PS:
17154 mips32_op = OPC_RSQRT2_PS;
17155 goto do_3d;
17156 default:
17157 goto pool32f_invalid;
17158 }
17159 break;
17160 case RECIP2_FMT:
17161 switch (fmt) {
17162 case FMT_SDPS_S:
17163 mips32_op = OPC_RECIP2_S;
17164 goto do_3d;
17165 case FMT_SDPS_D:
17166 mips32_op = OPC_RECIP2_D;
17167 goto do_3d;
17168 case FMT_SDPS_PS:
17169 mips32_op = OPC_RECIP2_PS;
17170 goto do_3d;
17171 default:
17172 goto pool32f_invalid;
17173 }
17174 break;
17175 case ADDR_PS:
17176 mips32_op = OPC_ADDR_PS;
17177 goto do_3d;
17178 case MULR_PS:
17179 mips32_op = OPC_MULR_PS;
17180 do_3d:
17181 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17182 break;
17183 default:
17184 goto pool32f_invalid;
17185 }
17186 break;
17187 case 0x20:
2a24a7ba 17188 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
17189 cc = (ctx->opcode >> 13) & 0x7;
17190 fmt = (ctx->opcode >> 9) & 0x3;
17191 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba 17192 case MOVF_FMT: /* RINT_FMT */
2e211e0a 17193 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
17194 /* RINT_FMT */
17195 switch (fmt) {
17196 case FMT_SDPS_S:
17197 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17198 break;
17199 case FMT_SDPS_D:
17200 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17201 break;
17202 default:
17203 goto pool32f_invalid;
17204 }
17205 } else {
17206 /* MOVF_FMT */
17207 switch (fmt) {
17208 case FMT_SDPS_S:
17209 gen_movcf_s(ctx, rs, rt, cc, 0);
17210 break;
17211 case FMT_SDPS_D:
17212 gen_movcf_d(ctx, rs, rt, cc, 0);
17213 break;
17214 case FMT_SDPS_PS:
17215 check_ps(ctx);
17216 gen_movcf_ps(ctx, rs, rt, cc, 0);
17217 break;
17218 default:
17219 goto pool32f_invalid;
17220 }
3c824109
NF
17221 }
17222 break;
2a24a7ba 17223 case MOVT_FMT: /* CLASS_FMT */
2e211e0a 17224 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
17225 /* CLASS_FMT */
17226 switch (fmt) {
17227 case FMT_SDPS_S:
17228 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17229 break;
17230 case FMT_SDPS_D:
17231 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17232 break;
17233 default:
17234 goto pool32f_invalid;
17235 }
17236 } else {
17237 /* MOVT_FMT */
17238 switch (fmt) {
17239 case FMT_SDPS_S:
17240 gen_movcf_s(ctx, rs, rt, cc, 1);
17241 break;
17242 case FMT_SDPS_D:
17243 gen_movcf_d(ctx, rs, rt, cc, 1);
17244 break;
17245 case FMT_SDPS_PS:
17246 check_ps(ctx);
17247 gen_movcf_ps(ctx, rs, rt, cc, 1);
17248 break;
17249 default:
17250 goto pool32f_invalid;
17251 }
3c824109
NF
17252 }
17253 break;
17254 case PREFX:
2e211e0a 17255 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17256 break;
17257 default:
17258 goto pool32f_invalid;
17259 }
17260 break;
17261#define FINSN_3ARG_SDPS(prfx) \
17262 switch ((ctx->opcode >> 8) & 0x3) { \
17263 case FMT_SDPS_S: \
17264 mips32_op = OPC_##prfx##_S; \
17265 goto do_fpop; \
17266 case FMT_SDPS_D: \
17267 mips32_op = OPC_##prfx##_D; \
17268 goto do_fpop; \
17269 case FMT_SDPS_PS: \
e29c9628 17270 check_ps(ctx); \
3c824109
NF
17271 mips32_op = OPC_##prfx##_PS; \
17272 goto do_fpop; \
17273 default: \
17274 goto pool32f_invalid; \
17275 }
2a24a7ba 17276 case MINA_FMT:
2e211e0a 17277 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17278 switch ((ctx->opcode >> 9) & 0x3) {
17279 case FMT_SDPS_S:
17280 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17281 break;
17282 case FMT_SDPS_D:
17283 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17284 break;
17285 default:
17286 goto pool32f_invalid;
17287 }
17288 break;
17289 case MAXA_FMT:
2e211e0a 17290 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17291 switch ((ctx->opcode >> 9) & 0x3) {
17292 case FMT_SDPS_S:
17293 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17294 break;
17295 case FMT_SDPS_D:
17296 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17297 break;
17298 default:
17299 goto pool32f_invalid;
17300 }
17301 break;
3c824109
NF
17302 case 0x30:
17303 /* regular FP ops */
17304 switch ((ctx->opcode >> 6) & 0x3) {
17305 case ADD_FMT:
17306 FINSN_3ARG_SDPS(ADD);
17307 break;
17308 case SUB_FMT:
17309 FINSN_3ARG_SDPS(SUB);
17310 break;
17311 case MUL_FMT:
17312 FINSN_3ARG_SDPS(MUL);
17313 break;
17314 case DIV_FMT:
17315 fmt = (ctx->opcode >> 8) & 0x3;
17316 if (fmt == 1) {
17317 mips32_op = OPC_DIV_D;
17318 } else if (fmt == 0) {
17319 mips32_op = OPC_DIV_S;
17320 } else {
17321 goto pool32f_invalid;
17322 }
17323 goto do_fpop;
17324 default:
17325 goto pool32f_invalid;
17326 }
17327 break;
17328 case 0x38:
17329 /* cmovs */
2a24a7ba 17330 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 17331 case MOVN_FMT: /* SELEQZ_FMT */
2e211e0a 17332 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 17333 /* SELEQZ_FMT */
2a24a7ba
YK
17334 switch ((ctx->opcode >> 9) & 0x3) {
17335 case FMT_SDPS_S:
fdac60cd 17336 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
17337 break;
17338 case FMT_SDPS_D:
fdac60cd 17339 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
17340 break;
17341 default:
17342 goto pool32f_invalid;
17343 }
17344 } else {
17345 /* MOVN_FMT */
17346 FINSN_3ARG_SDPS(MOVN);
17347 }
17348 break;
17349 case MOVN_FMT_04:
2e211e0a 17350 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17351 FINSN_3ARG_SDPS(MOVN);
17352 break;
fdac60cd 17353 case MOVZ_FMT: /* SELNEZ_FMT */
2e211e0a 17354 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 17355 /* SELNEZ_FMT */
2a24a7ba
YK
17356 switch ((ctx->opcode >> 9) & 0x3) {
17357 case FMT_SDPS_S:
fdac60cd 17358 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
17359 break;
17360 case FMT_SDPS_D:
fdac60cd 17361 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
17362 break;
17363 default:
17364 goto pool32f_invalid;
17365 }
17366 } else {
17367 /* MOVZ_FMT */
17368 FINSN_3ARG_SDPS(MOVZ);
17369 }
17370 break;
17371 case MOVZ_FMT_05:
2e211e0a 17372 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17373 FINSN_3ARG_SDPS(MOVZ);
17374 break;
2a24a7ba 17375 case SEL_FMT:
2e211e0a 17376 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17377 switch ((ctx->opcode >> 9) & 0x3) {
17378 case FMT_SDPS_S:
17379 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17380 break;
17381 case FMT_SDPS_D:
17382 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17383 break;
17384 default:
17385 goto pool32f_invalid;
17386 }
17387 break;
17388 case MADDF_FMT:
2e211e0a 17389 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17390 switch ((ctx->opcode >> 9) & 0x3) {
17391 case FMT_SDPS_S:
17392 mips32_op = OPC_MADDF_S;
17393 goto do_fpop;
17394 case FMT_SDPS_D:
17395 mips32_op = OPC_MADDF_D;
17396 goto do_fpop;
17397 default:
17398 goto pool32f_invalid;
17399 }
17400 break;
17401 case MSUBF_FMT:
2e211e0a 17402 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
17403 switch ((ctx->opcode >> 9) & 0x3) {
17404 case FMT_SDPS_S:
17405 mips32_op = OPC_MSUBF_S;
17406 goto do_fpop;
17407 case FMT_SDPS_D:
17408 mips32_op = OPC_MSUBF_D;
17409 goto do_fpop;
17410 default:
17411 goto pool32f_invalid;
17412 }
17413 break;
3c824109
NF
17414 default:
17415 goto pool32f_invalid;
17416 }
17417 break;
17418 do_fpop:
17419 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17420 break;
17421 default:
17422 pool32f_invalid:
17423 MIPS_INVAL("pool32f");
9c708c7f 17424 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17425 break;
17426 }
17427 } else {
17428 generate_exception_err(ctx, EXCP_CpU, 1);
17429 }
17430 break;
17431 case POOL32I:
17432 minor = (ctx->opcode >> 21) & 0x1f;
17433 switch (minor) {
17434 case BLTZ:
2e211e0a 17435 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17436 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17437 break;
3c824109 17438 case BLTZAL:
2e211e0a 17439 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17440 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17441 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17442 break;
3c824109 17443 case BLTZALS:
2e211e0a 17444 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17445 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17446 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17447 break;
3c824109 17448 case BGEZ:
2e211e0a 17449 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17450 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17451 break;
3c824109 17452 case BGEZAL:
2e211e0a 17453 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17454 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17455 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17456 break;
3c824109 17457 case BGEZALS:
2e211e0a 17458 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17459 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17460 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17461 break;
3c824109 17462 case BLEZ:
2e211e0a 17463 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
17464 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17465 break;
3c824109 17466 case BGTZ:
2e211e0a 17467 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103 17468 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
17469 break;
17470
17471 /* Traps */
65935f07 17472 case TLTI: /* BC1EQZC */
2e211e0a 17473 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17474 /* BC1EQZC */
17475 check_cp1_enabled(ctx);
17476 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17477 } else {
17478 /* TLTI */
17479 mips32_op = OPC_TLTI;
17480 goto do_trapi;
17481 }
17482 break;
17483 case TGEI: /* BC1NEZC */
2e211e0a 17484 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17485 /* BC1NEZC */
17486 check_cp1_enabled(ctx);
17487 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17488 } else {
17489 /* TGEI */
17490 mips32_op = OPC_TGEI;
17491 goto do_trapi;
17492 }
17493 break;
3c824109 17494 case TLTIU:
2e211e0a 17495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17496 mips32_op = OPC_TLTIU;
17497 goto do_trapi;
17498 case TGEIU:
2e211e0a 17499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17500 mips32_op = OPC_TGEIU;
17501 goto do_trapi;
3b4a5489 17502 case TNEI: /* SYNCI */
2e211e0a 17503 if (ctx->insn_flags & ISA_MIPS_R6) {
3b4a5489 17504 /* SYNCI */
7480515f
AM
17505 /*
17506 * Break the TB to be able to sync copied instructions
17507 * immediately.
17508 */
eeb3bba8 17509 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
17510 } else {
17511 /* TNEI */
17512 mips32_op = OPC_TNEI;
17513 goto do_trapi;
17514 }
17515 break;
3c824109 17516 case TEQI:
2e211e0a 17517 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17518 mips32_op = OPC_TEQI;
17519 do_trapi:
17520 gen_trap(ctx, mips32_op, rs, -1, imm);
17521 break;
17522
17523 case BNEZC:
17524 case BEQZC:
2e211e0a 17525 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17526 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 17527 4, rs, 0, imm << 1, 0);
7480515f
AM
17528 /*
17529 * Compact branches don't have a delay slot, so just let
17530 * the normal delay slot handling take us to the branch
17531 * target.
17532 */
3c824109
NF
17533 break;
17534 case LUI:
2e211e0a 17535 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5e88759a 17536 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
17537 break;
17538 case SYNCI:
2e211e0a 17539 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7480515f
AM
17540 /*
17541 * Break the TB to be able to sync copied instructions
17542 * immediately.
17543 */
eeb3bba8 17544 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
17545 break;
17546 case BC2F:
17547 case BC2T:
2e211e0a 17548 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17549 /* COP2: Not implemented. */
17550 generate_exception_err(ctx, EXCP_CpU, 2);
17551 break;
17552 case BC1F:
2e211e0a 17553 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17554 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17555 goto do_cp1branch;
17556 case BC1T:
2e211e0a 17557 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17558 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17559 goto do_cp1branch;
17560 case BC1ANY4F:
2e211e0a 17561 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17562 mips32_op = OPC_BC1FANY4;
17563 goto do_cp1mips3d;
17564 case BC1ANY4T:
2e211e0a 17565 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
17566 mips32_op = OPC_BC1TANY4;
17567 do_cp1mips3d:
17568 check_cop1x(ctx);
d75c135e 17569 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
17570 /* Fall through */
17571 do_cp1branch:
272f458d
MR
17572 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17573 check_cp1_enabled(ctx);
17574 gen_compute_branch1(ctx, mips32_op,
17575 (ctx->opcode >> 18) & 0x7, imm << 1);
17576 } else {
17577 generate_exception_err(ctx, EXCP_CpU, 1);
17578 }
3c824109
NF
17579 break;
17580 case BPOSGE64:
17581 case BPOSGE32:
17582 /* MIPS DSP: not implemented */
17583 /* Fall through */
17584 default:
17585 MIPS_INVAL("pool32i");
9c708c7f 17586 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17587 break;
17588 }
17589 break;
17590 case POOL32C:
17591 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489 17592 offset = sextract32(ctx->opcode, 0,
2e211e0a 17593 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
3c824109
NF
17594 switch (minor) {
17595 case LWL:
2e211e0a 17596 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17597 mips32_op = OPC_LWL;
5c13fdfd 17598 goto do_ld_lr;
3c824109 17599 case SWL:
2e211e0a 17600 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17601 mips32_op = OPC_SWL;
5c13fdfd 17602 goto do_st_lr;
3c824109 17603 case LWR:
2e211e0a 17604 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17605 mips32_op = OPC_LWR;
5c13fdfd 17606 goto do_ld_lr;
3c824109 17607 case SWR:
2e211e0a 17608 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17609 mips32_op = OPC_SWR;
5c13fdfd 17610 goto do_st_lr;
3c824109
NF
17611#if defined(TARGET_MIPS64)
17612 case LDL:
d9224450
MR
17613 check_insn(ctx, ISA_MIPS3);
17614 check_mips_64(ctx);
2e211e0a 17615 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17616 mips32_op = OPC_LDL;
5c13fdfd 17617 goto do_ld_lr;
3c824109 17618 case SDL:
d9224450
MR
17619 check_insn(ctx, ISA_MIPS3);
17620 check_mips_64(ctx);
2e211e0a 17621 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17622 mips32_op = OPC_SDL;
5c13fdfd 17623 goto do_st_lr;
3c824109 17624 case LDR:
d9224450
MR
17625 check_insn(ctx, ISA_MIPS3);
17626 check_mips_64(ctx);
2e211e0a 17627 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17628 mips32_op = OPC_LDR;
5c13fdfd 17629 goto do_ld_lr;
3c824109 17630 case SDR:
d9224450
MR
17631 check_insn(ctx, ISA_MIPS3);
17632 check_mips_64(ctx);
2e211e0a 17633 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17634 mips32_op = OPC_SDR;
5c13fdfd 17635 goto do_st_lr;
3c824109 17636 case LWU:
d9224450
MR
17637 check_insn(ctx, ISA_MIPS3);
17638 check_mips_64(ctx);
3c824109 17639 mips32_op = OPC_LWU;
5c13fdfd 17640 goto do_ld_lr;
3c824109 17641 case LLD:
d9224450
MR
17642 check_insn(ctx, ISA_MIPS3);
17643 check_mips_64(ctx);
3c824109 17644 mips32_op = OPC_LLD;
5c13fdfd 17645 goto do_ld_lr;
3c824109
NF
17646#endif
17647 case LL:
17648 mips32_op = OPC_LL;
5c13fdfd
AJ
17649 goto do_ld_lr;
17650 do_ld_lr:
3b4a5489 17651 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
17652 break;
17653 do_st_lr:
8fffc646 17654 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
17655 break;
17656 case SC:
33a07fa2 17657 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
17658 break;
17659#if defined(TARGET_MIPS64)
17660 case SCD:
d9224450
MR
17661 check_insn(ctx, ISA_MIPS3);
17662 check_mips_64(ctx);
33a07fa2 17663 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
17664 break;
17665#endif
8fffc646
JH
17666 case LD_EVA:
17667 if (!ctx->eva) {
17668 MIPS_INVAL("pool32c ld-eva");
17669 generate_exception_end(ctx, EXCP_RI);
17670 break;
17671 }
17672 check_cp0_enabled(ctx);
17673
17674 minor2 = (ctx->opcode >> 9) & 0x7;
17675 offset = sextract32(ctx->opcode, 0, 9);
17676 switch (minor2) {
17677 case LBUE:
17678 mips32_op = OPC_LBUE;
17679 goto do_ld_lr;
17680 case LHUE:
17681 mips32_op = OPC_LHUE;
17682 goto do_ld_lr;
17683 case LWLE:
2e211e0a 17684 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
17685 mips32_op = OPC_LWLE;
17686 goto do_ld_lr;
17687 case LWRE:
2e211e0a 17688 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
17689 mips32_op = OPC_LWRE;
17690 goto do_ld_lr;
17691 case LBE:
17692 mips32_op = OPC_LBE;
17693 goto do_ld_lr;
17694 case LHE:
17695 mips32_op = OPC_LHE;
17696 goto do_ld_lr;
17697 case LLE:
17698 mips32_op = OPC_LLE;
17699 goto do_ld_lr;
17700 case LWE:
17701 mips32_op = OPC_LWE;
17702 goto do_ld_lr;
17703 };
17704 break;
17705 case ST_EVA:
17706 if (!ctx->eva) {
17707 MIPS_INVAL("pool32c st-eva");
17708 generate_exception_end(ctx, EXCP_RI);
17709 break;
17710 }
17711 check_cp0_enabled(ctx);
17712
17713 minor2 = (ctx->opcode >> 9) & 0x7;
17714 offset = sextract32(ctx->opcode, 0, 9);
17715 switch (minor2) {
17716 case SWLE:
2e211e0a 17717 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
17718 mips32_op = OPC_SWLE;
17719 goto do_st_lr;
17720 case SWRE:
2e211e0a 17721 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
17722 mips32_op = OPC_SWRE;
17723 goto do_st_lr;
17724 case PREFE:
17725 /* Treat as no-op */
2e211e0a 17726 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
8fffc646
JH
17727 /* hint codes 24-31 are reserved and signal RI */
17728 generate_exception(ctx, EXCP_RI);
17729 }
17730 break;
17731 case CACHEE:
17732 /* Treat as no-op */
17733 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17734 gen_cache_operation(ctx, rt, rs, offset);
17735 }
17736 break;
17737 case SBE:
17738 mips32_op = OPC_SBE;
17739 goto do_st_lr;
17740 case SHE:
17741 mips32_op = OPC_SHE;
17742 goto do_st_lr;
17743 case SCE:
33a07fa2 17744 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
17745 break;
17746 case SWE:
17747 mips32_op = OPC_SWE;
17748 goto do_st_lr;
17749 };
17750 break;
3c824109
NF
17751 case PREF:
17752 /* Treat as no-op */
2e211e0a 17753 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
3b4a5489
YK
17754 /* hint codes 24-31 are reserved and signal RI */
17755 generate_exception(ctx, EXCP_RI);
17756 }
3c824109
NF
17757 break;
17758 default:
17759 MIPS_INVAL("pool32c");
9c708c7f 17760 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17761 break;
17762 }
17763 break;
ab39ee45 17764 case ADDI32: /* AUI, LUI */
2e211e0a 17765 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
17766 /* AUI, LUI */
17767 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17768 } else {
17769 /* ADDI32 */
17770 mips32_op = OPC_ADDI;
17771 goto do_addi;
17772 }
17773 break;
3c824109
NF
17774 case ADDIU32:
17775 mips32_op = OPC_ADDIU;
17776 do_addi:
d75c135e 17777 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17778 break;
17779
17780 /* Logical operations */
17781 case ORI32:
17782 mips32_op = OPC_ORI;
17783 goto do_logici;
17784 case XORI32:
17785 mips32_op = OPC_XORI;
17786 goto do_logici;
17787 case ANDI32:
17788 mips32_op = OPC_ANDI;
17789 do_logici:
d75c135e 17790 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17791 break;
17792
17793 /* Set less than immediate */
17794 case SLTI32:
17795 mips32_op = OPC_SLTI;
17796 goto do_slti;
17797 case SLTIU32:
17798 mips32_op = OPC_SLTIU;
17799 do_slti:
d75c135e 17800 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17801 break;
17802 case JALX32:
2e211e0a 17803 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 17804 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17805 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17806 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17807 break;
65935f07 17808 case JALS32: /* BOVC, BEQC, BEQZALC */
2e211e0a 17809 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17810 if (rs >= rt) {
17811 /* BOVC */
17812 mips32_op = OPC_BOVC;
17813 } else if (rs < rt && rs == 0) {
17814 /* BEQZALC */
17815 mips32_op = OPC_BEQZALC;
17816 } else {
17817 /* BEQC */
17818 mips32_op = OPC_BEQC;
17819 }
17820 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17821 } else {
17822 /* JALS32 */
17823 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17824 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17825 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17826 }
3c824109 17827 break;
65935f07 17828 case BEQ32: /* BC */
2e211e0a 17829 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17830 /* BC */
17831 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17832 sextract32(ctx->opcode << 1, 0, 27));
17833 } else {
17834 /* BEQ32 */
17835 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17836 }
3c824109 17837 break;
65935f07 17838 case BNE32: /* BALC */
2e211e0a 17839 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17840 /* BALC */
17841 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17842 sextract32(ctx->opcode << 1, 0, 27));
17843 } else {
17844 /* BNE32 */
17845 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17846 }
3c824109 17847 break;
65935f07 17848 case J32: /* BGTZC, BLTZC, BLTC */
2e211e0a 17849 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17850 if (rs == 0 && rt != 0) {
17851 /* BGTZC */
17852 mips32_op = OPC_BGTZC;
17853 } else if (rs != 0 && rt != 0 && rs == rt) {
17854 /* BLTZC */
17855 mips32_op = OPC_BLTZC;
17856 } else {
17857 /* BLTC */
17858 mips32_op = OPC_BLTC;
17859 }
17860 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17861 } else {
17862 /* J32 */
17863 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17864 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17865 }
3c824109 17866 break;
65935f07 17867 case JAL32: /* BLEZC, BGEZC, BGEC */
2e211e0a 17868 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
17869 if (rs == 0 && rt != 0) {
17870 /* BLEZC */
17871 mips32_op = OPC_BLEZC;
17872 } else if (rs != 0 && rt != 0 && rs == rt) {
17873 /* BGEZC */
17874 mips32_op = OPC_BGEZC;
17875 } else {
17876 /* BGEC */
17877 mips32_op = OPC_BGEC;
17878 }
17879 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17880 } else {
17881 /* JAL32 */
17882 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17883 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17884 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17885 }
3c824109
NF
17886 break;
17887 /* Floating point (COP1) */
17888 case LWC132:
17889 mips32_op = OPC_LWC1;
17890 goto do_cop1;
17891 case LDC132:
17892 mips32_op = OPC_LDC1;
17893 goto do_cop1;
17894 case SWC132:
17895 mips32_op = OPC_SWC1;
17896 goto do_cop1;
17897 case SDC132:
17898 mips32_op = OPC_SDC1;
17899 do_cop1:
5ab5c041 17900 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17901 break;
ab39ee45 17902 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
2e211e0a 17903 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
17904 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17905 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17906 case ADDIUPC_00:
17907 case ADDIUPC_01:
17908 case ADDIUPC_02:
17909 case ADDIUPC_03:
17910 case ADDIUPC_04:
17911 case ADDIUPC_05:
17912 case ADDIUPC_06:
17913 case ADDIUPC_07:
eeb3bba8 17914 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17915 break;
17916 case AUIPC:
eeb3bba8 17917 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17918 break;
17919 case ALUIPC:
eeb3bba8 17920 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17921 break;
c38a1d52
AR
17922 case LWPC_08:
17923 case LWPC_09:
17924 case LWPC_0A:
17925 case LWPC_0B:
17926 case LWPC_0C:
17927 case LWPC_0D:
17928 case LWPC_0E:
17929 case LWPC_0F:
eeb3bba8 17930 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17931 break;
17932 default:
17933 generate_exception(ctx, EXCP_RI);
17934 break;
17935 }
17936 } else {
17937 /* ADDIUPC */
3c824109 17938 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17939 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17940
17941 gen_addiupc(ctx, reg, offset, 0, 0);
17942 }
17943 break;
65935f07 17944 case BNVC: /* BNEC, BNEZALC */
2e211e0a 17945 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
17946 if (rs >= rt) {
17947 /* BNVC */
17948 mips32_op = OPC_BNVC;
17949 } else if (rs < rt && rs == 0) {
17950 /* BNEZALC */
17951 mips32_op = OPC_BNEZALC;
17952 } else {
17953 /* BNEC */
17954 mips32_op = OPC_BNEC;
17955 }
17956 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17957 break;
17958 case R6_BNEZC: /* JIALC */
2e211e0a 17959 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
17960 if (rt != 0) {
17961 /* BNEZC */
17962 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17963 sextract32(ctx->opcode << 1, 0, 22));
17964 } else {
17965 /* JIALC */
17966 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17967 }
17968 break;
17969 case R6_BEQZC: /* JIC */
2e211e0a 17970 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
17971 if (rt != 0) {
17972 /* BEQZC */
17973 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17974 sextract32(ctx->opcode << 1, 0, 22));
17975 } else {
17976 /* JIC */
17977 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17978 }
17979 break;
17980 case BLEZALC: /* BGEZALC, BGEUC */
2e211e0a 17981 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
17982 if (rs == 0 && rt != 0) {
17983 /* BLEZALC */
17984 mips32_op = OPC_BLEZALC;
17985 } else if (rs != 0 && rt != 0 && rs == rt) {
17986 /* BGEZALC */
17987 mips32_op = OPC_BGEZALC;
17988 } else {
17989 /* BGEUC */
17990 mips32_op = OPC_BGEUC;
17991 }
17992 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17993 break;
17994 case BGTZALC: /* BLTZALC, BLTUC */
2e211e0a 17995 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
17996 if (rs == 0 && rt != 0) {
17997 /* BGTZALC */
17998 mips32_op = OPC_BGTZALC;
17999 } else if (rs != 0 && rt != 0 && rs == rt) {
18000 /* BLTZALC */
18001 mips32_op = OPC_BLTZALC;
18002 } else {
18003 /* BLTUC */
18004 mips32_op = OPC_BLTUC;
18005 }
18006 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
18007 break;
3c824109
NF
18008 /* Loads and stores */
18009 case LB32:
18010 mips32_op = OPC_LB;
5c13fdfd 18011 goto do_ld;
3c824109
NF
18012 case LBU32:
18013 mips32_op = OPC_LBU;
5c13fdfd 18014 goto do_ld;
3c824109
NF
18015 case LH32:
18016 mips32_op = OPC_LH;
5c13fdfd 18017 goto do_ld;
3c824109
NF
18018 case LHU32:
18019 mips32_op = OPC_LHU;
5c13fdfd 18020 goto do_ld;
3c824109
NF
18021 case LW32:
18022 mips32_op = OPC_LW;
5c13fdfd 18023 goto do_ld;
3c824109
NF
18024#ifdef TARGET_MIPS64
18025 case LD32:
d9224450
MR
18026 check_insn(ctx, ISA_MIPS3);
18027 check_mips_64(ctx);
3c824109 18028 mips32_op = OPC_LD;
5c13fdfd 18029 goto do_ld;
3c824109 18030 case SD32:
d9224450
MR
18031 check_insn(ctx, ISA_MIPS3);
18032 check_mips_64(ctx);
3c824109 18033 mips32_op = OPC_SD;
5c13fdfd 18034 goto do_st;
3c824109
NF
18035#endif
18036 case SB32:
18037 mips32_op = OPC_SB;
5c13fdfd 18038 goto do_st;
3c824109
NF
18039 case SH32:
18040 mips32_op = OPC_SH;
5c13fdfd 18041 goto do_st;
3c824109
NF
18042 case SW32:
18043 mips32_op = OPC_SW;
5c13fdfd
AJ
18044 goto do_st;
18045 do_ld:
d75c135e 18046 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
18047 break;
18048 do_st:
18049 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
18050 break;
18051 default:
9c708c7f 18052 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
18053 break;
18054 }
18055}
18056
235785e8 18057static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
18058{
18059 uint32_t op;
18060
18061 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
18062 if (ctx->base.pc_next & 0x1) {
18063 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 18064 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
18065 return 2;
18066 }
18067
18068 op = (ctx->opcode >> 10) & 0x3f;
18069 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
18070 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
18071 switch (op & 0x7) { /* MSB-3..MSB-5 */
18072 case 0:
18073 /* POOL32A, POOL32B, POOL32I, POOL32C */
18074 case 4:
18075 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
18076 case 5:
18077 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
18078 case 6:
18079 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
18080 case 7:
18081 /* LB32, LH32, LWC132, LDC132, LW32 */
18082 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 18083 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
18084 return 2;
18085 }
18086 break;
b231c103
YK
18087 case 1:
18088 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
18089 case 2:
18090 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
18091 case 3:
18092 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
18093 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 18094 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
18095 return 2;
18096 }
18097 break;
3c824109
NF
18098 }
18099 }
b231c103 18100
3c824109
NF
18101 switch (op) {
18102 case POOL16A:
18103 {
18104 int rd = mmreg(uMIPS_RD(ctx->opcode));
18105 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
18106 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
18107 uint32_t opc = 0;
18108
18109 switch (ctx->opcode & 0x1) {
18110 case ADDU16:
18111 opc = OPC_ADDU;
18112 break;
18113 case SUBU16:
18114 opc = OPC_SUBU;
18115 break;
18116 }
2e211e0a 18117 if (ctx->insn_flags & ISA_MIPS_R6) {
7480515f
AM
18118 /*
18119 * In the Release 6, the register number location in
ed7ce6c0
YK
18120 * the instruction encoding has changed.
18121 */
18122 gen_arith(ctx, opc, rs1, rd, rs2);
18123 } else {
18124 gen_arith(ctx, opc, rd, rs1, rs2);
18125 }
3c824109
NF
18126 }
18127 break;
18128 case POOL16B:
18129 {
18130 int rd = mmreg(uMIPS_RD(ctx->opcode));
18131 int rs = mmreg(uMIPS_RS(ctx->opcode));
18132 int amount = (ctx->opcode >> 1) & 0x7;
18133 uint32_t opc = 0;
18134 amount = amount == 0 ? 8 : amount;
18135
18136 switch (ctx->opcode & 0x1) {
18137 case SLL16:
18138 opc = OPC_SLL;
18139 break;
18140 case SRL16:
18141 opc = OPC_SRL;
18142 break;
18143 }
18144
d75c135e 18145 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
18146 }
18147 break;
18148 case POOL16C:
2e211e0a 18149 if (ctx->insn_flags & ISA_MIPS_R6) {
ed7ce6c0
YK
18150 gen_pool16c_r6_insn(ctx);
18151 } else {
18152 gen_pool16c_insn(ctx);
18153 }
3c824109
NF
18154 break;
18155 case LWGP16:
18156 {
18157 int rd = mmreg(uMIPS_RD(ctx->opcode));
18158 int rb = 28; /* GP */
18159 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18160
d75c135e 18161 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
18162 }
18163 break;
18164 case POOL16F:
2e211e0a 18165 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 18166 if (ctx->opcode & 1) {
9c708c7f 18167 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
18168 } else {
18169 /* MOVEP */
18170 int enc_dest = uMIPS_RD(ctx->opcode);
18171 int enc_rt = uMIPS_RS2(ctx->opcode);
18172 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 18173 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
18174 }
18175 break;
18176 case LBU16:
18177 {
18178 int rd = mmreg(uMIPS_RD(ctx->opcode));
18179 int rb = mmreg(uMIPS_RS(ctx->opcode));
18180 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18181 offset = (offset == 0xf ? -1 : offset);
18182
d75c135e 18183 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
18184 }
18185 break;
18186 case LHU16:
18187 {
18188 int rd = mmreg(uMIPS_RD(ctx->opcode));
18189 int rb = mmreg(uMIPS_RS(ctx->opcode));
18190 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18191
d75c135e 18192 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
18193 }
18194 break;
18195 case LWSP16:
18196 {
18197 int rd = (ctx->opcode >> 5) & 0x1f;
18198 int rb = 29; /* SP */
18199 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18200
d75c135e 18201 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
18202 }
18203 break;
18204 case LW16:
18205 {
18206 int rd = mmreg(uMIPS_RD(ctx->opcode));
18207 int rb = mmreg(uMIPS_RS(ctx->opcode));
18208 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18209
d75c135e 18210 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
18211 }
18212 break;
18213 case SB16:
18214 {
18215 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18216 int rb = mmreg(uMIPS_RS(ctx->opcode));
18217 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18218
5c13fdfd 18219 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
18220 }
18221 break;
18222 case SH16:
18223 {
18224 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18225 int rb = mmreg(uMIPS_RS(ctx->opcode));
18226 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18227
5c13fdfd 18228 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
18229 }
18230 break;
18231 case SWSP16:
18232 {
18233 int rd = (ctx->opcode >> 5) & 0x1f;
18234 int rb = 29; /* SP */
18235 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18236
5c13fdfd 18237 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
18238 }
18239 break;
18240 case SW16:
18241 {
18242 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18243 int rb = mmreg(uMIPS_RS(ctx->opcode));
18244 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18245
5c13fdfd 18246 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
18247 }
18248 break;
18249 case MOVE16:
18250 {
18251 int rd = uMIPS_RD5(ctx->opcode);
18252 int rs = uMIPS_RS5(ctx->opcode);
18253
7215d7e7 18254 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
18255 }
18256 break;
18257 case ANDI16:
d75c135e 18258 gen_andi16(ctx);
3c824109
NF
18259 break;
18260 case POOL16D:
18261 switch (ctx->opcode & 0x1) {
18262 case ADDIUS5:
d75c135e 18263 gen_addius5(ctx);
3c824109
NF
18264 break;
18265 case ADDIUSP:
d75c135e 18266 gen_addiusp(ctx);
3c824109
NF
18267 break;
18268 }
18269 break;
18270 case POOL16E:
18271 switch (ctx->opcode & 0x1) {
18272 case ADDIUR2:
d75c135e 18273 gen_addiur2(ctx);
3c824109
NF
18274 break;
18275 case ADDIUR1SP:
d75c135e 18276 gen_addiur1sp(ctx);
3c824109
NF
18277 break;
18278 }
18279 break;
65935f07 18280 case B16: /* BC16 */
3c824109 18281 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07 18282 sextract32(ctx->opcode, 0, 10) << 1,
2e211e0a 18283 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
3c824109 18284 break;
65935f07
YK
18285 case BNEZ16: /* BNEZC16 */
18286 case BEQZ16: /* BEQZC16 */
3c824109
NF
18287 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18288 mmreg(uMIPS_RD(ctx->opcode)),
65935f07 18289 0, sextract32(ctx->opcode, 0, 7) << 1,
2e211e0a 18290 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
65935f07 18291
3c824109
NF
18292 break;
18293 case LI16:
18294 {
18295 int reg = mmreg(uMIPS_RD(ctx->opcode));
18296 int imm = ZIMM(ctx->opcode, 0, 7);
18297
18298 imm = (imm == 0x7f ? -1 : imm);
18299 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18300 }
18301 break;
3c824109 18302 case RES_29:
3c824109 18303 case RES_31:
3c824109 18304 case RES_39:
9c708c7f 18305 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
18306 break;
18307 default:
f60eeb0c 18308 decode_micromips32_opc(env, ctx);
3c824109
NF
18309 return 4;
18310 }
18311
18312 return 2;
18313}
18314
261c95a0
YK
18315/*
18316 *
18317 * nanoMIPS opcodes
18318 *
18319 */
18320
18321/* MAJOR, P16, and P32 pools opcodes */
18322enum {
18323 NM_P_ADDIU = 0x00,
18324 NM_ADDIUPC = 0x01,
18325 NM_MOVE_BALC = 0x02,
18326 NM_P16_MV = 0x04,
18327 NM_LW16 = 0x05,
18328 NM_BC16 = 0x06,
18329 NM_P16_SR = 0x07,
18330
18331 NM_POOL32A = 0x08,
18332 NM_P_BAL = 0x0a,
18333 NM_P16_SHIFT = 0x0c,
18334 NM_LWSP16 = 0x0d,
18335 NM_BALC16 = 0x0e,
18336 NM_P16_4X4 = 0x0f,
18337
18338 NM_P_GP_W = 0x10,
18339 NM_P_GP_BH = 0x11,
18340 NM_P_J = 0x12,
18341 NM_P16C = 0x14,
18342 NM_LWGP16 = 0x15,
18343 NM_P16_LB = 0x17,
18344
18345 NM_P48I = 0x18,
18346 NM_P16_A1 = 0x1c,
18347 NM_LW4X4 = 0x1d,
18348 NM_P16_LH = 0x1f,
18349
18350 NM_P_U12 = 0x20,
18351 NM_P_LS_U12 = 0x21,
18352 NM_P_BR1 = 0x22,
18353 NM_P16_A2 = 0x24,
18354 NM_SW16 = 0x25,
18355 NM_BEQZC16 = 0x26,
18356
18357 NM_POOL32F = 0x28,
18358 NM_P_LS_S9 = 0x29,
18359 NM_P_BR2 = 0x2a,
18360
18361 NM_P16_ADDU = 0x2c,
18362 NM_SWSP16 = 0x2d,
18363 NM_BNEZC16 = 0x2e,
18364 NM_MOVEP = 0x2f,
18365
18366 NM_POOL32S = 0x30,
18367 NM_P_BRI = 0x32,
18368 NM_LI16 = 0x34,
18369 NM_SWGP16 = 0x35,
18370 NM_P16_BR = 0x36,
18371
18372 NM_P_LUI = 0x38,
18373 NM_ANDI16 = 0x3c,
18374 NM_SW4X4 = 0x3d,
18375 NM_MOVEPREV = 0x3f,
18376};
18377
18378/* POOL32A instruction pool */
18379enum {
18380 NM_POOL32A0 = 0x00,
18381 NM_SPECIAL2 = 0x01,
18382 NM_COP2_1 = 0x02,
18383 NM_UDI = 0x03,
18384 NM_POOL32A5 = 0x05,
18385 NM_POOL32A7 = 0x07,
18386};
18387
18388/* P.GP.W instruction pool */
18389enum {
18390 NM_ADDIUGP_W = 0x00,
18391 NM_LWGP = 0x02,
18392 NM_SWGP = 0x03,
18393};
18394
18395/* P48I instruction pool */
18396enum {
18397 NM_LI48 = 0x00,
18398 NM_ADDIU48 = 0x01,
18399 NM_ADDIUGP48 = 0x02,
18400 NM_ADDIUPC48 = 0x03,
18401 NM_LWPC48 = 0x0b,
18402 NM_SWPC48 = 0x0f,
18403};
18404
18405/* P.U12 instruction pool */
18406enum {
18407 NM_ORI = 0x00,
18408 NM_XORI = 0x01,
18409 NM_ANDI = 0x02,
18410 NM_P_SR = 0x03,
18411 NM_SLTI = 0x04,
18412 NM_SLTIU = 0x05,
18413 NM_SEQI = 0x06,
18414 NM_ADDIUNEG = 0x08,
18415 NM_P_SHIFT = 0x0c,
18416 NM_P_ROTX = 0x0d,
18417 NM_P_INS = 0x0e,
18418 NM_P_EXT = 0x0f,
18419};
18420
18421/* POOL32F instruction pool */
18422enum {
18423 NM_POOL32F_0 = 0x00,
18424 NM_POOL32F_3 = 0x03,
18425 NM_POOL32F_5 = 0x05,
18426};
18427
18428/* POOL32S instruction pool */
18429enum {
18430 NM_POOL32S_0 = 0x00,
18431 NM_POOL32S_4 = 0x04,
18432};
18433
18434/* P.LUI instruction pool */
18435enum {
18436 NM_LUI = 0x00,
18437 NM_ALUIPC = 0x01,
18438};
18439
18440/* P.GP.BH instruction pool */
18441enum {
18442 NM_LBGP = 0x00,
18443 NM_SBGP = 0x01,
18444 NM_LBUGP = 0x02,
18445 NM_ADDIUGP_B = 0x03,
18446 NM_P_GP_LH = 0x04,
18447 NM_P_GP_SH = 0x05,
18448 NM_P_GP_CP1 = 0x06,
18449};
18450
18451/* P.LS.U12 instruction pool */
18452enum {
18453 NM_LB = 0x00,
18454 NM_SB = 0x01,
18455 NM_LBU = 0x02,
18456 NM_P_PREFU12 = 0x03,
18457 NM_LH = 0x04,
18458 NM_SH = 0x05,
18459 NM_LHU = 0x06,
18460 NM_LWU = 0x07,
18461 NM_LW = 0x08,
18462 NM_SW = 0x09,
18463 NM_LWC1 = 0x0a,
18464 NM_SWC1 = 0x0b,
18465 NM_LDC1 = 0x0e,
18466 NM_SDC1 = 0x0f,
18467};
18468
18469/* P.LS.S9 instruction pool */
18470enum {
18471 NM_P_LS_S0 = 0x00,
18472 NM_P_LS_S1 = 0x01,
18473 NM_P_LS_E0 = 0x02,
18474 NM_P_LS_WM = 0x04,
18475 NM_P_LS_UAWM = 0x05,
18476};
18477
18478/* P.BAL instruction pool */
18479enum {
18480 NM_BC = 0x00,
18481 NM_BALC = 0x01,
18482};
18483
18484/* P.J instruction pool */
18485enum {
18486 NM_JALRC = 0x00,
18487 NM_JALRC_HB = 0x01,
18488 NM_P_BALRSC = 0x08,
18489};
18490
18491/* P.BR1 instruction pool */
18492enum {
18493 NM_BEQC = 0x00,
18494 NM_P_BR3A = 0x01,
18495 NM_BGEC = 0x02,
18496 NM_BGEUC = 0x03,
18497};
18498
18499/* P.BR2 instruction pool */
18500enum {
18501 NM_BNEC = 0x00,
18502 NM_BLTC = 0x02,
18503 NM_BLTUC = 0x03,
18504};
18505
18506/* P.BRI instruction pool */
18507enum {
18508 NM_BEQIC = 0x00,
18509 NM_BBEQZC = 0x01,
18510 NM_BGEIC = 0x02,
18511 NM_BGEIUC = 0x03,
18512 NM_BNEIC = 0x04,
18513 NM_BBNEZC = 0x05,
18514 NM_BLTIC = 0x06,
18515 NM_BLTIUC = 0x07,
18516};
18517
18518/* P16.SHIFT instruction pool */
18519enum {
18520 NM_SLL16 = 0x00,
18521 NM_SRL16 = 0x01,
18522};
18523
18524/* POOL16C instruction pool */
18525enum {
18526 NM_POOL16C_0 = 0x00,
18527 NM_LWXS16 = 0x01,
18528};
18529
18530/* P16.A1 instruction pool */
18531enum {
18532 NM_ADDIUR1SP = 0x01,
18533};
18534
18535/* P16.A2 instruction pool */
18536enum {
18537 NM_ADDIUR2 = 0x00,
18538 NM_P_ADDIURS5 = 0x01,
18539};
18540
18541/* P16.ADDU instruction pool */
18542enum {
18543 NM_ADDU16 = 0x00,
18544 NM_SUBU16 = 0x01,
18545};
18546
18547/* P16.SR instruction pool */
18548enum {
18549 NM_SAVE16 = 0x00,
18550 NM_RESTORE_JRC16 = 0x01,
18551};
18552
18553/* P16.4X4 instruction pool */
18554enum {
18555 NM_ADDU4X4 = 0x00,
18556 NM_MUL4X4 = 0x01,
18557};
18558
18559/* P16.LB instruction pool */
18560enum {
18561 NM_LB16 = 0x00,
18562 NM_SB16 = 0x01,
18563 NM_LBU16 = 0x02,
18564};
18565
18566/* P16.LH instruction pool */
18567enum {
18568 NM_LH16 = 0x00,
18569 NM_SH16 = 0x01,
18570 NM_LHU16 = 0x02,
18571};
18572
18573/* P.RI instruction pool */
18574enum {
18575 NM_SIGRIE = 0x00,
18576 NM_P_SYSCALL = 0x01,
18577 NM_BREAK = 0x02,
18578 NM_SDBBP = 0x03,
18579};
18580
18581/* POOL32A0 instruction pool */
18582enum {
18583 NM_P_TRAP = 0x00,
18584 NM_SEB = 0x01,
18585 NM_SLLV = 0x02,
18586 NM_MUL = 0x03,
18587 NM_MFC0 = 0x06,
18588 NM_MFHC0 = 0x07,
18589 NM_SEH = 0x09,
18590 NM_SRLV = 0x0a,
18591 NM_MUH = 0x0b,
18592 NM_MTC0 = 0x0e,
18593 NM_MTHC0 = 0x0f,
18594 NM_SRAV = 0x12,
18595 NM_MULU = 0x13,
18596 NM_ROTRV = 0x1a,
18597 NM_MUHU = 0x1b,
18598 NM_ADD = 0x22,
18599 NM_DIV = 0x23,
18600 NM_ADDU = 0x2a,
18601 NM_MOD = 0x2b,
18602 NM_SUB = 0x32,
18603 NM_DIVU = 0x33,
18604 NM_RDHWR = 0x38,
18605 NM_SUBU = 0x3a,
18606 NM_MODU = 0x3b,
18607 NM_P_CMOVE = 0x42,
18608 NM_FORK = 0x45,
18609 NM_MFTR = 0x46,
18610 NM_MFHTR = 0x47,
18611 NM_AND = 0x4a,
18612 NM_YIELD = 0x4d,
18613 NM_MTTR = 0x4e,
18614 NM_MTHTR = 0x4f,
18615 NM_OR = 0x52,
18616 NM_D_E_MT_VPE = 0x56,
18617 NM_NOR = 0x5a,
18618 NM_XOR = 0x62,
18619 NM_SLT = 0x6a,
18620 NM_P_SLTU = 0x72,
18621 NM_SOV = 0x7a,
18622};
18623
ba1e8117
AM
18624/* CRC32 instruction pool */
18625enum {
18626 NM_CRC32B = 0x00,
18627 NM_CRC32H = 0x01,
18628 NM_CRC32W = 0x02,
18629 NM_CRC32CB = 0x04,
18630 NM_CRC32CH = 0x05,
18631 NM_CRC32CW = 0x06,
18632};
18633
b3979b6f
SM
18634/* POOL32A5 instruction pool */
18635enum {
18636 NM_CMP_EQ_PH = 0x00,
18637 NM_CMP_LT_PH = 0x08,
18638 NM_CMP_LE_PH = 0x10,
18639 NM_CMPGU_EQ_QB = 0x18,
18640 NM_CMPGU_LT_QB = 0x20,
18641 NM_CMPGU_LE_QB = 0x28,
18642 NM_CMPGDU_EQ_QB = 0x30,
18643 NM_CMPGDU_LT_QB = 0x38,
18644 NM_CMPGDU_LE_QB = 0x40,
18645 NM_CMPU_EQ_QB = 0x48,
18646 NM_CMPU_LT_QB = 0x50,
18647 NM_CMPU_LE_QB = 0x58,
18648 NM_ADDQ_S_W = 0x60,
18649 NM_SUBQ_S_W = 0x68,
18650 NM_ADDSC = 0x70,
18651 NM_ADDWC = 0x78,
18652
18653 NM_ADDQ_S_PH = 0x01,
18654 NM_ADDQH_R_PH = 0x09,
18655 NM_ADDQH_R_W = 0x11,
18656 NM_ADDU_S_QB = 0x19,
18657 NM_ADDU_S_PH = 0x21,
18658 NM_ADDUH_R_QB = 0x29,
18659 NM_SHRAV_R_PH = 0x31,
18660 NM_SHRAV_R_QB = 0x39,
18661 NM_SUBQ_S_PH = 0x41,
18662 NM_SUBQH_R_PH = 0x49,
18663 NM_SUBQH_R_W = 0x51,
18664 NM_SUBU_S_QB = 0x59,
18665 NM_SUBU_S_PH = 0x61,
18666 NM_SUBUH_R_QB = 0x69,
18667 NM_SHLLV_S_PH = 0x71,
18668 NM_PRECR_SRA_R_PH_W = 0x79,
18669
18670 NM_MULEU_S_PH_QBL = 0x12,
18671 NM_MULEU_S_PH_QBR = 0x1a,
18672 NM_MULQ_RS_PH = 0x22,
18673 NM_MULQ_S_PH = 0x2a,
18674 NM_MULQ_RS_W = 0x32,
18675 NM_MULQ_S_W = 0x3a,
18676 NM_APPEND = 0x42,
18677 NM_MODSUB = 0x52,
18678 NM_SHRAV_R_W = 0x5a,
18679 NM_SHRLV_PH = 0x62,
18680 NM_SHRLV_QB = 0x6a,
18681 NM_SHLLV_QB = 0x72,
18682 NM_SHLLV_S_W = 0x7a,
18683
18684 NM_SHILO = 0x03,
18685
18686 NM_MULEQ_S_W_PHL = 0x04,
18687 NM_MULEQ_S_W_PHR = 0x0c,
18688
18689 NM_MUL_S_PH = 0x05,
18690 NM_PRECR_QB_PH = 0x0d,
18691 NM_PRECRQ_QB_PH = 0x15,
18692 NM_PRECRQ_PH_W = 0x1d,
18693 NM_PRECRQ_RS_PH_W = 0x25,
18694 NM_PRECRQU_S_QB_PH = 0x2d,
18695 NM_PACKRL_PH = 0x35,
18696 NM_PICK_QB = 0x3d,
18697 NM_PICK_PH = 0x45,
18698
18699 NM_SHRA_R_W = 0x5e,
18700 NM_SHRA_R_PH = 0x66,
18701 NM_SHLL_S_PH = 0x76,
18702 NM_SHLL_S_W = 0x7e,
18703
18704 NM_REPL_PH = 0x07
18705};
18706
261c95a0
YK
18707/* POOL32A7 instruction pool */
18708enum {
18709 NM_P_LSX = 0x00,
18710 NM_LSA = 0x01,
18711 NM_EXTW = 0x03,
18712 NM_POOL32AXF = 0x07,
18713};
18714
18715/* P.SR instruction pool */
18716enum {
18717 NM_PP_SR = 0x00,
18718 NM_P_SR_F = 0x01,
18719};
18720
18721/* P.SHIFT instruction pool */
18722enum {
18723 NM_P_SLL = 0x00,
18724 NM_SRL = 0x02,
18725 NM_SRA = 0x04,
18726 NM_ROTR = 0x06,
18727};
18728
18729/* P.ROTX instruction pool */
18730enum {
18731 NM_ROTX = 0x00,
18732};
18733
18734/* P.INS instruction pool */
18735enum {
18736 NM_INS = 0x00,
18737};
18738
18739/* P.EXT instruction pool */
18740enum {
18741 NM_EXT = 0x00,
18742};
18743
18744/* POOL32F_0 (fmt) instruction pool */
18745enum {
18746 NM_RINT_S = 0x04,
18747 NM_RINT_D = 0x44,
18748 NM_ADD_S = 0x06,
18749 NM_SELEQZ_S = 0x07,
18750 NM_SELEQZ_D = 0x47,
18751 NM_CLASS_S = 0x0c,
18752 NM_CLASS_D = 0x4c,
18753 NM_SUB_S = 0x0e,
18754 NM_SELNEZ_S = 0x0f,
18755 NM_SELNEZ_D = 0x4f,
18756 NM_MUL_S = 0x16,
18757 NM_SEL_S = 0x17,
18758 NM_SEL_D = 0x57,
18759 NM_DIV_S = 0x1e,
18760 NM_ADD_D = 0x26,
18761 NM_SUB_D = 0x2e,
18762 NM_MUL_D = 0x36,
18763 NM_MADDF_S = 0x37,
18764 NM_MADDF_D = 0x77,
18765 NM_DIV_D = 0x3e,
18766 NM_MSUBF_S = 0x3f,
18767 NM_MSUBF_D = 0x7f,
18768};
18769
18770/* POOL32F_3 instruction pool */
18771enum {
18772 NM_MIN_FMT = 0x00,
18773 NM_MAX_FMT = 0x01,
18774 NM_MINA_FMT = 0x04,
18775 NM_MAXA_FMT = 0x05,
18776 NM_POOL32FXF = 0x07,
18777};
18778
18779/* POOL32F_5 instruction pool */
18780enum {
18781 NM_CMP_CONDN_S = 0x00,
18782 NM_CMP_CONDN_D = 0x02,
18783};
18784
18785/* P.GP.LH instruction pool */
18786enum {
18787 NM_LHGP = 0x00,
18788 NM_LHUGP = 0x01,
18789};
18790
18791/* P.GP.SH instruction pool */
18792enum {
18793 NM_SHGP = 0x00,
18794};
18795
18796/* P.GP.CP1 instruction pool */
18797enum {
18798 NM_LWC1GP = 0x00,
18799 NM_SWC1GP = 0x01,
18800 NM_LDC1GP = 0x02,
18801 NM_SDC1GP = 0x03,
18802};
18803
18804/* P.LS.S0 instruction pool */
18805enum {
18806 NM_LBS9 = 0x00,
18807 NM_LHS9 = 0x04,
18808 NM_LWS9 = 0x08,
18809 NM_LDS9 = 0x0c,
18810
18811 NM_SBS9 = 0x01,
18812 NM_SHS9 = 0x05,
18813 NM_SWS9 = 0x09,
18814 NM_SDS9 = 0x0d,
18815
18816 NM_LBUS9 = 0x02,
18817 NM_LHUS9 = 0x06,
18818 NM_LWC1S9 = 0x0a,
18819 NM_LDC1S9 = 0x0e,
18820
18821 NM_P_PREFS9 = 0x03,
18822 NM_LWUS9 = 0x07,
18823 NM_SWC1S9 = 0x0b,
18824 NM_SDC1S9 = 0x0f,
18825};
18826
18827/* P.LS.S1 instruction pool */
18828enum {
18829 NM_ASET_ACLR = 0x02,
18830 NM_UALH = 0x04,
18831 NM_UASH = 0x05,
18832 NM_CACHE = 0x07,
18833 NM_P_LL = 0x0a,
18834 NM_P_SC = 0x0b,
18835};
18836
0d30b3bb
DN
18837/* P.LS.E0 instruction pool */
18838enum {
18839 NM_LBE = 0x00,
18840 NM_SBE = 0x01,
18841 NM_LBUE = 0x02,
18842 NM_P_PREFE = 0x03,
18843 NM_LHE = 0x04,
18844 NM_SHE = 0x05,
18845 NM_LHUE = 0x06,
18846 NM_CACHEE = 0x07,
18847 NM_LWE = 0x08,
18848 NM_SWE = 0x09,
18849 NM_P_LLE = 0x0a,
18850 NM_P_SCE = 0x0b,
18851};
18852
18853/* P.PREFE instruction pool */
18854enum {
18855 NM_SYNCIE = 0x00,
18856 NM_PREFE = 0x01,
18857};
18858
18859/* P.LLE instruction pool */
18860enum {
18861 NM_LLE = 0x00,
18862 NM_LLWPE = 0x01,
18863};
18864
18865/* P.SCE instruction pool */
18866enum {
18867 NM_SCE = 0x00,
18868 NM_SCWPE = 0x01,
18869};
18870
261c95a0
YK
18871/* P.LS.WM instruction pool */
18872enum {
18873 NM_LWM = 0x00,
18874 NM_SWM = 0x01,
18875};
18876
18877/* P.LS.UAWM instruction pool */
18878enum {
18879 NM_UALWM = 0x00,
18880 NM_UASWM = 0x01,
18881};
18882
18883/* P.BR3A instruction pool */
18884enum {
18885 NM_BC1EQZC = 0x00,
18886 NM_BC1NEZC = 0x01,
18887 NM_BC2EQZC = 0x02,
18888 NM_BC2NEZC = 0x03,
18889 NM_BPOSGE32C = 0x04,
18890};
18891
18892/* P16.RI instruction pool */
18893enum {
18894 NM_P16_SYSCALL = 0x01,
18895 NM_BREAK16 = 0x02,
18896 NM_SDBBP16 = 0x03,
18897};
18898
18899/* POOL16C_0 instruction pool */
18900enum {
18901 NM_POOL16C_00 = 0x00,
18902};
18903
18904/* P16.JRC instruction pool */
18905enum {
18906 NM_JRC = 0x00,
18907 NM_JALRC16 = 0x01,
18908};
18909
18910/* P.SYSCALL instruction pool */
18911enum {
18912 NM_SYSCALL = 0x00,
18913 NM_HYPCALL = 0x01,
18914};
18915
18916/* P.TRAP instruction pool */
18917enum {
18918 NM_TEQ = 0x00,
18919 NM_TNE = 0x01,
18920};
18921
18922/* P.CMOVE instruction pool */
18923enum {
18924 NM_MOVZ = 0x00,
18925 NM_MOVN = 0x01,
18926};
18927
18928/* POOL32Axf instruction pool */
18929enum {
b3979b6f
SM
18930 NM_POOL32AXF_1 = 0x01,
18931 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18932 NM_POOL32AXF_4 = 0x04,
18933 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18934 NM_POOL32AXF_7 = 0x07,
18935};
18936
18937/* POOL32Axf_1 instruction pool */
18938enum {
18939 NM_POOL32AXF_1_0 = 0x00,
18940 NM_POOL32AXF_1_1 = 0x01,
18941 NM_POOL32AXF_1_3 = 0x03,
18942 NM_POOL32AXF_1_4 = 0x04,
18943 NM_POOL32AXF_1_5 = 0x05,
18944 NM_POOL32AXF_1_7 = 0x07,
18945};
18946
18947/* POOL32Axf_2 instruction pool */
18948enum {
18949 NM_POOL32AXF_2_0_7 = 0x00,
18950 NM_POOL32AXF_2_8_15 = 0x01,
18951 NM_POOL32AXF_2_16_23 = 0x02,
18952 NM_POOL32AXF_2_24_31 = 0x03,
18953};
18954
18955/* POOL32Axf_7 instruction pool */
18956enum {
18957 NM_SHRA_R_QB = 0x0,
18958 NM_SHRL_PH = 0x1,
18959 NM_REPL_QB = 0x2,
18960};
18961
18962/* POOL32Axf_1_0 instruction pool */
18963enum {
18964 NM_MFHI = 0x0,
18965 NM_MFLO = 0x1,
18966 NM_MTHI = 0x2,
18967 NM_MTLO = 0x3,
18968};
18969
18970/* POOL32Axf_1_1 instruction pool */
18971enum {
18972 NM_MTHLIP = 0x0,
18973 NM_SHILOV = 0x1,
18974};
18975
18976/* POOL32Axf_1_3 instruction pool */
18977enum {
18978 NM_RDDSP = 0x0,
18979 NM_WRDSP = 0x1,
18980 NM_EXTP = 0x2,
18981 NM_EXTPDP = 0x3,
18982};
18983
18984/* POOL32Axf_1_4 instruction pool */
18985enum {
18986 NM_SHLL_QB = 0x0,
18987 NM_SHRL_QB = 0x1,
18988};
18989
18990/* POOL32Axf_1_5 instruction pool */
18991enum {
18992 NM_MAQ_S_W_PHR = 0x0,
18993 NM_MAQ_S_W_PHL = 0x1,
18994 NM_MAQ_SA_W_PHR = 0x2,
18995 NM_MAQ_SA_W_PHL = 0x3,
18996};
18997
18998/* POOL32Axf_1_7 instruction pool */
18999enum {
19000 NM_EXTR_W = 0x0,
19001 NM_EXTR_R_W = 0x1,
19002 NM_EXTR_RS_W = 0x2,
19003 NM_EXTR_S_H = 0x3,
19004};
19005
19006/* POOL32Axf_2_0_7 instruction pool */
19007enum {
19008 NM_DPA_W_PH = 0x0,
19009 NM_DPAQ_S_W_PH = 0x1,
19010 NM_DPS_W_PH = 0x2,
19011 NM_DPSQ_S_W_PH = 0x3,
19012 NM_BALIGN = 0x4,
19013 NM_MADD = 0x5,
19014 NM_MULT = 0x6,
19015 NM_EXTRV_W = 0x7,
19016};
19017
19018/* POOL32Axf_2_8_15 instruction pool */
19019enum {
19020 NM_DPAX_W_PH = 0x0,
19021 NM_DPAQ_SA_L_W = 0x1,
19022 NM_DPSX_W_PH = 0x2,
19023 NM_DPSQ_SA_L_W = 0x3,
19024 NM_MADDU = 0x5,
19025 NM_MULTU = 0x6,
19026 NM_EXTRV_R_W = 0x7,
19027};
19028
19029/* POOL32Axf_2_16_23 instruction pool */
19030enum {
19031 NM_DPAU_H_QBL = 0x0,
19032 NM_DPAQX_S_W_PH = 0x1,
19033 NM_DPSU_H_QBL = 0x2,
19034 NM_DPSQX_S_W_PH = 0x3,
19035 NM_EXTPV = 0x4,
19036 NM_MSUB = 0x5,
19037 NM_MULSA_W_PH = 0x6,
19038 NM_EXTRV_RS_W = 0x7,
19039};
19040
19041/* POOL32Axf_2_24_31 instruction pool */
19042enum {
19043 NM_DPAU_H_QBR = 0x0,
19044 NM_DPAQX_SA_W_PH = 0x1,
19045 NM_DPSU_H_QBR = 0x2,
19046 NM_DPSQX_SA_W_PH = 0x3,
19047 NM_EXTPDPV = 0x4,
19048 NM_MSUBU = 0x5,
19049 NM_MULSAQ_S_W_PH = 0x6,
19050 NM_EXTRV_S_H = 0x7,
261c95a0
YK
19051};
19052
19053/* POOL32Axf_{4, 5} instruction pool */
19054enum {
19055 NM_CLO = 0x25,
19056 NM_CLZ = 0x2d,
19057
19058 NM_TLBP = 0x01,
19059 NM_TLBR = 0x09,
19060 NM_TLBWI = 0x11,
19061 NM_TLBWR = 0x19,
19062 NM_TLBINV = 0x03,
19063 NM_TLBINVF = 0x0b,
19064 NM_DI = 0x23,
19065 NM_EI = 0x2b,
19066 NM_RDPGPR = 0x70,
19067 NM_WRPGPR = 0x78,
19068 NM_WAIT = 0x61,
19069 NM_DERET = 0x71,
19070 NM_ERETX = 0x79,
b3979b6f
SM
19071
19072 /* nanoMIPS DSP instructions */
19073 NM_ABSQ_S_QB = 0x00,
19074 NM_ABSQ_S_PH = 0x08,
19075 NM_ABSQ_S_W = 0x10,
19076 NM_PRECEQ_W_PHL = 0x28,
19077 NM_PRECEQ_W_PHR = 0x30,
19078 NM_PRECEQU_PH_QBL = 0x38,
19079 NM_PRECEQU_PH_QBR = 0x48,
19080 NM_PRECEU_PH_QBL = 0x58,
19081 NM_PRECEU_PH_QBR = 0x68,
19082 NM_PRECEQU_PH_QBLA = 0x39,
19083 NM_PRECEQU_PH_QBRA = 0x49,
19084 NM_PRECEU_PH_QBLA = 0x59,
19085 NM_PRECEU_PH_QBRA = 0x69,
19086 NM_REPLV_PH = 0x01,
19087 NM_REPLV_QB = 0x09,
19088 NM_BITREV = 0x18,
19089 NM_INSV = 0x20,
19090 NM_RADDU_W_QB = 0x78,
19091
19092 NM_BITSWAP = 0x05,
19093 NM_WSBH = 0x3d,
261c95a0
YK
19094};
19095
19096/* PP.SR instruction pool */
19097enum {
19098 NM_SAVE = 0x00,
19099 NM_RESTORE = 0x02,
19100 NM_RESTORE_JRC = 0x03,
19101};
19102
19103/* P.SR.F instruction pool */
19104enum {
19105 NM_SAVEF = 0x00,
19106 NM_RESTOREF = 0x01,
19107};
19108
19109/* P16.SYSCALL instruction pool */
19110enum {
19111 NM_SYSCALL16 = 0x00,
19112 NM_HYPCALL16 = 0x01,
19113};
19114
19115/* POOL16C_00 instruction pool */
19116enum {
19117 NM_NOT16 = 0x00,
19118 NM_XOR16 = 0x01,
19119 NM_AND16 = 0x02,
19120 NM_OR16 = 0x03,
19121};
19122
19123/* PP.LSX and PP.LSXS instruction pool */
19124enum {
19125 NM_LBX = 0x00,
19126 NM_LHX = 0x04,
19127 NM_LWX = 0x08,
19128 NM_LDX = 0x0c,
19129
19130 NM_SBX = 0x01,
19131 NM_SHX = 0x05,
19132 NM_SWX = 0x09,
19133 NM_SDX = 0x0d,
19134
19135 NM_LBUX = 0x02,
19136 NM_LHUX = 0x06,
19137 NM_LWC1X = 0x0a,
19138 NM_LDC1X = 0x0e,
19139
19140 NM_LWUX = 0x07,
19141 NM_SWC1X = 0x0b,
19142 NM_SDC1X = 0x0f,
19143
19144 NM_LHXS = 0x04,
19145 NM_LWXS = 0x08,
19146 NM_LDXS = 0x0c,
19147
19148 NM_SHXS = 0x05,
19149 NM_SWXS = 0x09,
19150 NM_SDXS = 0x0d,
19151
19152 NM_LHUXS = 0x06,
19153 NM_LWC1XS = 0x0a,
19154 NM_LDC1XS = 0x0e,
19155
19156 NM_LWUXS = 0x07,
19157 NM_SWC1XS = 0x0b,
19158 NM_SDC1XS = 0x0f,
19159};
19160
19161/* ERETx instruction pool */
19162enum {
19163 NM_ERET = 0x00,
19164 NM_ERETNC = 0x01,
19165};
19166
19167/* POOL32FxF_{0, 1} insturction pool */
19168enum {
19169 NM_CFC1 = 0x40,
19170 NM_CTC1 = 0x60,
19171 NM_MFC1 = 0x80,
19172 NM_MTC1 = 0xa0,
19173 NM_MFHC1 = 0xc0,
19174 NM_MTHC1 = 0xe0,
19175
19176 NM_CVT_S_PL = 0x84,
19177 NM_CVT_S_PU = 0xa4,
19178
19179 NM_CVT_L_S = 0x004,
19180 NM_CVT_L_D = 0x104,
19181 NM_CVT_W_S = 0x024,
19182 NM_CVT_W_D = 0x124,
19183
19184 NM_RSQRT_S = 0x008,
19185 NM_RSQRT_D = 0x108,
19186
19187 NM_SQRT_S = 0x028,
19188 NM_SQRT_D = 0x128,
19189
19190 NM_RECIP_S = 0x048,
19191 NM_RECIP_D = 0x148,
19192
19193 NM_FLOOR_L_S = 0x00c,
19194 NM_FLOOR_L_D = 0x10c,
19195
19196 NM_FLOOR_W_S = 0x02c,
19197 NM_FLOOR_W_D = 0x12c,
19198
19199 NM_CEIL_L_S = 0x04c,
19200 NM_CEIL_L_D = 0x14c,
19201 NM_CEIL_W_S = 0x06c,
19202 NM_CEIL_W_D = 0x16c,
19203 NM_TRUNC_L_S = 0x08c,
19204 NM_TRUNC_L_D = 0x18c,
19205 NM_TRUNC_W_S = 0x0ac,
19206 NM_TRUNC_W_D = 0x1ac,
19207 NM_ROUND_L_S = 0x0cc,
19208 NM_ROUND_L_D = 0x1cc,
19209 NM_ROUND_W_S = 0x0ec,
19210 NM_ROUND_W_D = 0x1ec,
19211
19212 NM_MOV_S = 0x01,
19213 NM_MOV_D = 0x81,
19214 NM_ABS_S = 0x0d,
19215 NM_ABS_D = 0x8d,
19216 NM_NEG_S = 0x2d,
19217 NM_NEG_D = 0xad,
19218 NM_CVT_D_S = 0x04d,
19219 NM_CVT_D_W = 0x0cd,
19220 NM_CVT_D_L = 0x14d,
19221 NM_CVT_S_D = 0x06d,
19222 NM_CVT_S_W = 0x0ed,
19223 NM_CVT_S_L = 0x16d,
19224};
19225
19226/* P.LL instruction pool */
19227enum {
19228 NM_LL = 0x00,
19229 NM_LLWP = 0x01,
19230};
19231
19232/* P.SC instruction pool */
19233enum {
19234 NM_SC = 0x00,
19235 NM_SCWP = 0x01,
19236};
19237
19238/* P.DVP instruction pool */
19239enum {
19240 NM_DVP = 0x00,
19241 NM_EVP = 0x01,
19242};
19243
c533c0f4
AM
19244
19245/*
19246 *
19247 * nanoMIPS decoding engine
19248 *
19249 */
19250
6bfa9f4c
AM
19251
19252/* extraction utilities */
19253
99e49abf
AM
19254#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19255#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19256#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
19257#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19258#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19259
ea4ca3c2
YK
19260/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19261static inline int decode_gpr_gpr3(int r)
19262{
19263 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19264
19265 return map[r & 0x7];
19266}
19267
8bdb7029
YK
19268/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19269static inline int decode_gpr_gpr3_src_store(int r)
19270{
19271 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19272
19273 return map[r & 0x7];
19274}
19275
ea4ca3c2
YK
19276/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19277static inline int decode_gpr_gpr4(int r)
19278{
19279 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19280 16, 17, 18, 19, 20, 21, 22, 23 };
19281
19282 return map[r & 0xf];
19283}
19284
8bdb7029
YK
19285/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19286static inline int decode_gpr_gpr4_zero(int r)
19287{
19288 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19289 16, 17, 18, 19, 20, 21, 22, 23 };
19290
19291 return map[r & 0xf];
19292}
19293
6bfa9f4c 19294
bf0718c5
SM
19295static void gen_adjust_sp(DisasContext *ctx, int u)
19296{
19297 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19298}
19299
19300static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19301 uint8_t gp, uint16_t u)
19302{
19303 int counter = 0;
19304 TCGv va = tcg_temp_new();
19305 TCGv t0 = tcg_temp_new();
19306
19307 while (counter != count) {
19308 bool use_gp = gp && (counter == count - 1);
19309 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19310 int this_offset = -((counter + 1) << 2);
19311 gen_base_offset_addr(ctx, va, 29, this_offset);
19312 gen_load_gpr(t0, this_rt);
19313 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19314 (MO_TEUL | ctx->default_tcg_memop_mask));
19315 counter++;
19316 }
19317
19318 /* adjust stack pointer */
19319 gen_adjust_sp(ctx, -u);
19320
19321 tcg_temp_free(t0);
19322 tcg_temp_free(va);
19323}
19324
19325static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19326 uint8_t gp, uint16_t u)
19327{
19328 int counter = 0;
19329 TCGv va = tcg_temp_new();
19330 TCGv t0 = tcg_temp_new();
19331
19332 while (counter != count) {
19333 bool use_gp = gp && (counter == count - 1);
19334 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19335 int this_offset = u - ((counter + 1) << 2);
19336 gen_base_offset_addr(ctx, va, 29, this_offset);
19337 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19338 ctx->default_tcg_memop_mask);
19339 tcg_gen_ext32s_tl(t0, t0);
19340 gen_store_gpr(t0, this_rt);
19341 counter++;
19342 }
19343
19344 /* adjust stack pointer */
19345 gen_adjust_sp(ctx, u);
19346
19347 tcg_temp_free(t0);
19348 tcg_temp_free(va);
19349}
19350
80845edf
YK
19351static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19352{
99e49abf
AM
19353 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19354 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
19355
19356 switch (extract32(ctx->opcode, 2, 2)) {
19357 case NM_NOT16:
19358 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19359 break;
19360 case NM_AND16:
19361 gen_logic(ctx, OPC_AND, rt, rt, rs);
19362 break;
19363 case NM_XOR16:
19364 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19365 break;
19366 case NM_OR16:
19367 gen_logic(ctx, OPC_OR, rt, rt, rs);
19368 break;
19369 }
19370}
19371
0a1a6ed7 19372static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
19373{
19374 int rt = extract32(ctx->opcode, 21, 5);
19375 int rs = extract32(ctx->opcode, 16, 5);
19376 int rd = extract32(ctx->opcode, 11, 5);
19377
19378 switch (extract32(ctx->opcode, 3, 7)) {
19379 case NM_P_TRAP:
19380 switch (extract32(ctx->opcode, 10, 1)) {
19381 case NM_TEQ:
fb32f8c8 19382 check_nms(ctx);
e0cf0e65
YK
19383 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19384 break;
19385 case NM_TNE:
fb32f8c8 19386 check_nms(ctx);
e0cf0e65
YK
19387 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19388 break;
19389 }
19390 break;
19391 case NM_RDHWR:
fb32f8c8 19392 check_nms(ctx);
e0cf0e65
YK
19393 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19394 break;
19395 case NM_SEB:
fb32f8c8 19396 check_nms(ctx);
e0cf0e65
YK
19397 gen_bshfl(ctx, OPC_SEB, rs, rt);
19398 break;
19399 case NM_SEH:
19400 gen_bshfl(ctx, OPC_SEH, rs, rt);
19401 break;
19402 case NM_SLLV:
19403 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19404 break;
19405 case NM_SRLV:
19406 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19407 break;
19408 case NM_SRAV:
19409 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19410 break;
19411 case NM_ROTRV:
19412 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19413 break;
19414 case NM_ADD:
19415 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19416 break;
19417 case NM_ADDU:
19418 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19419 break;
19420 case NM_SUB:
fb32f8c8 19421 check_nms(ctx);
e0cf0e65
YK
19422 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19423 break;
19424 case NM_SUBU:
19425 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19426 break;
19427 case NM_P_CMOVE:
19428 switch (extract32(ctx->opcode, 10, 1)) {
19429 case NM_MOVZ:
19430 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19431 break;
19432 case NM_MOVN:
19433 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19434 break;
19435 }
19436 break;
19437 case NM_AND:
19438 gen_logic(ctx, OPC_AND, rd, rs, rt);
19439 break;
19440 case NM_OR:
19441 gen_logic(ctx, OPC_OR, rd, rs, rt);
19442 break;
19443 case NM_NOR:
19444 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19445 break;
19446 case NM_XOR:
19447 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19448 break;
19449 case NM_SLT:
19450 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19451 break;
19452 case NM_P_SLTU:
19453 if (rd == 0) {
19454 /* P_DVP */
19455#ifndef CONFIG_USER_ONLY
19456 TCGv t0 = tcg_temp_new();
19457 switch (extract32(ctx->opcode, 10, 1)) {
19458 case NM_DVP:
19459 if (ctx->vp) {
19460 check_cp0_enabled(ctx);
19461 gen_helper_dvp(t0, cpu_env);
19462 gen_store_gpr(t0, rt);
19463 }
19464 break;
19465 case NM_EVP:
19466 if (ctx->vp) {
19467 check_cp0_enabled(ctx);
19468 gen_helper_evp(t0, cpu_env);
19469 gen_store_gpr(t0, rt);
19470 }
19471 break;
19472 }
19473 tcg_temp_free(t0);
19474#endif
19475 } else {
19476 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19477 }
19478 break;
19479 case NM_SOV:
19480 {
19481 TCGv t0 = tcg_temp_new();
19482 TCGv t1 = tcg_temp_new();
19483 TCGv t2 = tcg_temp_new();
19484
19485 gen_load_gpr(t1, rs);
19486 gen_load_gpr(t2, rt);
19487 tcg_gen_add_tl(t0, t1, t2);
19488 tcg_gen_ext32s_tl(t0, t0);
19489 tcg_gen_xor_tl(t1, t1, t2);
19490 tcg_gen_xor_tl(t2, t0, t2);
19491 tcg_gen_andc_tl(t1, t2, t1);
19492
19493 /* operands of same sign, result different sign */
19494 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19495 gen_store_gpr(t0, rd);
19496
19497 tcg_temp_free(t0);
19498 tcg_temp_free(t1);
19499 tcg_temp_free(t2);
19500 }
19501 break;
19502 case NM_MUL:
19503 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19504 break;
19505 case NM_MUH:
19506 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19507 break;
19508 case NM_MULU:
19509 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19510 break;
19511 case NM_MUHU:
19512 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19513 break;
19514 case NM_DIV:
19515 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19516 break;
19517 case NM_MOD:
19518 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19519 break;
19520 case NM_DIVU:
19521 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19522 break;
19523 case NM_MODU:
19524 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19525 break;
19526#ifndef CONFIG_USER_ONLY
19527 case NM_MFC0:
19528 check_cp0_enabled(ctx);
19529 if (rt == 0) {
19530 /* Treat as NOP. */
19531 break;
19532 }
19533 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19534 break;
19535 case NM_MTC0:
19536 check_cp0_enabled(ctx);
19537 {
19538 TCGv t0 = tcg_temp_new();
19539
19540 gen_load_gpr(t0, rt);
19541 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19542 tcg_temp_free(t0);
19543 }
19544 break;
0a1a6ed7
SM
19545 case NM_D_E_MT_VPE:
19546 {
19547 uint8_t sc = extract32(ctx->opcode, 10, 1);
19548 TCGv t0 = tcg_temp_new();
19549
19550 switch (sc) {
19551 case 0:
19552 if (rs == 1) {
19553 /* DMT */
19554 check_cp0_mt(ctx);
19555 gen_helper_dmt(t0);
19556 gen_store_gpr(t0, rt);
19557 } else if (rs == 0) {
19558 /* DVPE */
19559 check_cp0_mt(ctx);
19560 gen_helper_dvpe(t0, cpu_env);
19561 gen_store_gpr(t0, rt);
19562 } else {
19563 generate_exception_end(ctx, EXCP_RI);
19564 }
19565 break;
19566 case 1:
19567 if (rs == 1) {
19568 /* EMT */
19569 check_cp0_mt(ctx);
19570 gen_helper_emt(t0);
19571 gen_store_gpr(t0, rt);
19572 } else if (rs == 0) {
19573 /* EVPE */
19574 check_cp0_mt(ctx);
19575 gen_helper_evpe(t0, cpu_env);
19576 gen_store_gpr(t0, rt);
19577 } else {
19578 generate_exception_end(ctx, EXCP_RI);
19579 }
19580 break;
19581 }
19582
19583 tcg_temp_free(t0);
19584 }
19585 break;
19586 case NM_FORK:
19587 check_mt(ctx);
19588 {
19589 TCGv t0 = tcg_temp_new();
19590 TCGv t1 = tcg_temp_new();
19591
19592 gen_load_gpr(t0, rt);
19593 gen_load_gpr(t1, rs);
19594 gen_helper_fork(t0, t1);
19595 tcg_temp_free(t0);
19596 tcg_temp_free(t1);
19597 }
19598 break;
19599 case NM_MFTR:
19600 case NM_MFHTR:
19601 check_cp0_enabled(ctx);
19602 if (rd == 0) {
19603 /* Treat as NOP. */
19604 return;
19605 }
19606 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19607 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19608 break;
19609 case NM_MTTR:
19610 case NM_MTHTR:
19611 check_cp0_enabled(ctx);
19612 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19613 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19614 break;
19615 case NM_YIELD:
19616 check_mt(ctx);
19617 {
19618 TCGv t0 = tcg_temp_new();
19619
19620 gen_load_gpr(t0, rs);
19621 gen_helper_yield(t0, cpu_env, t0);
19622 gen_store_gpr(t0, rt);
19623 tcg_temp_free(t0);
19624 }
19625 break;
e0cf0e65
YK
19626#endif
19627 default:
19628 generate_exception_end(ctx, EXCP_RI);
19629 break;
19630 }
19631}
19632
2ed42efa
SM
19633/* dsp */
19634static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19635 int ret, int v1, int v2)
19636{
19637 TCGv_i32 t0;
19638 TCGv v0_t;
19639 TCGv v1_t;
19640
19641 t0 = tcg_temp_new_i32();
19642
19643 v0_t = tcg_temp_new();
19644 v1_t = tcg_temp_new();
19645
19646 tcg_gen_movi_i32(t0, v2 >> 3);
19647
19648 gen_load_gpr(v0_t, ret);
19649 gen_load_gpr(v1_t, v1);
19650
19651 switch (opc) {
19652 case NM_MAQ_S_W_PHR:
19653 check_dsp(ctx);
19654 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19655 break;
19656 case NM_MAQ_S_W_PHL:
19657 check_dsp(ctx);
19658 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19659 break;
19660 case NM_MAQ_SA_W_PHR:
19661 check_dsp(ctx);
19662 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19663 break;
19664 case NM_MAQ_SA_W_PHL:
19665 check_dsp(ctx);
19666 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19667 break;
19668 default:
19669 generate_exception_end(ctx, EXCP_RI);
19670 break;
19671 }
19672
19673 tcg_temp_free_i32(t0);
19674
19675 tcg_temp_free(v0_t);
19676 tcg_temp_free(v1_t);
19677}
19678
19679
19680static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19681 int ret, int v1, int v2)
19682{
19683 int16_t imm;
19684 TCGv t0 = tcg_temp_new();
19685 TCGv t1 = tcg_temp_new();
19686 TCGv v0_t = tcg_temp_new();
19687
19688 gen_load_gpr(v0_t, v1);
19689
19690 switch (opc) {
19691 case NM_POOL32AXF_1_0:
19692 check_dsp(ctx);
19693 switch (extract32(ctx->opcode, 12, 2)) {
19694 case NM_MFHI:
19695 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19696 break;
19697 case NM_MFLO:
19698 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19699 break;
19700 case NM_MTHI:
19701 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19702 break;
19703 case NM_MTLO:
19704 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19705 break;
19706 }
19707 break;
19708 case NM_POOL32AXF_1_1:
19709 check_dsp(ctx);
19710 switch (extract32(ctx->opcode, 12, 2)) {
19711 case NM_MTHLIP:
19712 tcg_gen_movi_tl(t0, v2);
19713 gen_helper_mthlip(t0, v0_t, cpu_env);
19714 break;
19715 case NM_SHILOV:
19716 tcg_gen_movi_tl(t0, v2 >> 3);
19717 gen_helper_shilo(t0, v0_t, cpu_env);
19718 break;
19719 default:
19720 generate_exception_end(ctx, EXCP_RI);
19721 break;
19722 }
19723 break;
19724 case NM_POOL32AXF_1_3:
19725 check_dsp(ctx);
19726 imm = extract32(ctx->opcode, 14, 7);
19727 switch (extract32(ctx->opcode, 12, 2)) {
19728 case NM_RDDSP:
19729 tcg_gen_movi_tl(t0, imm);
19730 gen_helper_rddsp(t0, t0, cpu_env);
19731 gen_store_gpr(t0, ret);
19732 break;
19733 case NM_WRDSP:
19734 gen_load_gpr(t0, ret);
19735 tcg_gen_movi_tl(t1, imm);
19736 gen_helper_wrdsp(t0, t1, cpu_env);
19737 break;
19738 case NM_EXTP:
19739 tcg_gen_movi_tl(t0, v2 >> 3);
19740 tcg_gen_movi_tl(t1, v1);
19741 gen_helper_extp(t0, t0, t1, cpu_env);
19742 gen_store_gpr(t0, ret);
19743 break;
19744 case NM_EXTPDP:
19745 tcg_gen_movi_tl(t0, v2 >> 3);
19746 tcg_gen_movi_tl(t1, v1);
19747 gen_helper_extpdp(t0, t0, t1, cpu_env);
19748 gen_store_gpr(t0, ret);
19749 break;
19750 }
19751 break;
19752 case NM_POOL32AXF_1_4:
19753 check_dsp(ctx);
19754 tcg_gen_movi_tl(t0, v2 >> 2);
19755 switch (extract32(ctx->opcode, 12, 1)) {
19756 case NM_SHLL_QB:
19757 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19758 gen_store_gpr(t0, ret);
19759 break;
19760 case NM_SHRL_QB:
19761 gen_helper_shrl_qb(t0, t0, v0_t);
19762 gen_store_gpr(t0, ret);
19763 break;
19764 }
19765 break;
19766 case NM_POOL32AXF_1_5:
19767 opc = extract32(ctx->opcode, 12, 2);
19768 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19769 break;
19770 case NM_POOL32AXF_1_7:
19771 check_dsp(ctx);
19772 tcg_gen_movi_tl(t0, v2 >> 3);
19773 tcg_gen_movi_tl(t1, v1);
19774 switch (extract32(ctx->opcode, 12, 2)) {
19775 case NM_EXTR_W:
19776 gen_helper_extr_w(t0, t0, t1, cpu_env);
19777 gen_store_gpr(t0, ret);
19778 break;
19779 case NM_EXTR_R_W:
19780 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19781 gen_store_gpr(t0, ret);
19782 break;
19783 case NM_EXTR_RS_W:
19784 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19785 gen_store_gpr(t0, ret);
19786 break;
19787 case NM_EXTR_S_H:
19788 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19789 gen_store_gpr(t0, ret);
19790 break;
19791 }
19792 break;
19793 default:
19794 generate_exception_end(ctx, EXCP_RI);
19795 break;
19796 }
19797
19798 tcg_temp_free(t0);
19799 tcg_temp_free(t1);
19800 tcg_temp_free(v0_t);
19801}
19802
8b3698b2
SM
19803static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19804 TCGv v0, TCGv v1, int rd)
19805{
19806 TCGv_i32 t0;
19807
19808 t0 = tcg_temp_new_i32();
19809
19810 tcg_gen_movi_i32(t0, rd >> 3);
19811
19812 switch (opc) {
19813 case NM_POOL32AXF_2_0_7:
19814 switch (extract32(ctx->opcode, 9, 3)) {
19815 case NM_DPA_W_PH:
908f6be1 19816 check_dsp_r2(ctx);
8b3698b2
SM
19817 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19818 break;
19819 case NM_DPAQ_S_W_PH:
19820 check_dsp(ctx);
19821 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19822 break;
19823 case NM_DPS_W_PH:
908f6be1 19824 check_dsp_r2(ctx);
8b3698b2
SM
19825 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19826 break;
19827 case NM_DPSQ_S_W_PH:
19828 check_dsp(ctx);
19829 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19830 break;
19831 default:
19832 generate_exception_end(ctx, EXCP_RI);
19833 break;
19834 }
19835 break;
19836 case NM_POOL32AXF_2_8_15:
19837 switch (extract32(ctx->opcode, 9, 3)) {
19838 case NM_DPAX_W_PH:
908f6be1 19839 check_dsp_r2(ctx);
8b3698b2
SM
19840 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19841 break;
19842 case NM_DPAQ_SA_L_W:
19843 check_dsp(ctx);
19844 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19845 break;
19846 case NM_DPSX_W_PH:
908f6be1 19847 check_dsp_r2(ctx);
8b3698b2
SM
19848 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19849 break;
19850 case NM_DPSQ_SA_L_W:
19851 check_dsp(ctx);
19852 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19853 break;
19854 default:
19855 generate_exception_end(ctx, EXCP_RI);
19856 break;
19857 }
19858 break;
19859 case NM_POOL32AXF_2_16_23:
19860 switch (extract32(ctx->opcode, 9, 3)) {
19861 case NM_DPAU_H_QBL:
19862 check_dsp(ctx);
19863 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19864 break;
19865 case NM_DPAQX_S_W_PH:
908f6be1 19866 check_dsp_r2(ctx);
8b3698b2
SM
19867 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19868 break;
19869 case NM_DPSU_H_QBL:
19870 check_dsp(ctx);
19871 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19872 break;
19873 case NM_DPSQX_S_W_PH:
908f6be1 19874 check_dsp_r2(ctx);
8b3698b2
SM
19875 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19876 break;
19877 case NM_MULSA_W_PH:
908f6be1 19878 check_dsp_r2(ctx);
8b3698b2
SM
19879 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19880 break;
19881 default:
19882 generate_exception_end(ctx, EXCP_RI);
19883 break;
19884 }
19885 break;
19886 case NM_POOL32AXF_2_24_31:
19887 switch (extract32(ctx->opcode, 9, 3)) {
19888 case NM_DPAU_H_QBR:
19889 check_dsp(ctx);
19890 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19891 break;
19892 case NM_DPAQX_SA_W_PH:
908f6be1 19893 check_dsp_r2(ctx);
8b3698b2
SM
19894 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19895 break;
19896 case NM_DPSU_H_QBR:
19897 check_dsp(ctx);
19898 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19899 break;
19900 case NM_DPSQX_SA_W_PH:
908f6be1 19901 check_dsp_r2(ctx);
8b3698b2
SM
19902 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19903 break;
19904 case NM_MULSAQ_S_W_PH:
19905 check_dsp(ctx);
19906 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19907 break;
19908 default:
19909 generate_exception_end(ctx, EXCP_RI);
19910 break;
19911 }
19912 break;
19913 default:
19914 generate_exception_end(ctx, EXCP_RI);
19915 break;
19916 }
19917
19918 tcg_temp_free_i32(t0);
19919}
19920
19921static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19922 int rt, int rs, int rd)
19923{
19924 int ret = rt;
19925 TCGv t0 = tcg_temp_new();
19926 TCGv t1 = tcg_temp_new();
19927 TCGv v0_t = tcg_temp_new();
19928 TCGv v1_t = tcg_temp_new();
19929
19930 gen_load_gpr(v0_t, rt);
19931 gen_load_gpr(v1_t, rs);
19932
19933 switch (opc) {
19934 case NM_POOL32AXF_2_0_7:
19935 switch (extract32(ctx->opcode, 9, 3)) {
19936 case NM_DPA_W_PH:
19937 case NM_DPAQ_S_W_PH:
19938 case NM_DPS_W_PH:
19939 case NM_DPSQ_S_W_PH:
19940 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19941 break;
19942 case NM_BALIGN:
908f6be1 19943 check_dsp_r2(ctx);
8b3698b2
SM
19944 if (rt != 0) {
19945 gen_load_gpr(t0, rs);
19946 rd &= 3;
19947 if (rd != 0 && rd != 2) {
19948 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19949 tcg_gen_ext32u_tl(t0, t0);
19950 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19951 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19952 }
19953 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19954 }
19955 break;
19956 case NM_MADD:
19957 check_dsp(ctx);
19958 {
19959 int acc = extract32(ctx->opcode, 14, 2);
19960 TCGv_i64 t2 = tcg_temp_new_i64();
19961 TCGv_i64 t3 = tcg_temp_new_i64();
19962
19963 gen_load_gpr(t0, rt);
19964 gen_load_gpr(t1, rs);
19965 tcg_gen_ext_tl_i64(t2, t0);
19966 tcg_gen_ext_tl_i64(t3, t1);
19967 tcg_gen_mul_i64(t2, t2, t3);
19968 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19969 tcg_gen_add_i64(t2, t2, t3);
19970 tcg_temp_free_i64(t3);
19971 gen_move_low32(cpu_LO[acc], t2);
19972 gen_move_high32(cpu_HI[acc], t2);
19973 tcg_temp_free_i64(t2);
19974 }
19975 break;
19976 case NM_MULT:
19977 check_dsp(ctx);
19978 {
19979 int acc = extract32(ctx->opcode, 14, 2);
19980 TCGv_i32 t2 = tcg_temp_new_i32();
19981 TCGv_i32 t3 = tcg_temp_new_i32();
19982
19983 gen_load_gpr(t0, rs);
19984 gen_load_gpr(t1, rt);
19985 tcg_gen_trunc_tl_i32(t2, t0);
19986 tcg_gen_trunc_tl_i32(t3, t1);
19987 tcg_gen_muls2_i32(t2, t3, t2, t3);
19988 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19989 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19990 tcg_temp_free_i32(t2);
19991 tcg_temp_free_i32(t3);
19992 }
19993 break;
19994 case NM_EXTRV_W:
19995 check_dsp(ctx);
19996 gen_load_gpr(v1_t, rs);
19997 tcg_gen_movi_tl(t0, rd >> 3);
19998 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19999 gen_store_gpr(t0, ret);
20000 break;
20001 }
20002 break;
20003 case NM_POOL32AXF_2_8_15:
20004 switch (extract32(ctx->opcode, 9, 3)) {
20005 case NM_DPAX_W_PH:
20006 case NM_DPAQ_SA_L_W:
20007 case NM_DPSX_W_PH:
20008 case NM_DPSQ_SA_L_W:
20009 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20010 break;
20011 case NM_MADDU:
20012 check_dsp(ctx);
20013 {
20014 int acc = extract32(ctx->opcode, 14, 2);
20015 TCGv_i64 t2 = tcg_temp_new_i64();
20016 TCGv_i64 t3 = tcg_temp_new_i64();
20017
20018 gen_load_gpr(t0, rs);
20019 gen_load_gpr(t1, rt);
20020 tcg_gen_ext32u_tl(t0, t0);
20021 tcg_gen_ext32u_tl(t1, t1);
20022 tcg_gen_extu_tl_i64(t2, t0);
20023 tcg_gen_extu_tl_i64(t3, t1);
20024 tcg_gen_mul_i64(t2, t2, t3);
20025 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20026 tcg_gen_add_i64(t2, t2, t3);
20027 tcg_temp_free_i64(t3);
20028 gen_move_low32(cpu_LO[acc], t2);
20029 gen_move_high32(cpu_HI[acc], t2);
20030 tcg_temp_free_i64(t2);
20031 }
20032 break;
20033 case NM_MULTU:
20034 check_dsp(ctx);
20035 {
20036 int acc = extract32(ctx->opcode, 14, 2);
20037 TCGv_i32 t2 = tcg_temp_new_i32();
20038 TCGv_i32 t3 = tcg_temp_new_i32();
20039
20040 gen_load_gpr(t0, rs);
20041 gen_load_gpr(t1, rt);
20042 tcg_gen_trunc_tl_i32(t2, t0);
20043 tcg_gen_trunc_tl_i32(t3, t1);
20044 tcg_gen_mulu2_i32(t2, t3, t2, t3);
20045 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
20046 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
20047 tcg_temp_free_i32(t2);
20048 tcg_temp_free_i32(t3);
20049 }
20050 break;
20051 case NM_EXTRV_R_W:
20052 check_dsp(ctx);
20053 tcg_gen_movi_tl(t0, rd >> 3);
20054 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
20055 gen_store_gpr(t0, ret);
20056 break;
20057 default:
20058 generate_exception_end(ctx, EXCP_RI);
20059 break;
20060 }
20061 break;
20062 case NM_POOL32AXF_2_16_23:
20063 switch (extract32(ctx->opcode, 9, 3)) {
20064 case NM_DPAU_H_QBL:
20065 case NM_DPAQX_S_W_PH:
20066 case NM_DPSU_H_QBL:
20067 case NM_DPSQX_S_W_PH:
20068 case NM_MULSA_W_PH:
20069 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20070 break;
20071 case NM_EXTPV:
20072 check_dsp(ctx);
20073 tcg_gen_movi_tl(t0, rd >> 3);
20074 gen_helper_extp(t0, t0, v1_t, cpu_env);
20075 gen_store_gpr(t0, ret);
20076 break;
20077 case NM_MSUB:
20078 check_dsp(ctx);
20079 {
20080 int acc = extract32(ctx->opcode, 14, 2);
20081 TCGv_i64 t2 = tcg_temp_new_i64();
20082 TCGv_i64 t3 = tcg_temp_new_i64();
20083
20084 gen_load_gpr(t0, rs);
20085 gen_load_gpr(t1, rt);
20086 tcg_gen_ext_tl_i64(t2, t0);
20087 tcg_gen_ext_tl_i64(t3, t1);
20088 tcg_gen_mul_i64(t2, t2, t3);
20089 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20090 tcg_gen_sub_i64(t2, t3, t2);
20091 tcg_temp_free_i64(t3);
20092 gen_move_low32(cpu_LO[acc], t2);
20093 gen_move_high32(cpu_HI[acc], t2);
20094 tcg_temp_free_i64(t2);
20095 }
20096 break;
20097 case NM_EXTRV_RS_W:
20098 check_dsp(ctx);
20099 tcg_gen_movi_tl(t0, rd >> 3);
20100 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
20101 gen_store_gpr(t0, ret);
20102 break;
20103 }
20104 break;
20105 case NM_POOL32AXF_2_24_31:
20106 switch (extract32(ctx->opcode, 9, 3)) {
20107 case NM_DPAU_H_QBR:
20108 case NM_DPAQX_SA_W_PH:
20109 case NM_DPSU_H_QBR:
20110 case NM_DPSQX_SA_W_PH:
20111 case NM_MULSAQ_S_W_PH:
20112 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20113 break;
20114 case NM_EXTPDPV:
20115 check_dsp(ctx);
20116 tcg_gen_movi_tl(t0, rd >> 3);
20117 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
20118 gen_store_gpr(t0, ret);
20119 break;
20120 case NM_MSUBU:
20121 check_dsp(ctx);
20122 {
20123 int acc = extract32(ctx->opcode, 14, 2);
20124 TCGv_i64 t2 = tcg_temp_new_i64();
20125 TCGv_i64 t3 = tcg_temp_new_i64();
20126
20127 gen_load_gpr(t0, rs);
20128 gen_load_gpr(t1, rt);
20129 tcg_gen_ext32u_tl(t0, t0);
20130 tcg_gen_ext32u_tl(t1, t1);
20131 tcg_gen_extu_tl_i64(t2, t0);
20132 tcg_gen_extu_tl_i64(t3, t1);
20133 tcg_gen_mul_i64(t2, t2, t3);
20134 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20135 tcg_gen_sub_i64(t2, t3, t2);
20136 tcg_temp_free_i64(t3);
20137 gen_move_low32(cpu_LO[acc], t2);
20138 gen_move_high32(cpu_HI[acc], t2);
20139 tcg_temp_free_i64(t2);
20140 }
20141 break;
20142 case NM_EXTRV_S_H:
20143 check_dsp(ctx);
20144 tcg_gen_movi_tl(t0, rd >> 3);
20145 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20146 gen_store_gpr(t0, ret);
20147 break;
20148 }
20149 break;
20150 default:
20151 generate_exception_end(ctx, EXCP_RI);
20152 break;
20153 }
20154
20155 tcg_temp_free(t0);
20156 tcg_temp_free(t1);
20157
20158 tcg_temp_free(v0_t);
20159 tcg_temp_free(v1_t);
20160}
20161
4c75c985
SM
20162static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20163 int rt, int rs)
20164{
20165 int ret = rt;
20166 TCGv t0 = tcg_temp_new();
20167 TCGv v0_t = tcg_temp_new();
20168
20169 gen_load_gpr(v0_t, rs);
20170
20171 switch (opc) {
20172 case NM_ABSQ_S_QB:
908f6be1 20173 check_dsp_r2(ctx);
4c75c985
SM
20174 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20175 gen_store_gpr(v0_t, ret);
20176 break;
20177 case NM_ABSQ_S_PH:
20178 check_dsp(ctx);
20179 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20180 gen_store_gpr(v0_t, ret);
20181 break;
20182 case NM_ABSQ_S_W:
20183 check_dsp(ctx);
20184 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20185 gen_store_gpr(v0_t, ret);
20186 break;
20187 case NM_PRECEQ_W_PHL:
20188 check_dsp(ctx);
20189 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20190 tcg_gen_ext32s_tl(v0_t, v0_t);
20191 gen_store_gpr(v0_t, ret);
20192 break;
20193 case NM_PRECEQ_W_PHR:
20194 check_dsp(ctx);
20195 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20196 tcg_gen_shli_tl(v0_t, v0_t, 16);
20197 tcg_gen_ext32s_tl(v0_t, v0_t);
20198 gen_store_gpr(v0_t, ret);
20199 break;
20200 case NM_PRECEQU_PH_QBL:
20201 check_dsp(ctx);
20202 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20203 gen_store_gpr(v0_t, ret);
20204 break;
20205 case NM_PRECEQU_PH_QBR:
20206 check_dsp(ctx);
20207 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20208 gen_store_gpr(v0_t, ret);
20209 break;
20210 case NM_PRECEQU_PH_QBLA:
20211 check_dsp(ctx);
20212 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20213 gen_store_gpr(v0_t, ret);
20214 break;
20215 case NM_PRECEQU_PH_QBRA:
20216 check_dsp(ctx);
20217 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20218 gen_store_gpr(v0_t, ret);
20219 break;
20220 case NM_PRECEU_PH_QBL:
20221 check_dsp(ctx);
20222 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20223 gen_store_gpr(v0_t, ret);
20224 break;
20225 case NM_PRECEU_PH_QBR:
20226 check_dsp(ctx);
20227 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20228 gen_store_gpr(v0_t, ret);
20229 break;
20230 case NM_PRECEU_PH_QBLA:
20231 check_dsp(ctx);
20232 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20233 gen_store_gpr(v0_t, ret);
20234 break;
20235 case NM_PRECEU_PH_QBRA:
20236 check_dsp(ctx);
20237 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20238 gen_store_gpr(v0_t, ret);
20239 break;
20240 case NM_REPLV_PH:
20241 check_dsp(ctx);
20242 tcg_gen_ext16u_tl(v0_t, v0_t);
20243 tcg_gen_shli_tl(t0, v0_t, 16);
20244 tcg_gen_or_tl(v0_t, v0_t, t0);
20245 tcg_gen_ext32s_tl(v0_t, v0_t);
20246 gen_store_gpr(v0_t, ret);
20247 break;
20248 case NM_REPLV_QB:
20249 check_dsp(ctx);
20250 tcg_gen_ext8u_tl(v0_t, v0_t);
20251 tcg_gen_shli_tl(t0, v0_t, 8);
20252 tcg_gen_or_tl(v0_t, v0_t, t0);
20253 tcg_gen_shli_tl(t0, v0_t, 16);
20254 tcg_gen_or_tl(v0_t, v0_t, t0);
20255 tcg_gen_ext32s_tl(v0_t, v0_t);
20256 gen_store_gpr(v0_t, ret);
20257 break;
20258 case NM_BITREV:
20259 check_dsp(ctx);
20260 gen_helper_bitrev(v0_t, v0_t);
20261 gen_store_gpr(v0_t, ret);
20262 break;
20263 case NM_INSV:
20264 check_dsp(ctx);
20265 {
20266 TCGv tv0 = tcg_temp_new();
20267
20268 gen_load_gpr(tv0, rt);
20269 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20270 gen_store_gpr(v0_t, ret);
20271 tcg_temp_free(tv0);
20272 }
20273 break;
20274 case NM_RADDU_W_QB:
20275 check_dsp(ctx);
20276 gen_helper_raddu_w_qb(v0_t, v0_t);
20277 gen_store_gpr(v0_t, ret);
20278 break;
20279 case NM_BITSWAP:
20280 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20281 break;
20282 case NM_CLO:
fb32f8c8 20283 check_nms(ctx);
4c75c985
SM
20284 gen_cl(ctx, OPC_CLO, ret, rs);
20285 break;
20286 case NM_CLZ:
fb32f8c8 20287 check_nms(ctx);
4c75c985
SM
20288 gen_cl(ctx, OPC_CLZ, ret, rs);
20289 break;
20290 case NM_WSBH:
20291 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20292 break;
20293 default:
20294 generate_exception_end(ctx, EXCP_RI);
20295 break;
20296 }
20297
20298 tcg_temp_free(v0_t);
20299 tcg_temp_free(t0);
20300}
20301
0b591184
SM
20302static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20303 int rt, int rs, int rd)
20304{
20305 TCGv t0 = tcg_temp_new();
20306 TCGv rs_t = tcg_temp_new();
20307
20308 gen_load_gpr(rs_t, rs);
20309
20310 switch (opc) {
20311 case NM_SHRA_R_QB:
908f6be1 20312 check_dsp_r2(ctx);
0b591184
SM
20313 tcg_gen_movi_tl(t0, rd >> 2);
20314 switch (extract32(ctx->opcode, 12, 1)) {
20315 case 0:
20316 /* NM_SHRA_QB */
20317 gen_helper_shra_qb(t0, t0, rs_t);
20318 gen_store_gpr(t0, rt);
20319 break;
20320 case 1:
20321 /* NM_SHRA_R_QB */
20322 gen_helper_shra_r_qb(t0, t0, rs_t);
20323 gen_store_gpr(t0, rt);
20324 break;
20325 }
20326 break;
20327 case NM_SHRL_PH:
908f6be1 20328 check_dsp_r2(ctx);
0b591184
SM
20329 tcg_gen_movi_tl(t0, rd >> 1);
20330 gen_helper_shrl_ph(t0, t0, rs_t);
20331 gen_store_gpr(t0, rt);
20332 break;
20333 case NM_REPL_QB:
20334 check_dsp(ctx);
20335 {
20336 int16_t imm;
20337 target_long result;
20338 imm = extract32(ctx->opcode, 13, 8);
20339 result = (uint32_t)imm << 24 |
20340 (uint32_t)imm << 16 |
20341 (uint32_t)imm << 8 |
20342 (uint32_t)imm;
20343 result = (int32_t)result;
20344 tcg_gen_movi_tl(t0, result);
20345 gen_store_gpr(t0, rt);
20346 }
20347 break;
20348 default:
20349 generate_exception_end(ctx, EXCP_RI);
20350 break;
20351 }
20352 tcg_temp_free(t0);
20353 tcg_temp_free(rs_t);
20354}
20355
2ed42efa 20356
64224187
YK
20357static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20358{
64224187
YK
20359 int rt = extract32(ctx->opcode, 21, 5);
20360 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 20361 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
20362
20363 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
20364 case NM_POOL32AXF_1:
20365 {
20366 int32_t op1 = extract32(ctx->opcode, 9, 3);
20367 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20368 }
20369 break;
20370 case NM_POOL32AXF_2:
8b3698b2
SM
20371 {
20372 int32_t op1 = extract32(ctx->opcode, 12, 2);
20373 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20374 }
2ed42efa 20375 break;
64224187 20376 case NM_POOL32AXF_4:
4c75c985
SM
20377 {
20378 int32_t op1 = extract32(ctx->opcode, 9, 7);
20379 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20380 }
2ed42efa 20381 break;
64224187
YK
20382 case NM_POOL32AXF_5:
20383 switch (extract32(ctx->opcode, 9, 7)) {
20384#ifndef CONFIG_USER_ONLY
20385 case NM_TLBP:
20386 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20387 break;
20388 case NM_TLBR:
20389 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20390 break;
20391 case NM_TLBWI:
20392 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20393 break;
20394 case NM_TLBWR:
20395 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20396 break;
20397 case NM_TLBINV:
20398 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20399 break;
20400 case NM_TLBINVF:
20401 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20402 break;
20403 case NM_DI:
20404 check_cp0_enabled(ctx);
20405 {
20406 TCGv t0 = tcg_temp_new();
20407
20408 save_cpu_state(ctx, 1);
20409 gen_helper_di(t0, cpu_env);
20410 gen_store_gpr(t0, rt);
20411 /* Stop translation as we may have switched the execution mode */
20412 ctx->base.is_jmp = DISAS_STOP;
20413 tcg_temp_free(t0);
20414 }
20415 break;
20416 case NM_EI:
20417 check_cp0_enabled(ctx);
20418 {
20419 TCGv t0 = tcg_temp_new();
20420
20421 save_cpu_state(ctx, 1);
20422 gen_helper_ei(t0, cpu_env);
20423 gen_store_gpr(t0, rt);
20424 /* Stop translation as we may have switched the execution mode */
20425 ctx->base.is_jmp = DISAS_STOP;
20426 tcg_temp_free(t0);
20427 }
20428 break;
20429 case NM_RDPGPR:
20430 gen_load_srsgpr(rs, rt);
20431 break;
20432 case NM_WRPGPR:
20433 gen_store_srsgpr(rs, rt);
20434 break;
20435 case NM_WAIT:
20436 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20437 break;
20438 case NM_DERET:
20439 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20440 break;
20441 case NM_ERETX:
20442 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20443 break;
20444#endif
20445 default:
20446 generate_exception_end(ctx, EXCP_RI);
20447 break;
20448 }
20449 break;
2ed42efa 20450 case NM_POOL32AXF_7:
0b591184
SM
20451 {
20452 int32_t op1 = extract32(ctx->opcode, 9, 3);
20453 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20454 }
2ed42efa 20455 break;
64224187
YK
20456 default:
20457 generate_exception_end(ctx, EXCP_RI);
20458 break;
20459 }
20460}
20461
11d0fc10
SM
20462/* Immediate Value Compact Branches */
20463static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20464 int rt, int32_t imm, int32_t offset)
20465{
10266143 20466 TCGCond cond = TCG_COND_ALWAYS;
11d0fc10
SM
20467 TCGv t0 = tcg_temp_new();
20468 TCGv t1 = tcg_temp_new();
20469
20470 gen_load_gpr(t0, rt);
20471 tcg_gen_movi_tl(t1, imm);
20472 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20473
20474 /* Load needed operands and calculate btarget */
20475 switch (opc) {
20476 case NM_BEQIC:
20477 if (rt == 0 && imm == 0) {
20478 /* Unconditional branch */
20479 } else if (rt == 0 && imm != 0) {
20480 /* Treat as NOP */
20481 goto out;
20482 } else {
11d0fc10
SM
20483 cond = TCG_COND_EQ;
20484 }
20485 break;
20486 case NM_BBEQZC:
20487 case NM_BBNEZC:
fb32f8c8 20488 check_nms(ctx);
11d0fc10
SM
20489 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20490 generate_exception_end(ctx, EXCP_RI);
20491 goto out;
20492 } else if (rt == 0 && opc == NM_BBEQZC) {
20493 /* Unconditional branch */
20494 } else if (rt == 0 && opc == NM_BBNEZC) {
20495 /* Treat as NOP */
20496 goto out;
20497 } else {
20498 tcg_gen_shri_tl(t0, t0, imm);
20499 tcg_gen_andi_tl(t0, t0, 1);
20500 tcg_gen_movi_tl(t1, 0);
11d0fc10
SM
20501 if (opc == NM_BBEQZC) {
20502 cond = TCG_COND_EQ;
20503 } else {
20504 cond = TCG_COND_NE;
20505 }
20506 }
20507 break;
20508 case NM_BNEIC:
20509 if (rt == 0 && imm == 0) {
20510 /* Treat as NOP */
20511 goto out;
20512 } else if (rt == 0 && imm != 0) {
20513 /* Unconditional branch */
20514 } else {
11d0fc10
SM
20515 cond = TCG_COND_NE;
20516 }
20517 break;
20518 case NM_BGEIC:
20519 if (rt == 0 && imm == 0) {
20520 /* Unconditional branch */
20521 } else {
11d0fc10
SM
20522 cond = TCG_COND_GE;
20523 }
20524 break;
20525 case NM_BLTIC:
11d0fc10
SM
20526 cond = TCG_COND_LT;
20527 break;
20528 case NM_BGEIUC:
20529 if (rt == 0 && imm == 0) {
20530 /* Unconditional branch */
20531 } else {
11d0fc10
SM
20532 cond = TCG_COND_GEU;
20533 }
20534 break;
20535 case NM_BLTIUC:
11d0fc10
SM
20536 cond = TCG_COND_LTU;
20537 break;
20538 default:
20539 MIPS_INVAL("Immediate Value Compact branch");
20540 generate_exception_end(ctx, EXCP_RI);
20541 goto out;
20542 }
20543
697b7b6b
SM
20544 /* branch completion */
20545 clear_branch_hflags(ctx);
20546 ctx->base.is_jmp = DISAS_NORETURN;
20547
10266143 20548 if (cond == TCG_COND_ALWAYS) {
11d0fc10
SM
20549 /* Uncoditional compact branch */
20550 gen_goto_tb(ctx, 0, ctx->btarget);
20551 } else {
20552 /* Conditional compact branch */
20553 TCGLabel *fs = gen_new_label();
20554
20555 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20556
20557 gen_goto_tb(ctx, 1, ctx->btarget);
20558 gen_set_label(fs);
20559
20560 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20561 }
20562
20563out:
20564 tcg_temp_free(t0);
20565 tcg_temp_free(t1);
20566}
20567
20568/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20569static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20570 int rt)
20571{
20572 TCGv t0 = tcg_temp_new();
20573 TCGv t1 = tcg_temp_new();
20574
20575 /* load rs */
20576 gen_load_gpr(t0, rs);
20577
20578 /* link */
20579 if (rt != 0) {
20580 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20581 }
20582
20583 /* calculate btarget */
20584 tcg_gen_shli_tl(t0, t0, 1);
20585 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20586 gen_op_addr_add(ctx, btarget, t1, t0);
20587
697b7b6b
SM
20588 /* branch completion */
20589 clear_branch_hflags(ctx);
20590 ctx->base.is_jmp = DISAS_NORETURN;
20591
11d0fc10
SM
20592 /* unconditional branch to register */
20593 tcg_gen_mov_tl(cpu_PC, btarget);
20594 tcg_gen_lookup_and_goto_ptr();
20595
20596 tcg_temp_free(t0);
20597 tcg_temp_free(t1);
20598}
20599
20600/* nanoMIPS Branches */
20601static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20602 int rs, int rt, int32_t offset)
20603{
20604 int bcond_compute = 0;
20605 TCGv t0 = tcg_temp_new();
20606 TCGv t1 = tcg_temp_new();
20607
20608 /* Load needed operands and calculate btarget */
20609 switch (opc) {
20610 /* compact branch */
20611 case OPC_BGEC:
20612 case OPC_BLTC:
20613 gen_load_gpr(t0, rs);
20614 gen_load_gpr(t1, rt);
20615 bcond_compute = 1;
20616 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20617 break;
20618 case OPC_BGEUC:
20619 case OPC_BLTUC:
20620 if (rs == 0 || rs == rt) {
20621 /* OPC_BLEZALC, OPC_BGEZALC */
20622 /* OPC_BGTZALC, OPC_BLTZALC */
20623 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20624 }
20625 gen_load_gpr(t0, rs);
20626 gen_load_gpr(t1, rt);
20627 bcond_compute = 1;
20628 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20629 break;
20630 case OPC_BC:
20631 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20632 break;
20633 case OPC_BEQZC:
20634 if (rs != 0) {
20635 /* OPC_BEQZC, OPC_BNEZC */
20636 gen_load_gpr(t0, rs);
20637 bcond_compute = 1;
20638 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20639 } else {
20640 /* OPC_JIC, OPC_JIALC */
20641 TCGv tbase = tcg_temp_new();
20642 TCGv toffset = tcg_temp_new();
20643
20644 gen_load_gpr(tbase, rt);
20645 tcg_gen_movi_tl(toffset, offset);
20646 gen_op_addr_add(ctx, btarget, tbase, toffset);
20647 tcg_temp_free(tbase);
20648 tcg_temp_free(toffset);
20649 }
20650 break;
20651 default:
20652 MIPS_INVAL("Compact branch/jump");
20653 generate_exception_end(ctx, EXCP_RI);
20654 goto out;
20655 }
20656
20657 if (bcond_compute == 0) {
20658 /* Uncoditional compact branch */
20659 switch (opc) {
20660 case OPC_BC:
20661 gen_goto_tb(ctx, 0, ctx->btarget);
20662 break;
20663 default:
20664 MIPS_INVAL("Compact branch/jump");
20665 generate_exception_end(ctx, EXCP_RI);
20666 goto out;
20667 }
20668 } else {
20669 /* Conditional compact branch */
20670 TCGLabel *fs = gen_new_label();
20671
20672 switch (opc) {
20673 case OPC_BGEUC:
20674 if (rs == 0 && rt != 0) {
20675 /* OPC_BLEZALC */
20676 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20677 } else if (rs != 0 && rt != 0 && rs == rt) {
20678 /* OPC_BGEZALC */
20679 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20680 } else {
20681 /* OPC_BGEUC */
20682 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20683 }
20684 break;
20685 case OPC_BLTUC:
20686 if (rs == 0 && rt != 0) {
20687 /* OPC_BGTZALC */
20688 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20689 } else if (rs != 0 && rt != 0 && rs == rt) {
20690 /* OPC_BLTZALC */
20691 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20692 } else {
20693 /* OPC_BLTUC */
20694 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20695 }
20696 break;
20697 case OPC_BGEC:
20698 if (rs == 0 && rt != 0) {
20699 /* OPC_BLEZC */
20700 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20701 } else if (rs != 0 && rt != 0 && rs == rt) {
20702 /* OPC_BGEZC */
20703 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20704 } else {
20705 /* OPC_BGEC */
20706 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20707 }
20708 break;
20709 case OPC_BLTC:
20710 if (rs == 0 && rt != 0) {
20711 /* OPC_BGTZC */
20712 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20713 } else if (rs != 0 && rt != 0 && rs == rt) {
20714 /* OPC_BLTZC */
20715 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20716 } else {
20717 /* OPC_BLTC */
20718 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20719 }
20720 break;
20721 case OPC_BEQZC:
20722 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20723 break;
20724 default:
20725 MIPS_INVAL("Compact conditional branch/jump");
20726 generate_exception_end(ctx, EXCP_RI);
20727 goto out;
20728 }
20729
697b7b6b
SM
20730 /* branch completion */
20731 clear_branch_hflags(ctx);
20732 ctx->base.is_jmp = DISAS_NORETURN;
20733
11d0fc10
SM
20734 /* Generating branch here as compact branches don't have delay slot */
20735 gen_goto_tb(ctx, 1, ctx->btarget);
20736 gen_set_label(fs);
20737
20738 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20739 }
20740
20741out:
20742 tcg_temp_free(t0);
20743 tcg_temp_free(t1);
20744}
20745
20746
20747/* nanoMIPS CP1 Branches */
20748static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20749 int32_t ft, int32_t offset)
20750{
20751 target_ulong btarget;
20752 TCGv_i64 t0 = tcg_temp_new_i64();
20753
20754 gen_load_fpr64(ctx, t0, ft);
20755 tcg_gen_andi_i64(t0, t0, 1);
20756
20757 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20758
20759 switch (op) {
20760 case NM_BC1EQZC:
20761 tcg_gen_xori_i64(t0, t0, 1);
20762 ctx->hflags |= MIPS_HFLAG_BC;
20763 break;
20764 case NM_BC1NEZC:
20765 /* t0 already set */
20766 ctx->hflags |= MIPS_HFLAG_BC;
20767 break;
20768 default:
20769 MIPS_INVAL("cp1 cond branch");
20770 generate_exception_end(ctx, EXCP_RI);
20771 goto out;
20772 }
20773
20774 tcg_gen_trunc_i64_tl(bcond, t0);
20775
20776 ctx->btarget = btarget;
20777
20778out:
20779 tcg_temp_free_i64(t0);
20780}
20781
eac52664
YK
20782
20783static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20784{
20785 TCGv t0, t1;
20786 t0 = tcg_temp_new();
20787 t1 = tcg_temp_new();
20788
20789 gen_load_gpr(t0, rs);
20790 gen_load_gpr(t1, rt);
20791
20792 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20793 /* PP.LSXS instructions require shifting */
20794 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20795 case NM_SHXS:
fb32f8c8 20796 check_nms(ctx);
45152d05 20797 /* fall through */
fb32f8c8 20798 case NM_LHXS:
eac52664
YK
20799 case NM_LHUXS:
20800 tcg_gen_shli_tl(t0, t0, 1);
20801 break;
eac52664 20802 case NM_SWXS:
fb32f8c8 20803 check_nms(ctx);
45152d05 20804 /* fall through */
fb32f8c8 20805 case NM_LWXS:
eac52664
YK
20806 case NM_LWC1XS:
20807 case NM_SWC1XS:
20808 tcg_gen_shli_tl(t0, t0, 2);
20809 break;
20810 case NM_LDC1XS:
20811 case NM_SDC1XS:
20812 tcg_gen_shli_tl(t0, t0, 3);
20813 break;
20814 }
20815 }
20816 gen_op_addr_add(ctx, t0, t0, t1);
20817
20818 switch (extract32(ctx->opcode, 7, 4)) {
20819 case NM_LBX:
20820 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20821 MO_SB);
20822 gen_store_gpr(t0, rd);
20823 break;
20824 case NM_LHX:
20825 /*case NM_LHXS:*/
20826 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20827 MO_TESW);
20828 gen_store_gpr(t0, rd);
20829 break;
20830 case NM_LWX:
20831 /*case NM_LWXS:*/
20832 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20833 MO_TESL);
20834 gen_store_gpr(t0, rd);
20835 break;
20836 case NM_LBUX:
20837 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20838 MO_UB);
20839 gen_store_gpr(t0, rd);
20840 break;
20841 case NM_LHUX:
20842 /*case NM_LHUXS:*/
20843 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20844 MO_TEUW);
20845 gen_store_gpr(t0, rd);
20846 break;
20847 case NM_SBX:
fb32f8c8 20848 check_nms(ctx);
eac52664
YK
20849 gen_load_gpr(t1, rd);
20850 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20851 MO_8);
20852 break;
20853 case NM_SHX:
20854 /*case NM_SHXS:*/
fb32f8c8 20855 check_nms(ctx);
eac52664
YK
20856 gen_load_gpr(t1, rd);
20857 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20858 MO_TEUW);
20859 break;
20860 case NM_SWX:
20861 /*case NM_SWXS:*/
fb32f8c8 20862 check_nms(ctx);
eac52664
YK
20863 gen_load_gpr(t1, rd);
20864 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20865 MO_TEUL);
20866 break;
20867 case NM_LWC1X:
20868 /*case NM_LWC1XS:*/
20869 case NM_LDC1X:
20870 /*case NM_LDC1XS:*/
20871 case NM_SWC1X:
20872 /*case NM_SWC1XS:*/
20873 case NM_SDC1X:
20874 /*case NM_SDC1XS:*/
20875 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20876 check_cp1_enabled(ctx);
20877 switch (extract32(ctx->opcode, 7, 4)) {
20878 case NM_LWC1X:
20879 /*case NM_LWC1XS:*/
20880 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20881 break;
20882 case NM_LDC1X:
20883 /*case NM_LDC1XS:*/
20884 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20885 break;
20886 case NM_SWC1X:
20887 /*case NM_SWC1XS:*/
20888 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20889 break;
20890 case NM_SDC1X:
20891 /*case NM_SDC1XS:*/
20892 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20893 break;
20894 }
20895 } else {
20896 generate_exception_err(ctx, EXCP_CpU, 1);
20897 }
20898 break;
20899 default:
20900 generate_exception_end(ctx, EXCP_RI);
20901 break;
20902 }
20903
20904 tcg_temp_free(t0);
20905 tcg_temp_free(t1);
20906}
20907
579b8ea9
YK
20908static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20909{
20910 int rt, rs, rd;
20911
20912 rt = extract32(ctx->opcode, 21, 5);
20913 rs = extract32(ctx->opcode, 16, 5);
20914 rd = extract32(ctx->opcode, 11, 5);
20915
20916 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20917 generate_exception_end(ctx, EXCP_RI);
20918 return;
20919 }
20920 check_cp1_enabled(ctx);
20921 switch (extract32(ctx->opcode, 0, 3)) {
20922 case NM_POOL32F_0:
20923 switch (extract32(ctx->opcode, 3, 7)) {
20924 case NM_RINT_S:
20925 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20926 break;
20927 case NM_RINT_D:
20928 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20929 break;
20930 case NM_CLASS_S:
20931 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20932 break;
20933 case NM_CLASS_D:
20934 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20935 break;
20936 case NM_ADD_S:
20937 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20938 break;
20939 case NM_ADD_D:
20940 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20941 break;
20942 case NM_SUB_S:
20943 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20944 break;
20945 case NM_SUB_D:
20946 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20947 break;
20948 case NM_MUL_S:
20949 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20950 break;
20951 case NM_MUL_D:
20952 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20953 break;
20954 case NM_DIV_S:
20955 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20956 break;
20957 case NM_DIV_D:
20958 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20959 break;
20960 case NM_SELEQZ_S:
20961 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20962 break;
20963 case NM_SELEQZ_D:
20964 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20965 break;
20966 case NM_SELNEZ_S:
20967 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20968 break;
20969 case NM_SELNEZ_D:
20970 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20971 break;
20972 case NM_SEL_S:
20973 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20974 break;
20975 case NM_SEL_D:
20976 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20977 break;
20978 case NM_MADDF_S:
20979 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20980 break;
20981 case NM_MADDF_D:
20982 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20983 break;
20984 case NM_MSUBF_S:
20985 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20986 break;
20987 case NM_MSUBF_D:
20988 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20989 break;
20990 default:
20991 generate_exception_end(ctx, EXCP_RI);
20992 break;
20993 }
20994 break;
20995 case NM_POOL32F_3:
20996 switch (extract32(ctx->opcode, 3, 3)) {
20997 case NM_MIN_FMT:
20998 switch (extract32(ctx->opcode, 9, 1)) {
20999 case FMT_SDPS_S:
21000 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
21001 break;
21002 case FMT_SDPS_D:
21003 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
21004 break;
21005 }
21006 break;
21007 case NM_MAX_FMT:
21008 switch (extract32(ctx->opcode, 9, 1)) {
21009 case FMT_SDPS_S:
21010 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
21011 break;
21012 case FMT_SDPS_D:
21013 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
21014 break;
21015 }
21016 break;
21017 case NM_MINA_FMT:
21018 switch (extract32(ctx->opcode, 9, 1)) {
21019 case FMT_SDPS_S:
21020 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
21021 break;
21022 case FMT_SDPS_D:
21023 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
21024 break;
21025 }
21026 break;
21027 case NM_MAXA_FMT:
21028 switch (extract32(ctx->opcode, 9, 1)) {
21029 case FMT_SDPS_S:
21030 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
21031 break;
21032 case FMT_SDPS_D:
21033 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
21034 break;
21035 }
21036 break;
21037 case NM_POOL32FXF:
21038 switch (extract32(ctx->opcode, 6, 8)) {
21039 case NM_CFC1:
21040 gen_cp1(ctx, OPC_CFC1, rt, rs);
21041 break;
21042 case NM_CTC1:
21043 gen_cp1(ctx, OPC_CTC1, rt, rs);
21044 break;
21045 case NM_MFC1:
21046 gen_cp1(ctx, OPC_MFC1, rt, rs);
21047 break;
21048 case NM_MTC1:
21049 gen_cp1(ctx, OPC_MTC1, rt, rs);
21050 break;
21051 case NM_MFHC1:
21052 gen_cp1(ctx, OPC_MFHC1, rt, rs);
21053 break;
21054 case NM_MTHC1:
21055 gen_cp1(ctx, OPC_MTHC1, rt, rs);
21056 break;
21057 case NM_CVT_S_PL:
21058 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
21059 break;
21060 case NM_CVT_S_PU:
21061 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
21062 break;
21063 default:
21064 switch (extract32(ctx->opcode, 6, 9)) {
21065 case NM_CVT_L_S:
21066 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
21067 break;
21068 case NM_CVT_L_D:
21069 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
21070 break;
21071 case NM_CVT_W_S:
21072 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
21073 break;
21074 case NM_CVT_W_D:
21075 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
21076 break;
21077 case NM_RSQRT_S:
21078 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
21079 break;
21080 case NM_RSQRT_D:
21081 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
21082 break;
21083 case NM_SQRT_S:
21084 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
21085 break;
21086 case NM_SQRT_D:
21087 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
21088 break;
21089 case NM_RECIP_S:
21090 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
21091 break;
21092 case NM_RECIP_D:
21093 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
21094 break;
21095 case NM_FLOOR_L_S:
21096 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
21097 break;
21098 case NM_FLOOR_L_D:
21099 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
21100 break;
21101 case NM_FLOOR_W_S:
21102 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
21103 break;
21104 case NM_FLOOR_W_D:
21105 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
21106 break;
21107 case NM_CEIL_L_S:
21108 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
21109 break;
21110 case NM_CEIL_L_D:
21111 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
21112 break;
21113 case NM_CEIL_W_S:
21114 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
21115 break;
21116 case NM_CEIL_W_D:
21117 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
21118 break;
21119 case NM_TRUNC_L_S:
21120 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
21121 break;
21122 case NM_TRUNC_L_D:
21123 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
21124 break;
21125 case NM_TRUNC_W_S:
21126 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21127 break;
21128 case NM_TRUNC_W_D:
21129 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21130 break;
21131 case NM_ROUND_L_S:
21132 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21133 break;
21134 case NM_ROUND_L_D:
21135 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21136 break;
21137 case NM_ROUND_W_S:
21138 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21139 break;
21140 case NM_ROUND_W_D:
21141 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21142 break;
21143 case NM_MOV_S:
21144 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21145 break;
21146 case NM_MOV_D:
21147 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21148 break;
21149 case NM_ABS_S:
21150 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21151 break;
21152 case NM_ABS_D:
21153 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21154 break;
21155 case NM_NEG_S:
21156 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21157 break;
21158 case NM_NEG_D:
21159 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21160 break;
21161 case NM_CVT_D_S:
21162 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21163 break;
21164 case NM_CVT_D_W:
21165 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21166 break;
21167 case NM_CVT_D_L:
21168 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21169 break;
21170 case NM_CVT_S_D:
21171 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21172 break;
21173 case NM_CVT_S_W:
21174 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21175 break;
21176 case NM_CVT_S_L:
21177 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21178 break;
21179 default:
21180 generate_exception_end(ctx, EXCP_RI);
21181 break;
21182 }
21183 break;
21184 }
21185 break;
21186 }
21187 break;
21188 case NM_POOL32F_5:
21189 switch (extract32(ctx->opcode, 3, 3)) {
21190 case NM_CMP_CONDN_S:
21191 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21192 break;
21193 case NM_CMP_CONDN_D:
21194 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21195 break;
21196 default:
21197 generate_exception_end(ctx, EXCP_RI);
21198 break;
21199 }
21200 break;
21201 default:
21202 generate_exception_end(ctx, EXCP_RI);
21203 break;
21204 }
21205}
21206
3285a3e4
SM
21207static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21208 int rd, int rs, int rt)
21209{
21210 int ret = rd;
21211 TCGv t0 = tcg_temp_new();
21212 TCGv v1_t = tcg_temp_new();
21213 TCGv v2_t = tcg_temp_new();
21214
21215 gen_load_gpr(v1_t, rs);
21216 gen_load_gpr(v2_t, rt);
21217
21218 switch (opc) {
21219 case NM_CMP_EQ_PH:
21220 check_dsp(ctx);
21221 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21222 break;
21223 case NM_CMP_LT_PH:
21224 check_dsp(ctx);
21225 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21226 break;
21227 case NM_CMP_LE_PH:
21228 check_dsp(ctx);
21229 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21230 break;
21231 case NM_CMPU_EQ_QB:
21232 check_dsp(ctx);
21233 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21234 break;
21235 case NM_CMPU_LT_QB:
21236 check_dsp(ctx);
21237 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21238 break;
21239 case NM_CMPU_LE_QB:
21240 check_dsp(ctx);
21241 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21242 break;
21243 case NM_CMPGU_EQ_QB:
21244 check_dsp(ctx);
21245 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21246 gen_store_gpr(v1_t, ret);
21247 break;
21248 case NM_CMPGU_LT_QB:
21249 check_dsp(ctx);
21250 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21251 gen_store_gpr(v1_t, ret);
21252 break;
21253 case NM_CMPGU_LE_QB:
21254 check_dsp(ctx);
21255 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21256 gen_store_gpr(v1_t, ret);
21257 break;
21258 case NM_CMPGDU_EQ_QB:
908f6be1 21259 check_dsp_r2(ctx);
3285a3e4
SM
21260 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21261 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21262 gen_store_gpr(v1_t, ret);
21263 break;
21264 case NM_CMPGDU_LT_QB:
908f6be1 21265 check_dsp_r2(ctx);
3285a3e4
SM
21266 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21267 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21268 gen_store_gpr(v1_t, ret);
21269 break;
21270 case NM_CMPGDU_LE_QB:
908f6be1 21271 check_dsp_r2(ctx);
3285a3e4
SM
21272 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21273 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21274 gen_store_gpr(v1_t, ret);
21275 break;
21276 case NM_PACKRL_PH:
21277 check_dsp(ctx);
21278 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21279 gen_store_gpr(v1_t, ret);
21280 break;
21281 case NM_PICK_QB:
21282 check_dsp(ctx);
21283 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21284 gen_store_gpr(v1_t, ret);
21285 break;
21286 case NM_PICK_PH:
21287 check_dsp(ctx);
21288 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21289 gen_store_gpr(v1_t, ret);
21290 break;
21291 case NM_ADDQ_S_W:
21292 check_dsp(ctx);
21293 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21294 gen_store_gpr(v1_t, ret);
21295 break;
21296 case NM_SUBQ_S_W:
21297 check_dsp(ctx);
21298 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21299 gen_store_gpr(v1_t, ret);
21300 break;
21301 case NM_ADDSC:
21302 check_dsp(ctx);
21303 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21304 gen_store_gpr(v1_t, ret);
21305 break;
21306 case NM_ADDWC:
21307 check_dsp(ctx);
21308 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21309 gen_store_gpr(v1_t, ret);
21310 break;
21311 case NM_ADDQ_S_PH:
21312 check_dsp(ctx);
21313 switch (extract32(ctx->opcode, 10, 1)) {
21314 case 0:
21315 /* ADDQ_PH */
21316 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21317 gen_store_gpr(v1_t, ret);
21318 break;
21319 case 1:
21320 /* ADDQ_S_PH */
21321 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21322 gen_store_gpr(v1_t, ret);
21323 break;
21324 }
21325 break;
21326 case NM_ADDQH_R_PH:
908f6be1 21327 check_dsp_r2(ctx);
3285a3e4
SM
21328 switch (extract32(ctx->opcode, 10, 1)) {
21329 case 0:
21330 /* ADDQH_PH */
21331 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21332 gen_store_gpr(v1_t, ret);
21333 break;
21334 case 1:
21335 /* ADDQH_R_PH */
21336 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21337 gen_store_gpr(v1_t, ret);
21338 break;
21339 }
21340 break;
21341 case NM_ADDQH_R_W:
908f6be1 21342 check_dsp_r2(ctx);
3285a3e4
SM
21343 switch (extract32(ctx->opcode, 10, 1)) {
21344 case 0:
21345 /* ADDQH_W */
21346 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21347 gen_store_gpr(v1_t, ret);
21348 break;
21349 case 1:
21350 /* ADDQH_R_W */
21351 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21352 gen_store_gpr(v1_t, ret);
21353 break;
21354 }
21355 break;
21356 case NM_ADDU_S_QB:
21357 check_dsp(ctx);
21358 switch (extract32(ctx->opcode, 10, 1)) {
21359 case 0:
21360 /* ADDU_QB */
21361 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21362 gen_store_gpr(v1_t, ret);
21363 break;
21364 case 1:
21365 /* ADDU_S_QB */
21366 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21367 gen_store_gpr(v1_t, ret);
21368 break;
21369 }
21370 break;
21371 case NM_ADDU_S_PH:
908f6be1 21372 check_dsp_r2(ctx);
3285a3e4
SM
21373 switch (extract32(ctx->opcode, 10, 1)) {
21374 case 0:
21375 /* ADDU_PH */
21376 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21377 gen_store_gpr(v1_t, ret);
21378 break;
21379 case 1:
21380 /* ADDU_S_PH */
21381 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21382 gen_store_gpr(v1_t, ret);
21383 break;
21384 }
21385 break;
21386 case NM_ADDUH_R_QB:
908f6be1 21387 check_dsp_r2(ctx);
3285a3e4
SM
21388 switch (extract32(ctx->opcode, 10, 1)) {
21389 case 0:
21390 /* ADDUH_QB */
21391 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21392 gen_store_gpr(v1_t, ret);
21393 break;
21394 case 1:
21395 /* ADDUH_R_QB */
21396 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21397 gen_store_gpr(v1_t, ret);
21398 break;
21399 }
21400 break;
21401 case NM_SHRAV_R_PH:
21402 check_dsp(ctx);
21403 switch (extract32(ctx->opcode, 10, 1)) {
21404 case 0:
21405 /* SHRAV_PH */
21406 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21407 gen_store_gpr(v1_t, ret);
21408 break;
21409 case 1:
21410 /* SHRAV_R_PH */
21411 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21412 gen_store_gpr(v1_t, ret);
21413 break;
21414 }
21415 break;
21416 case NM_SHRAV_R_QB:
908f6be1 21417 check_dsp_r2(ctx);
3285a3e4
SM
21418 switch (extract32(ctx->opcode, 10, 1)) {
21419 case 0:
21420 /* SHRAV_QB */
21421 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21422 gen_store_gpr(v1_t, ret);
21423 break;
21424 case 1:
21425 /* SHRAV_R_QB */
21426 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21427 gen_store_gpr(v1_t, ret);
21428 break;
21429 }
21430 break;
21431 case NM_SUBQ_S_PH:
21432 check_dsp(ctx);
21433 switch (extract32(ctx->opcode, 10, 1)) {
21434 case 0:
21435 /* SUBQ_PH */
21436 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21437 gen_store_gpr(v1_t, ret);
21438 break;
21439 case 1:
21440 /* SUBQ_S_PH */
21441 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21442 gen_store_gpr(v1_t, ret);
21443 break;
21444 }
21445 break;
21446 case NM_SUBQH_R_PH:
908f6be1 21447 check_dsp_r2(ctx);
3285a3e4
SM
21448 switch (extract32(ctx->opcode, 10, 1)) {
21449 case 0:
21450 /* SUBQH_PH */
21451 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21452 gen_store_gpr(v1_t, ret);
21453 break;
21454 case 1:
21455 /* SUBQH_R_PH */
21456 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21457 gen_store_gpr(v1_t, ret);
21458 break;
21459 }
21460 break;
21461 case NM_SUBQH_R_W:
908f6be1 21462 check_dsp_r2(ctx);
3285a3e4
SM
21463 switch (extract32(ctx->opcode, 10, 1)) {
21464 case 0:
21465 /* SUBQH_W */
21466 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21467 gen_store_gpr(v1_t, ret);
21468 break;
21469 case 1:
21470 /* SUBQH_R_W */
21471 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21472 gen_store_gpr(v1_t, ret);
21473 break;
21474 }
21475 break;
21476 case NM_SUBU_S_QB:
21477 check_dsp(ctx);
21478 switch (extract32(ctx->opcode, 10, 1)) {
21479 case 0:
21480 /* SUBU_QB */
21481 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21482 gen_store_gpr(v1_t, ret);
21483 break;
21484 case 1:
21485 /* SUBU_S_QB */
21486 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21487 gen_store_gpr(v1_t, ret);
21488 break;
21489 }
21490 break;
21491 case NM_SUBU_S_PH:
908f6be1 21492 check_dsp_r2(ctx);
3285a3e4
SM
21493 switch (extract32(ctx->opcode, 10, 1)) {
21494 case 0:
21495 /* SUBU_PH */
21496 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21497 gen_store_gpr(v1_t, ret);
21498 break;
21499 case 1:
21500 /* SUBU_S_PH */
21501 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21502 gen_store_gpr(v1_t, ret);
21503 break;
21504 }
21505 break;
21506 case NM_SUBUH_R_QB:
908f6be1 21507 check_dsp_r2(ctx);
3285a3e4
SM
21508 switch (extract32(ctx->opcode, 10, 1)) {
21509 case 0:
21510 /* SUBUH_QB */
21511 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21512 gen_store_gpr(v1_t, ret);
21513 break;
21514 case 1:
21515 /* SUBUH_R_QB */
21516 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21517 gen_store_gpr(v1_t, ret);
21518 break;
21519 }
21520 break;
21521 case NM_SHLLV_S_PH:
21522 check_dsp(ctx);
21523 switch (extract32(ctx->opcode, 10, 1)) {
21524 case 0:
21525 /* SHLLV_PH */
21526 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21527 gen_store_gpr(v1_t, ret);
21528 break;
21529 case 1:
21530 /* SHLLV_S_PH */
21531 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21532 gen_store_gpr(v1_t, ret);
21533 break;
21534 }
21535 break;
21536 case NM_PRECR_SRA_R_PH_W:
908f6be1 21537 check_dsp_r2(ctx);
3285a3e4
SM
21538 switch (extract32(ctx->opcode, 10, 1)) {
21539 case 0:
21540 /* PRECR_SRA_PH_W */
21541 {
21542 TCGv_i32 sa_t = tcg_const_i32(rd);
21543 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21544 cpu_gpr[rt]);
21545 gen_store_gpr(v1_t, rt);
21546 tcg_temp_free_i32(sa_t);
21547 }
21548 break;
21549 case 1:
21550 /* PRECR_SRA_R_PH_W */
21551 {
21552 TCGv_i32 sa_t = tcg_const_i32(rd);
21553 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21554 cpu_gpr[rt]);
21555 gen_store_gpr(v1_t, rt);
21556 tcg_temp_free_i32(sa_t);
21557 }
21558 break;
21559 }
21560 break;
21561 case NM_MULEU_S_PH_QBL:
21562 check_dsp(ctx);
21563 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21564 gen_store_gpr(v1_t, ret);
21565 break;
21566 case NM_MULEU_S_PH_QBR:
21567 check_dsp(ctx);
21568 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21569 gen_store_gpr(v1_t, ret);
21570 break;
21571 case NM_MULQ_RS_PH:
21572 check_dsp(ctx);
21573 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21574 gen_store_gpr(v1_t, ret);
21575 break;
21576 case NM_MULQ_S_PH:
908f6be1 21577 check_dsp_r2(ctx);
3285a3e4
SM
21578 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21579 gen_store_gpr(v1_t, ret);
21580 break;
21581 case NM_MULQ_RS_W:
908f6be1 21582 check_dsp_r2(ctx);
3285a3e4
SM
21583 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21584 gen_store_gpr(v1_t, ret);
21585 break;
21586 case NM_MULQ_S_W:
908f6be1 21587 check_dsp_r2(ctx);
3285a3e4
SM
21588 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21589 gen_store_gpr(v1_t, ret);
21590 break;
21591 case NM_APPEND:
908f6be1 21592 check_dsp_r2(ctx);
3285a3e4
SM
21593 gen_load_gpr(t0, rs);
21594 if (rd != 0) {
21595 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21596 }
21597 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21598 break;
21599 case NM_MODSUB:
21600 check_dsp(ctx);
21601 gen_helper_modsub(v1_t, v1_t, v2_t);
21602 gen_store_gpr(v1_t, ret);
21603 break;
21604 case NM_SHRAV_R_W:
21605 check_dsp(ctx);
21606 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21607 gen_store_gpr(v1_t, ret);
21608 break;
21609 case NM_SHRLV_PH:
908f6be1 21610 check_dsp_r2(ctx);
3285a3e4
SM
21611 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21612 gen_store_gpr(v1_t, ret);
21613 break;
21614 case NM_SHRLV_QB:
21615 check_dsp(ctx);
21616 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21617 gen_store_gpr(v1_t, ret);
21618 break;
21619 case NM_SHLLV_QB:
21620 check_dsp(ctx);
21621 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21622 gen_store_gpr(v1_t, ret);
21623 break;
21624 case NM_SHLLV_S_W:
21625 check_dsp(ctx);
21626 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21627 gen_store_gpr(v1_t, ret);
21628 break;
21629 case NM_SHILO:
21630 check_dsp(ctx);
21631 {
21632 TCGv tv0 = tcg_temp_new();
21633 TCGv tv1 = tcg_temp_new();
21634 int16_t imm = extract32(ctx->opcode, 16, 7);
21635
21636 tcg_gen_movi_tl(tv0, rd >> 3);
21637 tcg_gen_movi_tl(tv1, imm);
21638 gen_helper_shilo(tv0, tv1, cpu_env);
21639 }
21640 break;
21641 case NM_MULEQ_S_W_PHL:
21642 check_dsp(ctx);
21643 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21644 gen_store_gpr(v1_t, ret);
21645 break;
21646 case NM_MULEQ_S_W_PHR:
21647 check_dsp(ctx);
21648 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21649 gen_store_gpr(v1_t, ret);
21650 break;
21651 case NM_MUL_S_PH:
908f6be1 21652 check_dsp_r2(ctx);
3285a3e4
SM
21653 switch (extract32(ctx->opcode, 10, 1)) {
21654 case 0:
21655 /* MUL_PH */
21656 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21657 gen_store_gpr(v1_t, ret);
21658 break;
21659 case 1:
21660 /* MUL_S_PH */
21661 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21662 gen_store_gpr(v1_t, ret);
21663 break;
21664 }
21665 break;
21666 case NM_PRECR_QB_PH:
908f6be1 21667 check_dsp_r2(ctx);
3285a3e4
SM
21668 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21669 gen_store_gpr(v1_t, ret);
21670 break;
21671 case NM_PRECRQ_QB_PH:
21672 check_dsp(ctx);
21673 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21674 gen_store_gpr(v1_t, ret);
21675 break;
21676 case NM_PRECRQ_PH_W:
21677 check_dsp(ctx);
21678 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21679 gen_store_gpr(v1_t, ret);
21680 break;
21681 case NM_PRECRQ_RS_PH_W:
21682 check_dsp(ctx);
21683 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21684 gen_store_gpr(v1_t, ret);
21685 break;
21686 case NM_PRECRQU_S_QB_PH:
21687 check_dsp(ctx);
21688 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21689 gen_store_gpr(v1_t, ret);
21690 break;
21691 case NM_SHRA_R_W:
21692 check_dsp(ctx);
21693 tcg_gen_movi_tl(t0, rd);
21694 gen_helper_shra_r_w(v1_t, t0, v1_t);
21695 gen_store_gpr(v1_t, rt);
21696 break;
21697 case NM_SHRA_R_PH:
21698 check_dsp(ctx);
21699 tcg_gen_movi_tl(t0, rd >> 1);
21700 switch (extract32(ctx->opcode, 10, 1)) {
21701 case 0:
21702 /* SHRA_PH */
21703 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 21704 gen_store_gpr(v1_t, rt);
d5ebcbaf 21705 break;
3285a3e4
SM
21706 case 1:
21707 /* SHRA_R_PH */
21708 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21709 gen_store_gpr(v1_t, rt);
21710 break;
21711 }
21712 break;
21713 case NM_SHLL_S_PH:
21714 check_dsp(ctx);
21715 tcg_gen_movi_tl(t0, rd >> 1);
21716 switch (extract32(ctx->opcode, 10, 2)) {
21717 case 0:
21718 /* SHLL_PH */
21719 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21720 gen_store_gpr(v1_t, rt);
21721 break;
21722 case 2:
21723 /* SHLL_S_PH */
21724 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21725 gen_store_gpr(v1_t, rt);
21726 break;
21727 default:
21728 generate_exception_end(ctx, EXCP_RI);
21729 break;
21730 }
21731 break;
21732 case NM_SHLL_S_W:
21733 check_dsp(ctx);
21734 tcg_gen_movi_tl(t0, rd);
21735 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21736 gen_store_gpr(v1_t, rt);
21737 break;
21738 case NM_REPL_PH:
21739 check_dsp(ctx);
21740 {
21741 int16_t imm;
21742 imm = sextract32(ctx->opcode, 11, 11);
21743 imm = (int16_t)(imm << 6) >> 6;
21744 if (rt != 0) {
21745 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21746 }
21747 }
21748 break;
21749 default:
21750 generate_exception_end(ctx, EXCP_RI);
21751 break;
21752 }
21753}
21754
c0280983
YK
21755static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21756{
21757 uint16_t insn;
21758 uint32_t op;
eac52664 21759 int rt, rs, rd;
c0280983
YK
21760 int offset;
21761 int imm;
21762
21763 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21764 ctx->opcode = (ctx->opcode << 16) | insn;
21765
21766 rt = extract32(ctx->opcode, 21, 5);
21767 rs = extract32(ctx->opcode, 16, 5);
eac52664 21768 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
21769
21770 op = extract32(ctx->opcode, 26, 6);
21771 switch (op) {
21772 case NM_P_ADDIU:
21773 if (rt == 0) {
21774 /* P.RI */
21775 switch (extract32(ctx->opcode, 19, 2)) {
21776 case NM_SIGRIE:
21777 default:
21778 generate_exception_end(ctx, EXCP_RI);
21779 break;
21780 case NM_P_SYSCALL:
21781 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21782 generate_exception_end(ctx, EXCP_SYSCALL);
21783 } else {
21784 generate_exception_end(ctx, EXCP_RI);
21785 }
21786 break;
21787 case NM_BREAK:
21788 generate_exception_end(ctx, EXCP_BREAK);
21789 break;
21790 case NM_SDBBP:
21791 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21792 gen_helper_do_semihosting(cpu_env);
21793 } else {
21794 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21795 generate_exception_end(ctx, EXCP_RI);
21796 } else {
21797 generate_exception_end(ctx, EXCP_DBp);
21798 }
21799 }
21800 break;
21801 }
21802 } else {
21803 /* NM_ADDIU */
21804 imm = extract32(ctx->opcode, 0, 16);
21805 if (rs != 0) {
21806 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21807 } else {
21808 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21809 }
21810 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21811 }
21812 break;
21813 case NM_ADDIUPC:
21814 if (rt != 0) {
21815 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21816 extract32(ctx->opcode, 1, 20) << 1;
21817 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21818 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21819 }
21820 break;
21821 case NM_POOL32A:
e0cf0e65
YK
21822 switch (ctx->opcode & 0x07) {
21823 case NM_POOL32A0:
0a1a6ed7 21824 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21825 break;
3285a3e4
SM
21826 case NM_POOL32A5:
21827 {
21828 int32_t op1 = extract32(ctx->opcode, 3, 7);
21829 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21830 }
21831 break;
e0cf0e65 21832 case NM_POOL32A7:
64224187 21833 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21834 case NM_P_LSX:
21835 gen_p_lsx(ctx, rd, rs, rt);
21836 break;
21837 case NM_LSA:
7480515f
AM
21838 /*
21839 * In nanoMIPS, the shift field directly encodes the shift
eac52664 21840 * amount, meaning that the supported shift values are in
7480515f
AM
21841 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21842 */
eac52664
YK
21843 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21844 extract32(ctx->opcode, 9, 2) - 1);
21845 break;
821f2008
JH
21846 case NM_EXTW:
21847 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21848 break;
64224187
YK
21849 case NM_POOL32AXF:
21850 gen_pool32axf_nanomips_insn(env, ctx);
21851 break;
21852 default:
21853 generate_exception_end(ctx, EXCP_RI);
21854 break;
21855 }
e0cf0e65
YK
21856 break;
21857 default:
21858 generate_exception_end(ctx, EXCP_RI);
21859 break;
21860 }
c0280983
YK
21861 break;
21862 case NM_P_GP_W:
21863 switch (ctx->opcode & 0x03) {
21864 case NM_ADDIUGP_W:
21865 if (rt != 0) {
21866 offset = extract32(ctx->opcode, 0, 21);
21867 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21868 }
21869 break;
21870 case NM_LWGP:
21871 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21872 break;
21873 case NM_SWGP:
21874 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21875 break;
21876 default:
21877 generate_exception_end(ctx, EXCP_RI);
21878 break;
21879 }
21880 break;
21881 case NM_P48I:
7ef009b2
YK
21882 {
21883 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21884 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21885 switch (extract32(ctx->opcode, 16, 5)) {
21886 case NM_LI48:
fb32f8c8 21887 check_nms(ctx);
7ef009b2
YK
21888 if (rt != 0) {
21889 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21890 }
21891 break;
21892 case NM_ADDIU48:
fb32f8c8 21893 check_nms(ctx);
7ef009b2
YK
21894 if (rt != 0) {
21895 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21896 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21897 }
21898 break;
21899 case NM_ADDIUGP48:
fb32f8c8 21900 check_nms(ctx);
7ef009b2
YK
21901 if (rt != 0) {
21902 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21903 }
21904 break;
21905 case NM_ADDIUPC48:
fb32f8c8 21906 check_nms(ctx);
7ef009b2
YK
21907 if (rt != 0) {
21908 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21909 addr_off);
21910
21911 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21912 }
21913 break;
21914 case NM_LWPC48:
fb32f8c8 21915 check_nms(ctx);
7ef009b2
YK
21916 if (rt != 0) {
21917 TCGv t0;
21918 t0 = tcg_temp_new();
21919
21920 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21921 addr_off);
21922
21923 tcg_gen_movi_tl(t0, addr);
21924 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21925 tcg_temp_free(t0);
21926 }
21927 break;
21928 case NM_SWPC48:
fb32f8c8 21929 check_nms(ctx);
7ef009b2
YK
21930 {
21931 TCGv t0, t1;
21932 t0 = tcg_temp_new();
21933 t1 = tcg_temp_new();
21934
21935 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21936 addr_off);
21937
21938 tcg_gen_movi_tl(t0, addr);
21939 gen_load_gpr(t1, rt);
21940
21941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21942
21943 tcg_temp_free(t0);
21944 tcg_temp_free(t1);
21945 }
21946 break;
21947 default:
21948 generate_exception_end(ctx, EXCP_RI);
21949 break;
21950 }
21951 return 6;
21952 }
c0280983
YK
21953 case NM_P_U12:
21954 switch (extract32(ctx->opcode, 12, 4)) {
21955 case NM_ORI:
21956 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21957 break;
21958 case NM_XORI:
21959 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21960 break;
21961 case NM_ANDI:
21962 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21963 break;
21964 case NM_P_SR:
21965 switch (extract32(ctx->opcode, 20, 1)) {
21966 case NM_PP_SR:
21967 switch (ctx->opcode & 3) {
21968 case NM_SAVE:
21969 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21970 extract32(ctx->opcode, 2, 1),
21971 extract32(ctx->opcode, 3, 9) << 3);
21972 break;
21973 case NM_RESTORE:
21974 case NM_RESTORE_JRC:
21975 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21976 extract32(ctx->opcode, 2, 1),
21977 extract32(ctx->opcode, 3, 9) << 3);
21978 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21979 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21980 }
21981 break;
21982 default:
21983 generate_exception_end(ctx, EXCP_RI);
21984 break;
21985 }
21986 break;
21987 case NM_P_SR_F:
21988 generate_exception_end(ctx, EXCP_RI);
21989 break;
21990 }
21991 break;
21992 case NM_SLTI:
21993 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21994 break;
21995 case NM_SLTIU:
21996 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21997 break;
21998 case NM_SEQI:
21999 {
22000 TCGv t0 = tcg_temp_new();
22001
22002 imm = extract32(ctx->opcode, 0, 12);
22003 gen_load_gpr(t0, rs);
22004 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
22005 gen_store_gpr(t0, rt);
22006
22007 tcg_temp_free(t0);
22008 }
22009 break;
22010 case NM_ADDIUNEG:
22011 imm = (int16_t) extract32(ctx->opcode, 0, 12);
22012 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
22013 break;
22014 case NM_P_SHIFT:
22015 {
22016 int shift = extract32(ctx->opcode, 0, 5);
22017 switch (extract32(ctx->opcode, 5, 4)) {
22018 case NM_P_SLL:
22019 if (rt == 0 && shift == 0) {
22020 /* NOP */
22021 } else if (rt == 0 && shift == 3) {
22022 /* EHB - treat as NOP */
22023 } else if (rt == 0 && shift == 5) {
22024 /* PAUSE - treat as NOP */
22025 } else if (rt == 0 && shift == 6) {
22026 /* SYNC */
22027 gen_sync(extract32(ctx->opcode, 16, 5));
22028 } else {
22029 /* SLL */
22030 gen_shift_imm(ctx, OPC_SLL, rt, rs,
22031 extract32(ctx->opcode, 0, 5));
22032 }
22033 break;
22034 case NM_SRL:
22035 gen_shift_imm(ctx, OPC_SRL, rt, rs,
22036 extract32(ctx->opcode, 0, 5));
22037 break;
22038 case NM_SRA:
22039 gen_shift_imm(ctx, OPC_SRA, rt, rs,
22040 extract32(ctx->opcode, 0, 5));
22041 break;
22042 case NM_ROTR:
22043 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
22044 extract32(ctx->opcode, 0, 5));
22045 break;
22046 }
22047 }
22048 break;
22049 case NM_P_ROTX:
fb32f8c8 22050 check_nms(ctx);
e222f506
MF
22051 if (rt != 0) {
22052 TCGv t0 = tcg_temp_new();
22053 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
22054 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
22055 << 1);
22056 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
22057
22058 gen_load_gpr(t0, rs);
22059 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
22060 tcg_temp_free(t0);
22061
22062 tcg_temp_free_i32(shift);
22063 tcg_temp_free_i32(shiftx);
22064 tcg_temp_free_i32(stripe);
22065 }
c0280983
YK
22066 break;
22067 case NM_P_INS:
22068 switch (((ctx->opcode >> 10) & 2) |
22069 (extract32(ctx->opcode, 5, 1))) {
22070 case NM_INS:
fb32f8c8 22071 check_nms(ctx);
c0280983
YK
22072 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
22073 extract32(ctx->opcode, 6, 5));
22074 break;
22075 default:
22076 generate_exception_end(ctx, EXCP_RI);
22077 break;
22078 }
22079 break;
22080 case NM_P_EXT:
22081 switch (((ctx->opcode >> 10) & 2) |
22082 (extract32(ctx->opcode, 5, 1))) {
22083 case NM_EXT:
fb32f8c8 22084 check_nms(ctx);
c0280983
YK
22085 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
22086 extract32(ctx->opcode, 6, 5));
22087 break;
22088 default:
22089 generate_exception_end(ctx, EXCP_RI);
22090 break;
22091 }
22092 break;
22093 default:
22094 generate_exception_end(ctx, EXCP_RI);
22095 break;
22096 }
22097 break;
22098 case NM_POOL32F:
579b8ea9 22099 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
22100 break;
22101 case NM_POOL32S:
22102 break;
22103 case NM_P_LUI:
22104 switch (extract32(ctx->opcode, 1, 1)) {
22105 case NM_LUI:
22106 if (rt != 0) {
22107 tcg_gen_movi_tl(cpu_gpr[rt],
22108 sextract32(ctx->opcode, 0, 1) << 31 |
22109 extract32(ctx->opcode, 2, 10) << 21 |
22110 extract32(ctx->opcode, 12, 9) << 12);
22111 }
22112 break;
22113 case NM_ALUIPC:
22114 if (rt != 0) {
22115 offset = sextract32(ctx->opcode, 0, 1) << 31 |
22116 extract32(ctx->opcode, 2, 10) << 21 |
22117 extract32(ctx->opcode, 12, 9) << 12;
22118 target_long addr;
22119 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
22120 tcg_gen_movi_tl(cpu_gpr[rt], addr);
22121 }
22122 break;
22123 }
22124 break;
22125 case NM_P_GP_BH:
8f1d9b6d
YK
22126 {
22127 uint32_t u = extract32(ctx->opcode, 0, 18);
22128
22129 switch (extract32(ctx->opcode, 18, 3)) {
22130 case NM_LBGP:
22131 gen_ld(ctx, OPC_LB, rt, 28, u);
22132 break;
22133 case NM_SBGP:
22134 gen_st(ctx, OPC_SB, rt, 28, u);
22135 break;
22136 case NM_LBUGP:
22137 gen_ld(ctx, OPC_LBU, rt, 28, u);
22138 break;
22139 case NM_ADDIUGP_B:
22140 if (rt != 0) {
22141 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22142 }
22143 break;
22144 case NM_P_GP_LH:
22145 u &= ~1;
22146 switch (ctx->opcode & 1) {
22147 case NM_LHGP:
22148 gen_ld(ctx, OPC_LH, rt, 28, u);
22149 break;
22150 case NM_LHUGP:
22151 gen_ld(ctx, OPC_LHU, rt, 28, u);
22152 break;
22153 }
22154 break;
22155 case NM_P_GP_SH:
22156 u &= ~1;
22157 switch (ctx->opcode & 1) {
22158 case NM_SHGP:
22159 gen_st(ctx, OPC_SH, rt, 28, u);
22160 break;
22161 default:
22162 generate_exception_end(ctx, EXCP_RI);
22163 break;
22164 }
22165 break;
22166 case NM_P_GP_CP1:
22167 u &= ~0x3;
22168 switch (ctx->opcode & 0x3) {
22169 case NM_LWC1GP:
22170 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22171 break;
22172 case NM_LDC1GP:
22173 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22174 break;
22175 case NM_SWC1GP:
22176 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22177 break;
22178 case NM_SDC1GP:
22179 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22180 break;
22181 }
22182 break;
22183 default:
22184 generate_exception_end(ctx, EXCP_RI);
22185 break;
22186 }
22187 }
c0280983
YK
22188 break;
22189 case NM_P_LS_U12:
8f1d9b6d
YK
22190 {
22191 uint32_t u = extract32(ctx->opcode, 0, 12);
22192
22193 switch (extract32(ctx->opcode, 12, 4)) {
22194 case NM_P_PREFU12:
22195 if (rt == 31) {
22196 /* SYNCI */
7480515f
AM
22197 /*
22198 * Break the TB to be able to sync copied instructions
22199 * immediately.
22200 */
8f1d9b6d
YK
22201 ctx->base.is_jmp = DISAS_STOP;
22202 } else {
22203 /* PREF */
22204 /* Treat as NOP. */
22205 }
22206 break;
22207 case NM_LB:
22208 gen_ld(ctx, OPC_LB, rt, rs, u);
22209 break;
22210 case NM_LH:
22211 gen_ld(ctx, OPC_LH, rt, rs, u);
22212 break;
22213 case NM_LW:
22214 gen_ld(ctx, OPC_LW, rt, rs, u);
22215 break;
22216 case NM_LBU:
22217 gen_ld(ctx, OPC_LBU, rt, rs, u);
22218 break;
22219 case NM_LHU:
22220 gen_ld(ctx, OPC_LHU, rt, rs, u);
22221 break;
22222 case NM_SB:
22223 gen_st(ctx, OPC_SB, rt, rs, u);
22224 break;
22225 case NM_SH:
22226 gen_st(ctx, OPC_SH, rt, rs, u);
22227 break;
22228 case NM_SW:
22229 gen_st(ctx, OPC_SW, rt, rs, u);
22230 break;
22231 case NM_LWC1:
22232 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22233 break;
22234 case NM_LDC1:
22235 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22236 break;
22237 case NM_SWC1:
22238 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22239 break;
22240 case NM_SDC1:
22241 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22242 break;
22243 default:
22244 generate_exception_end(ctx, EXCP_RI);
22245 break;
22246 }
22247 }
c0280983
YK
22248 break;
22249 case NM_P_LS_S9:
8f1d9b6d
YK
22250 {
22251 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22252 extract32(ctx->opcode, 0, 8);
22253
22254 switch (extract32(ctx->opcode, 8, 3)) {
22255 case NM_P_LS_S0:
22256 switch (extract32(ctx->opcode, 11, 4)) {
22257 case NM_LBS9:
22258 gen_ld(ctx, OPC_LB, rt, rs, s);
22259 break;
22260 case NM_LHS9:
22261 gen_ld(ctx, OPC_LH, rt, rs, s);
22262 break;
22263 case NM_LWS9:
22264 gen_ld(ctx, OPC_LW, rt, rs, s);
22265 break;
22266 case NM_LBUS9:
22267 gen_ld(ctx, OPC_LBU, rt, rs, s);
22268 break;
22269 case NM_LHUS9:
22270 gen_ld(ctx, OPC_LHU, rt, rs, s);
22271 break;
22272 case NM_SBS9:
22273 gen_st(ctx, OPC_SB, rt, rs, s);
22274 break;
22275 case NM_SHS9:
22276 gen_st(ctx, OPC_SH, rt, rs, s);
22277 break;
22278 case NM_SWS9:
22279 gen_st(ctx, OPC_SW, rt, rs, s);
22280 break;
22281 case NM_LWC1S9:
22282 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22283 break;
22284 case NM_LDC1S9:
22285 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22286 break;
22287 case NM_SWC1S9:
22288 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22289 break;
22290 case NM_SDC1S9:
22291 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22292 break;
22293 case NM_P_PREFS9:
22294 if (rt == 31) {
22295 /* SYNCI */
7480515f
AM
22296 /*
22297 * Break the TB to be able to sync copied instructions
22298 * immediately.
22299 */
8f1d9b6d
YK
22300 ctx->base.is_jmp = DISAS_STOP;
22301 } else {
22302 /* PREF */
22303 /* Treat as NOP. */
22304 }
22305 break;
22306 default:
22307 generate_exception_end(ctx, EXCP_RI);
22308 break;
22309 }
22310 break;
22311 case NM_P_LS_S1:
22312 switch (extract32(ctx->opcode, 11, 4)) {
22313 case NM_UALH:
22314 case NM_UASH:
fb32f8c8 22315 check_nms(ctx);
8f1d9b6d
YK
22316 {
22317 TCGv t0 = tcg_temp_new();
22318 TCGv t1 = tcg_temp_new();
22319
22320 gen_base_offset_addr(ctx, t0, rs, s);
22321
22322 switch (extract32(ctx->opcode, 11, 4)) {
22323 case NM_UALH:
22324 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22325 MO_UNALN);
22326 gen_store_gpr(t0, rt);
22327 break;
22328 case NM_UASH:
22329 gen_load_gpr(t1, rt);
22330 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22331 MO_UNALN);
22332 break;
22333 }
22334 tcg_temp_free(t0);
22335 tcg_temp_free(t1);
22336 }
22337 break;
22338 case NM_P_LL:
22339 switch (ctx->opcode & 0x03) {
22340 case NM_LL:
22341 gen_ld(ctx, OPC_LL, rt, rs, s);
22342 break;
22343 case NM_LLWP:
0b16dcd1
AR
22344 check_xnp(ctx);
22345 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
22346 break;
22347 }
22348 break;
22349 case NM_P_SC:
22350 switch (ctx->opcode & 0x03) {
22351 case NM_SC:
33a07fa2 22352 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
22353 break;
22354 case NM_SCWP:
0b16dcd1 22355 check_xnp(ctx);
8d5388c1
AM
22356 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22357 false);
8f1d9b6d
YK
22358 break;
22359 }
22360 break;
22361 case NM_CACHE:
22362 check_cp0_enabled(ctx);
22363 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22364 gen_cache_operation(ctx, rt, rs, s);
22365 }
22366 break;
22367 }
22368 break;
d046a9ea
DN
22369 case NM_P_LS_E0:
22370 switch (extract32(ctx->opcode, 11, 4)) {
22371 case NM_LBE:
22372 check_eva(ctx);
22373 check_cp0_enabled(ctx);
22374 gen_ld(ctx, OPC_LBE, rt, rs, s);
22375 break;
22376 case NM_SBE:
22377 check_eva(ctx);
22378 check_cp0_enabled(ctx);
22379 gen_st(ctx, OPC_SBE, rt, rs, s);
22380 break;
22381 case NM_LBUE:
22382 check_eva(ctx);
22383 check_cp0_enabled(ctx);
22384 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22385 break;
22386 case NM_P_PREFE:
22387 if (rt == 31) {
22388 /* case NM_SYNCIE */
22389 check_eva(ctx);
22390 check_cp0_enabled(ctx);
7480515f
AM
22391 /*
22392 * Break the TB to be able to sync copied instructions
22393 * immediately.
22394 */
d046a9ea
DN
22395 ctx->base.is_jmp = DISAS_STOP;
22396 } else {
22397 /* case NM_PREFE */
22398 check_eva(ctx);
22399 check_cp0_enabled(ctx);
22400 /* Treat as NOP. */
22401 }
22402 break;
22403 case NM_LHE:
22404 check_eva(ctx);
22405 check_cp0_enabled(ctx);
22406 gen_ld(ctx, OPC_LHE, rt, rs, s);
22407 break;
22408 case NM_SHE:
22409 check_eva(ctx);
22410 check_cp0_enabled(ctx);
22411 gen_st(ctx, OPC_SHE, rt, rs, s);
22412 break;
22413 case NM_LHUE:
22414 check_eva(ctx);
22415 check_cp0_enabled(ctx);
22416 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22417 break;
22418 case NM_CACHEE:
22419 check_nms_dl_il_sl_tl_l2c(ctx);
22420 gen_cache_operation(ctx, rt, rs, s);
22421 break;
22422 case NM_LWE:
22423 check_eva(ctx);
22424 check_cp0_enabled(ctx);
22425 gen_ld(ctx, OPC_LWE, rt, rs, s);
22426 break;
22427 case NM_SWE:
22428 check_eva(ctx);
22429 check_cp0_enabled(ctx);
22430 gen_st(ctx, OPC_SWE, rt, rs, s);
22431 break;
22432 case NM_P_LLE:
22433 switch (extract32(ctx->opcode, 2, 2)) {
22434 case NM_LLE:
22435 check_xnp(ctx);
22436 check_eva(ctx);
22437 check_cp0_enabled(ctx);
22438 gen_ld(ctx, OPC_LLE, rt, rs, s);
22439 break;
22440 case NM_LLWPE:
22441 check_xnp(ctx);
22442 check_eva(ctx);
22443 check_cp0_enabled(ctx);
22444 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 22445 break;
d046a9ea
DN
22446 default:
22447 generate_exception_end(ctx, EXCP_RI);
22448 break;
22449 }
22450 break;
22451 case NM_P_SCE:
22452 switch (extract32(ctx->opcode, 2, 2)) {
22453 case NM_SCE:
22454 check_xnp(ctx);
22455 check_eva(ctx);
22456 check_cp0_enabled(ctx);
33a07fa2 22457 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
22458 break;
22459 case NM_SCWPE:
22460 check_xnp(ctx);
22461 check_eva(ctx);
22462 check_cp0_enabled(ctx);
8d5388c1
AM
22463 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22464 true);
2431a422 22465 break;
d046a9ea
DN
22466 default:
22467 generate_exception_end(ctx, EXCP_RI);
22468 break;
22469 }
22470 break;
22471 }
22472 break;
8f1d9b6d
YK
22473 case NM_P_LS_WM:
22474 case NM_P_LS_UAWM:
fb32f8c8 22475 check_nms(ctx);
8f1d9b6d
YK
22476 {
22477 int count = extract32(ctx->opcode, 12, 3);
22478 int counter = 0;
22479
22480 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22481 extract32(ctx->opcode, 0, 8);
22482 TCGv va = tcg_temp_new();
22483 TCGv t1 = tcg_temp_new();
14776ab5 22484 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
22485 NM_P_LS_UAWM ? MO_UNALN : 0;
22486
22487 count = (count == 0) ? 8 : count;
22488 while (counter != count) {
22489 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22490 int this_offset = offset + (counter << 2);
22491
22492 gen_base_offset_addr(ctx, va, rs, this_offset);
22493
22494 switch (extract32(ctx->opcode, 11, 1)) {
22495 case NM_LWM:
22496 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22497 memop | MO_TESL);
22498 gen_store_gpr(t1, this_rt);
22499 if ((this_rt == rs) &&
22500 (counter != (count - 1))) {
22501 /* UNPREDICTABLE */
22502 }
22503 break;
22504 case NM_SWM:
22505 this_rt = (rt == 0) ? 0 : this_rt;
22506 gen_load_gpr(t1, this_rt);
22507 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22508 memop | MO_TEUL);
22509 break;
22510 }
22511 counter++;
22512 }
22513 tcg_temp_free(va);
22514 tcg_temp_free(t1);
22515 }
22516 break;
22517 default:
22518 generate_exception_end(ctx, EXCP_RI);
22519 break;
22520 }
22521 }
c0280983
YK
22522 break;
22523 case NM_MOVE_BALC:
fb32f8c8 22524 check_nms(ctx);
11d0fc10
SM
22525 {
22526 TCGv t0 = tcg_temp_new();
22527 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22528 extract32(ctx->opcode, 1, 20) << 1;
22529 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22530 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22531 extract32(ctx->opcode, 21, 3));
22532 gen_load_gpr(t0, rt);
22533 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22534 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22535 tcg_temp_free(t0);
22536 }
c0280983
YK
22537 break;
22538 case NM_P_BAL:
11d0fc10
SM
22539 {
22540 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22541 extract32(ctx->opcode, 1, 24) << 1;
22542
22543 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22544 /* BC */
22545 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22546 } else {
22547 /* BALC */
22548 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22549 }
22550 }
c0280983
YK
22551 break;
22552 case NM_P_J:
11d0fc10
SM
22553 switch (extract32(ctx->opcode, 12, 4)) {
22554 case NM_JALRC:
22555 case NM_JALRC_HB:
22556 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22557 break;
22558 case NM_P_BALRSC:
22559 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22560 break;
22561 default:
22562 generate_exception_end(ctx, EXCP_RI);
22563 break;
22564 }
c0280983
YK
22565 break;
22566 case NM_P_BR1:
11d0fc10
SM
22567 {
22568 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22569 extract32(ctx->opcode, 1, 13) << 1;
22570 switch (extract32(ctx->opcode, 14, 2)) {
22571 case NM_BEQC:
fb32f8c8 22572 check_nms(ctx);
11d0fc10
SM
22573 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22574 break;
22575 case NM_P_BR3A:
22576 s = sextract32(ctx->opcode, 0, 1) << 14 |
22577 extract32(ctx->opcode, 1, 13) << 1;
22578 check_cp1_enabled(ctx);
22579 switch (extract32(ctx->opcode, 16, 5)) {
22580 case NM_BC1EQZC:
22581 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22582 break;
22583 case NM_BC1NEZC:
22584 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22585 break;
6d033ca7 22586 case NM_BPOSGE32C:
908f6be1 22587 check_dsp_r3(ctx);
6d033ca7
SM
22588 {
22589 int32_t imm = extract32(ctx->opcode, 1, 13) |
22590 extract32(ctx->opcode, 0, 1) << 13;
22591
22592 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22593 imm);
22594 }
22595 break;
11d0fc10
SM
22596 default:
22597 generate_exception_end(ctx, EXCP_RI);
22598 break;
22599 }
22600 break;
22601 case NM_BGEC:
22602 if (rs == rt) {
22603 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22604 } else {
22605 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22606 }
22607 break;
22608 case NM_BGEUC:
22609 if (rs == rt || rt == 0) {
22610 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22611 } else if (rs == 0) {
22612 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22613 } else {
22614 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22615 }
22616 break;
22617 }
22618 }
c0280983
YK
22619 break;
22620 case NM_P_BR2:
11d0fc10
SM
22621 {
22622 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22623 extract32(ctx->opcode, 1, 13) << 1;
22624 switch (extract32(ctx->opcode, 14, 2)) {
22625 case NM_BNEC:
fb32f8c8 22626 check_nms(ctx);
11d0fc10
SM
22627 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22628 break;
22629 case NM_BLTC:
22630 if (rs != 0 && rt != 0 && rs == rt) {
22631 /* NOP */
22632 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22633 } else {
22634 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22635 }
22636 break;
22637 case NM_BLTUC:
22638 if (rs == 0 || rs == rt) {
22639 /* NOP */
22640 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22641 } else {
22642 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22643 }
22644 break;
22645 default:
22646 generate_exception_end(ctx, EXCP_RI);
22647 break;
22648 }
22649 }
c0280983
YK
22650 break;
22651 case NM_P_BRI:
11d0fc10
SM
22652 {
22653 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22654 extract32(ctx->opcode, 1, 10) << 1;
22655 uint32_t u = extract32(ctx->opcode, 11, 7);
22656
22657 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22658 rt, u, s);
22659 }
c0280983
YK
22660 break;
22661 default:
22662 generate_exception_end(ctx, EXCP_RI);
22663 break;
22664 }
22665 return 4;
22666}
22667
c533c0f4
AM
22668static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22669{
ea4ca3c2 22670 uint32_t op;
99e49abf
AM
22671 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22672 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22673 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 22674 int offset;
ea4ca3c2
YK
22675 int imm;
22676
22677 /* make sure instructions are on a halfword boundary */
22678 if (ctx->base.pc_next & 0x1) {
22679 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22680 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22681 tcg_temp_free(tmp);
22682 generate_exception_end(ctx, EXCP_AdEL);
22683 return 2;
22684 }
22685
22686 op = extract32(ctx->opcode, 10, 6);
22687 switch (op) {
22688 case NM_P16_MV:
8869ad02
YK
22689 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22690 if (rt != 0) {
22691 /* MOVE */
22692 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22693 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22694 } else {
22695 /* P16.RI */
22696 switch (extract32(ctx->opcode, 3, 2)) {
22697 case NM_P16_SYSCALL:
22698 if (extract32(ctx->opcode, 2, 1) == 0) {
22699 generate_exception_end(ctx, EXCP_SYSCALL);
22700 } else {
22701 generate_exception_end(ctx, EXCP_RI);
22702 }
22703 break;
22704 case NM_BREAK16:
22705 generate_exception_end(ctx, EXCP_BREAK);
22706 break;
22707 case NM_SDBBP16:
22708 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22709 gen_helper_do_semihosting(cpu_env);
22710 } else {
22711 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22712 generate_exception_end(ctx, EXCP_RI);
22713 } else {
22714 generate_exception_end(ctx, EXCP_DBp);
22715 }
22716 }
22717 break;
22718 default:
22719 generate_exception_end(ctx, EXCP_RI);
22720 break;
22721 }
22722 }
ea4ca3c2
YK
22723 break;
22724 case NM_P16_SHIFT:
c46562fb
YK
22725 {
22726 int shift = extract32(ctx->opcode, 0, 3);
22727 uint32_t opc = 0;
22728 shift = (shift == 0) ? 8 : shift;
22729
22730 switch (extract32(ctx->opcode, 3, 1)) {
22731 case NM_SLL16:
22732 opc = OPC_SLL;
22733 break;
22734 case NM_SRL16:
22735 opc = OPC_SRL;
22736 break;
22737 }
22738 gen_shift_imm(ctx, opc, rt, rs, shift);
22739 }
ea4ca3c2
YK
22740 break;
22741 case NM_P16C:
8bdb7029
YK
22742 switch (ctx->opcode & 1) {
22743 case NM_POOL16C_0:
80845edf 22744 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
22745 break;
22746 case NM_LWXS16:
22747 gen_ldxs(ctx, rt, rs, rd);
22748 break;
22749 }
ea4ca3c2
YK
22750 break;
22751 case NM_P16_A1:
22752 switch (extract32(ctx->opcode, 6, 1)) {
22753 case NM_ADDIUR1SP:
22754 imm = extract32(ctx->opcode, 0, 6) << 2;
22755 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22756 break;
22757 default:
22758 generate_exception_end(ctx, EXCP_RI);
22759 break;
22760 }
22761 break;
22762 case NM_P16_A2:
22763 switch (extract32(ctx->opcode, 3, 1)) {
22764 case NM_ADDIUR2:
22765 imm = extract32(ctx->opcode, 0, 3) << 2;
22766 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22767 break;
22768 case NM_P_ADDIURS5:
22769 rt = extract32(ctx->opcode, 5, 5);
22770 if (rt != 0) {
22771 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22772 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22773 (extract32(ctx->opcode, 0, 3));
22774 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22775 }
22776 break;
22777 }
22778 break;
22779 case NM_P16_ADDU:
22780 switch (ctx->opcode & 0x1) {
22781 case NM_ADDU16:
22782 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22783 break;
22784 case NM_SUBU16:
22785 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22786 break;
22787 }
22788 break;
22789 case NM_P16_4X4:
22790 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22791 extract32(ctx->opcode, 5, 3);
22792 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22793 extract32(ctx->opcode, 0, 3);
22794 rt = decode_gpr_gpr4(rt);
22795 rs = decode_gpr_gpr4(rs);
22796 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22797 (extract32(ctx->opcode, 3, 1))) {
22798 case NM_ADDU4X4:
fb32f8c8 22799 check_nms(ctx);
ea4ca3c2
YK
22800 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22801 break;
22802 case NM_MUL4X4:
fb32f8c8 22803 check_nms(ctx);
ea4ca3c2
YK
22804 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22805 break;
22806 default:
22807 generate_exception_end(ctx, EXCP_RI);
22808 break;
22809 }
22810 break;
22811 case NM_LI16:
8869ad02
YK
22812 {
22813 int imm = extract32(ctx->opcode, 0, 7);
22814 imm = (imm == 0x7f ? -1 : imm);
22815 if (rt != 0) {
22816 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22817 }
22818 }
ea4ca3c2
YK
22819 break;
22820 case NM_ANDI16:
80845edf
YK
22821 {
22822 uint32_t u = extract32(ctx->opcode, 0, 4);
22823 u = (u == 12) ? 0xff :
22824 (u == 13) ? 0xffff : u;
22825 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22826 }
ea4ca3c2
YK
22827 break;
22828 case NM_P16_LB:
8bdb7029
YK
22829 offset = extract32(ctx->opcode, 0, 2);
22830 switch (extract32(ctx->opcode, 2, 2)) {
22831 case NM_LB16:
22832 gen_ld(ctx, OPC_LB, rt, rs, offset);
22833 break;
22834 case NM_SB16:
22835 rt = decode_gpr_gpr3_src_store(
99e49abf 22836 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22837 gen_st(ctx, OPC_SB, rt, rs, offset);
22838 break;
22839 case NM_LBU16:
22840 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22841 break;
22842 default:
22843 generate_exception_end(ctx, EXCP_RI);
22844 break;
22845 }
ea4ca3c2
YK
22846 break;
22847 case NM_P16_LH:
8bdb7029
YK
22848 offset = extract32(ctx->opcode, 1, 2) << 1;
22849 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22850 case NM_LH16:
22851 gen_ld(ctx, OPC_LH, rt, rs, offset);
22852 break;
22853 case NM_SH16:
22854 rt = decode_gpr_gpr3_src_store(
99e49abf 22855 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22856 gen_st(ctx, OPC_SH, rt, rs, offset);
22857 break;
22858 case NM_LHU16:
22859 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22860 break;
22861 default:
22862 generate_exception_end(ctx, EXCP_RI);
22863 break;
22864 }
ea4ca3c2
YK
22865 break;
22866 case NM_LW16:
8bdb7029
YK
22867 offset = extract32(ctx->opcode, 0, 4) << 2;
22868 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22869 break;
22870 case NM_LWSP16:
8bdb7029
YK
22871 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22872 offset = extract32(ctx->opcode, 0, 5) << 2;
22873 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22874 break;
22875 case NM_LW4X4:
fb32f8c8 22876 check_nms(ctx);
8bdb7029
YK
22877 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22878 extract32(ctx->opcode, 5, 3);
22879 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22880 extract32(ctx->opcode, 0, 3);
22881 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22882 (extract32(ctx->opcode, 8, 1) << 2);
22883 rt = decode_gpr_gpr4(rt);
22884 rs = decode_gpr_gpr4(rs);
22885 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22886 break;
22887 case NM_SW4X4:
fb32f8c8 22888 check_nms(ctx);
8bdb7029
YK
22889 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22890 extract32(ctx->opcode, 5, 3);
22891 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22892 extract32(ctx->opcode, 0, 3);
22893 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22894 (extract32(ctx->opcode, 8, 1) << 2);
22895 rt = decode_gpr_gpr4_zero(rt);
22896 rs = decode_gpr_gpr4(rs);
22897 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22898 break;
22899 case NM_LWGP16:
8bdb7029
YK
22900 offset = extract32(ctx->opcode, 0, 7) << 2;
22901 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22902 break;
22903 case NM_SWSP16:
8bdb7029
YK
22904 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22905 offset = extract32(ctx->opcode, 0, 5) << 2;
22906 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22907 break;
22908 case NM_SW16:
8bdb7029 22909 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
22910 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22911 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
22912 offset = extract32(ctx->opcode, 0, 4) << 2;
22913 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22914 break;
22915 case NM_SWGP16:
8bdb7029 22916 rt = decode_gpr_gpr3_src_store(
99e49abf 22917 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
22918 offset = extract32(ctx->opcode, 0, 7) << 2;
22919 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22920 break;
22921 case NM_BC16:
764371d2
SM
22922 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22923 (sextract32(ctx->opcode, 0, 1) << 10) |
22924 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22925 break;
22926 case NM_BALC16:
764371d2
SM
22927 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22928 (sextract32(ctx->opcode, 0, 1) << 10) |
22929 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22930 break;
22931 case NM_BEQZC16:
764371d2
SM
22932 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22933 (sextract32(ctx->opcode, 0, 1) << 7) |
22934 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22935 break;
22936 case NM_BNEZC16:
764371d2
SM
22937 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22938 (sextract32(ctx->opcode, 0, 1) << 7) |
22939 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22940 break;
22941 case NM_P16_BR:
764371d2
SM
22942 switch (ctx->opcode & 0xf) {
22943 case 0:
22944 /* P16.JRC */
22945 switch (extract32(ctx->opcode, 4, 1)) {
22946 case NM_JRC:
22947 gen_compute_branch_nm(ctx, OPC_JR, 2,
22948 extract32(ctx->opcode, 5, 5), 0, 0);
22949 break;
22950 case NM_JALRC16:
22951 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22952 extract32(ctx->opcode, 5, 5), 31, 0);
22953 break;
22954 }
22955 break;
22956 default:
22957 {
22958 /* P16.BRI */
22959 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22960 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22961 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22962 extract32(ctx->opcode, 0, 4) << 1);
22963 }
22964 break;
22965 }
ea4ca3c2
YK
22966 break;
22967 case NM_P16_SR:
bf0718c5
SM
22968 {
22969 int count = extract32(ctx->opcode, 0, 4);
22970 int u = extract32(ctx->opcode, 4, 4) << 4;
22971
22972 rt = 30 + extract32(ctx->opcode, 9, 1);
22973 switch (extract32(ctx->opcode, 8, 1)) {
22974 case NM_SAVE16:
22975 gen_save(ctx, rt, count, 0, u);
22976 break;
22977 case NM_RESTORE_JRC16:
22978 gen_restore(ctx, rt, count, 0, u);
22979 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22980 break;
22981 }
22982 }
ea4ca3c2
YK
22983 break;
22984 case NM_MOVEP:
ea4ca3c2 22985 case NM_MOVEPREV:
fb32f8c8 22986 check_nms(ctx);
4d18232c
YK
22987 {
22988 static const int gpr2reg1[] = {4, 5, 6, 7};
22989 static const int gpr2reg2[] = {5, 6, 7, 8};
22990 int re;
22991 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22992 extract32(ctx->opcode, 8, 1);
22993 int r1 = gpr2reg1[rd2];
22994 int r2 = gpr2reg2[rd2];
22995 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22996 extract32(ctx->opcode, 0, 3);
22997 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22998 extract32(ctx->opcode, 5, 3);
22999 TCGv t0 = tcg_temp_new();
23000 TCGv t1 = tcg_temp_new();
23001 if (op == NM_MOVEP) {
23002 rd = r1;
23003 re = r2;
23004 rs = decode_gpr_gpr4_zero(r3);
23005 rt = decode_gpr_gpr4_zero(r4);
23006 } else {
23007 rd = decode_gpr_gpr4(r3);
23008 re = decode_gpr_gpr4(r4);
23009 rs = r1;
23010 rt = r2;
23011 }
23012 gen_load_gpr(t0, rs);
23013 gen_load_gpr(t1, rt);
23014 tcg_gen_mov_tl(cpu_gpr[rd], t0);
23015 tcg_gen_mov_tl(cpu_gpr[re], t1);
23016 tcg_temp_free(t0);
23017 tcg_temp_free(t1);
23018 }
ea4ca3c2
YK
23019 break;
23020 default:
c0280983 23021 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
23022 }
23023
c533c0f4
AM
23024 return 2;
23025}
23026
23027
3c824109
NF
23028/* SmartMIPS extension to MIPS32 */
23029
23030#if defined(TARGET_MIPS64)
23031
23032/* MDMX extension to MIPS64 */
23033
23034#endif
23035
9b1a1d68 23036/* MIPSDSP functions. */
d75c135e 23037static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
23038 int rd, int base, int offset)
23039{
9b1a1d68
JL
23040 TCGv t0;
23041
9b1a1d68
JL
23042 check_dsp(ctx);
23043 t0 = tcg_temp_new();
23044
23045 if (base == 0) {
23046 gen_load_gpr(t0, offset);
23047 } else if (offset == 0) {
23048 gen_load_gpr(t0, base);
23049 } else {
23050 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
23051 }
23052
9b1a1d68
JL
23053 switch (opc) {
23054 case OPC_LBUX:
5f68f5ae 23055 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 23056 gen_store_gpr(t0, rd);
9b1a1d68
JL
23057 break;
23058 case OPC_LHX:
5f68f5ae 23059 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 23060 gen_store_gpr(t0, rd);
9b1a1d68
JL
23061 break;
23062 case OPC_LWX:
5f68f5ae 23063 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 23064 gen_store_gpr(t0, rd);
9b1a1d68
JL
23065 break;
23066#if defined(TARGET_MIPS64)
23067 case OPC_LDX:
5f68f5ae 23068 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 23069 gen_store_gpr(t0, rd);
9b1a1d68
JL
23070 break;
23071#endif
23072 }
9b1a1d68
JL
23073 tcg_temp_free(t0);
23074}
23075
461c08df
JL
23076static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
23077 int ret, int v1, int v2)
23078{
461c08df
JL
23079 TCGv v1_t;
23080 TCGv v2_t;
23081
23082 if (ret == 0) {
23083 /* Treat as NOP. */
461c08df
JL
23084 return;
23085 }
23086
23087 v1_t = tcg_temp_new();
23088 v2_t = tcg_temp_new();
23089
23090 gen_load_gpr(v1_t, v1);
23091 gen_load_gpr(v2_t, v2);
23092
23093 switch (op1) {
23094 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
23095 case OPC_MULT_G_2E:
908f6be1 23096 check_dsp_r2(ctx);
461c08df
JL
23097 switch (op2) {
23098 case OPC_ADDUH_QB:
23099 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
23100 break;
23101 case OPC_ADDUH_R_QB:
23102 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23103 break;
23104 case OPC_ADDQH_PH:
23105 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
23106 break;
23107 case OPC_ADDQH_R_PH:
23108 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23109 break;
23110 case OPC_ADDQH_W:
23111 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
23112 break;
23113 case OPC_ADDQH_R_W:
23114 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23115 break;
23116 case OPC_SUBUH_QB:
23117 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
23118 break;
23119 case OPC_SUBUH_R_QB:
23120 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23121 break;
23122 case OPC_SUBQH_PH:
23123 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
23124 break;
23125 case OPC_SUBQH_R_PH:
23126 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23127 break;
23128 case OPC_SUBQH_W:
23129 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23130 break;
23131 case OPC_SUBQH_R_W:
23132 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23133 break;
23134 }
23135 break;
23136 case OPC_ABSQ_S_PH_DSP:
23137 switch (op2) {
23138 case OPC_ABSQ_S_QB:
908f6be1 23139 check_dsp_r2(ctx);
461c08df
JL
23140 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23141 break;
23142 case OPC_ABSQ_S_PH:
23143 check_dsp(ctx);
23144 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23145 break;
23146 case OPC_ABSQ_S_W:
23147 check_dsp(ctx);
23148 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23149 break;
23150 case OPC_PRECEQ_W_PHL:
23151 check_dsp(ctx);
23152 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23153 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23154 break;
23155 case OPC_PRECEQ_W_PHR:
23156 check_dsp(ctx);
23157 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23158 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23159 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23160 break;
23161 case OPC_PRECEQU_PH_QBL:
23162 check_dsp(ctx);
23163 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23164 break;
23165 case OPC_PRECEQU_PH_QBR:
23166 check_dsp(ctx);
23167 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23168 break;
23169 case OPC_PRECEQU_PH_QBLA:
23170 check_dsp(ctx);
23171 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23172 break;
23173 case OPC_PRECEQU_PH_QBRA:
23174 check_dsp(ctx);
23175 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23176 break;
23177 case OPC_PRECEU_PH_QBL:
23178 check_dsp(ctx);
23179 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23180 break;
23181 case OPC_PRECEU_PH_QBR:
23182 check_dsp(ctx);
23183 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23184 break;
23185 case OPC_PRECEU_PH_QBLA:
23186 check_dsp(ctx);
23187 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23188 break;
23189 case OPC_PRECEU_PH_QBRA:
23190 check_dsp(ctx);
23191 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23192 break;
23193 }
23194 break;
23195 case OPC_ADDU_QB_DSP:
23196 switch (op2) {
23197 case OPC_ADDQ_PH:
23198 check_dsp(ctx);
23199 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23200 break;
23201 case OPC_ADDQ_S_PH:
23202 check_dsp(ctx);
23203 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23204 break;
23205 case OPC_ADDQ_S_W:
23206 check_dsp(ctx);
23207 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23208 break;
23209 case OPC_ADDU_QB:
23210 check_dsp(ctx);
23211 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23212 break;
23213 case OPC_ADDU_S_QB:
23214 check_dsp(ctx);
23215 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23216 break;
23217 case OPC_ADDU_PH:
908f6be1 23218 check_dsp_r2(ctx);
461c08df
JL
23219 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23220 break;
23221 case OPC_ADDU_S_PH:
908f6be1 23222 check_dsp_r2(ctx);
461c08df
JL
23223 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_SUBQ_PH:
23226 check_dsp(ctx);
23227 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_SUBQ_S_PH:
23230 check_dsp(ctx);
23231 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_SUBQ_S_W:
23234 check_dsp(ctx);
23235 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_SUBU_QB:
23238 check_dsp(ctx);
23239 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23240 break;
23241 case OPC_SUBU_S_QB:
23242 check_dsp(ctx);
23243 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23244 break;
23245 case OPC_SUBU_PH:
908f6be1 23246 check_dsp_r2(ctx);
461c08df
JL
23247 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23248 break;
23249 case OPC_SUBU_S_PH:
908f6be1 23250 check_dsp_r2(ctx);
461c08df
JL
23251 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23252 break;
23253 case OPC_ADDSC:
23254 check_dsp(ctx);
23255 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23256 break;
23257 case OPC_ADDWC:
23258 check_dsp(ctx);
23259 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_MODSUB:
23262 check_dsp(ctx);
23263 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23264 break;
23265 case OPC_RADDU_W_QB:
23266 check_dsp(ctx);
23267 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23268 break;
23269 }
23270 break;
23271 case OPC_CMPU_EQ_QB_DSP:
23272 switch (op2) {
23273 case OPC_PRECR_QB_PH:
908f6be1 23274 check_dsp_r2(ctx);
461c08df
JL
23275 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23276 break;
23277 case OPC_PRECRQ_QB_PH:
23278 check_dsp(ctx);
23279 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23280 break;
23281 case OPC_PRECR_SRA_PH_W:
908f6be1 23282 check_dsp_r2(ctx);
461c08df
JL
23283 {
23284 TCGv_i32 sa_t = tcg_const_i32(v2);
23285 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23286 cpu_gpr[ret]);
23287 tcg_temp_free_i32(sa_t);
23288 break;
23289 }
23290 case OPC_PRECR_SRA_R_PH_W:
908f6be1 23291 check_dsp_r2(ctx);
461c08df
JL
23292 {
23293 TCGv_i32 sa_t = tcg_const_i32(v2);
23294 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23295 cpu_gpr[ret]);
23296 tcg_temp_free_i32(sa_t);
23297 break;
23298 }
23299 case OPC_PRECRQ_PH_W:
23300 check_dsp(ctx);
23301 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23302 break;
23303 case OPC_PRECRQ_RS_PH_W:
23304 check_dsp(ctx);
23305 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23306 break;
23307 case OPC_PRECRQU_S_QB_PH:
23308 check_dsp(ctx);
23309 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23310 break;
23311 }
23312 break;
23313#ifdef TARGET_MIPS64
23314 case OPC_ABSQ_S_QH_DSP:
23315 switch (op2) {
23316 case OPC_PRECEQ_L_PWL:
23317 check_dsp(ctx);
23318 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23319 break;
23320 case OPC_PRECEQ_L_PWR:
23321 check_dsp(ctx);
23322 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23323 break;
23324 case OPC_PRECEQ_PW_QHL:
23325 check_dsp(ctx);
23326 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23327 break;
23328 case OPC_PRECEQ_PW_QHR:
23329 check_dsp(ctx);
23330 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23331 break;
23332 case OPC_PRECEQ_PW_QHLA:
23333 check_dsp(ctx);
23334 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23335 break;
23336 case OPC_PRECEQ_PW_QHRA:
23337 check_dsp(ctx);
23338 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23339 break;
23340 case OPC_PRECEQU_QH_OBL:
23341 check_dsp(ctx);
23342 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23343 break;
23344 case OPC_PRECEQU_QH_OBR:
23345 check_dsp(ctx);
23346 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23347 break;
23348 case OPC_PRECEQU_QH_OBLA:
23349 check_dsp(ctx);
23350 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23351 break;
23352 case OPC_PRECEQU_QH_OBRA:
23353 check_dsp(ctx);
23354 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23355 break;
23356 case OPC_PRECEU_QH_OBL:
23357 check_dsp(ctx);
23358 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23359 break;
23360 case OPC_PRECEU_QH_OBR:
23361 check_dsp(ctx);
23362 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23363 break;
23364 case OPC_PRECEU_QH_OBLA:
23365 check_dsp(ctx);
23366 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23367 break;
23368 case OPC_PRECEU_QH_OBRA:
23369 check_dsp(ctx);
23370 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23371 break;
23372 case OPC_ABSQ_S_OB:
908f6be1 23373 check_dsp_r2(ctx);
461c08df
JL
23374 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23375 break;
23376 case OPC_ABSQ_S_PW:
23377 check_dsp(ctx);
23378 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23379 break;
23380 case OPC_ABSQ_S_QH:
23381 check_dsp(ctx);
23382 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23383 break;
23384 }
23385 break;
23386 case OPC_ADDU_OB_DSP:
23387 switch (op2) {
23388 case OPC_RADDU_L_OB:
23389 check_dsp(ctx);
23390 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23391 break;
23392 case OPC_SUBQ_PW:
23393 check_dsp(ctx);
23394 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23395 break;
23396 case OPC_SUBQ_S_PW:
23397 check_dsp(ctx);
23398 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23399 break;
23400 case OPC_SUBQ_QH:
23401 check_dsp(ctx);
23402 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23403 break;
23404 case OPC_SUBQ_S_QH:
23405 check_dsp(ctx);
23406 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23407 break;
23408 case OPC_SUBU_OB:
23409 check_dsp(ctx);
23410 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23411 break;
23412 case OPC_SUBU_S_OB:
23413 check_dsp(ctx);
23414 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23415 break;
23416 case OPC_SUBU_QH:
908f6be1 23417 check_dsp_r2(ctx);
461c08df
JL
23418 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23419 break;
23420 case OPC_SUBU_S_QH:
908f6be1 23421 check_dsp_r2(ctx);
461c08df
JL
23422 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23423 break;
23424 case OPC_SUBUH_OB:
908f6be1 23425 check_dsp_r2(ctx);
461c08df
JL
23426 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23427 break;
23428 case OPC_SUBUH_R_OB:
908f6be1 23429 check_dsp_r2(ctx);
461c08df
JL
23430 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23431 break;
23432 case OPC_ADDQ_PW:
23433 check_dsp(ctx);
23434 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23435 break;
23436 case OPC_ADDQ_S_PW:
23437 check_dsp(ctx);
23438 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_ADDQ_QH:
23441 check_dsp(ctx);
23442 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_ADDQ_S_QH:
23445 check_dsp(ctx);
23446 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_ADDU_OB:
23449 check_dsp(ctx);
23450 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23451 break;
23452 case OPC_ADDU_S_OB:
23453 check_dsp(ctx);
23454 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23455 break;
23456 case OPC_ADDU_QH:
908f6be1 23457 check_dsp_r2(ctx);
461c08df
JL
23458 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23459 break;
23460 case OPC_ADDU_S_QH:
908f6be1 23461 check_dsp_r2(ctx);
461c08df
JL
23462 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23463 break;
23464 case OPC_ADDUH_OB:
908f6be1 23465 check_dsp_r2(ctx);
461c08df
JL
23466 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23467 break;
23468 case OPC_ADDUH_R_OB:
908f6be1 23469 check_dsp_r2(ctx);
461c08df
JL
23470 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23471 break;
23472 }
23473 break;
23474 case OPC_CMPU_EQ_OB_DSP:
23475 switch (op2) {
23476 case OPC_PRECR_OB_QH:
908f6be1 23477 check_dsp_r2(ctx);
461c08df
JL
23478 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23479 break;
23480 case OPC_PRECR_SRA_QH_PW:
908f6be1 23481 check_dsp_r2(ctx);
461c08df
JL
23482 {
23483 TCGv_i32 ret_t = tcg_const_i32(ret);
23484 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23485 tcg_temp_free_i32(ret_t);
23486 break;
23487 }
23488 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 23489 check_dsp_r2(ctx);
461c08df
JL
23490 {
23491 TCGv_i32 sa_v = tcg_const_i32(ret);
23492 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23493 tcg_temp_free_i32(sa_v);
23494 break;
23495 }
23496 case OPC_PRECRQ_OB_QH:
23497 check_dsp(ctx);
23498 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23499 break;
23500 case OPC_PRECRQ_PW_L:
23501 check_dsp(ctx);
23502 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23503 break;
23504 case OPC_PRECRQ_QH_PW:
23505 check_dsp(ctx);
23506 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23507 break;
23508 case OPC_PRECRQ_RS_QH_PW:
23509 check_dsp(ctx);
23510 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23511 break;
23512 case OPC_PRECRQU_S_OB_QH:
23513 check_dsp(ctx);
23514 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23515 break;
23516 }
23517 break;
23518#endif
23519 }
23520
23521 tcg_temp_free(v1_t);
23522 tcg_temp_free(v2_t);
461c08df 23523}
9b1a1d68 23524
77c5fa8b
JL
23525static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23526 int ret, int v1, int v2)
23527{
23528 uint32_t op2;
77c5fa8b
JL
23529 TCGv t0;
23530 TCGv v1_t;
23531 TCGv v2_t;
23532
23533 if (ret == 0) {
23534 /* Treat as NOP. */
77c5fa8b
JL
23535 return;
23536 }
23537
23538 t0 = tcg_temp_new();
23539 v1_t = tcg_temp_new();
23540 v2_t = tcg_temp_new();
23541
23542 tcg_gen_movi_tl(t0, v1);
23543 gen_load_gpr(v1_t, v1);
23544 gen_load_gpr(v2_t, v2);
23545
23546 switch (opc) {
23547 case OPC_SHLL_QB_DSP:
23548 {
23549 op2 = MASK_SHLL_QB(ctx->opcode);
23550 switch (op2) {
23551 case OPC_SHLL_QB:
23552 check_dsp(ctx);
23553 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23554 break;
23555 case OPC_SHLLV_QB:
23556 check_dsp(ctx);
23557 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23558 break;
23559 case OPC_SHLL_PH:
23560 check_dsp(ctx);
23561 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23562 break;
23563 case OPC_SHLLV_PH:
23564 check_dsp(ctx);
23565 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23566 break;
23567 case OPC_SHLL_S_PH:
23568 check_dsp(ctx);
23569 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23570 break;
23571 case OPC_SHLLV_S_PH:
23572 check_dsp(ctx);
23573 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23574 break;
23575 case OPC_SHLL_S_W:
23576 check_dsp(ctx);
23577 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23578 break;
23579 case OPC_SHLLV_S_W:
23580 check_dsp(ctx);
23581 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23582 break;
23583 case OPC_SHRL_QB:
23584 check_dsp(ctx);
23585 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23586 break;
23587 case OPC_SHRLV_QB:
23588 check_dsp(ctx);
23589 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23590 break;
23591 case OPC_SHRL_PH:
908f6be1 23592 check_dsp_r2(ctx);
77c5fa8b
JL
23593 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23594 break;
23595 case OPC_SHRLV_PH:
908f6be1 23596 check_dsp_r2(ctx);
77c5fa8b
JL
23597 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23598 break;
23599 case OPC_SHRA_QB:
908f6be1 23600 check_dsp_r2(ctx);
77c5fa8b
JL
23601 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23602 break;
23603 case OPC_SHRA_R_QB:
908f6be1 23604 check_dsp_r2(ctx);
77c5fa8b
JL
23605 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23606 break;
23607 case OPC_SHRAV_QB:
908f6be1 23608 check_dsp_r2(ctx);
77c5fa8b
JL
23609 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23610 break;
23611 case OPC_SHRAV_R_QB:
908f6be1 23612 check_dsp_r2(ctx);
77c5fa8b
JL
23613 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23614 break;
23615 case OPC_SHRA_PH:
23616 check_dsp(ctx);
23617 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23618 break;
23619 case OPC_SHRA_R_PH:
23620 check_dsp(ctx);
23621 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23622 break;
23623 case OPC_SHRAV_PH:
23624 check_dsp(ctx);
23625 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23626 break;
23627 case OPC_SHRAV_R_PH:
23628 check_dsp(ctx);
23629 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23630 break;
23631 case OPC_SHRA_R_W:
23632 check_dsp(ctx);
23633 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23634 break;
23635 case OPC_SHRAV_R_W:
23636 check_dsp(ctx);
23637 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23638 break;
23639 default: /* Invalid */
23640 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 23641 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23642 break;
23643 }
23644 break;
23645 }
23646#ifdef TARGET_MIPS64
23647 case OPC_SHLL_OB_DSP:
23648 op2 = MASK_SHLL_OB(ctx->opcode);
23649 switch (op2) {
23650 case OPC_SHLL_PW:
23651 check_dsp(ctx);
23652 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23653 break;
23654 case OPC_SHLLV_PW:
23655 check_dsp(ctx);
23656 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23657 break;
23658 case OPC_SHLL_S_PW:
23659 check_dsp(ctx);
23660 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23661 break;
23662 case OPC_SHLLV_S_PW:
23663 check_dsp(ctx);
23664 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23665 break;
23666 case OPC_SHLL_OB:
23667 check_dsp(ctx);
23668 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23669 break;
23670 case OPC_SHLLV_OB:
23671 check_dsp(ctx);
23672 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23673 break;
23674 case OPC_SHLL_QH:
23675 check_dsp(ctx);
23676 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23677 break;
23678 case OPC_SHLLV_QH:
23679 check_dsp(ctx);
23680 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23681 break;
23682 case OPC_SHLL_S_QH:
23683 check_dsp(ctx);
23684 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23685 break;
23686 case OPC_SHLLV_S_QH:
23687 check_dsp(ctx);
23688 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23689 break;
23690 case OPC_SHRA_OB:
908f6be1 23691 check_dsp_r2(ctx);
77c5fa8b
JL
23692 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23693 break;
23694 case OPC_SHRAV_OB:
908f6be1 23695 check_dsp_r2(ctx);
77c5fa8b
JL
23696 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23697 break;
23698 case OPC_SHRA_R_OB:
908f6be1 23699 check_dsp_r2(ctx);
77c5fa8b
JL
23700 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23701 break;
23702 case OPC_SHRAV_R_OB:
908f6be1 23703 check_dsp_r2(ctx);
77c5fa8b
JL
23704 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23705 break;
23706 case OPC_SHRA_PW:
23707 check_dsp(ctx);
23708 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23709 break;
23710 case OPC_SHRAV_PW:
23711 check_dsp(ctx);
23712 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23713 break;
23714 case OPC_SHRA_R_PW:
23715 check_dsp(ctx);
23716 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23717 break;
23718 case OPC_SHRAV_R_PW:
23719 check_dsp(ctx);
23720 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23721 break;
23722 case OPC_SHRA_QH:
23723 check_dsp(ctx);
23724 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23725 break;
23726 case OPC_SHRAV_QH:
23727 check_dsp(ctx);
23728 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23729 break;
23730 case OPC_SHRA_R_QH:
23731 check_dsp(ctx);
23732 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23733 break;
23734 case OPC_SHRAV_R_QH:
23735 check_dsp(ctx);
23736 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23737 break;
23738 case OPC_SHRL_OB:
23739 check_dsp(ctx);
23740 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23741 break;
23742 case OPC_SHRLV_OB:
23743 check_dsp(ctx);
23744 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23745 break;
23746 case OPC_SHRL_QH:
908f6be1 23747 check_dsp_r2(ctx);
77c5fa8b
JL
23748 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23749 break;
23750 case OPC_SHRLV_QH:
908f6be1 23751 check_dsp_r2(ctx);
77c5fa8b
JL
23752 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23753 break;
23754 default: /* Invalid */
23755 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 23756 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
23757 break;
23758 }
23759 break;
23760#endif
23761 }
23762
23763 tcg_temp_free(t0);
23764 tcg_temp_free(v1_t);
23765 tcg_temp_free(v2_t);
77c5fa8b
JL
23766}
23767
a22260ae
JL
23768static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23769 int ret, int v1, int v2, int check_ret)
23770{
a22260ae
JL
23771 TCGv_i32 t0;
23772 TCGv v1_t;
23773 TCGv v2_t;
23774
23775 if ((ret == 0) && (check_ret == 1)) {
23776 /* Treat as NOP. */
a22260ae
JL
23777 return;
23778 }
23779
23780 t0 = tcg_temp_new_i32();
23781 v1_t = tcg_temp_new();
23782 v2_t = tcg_temp_new();
23783
23784 tcg_gen_movi_i32(t0, ret);
23785 gen_load_gpr(v1_t, v1);
23786 gen_load_gpr(v2_t, v2);
23787
23788 switch (op1) {
7480515f
AM
23789 /*
23790 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23791 * the same mask and op1.
23792 */
a22260ae 23793 case OPC_MULT_G_2E:
908f6be1 23794 check_dsp_r2(ctx);
a22260ae
JL
23795 switch (op2) {
23796 case OPC_MUL_PH:
23797 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23798 break;
23799 case OPC_MUL_S_PH:
23800 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23801 break;
23802 case OPC_MULQ_S_W:
23803 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23804 break;
23805 case OPC_MULQ_RS_W:
23806 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23807 break;
23808 }
23809 break;
23810 case OPC_DPA_W_PH_DSP:
23811 switch (op2) {
23812 case OPC_DPAU_H_QBL:
23813 check_dsp(ctx);
23814 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23815 break;
23816 case OPC_DPAU_H_QBR:
23817 check_dsp(ctx);
23818 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23819 break;
23820 case OPC_DPSU_H_QBL:
23821 check_dsp(ctx);
23822 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23823 break;
23824 case OPC_DPSU_H_QBR:
23825 check_dsp(ctx);
23826 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23827 break;
23828 case OPC_DPA_W_PH:
908f6be1 23829 check_dsp_r2(ctx);
a22260ae
JL
23830 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23831 break;
23832 case OPC_DPAX_W_PH:
908f6be1 23833 check_dsp_r2(ctx);
a22260ae
JL
23834 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_DPAQ_S_W_PH:
23837 check_dsp(ctx);
23838 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23839 break;
23840 case OPC_DPAQX_S_W_PH:
908f6be1 23841 check_dsp_r2(ctx);
a22260ae
JL
23842 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23843 break;
23844 case OPC_DPAQX_SA_W_PH:
908f6be1 23845 check_dsp_r2(ctx);
a22260ae
JL
23846 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23847 break;
23848 case OPC_DPS_W_PH:
908f6be1 23849 check_dsp_r2(ctx);
a22260ae
JL
23850 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23851 break;
23852 case OPC_DPSX_W_PH:
908f6be1 23853 check_dsp_r2(ctx);
a22260ae
JL
23854 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23855 break;
23856 case OPC_DPSQ_S_W_PH:
23857 check_dsp(ctx);
23858 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23859 break;
23860 case OPC_DPSQX_S_W_PH:
908f6be1 23861 check_dsp_r2(ctx);
a22260ae
JL
23862 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23863 break;
23864 case OPC_DPSQX_SA_W_PH:
908f6be1 23865 check_dsp_r2(ctx);
a22260ae
JL
23866 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_MULSAQ_S_W_PH:
23869 check_dsp(ctx);
23870 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_DPAQ_SA_L_W:
23873 check_dsp(ctx);
23874 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23875 break;
23876 case OPC_DPSQ_SA_L_W:
23877 check_dsp(ctx);
23878 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23879 break;
23880 case OPC_MAQ_S_W_PHL:
23881 check_dsp(ctx);
23882 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23883 break;
23884 case OPC_MAQ_S_W_PHR:
23885 check_dsp(ctx);
23886 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23887 break;
23888 case OPC_MAQ_SA_W_PHL:
23889 check_dsp(ctx);
23890 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23891 break;
23892 case OPC_MAQ_SA_W_PHR:
23893 check_dsp(ctx);
23894 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23895 break;
23896 case OPC_MULSA_W_PH:
908f6be1 23897 check_dsp_r2(ctx);
a22260ae
JL
23898 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23899 break;
23900 }
23901 break;
23902#ifdef TARGET_MIPS64
23903 case OPC_DPAQ_W_QH_DSP:
23904 {
23905 int ac = ret & 0x03;
23906 tcg_gen_movi_i32(t0, ac);
23907
23908 switch (op2) {
23909 case OPC_DMADD:
23910 check_dsp(ctx);
23911 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23912 break;
23913 case OPC_DMADDU:
23914 check_dsp(ctx);
23915 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23916 break;
23917 case OPC_DMSUB:
23918 check_dsp(ctx);
23919 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23920 break;
23921 case OPC_DMSUBU:
23922 check_dsp(ctx);
23923 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23924 break;
23925 case OPC_DPA_W_QH:
908f6be1 23926 check_dsp_r2(ctx);
a22260ae
JL
23927 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23928 break;
23929 case OPC_DPAQ_S_W_QH:
23930 check_dsp(ctx);
23931 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23932 break;
23933 case OPC_DPAQ_SA_L_PW:
23934 check_dsp(ctx);
23935 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23936 break;
23937 case OPC_DPAU_H_OBL:
23938 check_dsp(ctx);
23939 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23940 break;
23941 case OPC_DPAU_H_OBR:
23942 check_dsp(ctx);
23943 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23944 break;
23945 case OPC_DPS_W_QH:
908f6be1 23946 check_dsp_r2(ctx);
a22260ae
JL
23947 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23948 break;
23949 case OPC_DPSQ_S_W_QH:
23950 check_dsp(ctx);
23951 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23952 break;
23953 case OPC_DPSQ_SA_L_PW:
23954 check_dsp(ctx);
23955 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23956 break;
23957 case OPC_DPSU_H_OBL:
23958 check_dsp(ctx);
23959 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23960 break;
23961 case OPC_DPSU_H_OBR:
23962 check_dsp(ctx);
23963 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23964 break;
23965 case OPC_MAQ_S_L_PWL:
23966 check_dsp(ctx);
23967 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23968 break;
23969 case OPC_MAQ_S_L_PWR:
23970 check_dsp(ctx);
23971 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23972 break;
23973 case OPC_MAQ_S_W_QHLL:
23974 check_dsp(ctx);
23975 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23976 break;
23977 case OPC_MAQ_SA_W_QHLL:
23978 check_dsp(ctx);
23979 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23980 break;
23981 case OPC_MAQ_S_W_QHLR:
23982 check_dsp(ctx);
23983 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23984 break;
23985 case OPC_MAQ_SA_W_QHLR:
23986 check_dsp(ctx);
23987 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23988 break;
23989 case OPC_MAQ_S_W_QHRL:
23990 check_dsp(ctx);
23991 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23992 break;
23993 case OPC_MAQ_SA_W_QHRL:
23994 check_dsp(ctx);
23995 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23996 break;
23997 case OPC_MAQ_S_W_QHRR:
23998 check_dsp(ctx);
23999 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
24000 break;
24001 case OPC_MAQ_SA_W_QHRR:
24002 check_dsp(ctx);
24003 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
24004 break;
24005 case OPC_MULSAQ_S_L_PW:
24006 check_dsp(ctx);
24007 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
24008 break;
24009 case OPC_MULSAQ_S_W_QH:
24010 check_dsp(ctx);
24011 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
24012 break;
24013 }
24014 }
24015 break;
24016#endif
24017 case OPC_ADDU_QB_DSP:
24018 switch (op2) {
24019 case OPC_MULEU_S_PH_QBL:
24020 check_dsp(ctx);
24021 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24022 break;
24023 case OPC_MULEU_S_PH_QBR:
24024 check_dsp(ctx);
24025 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24026 break;
24027 case OPC_MULQ_RS_PH:
24028 check_dsp(ctx);
24029 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24030 break;
24031 case OPC_MULEQ_S_W_PHL:
24032 check_dsp(ctx);
24033 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24034 break;
24035 case OPC_MULEQ_S_W_PHR:
24036 check_dsp(ctx);
24037 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24038 break;
24039 case OPC_MULQ_S_PH:
908f6be1 24040 check_dsp_r2(ctx);
a22260ae
JL
24041 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24042 break;
24043 }
24044 break;
24045#ifdef TARGET_MIPS64
24046 case OPC_ADDU_OB_DSP:
24047 switch (op2) {
24048 case OPC_MULEQ_S_PW_QHL:
24049 check_dsp(ctx);
24050 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24051 break;
24052 case OPC_MULEQ_S_PW_QHR:
24053 check_dsp(ctx);
24054 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24055 break;
24056 case OPC_MULEU_S_QH_OBL:
24057 check_dsp(ctx);
24058 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24059 break;
24060 case OPC_MULEU_S_QH_OBR:
24061 check_dsp(ctx);
24062 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24063 break;
24064 case OPC_MULQ_RS_QH:
24065 check_dsp(ctx);
24066 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24067 break;
24068 }
24069 break;
24070#endif
24071 }
24072
24073 tcg_temp_free_i32(t0);
24074 tcg_temp_free(v1_t);
24075 tcg_temp_free(v2_t);
a22260ae
JL
24076}
24077
d75c135e 24078static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
24079 int ret, int val)
24080{
1cb6686c
JL
24081 int16_t imm;
24082 TCGv t0;
24083 TCGv val_t;
24084
24085 if (ret == 0) {
24086 /* Treat as NOP. */
1cb6686c
JL
24087 return;
24088 }
24089
24090 t0 = tcg_temp_new();
24091 val_t = tcg_temp_new();
24092 gen_load_gpr(val_t, val);
24093
24094 switch (op1) {
24095 case OPC_ABSQ_S_PH_DSP:
24096 switch (op2) {
24097 case OPC_BITREV:
24098 check_dsp(ctx);
24099 gen_helper_bitrev(cpu_gpr[ret], val_t);
24100 break;
24101 case OPC_REPL_QB:
24102 check_dsp(ctx);
24103 {
24104 target_long result;
24105 imm = (ctx->opcode >> 16) & 0xFF;
24106 result = (uint32_t)imm << 24 |
24107 (uint32_t)imm << 16 |
24108 (uint32_t)imm << 8 |
24109 (uint32_t)imm;
24110 result = (int32_t)result;
24111 tcg_gen_movi_tl(cpu_gpr[ret], result);
24112 }
24113 break;
24114 case OPC_REPLV_QB:
24115 check_dsp(ctx);
24116 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24117 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24118 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24119 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24120 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24121 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24122 break;
24123 case OPC_REPL_PH:
24124 check_dsp(ctx);
24125 {
24126 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 24127 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
24128 tcg_gen_movi_tl(cpu_gpr[ret], \
24129 (target_long)((int32_t)imm << 16 | \
c4aaba92 24130 (uint16_t)imm));
1cb6686c
JL
24131 }
24132 break;
24133 case OPC_REPLV_PH:
24134 check_dsp(ctx);
24135 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24136 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24137 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24138 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24139 break;
24140 }
24141 break;
24142#ifdef TARGET_MIPS64
24143 case OPC_ABSQ_S_QH_DSP:
24144 switch (op2) {
24145 case OPC_REPL_OB:
24146 check_dsp(ctx);
24147 {
24148 target_long temp;
24149
24150 imm = (ctx->opcode >> 16) & 0xFF;
24151 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24152 temp = (temp << 16) | temp;
24153 temp = (temp << 32) | temp;
24154 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24155 break;
24156 }
24157 case OPC_REPL_PW:
24158 check_dsp(ctx);
24159 {
24160 target_long temp;
24161
24162 imm = (ctx->opcode >> 16) & 0x03FF;
24163 imm = (int16_t)(imm << 6) >> 6;
24164 temp = ((target_long)imm << 32) \
24165 | ((target_long)imm & 0xFFFFFFFF);
24166 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24167 break;
24168 }
24169 case OPC_REPL_QH:
24170 check_dsp(ctx);
24171 {
24172 target_long temp;
24173
24174 imm = (ctx->opcode >> 16) & 0x03FF;
24175 imm = (int16_t)(imm << 6) >> 6;
24176
24177 temp = ((uint64_t)(uint16_t)imm << 48) |
24178 ((uint64_t)(uint16_t)imm << 32) |
24179 ((uint64_t)(uint16_t)imm << 16) |
24180 (uint64_t)(uint16_t)imm;
24181 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24182 break;
24183 }
24184 case OPC_REPLV_OB:
24185 check_dsp(ctx);
24186 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24187 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24188 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24189 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24190 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24191 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24192 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24193 break;
24194 case OPC_REPLV_PW:
24195 check_dsp(ctx);
24196 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24197 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24198 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24199 break;
24200 case OPC_REPLV_QH:
24201 check_dsp(ctx);
24202 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24203 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24204 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24205 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24206 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24207 break;
24208 }
24209 break;
24210#endif
24211 }
24212 tcg_temp_free(t0);
24213 tcg_temp_free(val_t);
1cb6686c
JL
24214}
24215
26690560
JL
24216static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24217 uint32_t op1, uint32_t op2,
24218 int ret, int v1, int v2, int check_ret)
24219{
26690560
JL
24220 TCGv t1;
24221 TCGv v1_t;
24222 TCGv v2_t;
24223
24224 if ((ret == 0) && (check_ret == 1)) {
24225 /* Treat as NOP. */
26690560
JL
24226 return;
24227 }
24228
26690560
JL
24229 t1 = tcg_temp_new();
24230 v1_t = tcg_temp_new();
24231 v2_t = tcg_temp_new();
24232
24233 gen_load_gpr(v1_t, v1);
24234 gen_load_gpr(v2_t, v2);
24235
24236 switch (op1) {
26690560
JL
24237 case OPC_CMPU_EQ_QB_DSP:
24238 switch (op2) {
24239 case OPC_CMPU_EQ_QB:
24240 check_dsp(ctx);
24241 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24242 break;
24243 case OPC_CMPU_LT_QB:
24244 check_dsp(ctx);
24245 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24246 break;
24247 case OPC_CMPU_LE_QB:
24248 check_dsp(ctx);
24249 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24250 break;
24251 case OPC_CMPGU_EQ_QB:
24252 check_dsp(ctx);
24253 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24254 break;
24255 case OPC_CMPGU_LT_QB:
24256 check_dsp(ctx);
24257 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24258 break;
24259 case OPC_CMPGU_LE_QB:
24260 check_dsp(ctx);
24261 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24262 break;
24263 case OPC_CMPGDU_EQ_QB:
908f6be1 24264 check_dsp_r2(ctx);
26690560
JL
24265 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24266 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24267 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24268 tcg_gen_shli_tl(t1, t1, 24);
24269 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24270 break;
24271 case OPC_CMPGDU_LT_QB:
908f6be1 24272 check_dsp_r2(ctx);
26690560
JL
24273 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24274 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24275 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24276 tcg_gen_shli_tl(t1, t1, 24);
24277 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24278 break;
24279 case OPC_CMPGDU_LE_QB:
908f6be1 24280 check_dsp_r2(ctx);
26690560
JL
24281 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24282 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24283 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24284 tcg_gen_shli_tl(t1, t1, 24);
24285 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24286 break;
24287 case OPC_CMP_EQ_PH:
24288 check_dsp(ctx);
24289 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24290 break;
24291 case OPC_CMP_LT_PH:
24292 check_dsp(ctx);
24293 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24294 break;
24295 case OPC_CMP_LE_PH:
24296 check_dsp(ctx);
24297 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24298 break;
24299 case OPC_PICK_QB:
24300 check_dsp(ctx);
24301 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24302 break;
24303 case OPC_PICK_PH:
24304 check_dsp(ctx);
24305 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24306 break;
24307 case OPC_PACKRL_PH:
24308 check_dsp(ctx);
24309 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24310 break;
24311 }
24312 break;
24313#ifdef TARGET_MIPS64
24314 case OPC_CMPU_EQ_OB_DSP:
24315 switch (op2) {
24316 case OPC_CMP_EQ_PW:
24317 check_dsp(ctx);
24318 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24319 break;
24320 case OPC_CMP_LT_PW:
24321 check_dsp(ctx);
24322 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24323 break;
24324 case OPC_CMP_LE_PW:
24325 check_dsp(ctx);
24326 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24327 break;
24328 case OPC_CMP_EQ_QH:
24329 check_dsp(ctx);
24330 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24331 break;
24332 case OPC_CMP_LT_QH:
24333 check_dsp(ctx);
24334 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24335 break;
24336 case OPC_CMP_LE_QH:
24337 check_dsp(ctx);
24338 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24339 break;
24340 case OPC_CMPGDU_EQ_OB:
908f6be1 24341 check_dsp_r2(ctx);
26690560
JL
24342 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24343 break;
24344 case OPC_CMPGDU_LT_OB:
908f6be1 24345 check_dsp_r2(ctx);
26690560
JL
24346 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24347 break;
24348 case OPC_CMPGDU_LE_OB:
908f6be1 24349 check_dsp_r2(ctx);
26690560
JL
24350 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24351 break;
24352 case OPC_CMPGU_EQ_OB:
24353 check_dsp(ctx);
24354 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24355 break;
24356 case OPC_CMPGU_LT_OB:
24357 check_dsp(ctx);
24358 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24359 break;
24360 case OPC_CMPGU_LE_OB:
24361 check_dsp(ctx);
24362 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24363 break;
24364 case OPC_CMPU_EQ_OB:
24365 check_dsp(ctx);
24366 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24367 break;
24368 case OPC_CMPU_LT_OB:
24369 check_dsp(ctx);
24370 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24371 break;
24372 case OPC_CMPU_LE_OB:
24373 check_dsp(ctx);
24374 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24375 break;
24376 case OPC_PACKRL_PW:
24377 check_dsp(ctx);
24378 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24379 break;
24380 case OPC_PICK_OB:
24381 check_dsp(ctx);
24382 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24383 break;
24384 case OPC_PICK_PW:
24385 check_dsp(ctx);
24386 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24387 break;
24388 case OPC_PICK_QH:
24389 check_dsp(ctx);
24390 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24391 break;
24392 }
24393 break;
df6126a7
AJ
24394#endif
24395 }
24396
24397 tcg_temp_free(t1);
24398 tcg_temp_free(v1_t);
24399 tcg_temp_free(v2_t);
df6126a7
AJ
24400}
24401
24402static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24403 uint32_t op1, int rt, int rs, int sa)
24404{
df6126a7
AJ
24405 TCGv t0;
24406
908f6be1 24407 check_dsp_r2(ctx);
df6126a7
AJ
24408
24409 if (rt == 0) {
24410 /* Treat as NOP. */
df6126a7
AJ
24411 return;
24412 }
24413
24414 t0 = tcg_temp_new();
24415 gen_load_gpr(t0, rs);
24416
24417 switch (op1) {
24418 case OPC_APPEND_DSP:
24419 switch (MASK_APPEND(ctx->opcode)) {
24420 case OPC_APPEND:
24421 if (sa != 0) {
24422 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24423 }
24424 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24425 break;
24426 case OPC_PREPEND:
24427 if (sa != 0) {
24428 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24429 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24430 tcg_gen_shli_tl(t0, t0, 32 - sa);
24431 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24432 }
24433 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24434 break;
24435 case OPC_BALIGN:
24436 sa &= 3;
24437 if (sa != 0 && sa != 2) {
24438 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24439 tcg_gen_ext32u_tl(t0, t0);
24440 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24441 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24442 }
24443 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24444 break;
24445 default: /* Invalid */
24446 MIPS_INVAL("MASK APPEND");
9c708c7f 24447 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
24448 break;
24449 }
24450 break;
24451#ifdef TARGET_MIPS64
26690560 24452 case OPC_DAPPEND_DSP:
df6126a7 24453 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 24454 case OPC_DAPPEND:
df6126a7
AJ
24455 if (sa != 0) {
24456 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24457 }
26690560
JL
24458 break;
24459 case OPC_PREPENDD:
df6126a7
AJ
24460 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24461 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24462 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
24463 break;
24464 case OPC_PREPENDW:
df6126a7
AJ
24465 if (sa != 0) {
24466 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24467 tcg_gen_shli_tl(t0, t0, 64 - sa);
24468 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24469 }
26690560
JL
24470 break;
24471 case OPC_DBALIGN:
df6126a7
AJ
24472 sa &= 7;
24473 if (sa != 0 && sa != 2 && sa != 4) {
24474 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24475 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24476 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24477 }
26690560
JL
24478 break;
24479 default: /* Invalid */
24480 MIPS_INVAL("MASK DAPPEND");
9c708c7f 24481 generate_exception_end(ctx, EXCP_RI);
26690560
JL
24482 break;
24483 }
24484 break;
24485#endif
24486 }
df6126a7 24487 tcg_temp_free(t0);
26690560
JL
24488}
24489
b53371ed
JL
24490static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24491 int ret, int v1, int v2, int check_ret)
24492
24493{
b53371ed
JL
24494 TCGv t0;
24495 TCGv t1;
24496 TCGv v1_t;
24497 TCGv v2_t;
24498 int16_t imm;
24499
24500 if ((ret == 0) && (check_ret == 1)) {
24501 /* Treat as NOP. */
b53371ed
JL
24502 return;
24503 }
24504
24505 t0 = tcg_temp_new();
24506 t1 = tcg_temp_new();
24507 v1_t = tcg_temp_new();
24508 v2_t = tcg_temp_new();
24509
24510 gen_load_gpr(v1_t, v1);
24511 gen_load_gpr(v2_t, v2);
24512
24513 switch (op1) {
24514 case OPC_EXTR_W_DSP:
24515 check_dsp(ctx);
24516 switch (op2) {
24517 case OPC_EXTR_W:
24518 tcg_gen_movi_tl(t0, v2);
24519 tcg_gen_movi_tl(t1, v1);
24520 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24521 break;
24522 case OPC_EXTR_R_W:
24523 tcg_gen_movi_tl(t0, v2);
24524 tcg_gen_movi_tl(t1, v1);
24525 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24526 break;
24527 case OPC_EXTR_RS_W:
24528 tcg_gen_movi_tl(t0, v2);
24529 tcg_gen_movi_tl(t1, v1);
24530 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24531 break;
24532 case OPC_EXTR_S_H:
24533 tcg_gen_movi_tl(t0, v2);
24534 tcg_gen_movi_tl(t1, v1);
24535 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24536 break;
24537 case OPC_EXTRV_S_H:
24538 tcg_gen_movi_tl(t0, v2);
24539 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24540 break;
24541 case OPC_EXTRV_W:
24542 tcg_gen_movi_tl(t0, v2);
24543 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24544 break;
24545 case OPC_EXTRV_R_W:
24546 tcg_gen_movi_tl(t0, v2);
24547 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24548 break;
24549 case OPC_EXTRV_RS_W:
24550 tcg_gen_movi_tl(t0, v2);
24551 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24552 break;
24553 case OPC_EXTP:
24554 tcg_gen_movi_tl(t0, v2);
24555 tcg_gen_movi_tl(t1, v1);
24556 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24557 break;
24558 case OPC_EXTPV:
24559 tcg_gen_movi_tl(t0, v2);
24560 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24561 break;
24562 case OPC_EXTPDP:
24563 tcg_gen_movi_tl(t0, v2);
24564 tcg_gen_movi_tl(t1, v1);
24565 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24566 break;
24567 case OPC_EXTPDPV:
24568 tcg_gen_movi_tl(t0, v2);
24569 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24570 break;
24571 case OPC_SHILO:
24572 imm = (ctx->opcode >> 20) & 0x3F;
24573 tcg_gen_movi_tl(t0, ret);
24574 tcg_gen_movi_tl(t1, imm);
24575 gen_helper_shilo(t0, t1, cpu_env);
24576 break;
24577 case OPC_SHILOV:
24578 tcg_gen_movi_tl(t0, ret);
24579 gen_helper_shilo(t0, v1_t, cpu_env);
24580 break;
24581 case OPC_MTHLIP:
24582 tcg_gen_movi_tl(t0, ret);
24583 gen_helper_mthlip(t0, v1_t, cpu_env);
24584 break;
24585 case OPC_WRDSP:
24586 imm = (ctx->opcode >> 11) & 0x3FF;
24587 tcg_gen_movi_tl(t0, imm);
24588 gen_helper_wrdsp(v1_t, t0, cpu_env);
24589 break;
24590 case OPC_RDDSP:
24591 imm = (ctx->opcode >> 16) & 0x03FF;
24592 tcg_gen_movi_tl(t0, imm);
24593 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24594 break;
24595 }
24596 break;
24597#ifdef TARGET_MIPS64
24598 case OPC_DEXTR_W_DSP:
24599 check_dsp(ctx);
24600 switch (op2) {
24601 case OPC_DMTHLIP:
24602 tcg_gen_movi_tl(t0, ret);
24603 gen_helper_dmthlip(v1_t, t0, cpu_env);
24604 break;
24605 case OPC_DSHILO:
24606 {
24607 int shift = (ctx->opcode >> 19) & 0x7F;
24608 int ac = (ctx->opcode >> 11) & 0x03;
24609 tcg_gen_movi_tl(t0, shift);
24610 tcg_gen_movi_tl(t1, ac);
24611 gen_helper_dshilo(t0, t1, cpu_env);
24612 break;
24613 }
24614 case OPC_DSHILOV:
24615 {
24616 int ac = (ctx->opcode >> 11) & 0x03;
24617 tcg_gen_movi_tl(t0, ac);
24618 gen_helper_dshilo(v1_t, t0, cpu_env);
24619 break;
24620 }
24621 case OPC_DEXTP:
24622 tcg_gen_movi_tl(t0, v2);
24623 tcg_gen_movi_tl(t1, v1);
24624
24625 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24626 break;
24627 case OPC_DEXTPV:
24628 tcg_gen_movi_tl(t0, v2);
24629 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24630 break;
24631 case OPC_DEXTPDP:
24632 tcg_gen_movi_tl(t0, v2);
24633 tcg_gen_movi_tl(t1, v1);
24634 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24635 break;
24636 case OPC_DEXTPDPV:
24637 tcg_gen_movi_tl(t0, v2);
24638 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24639 break;
24640 case OPC_DEXTR_L:
24641 tcg_gen_movi_tl(t0, v2);
24642 tcg_gen_movi_tl(t1, v1);
24643 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24644 break;
24645 case OPC_DEXTR_R_L:
24646 tcg_gen_movi_tl(t0, v2);
24647 tcg_gen_movi_tl(t1, v1);
24648 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24649 break;
24650 case OPC_DEXTR_RS_L:
24651 tcg_gen_movi_tl(t0, v2);
24652 tcg_gen_movi_tl(t1, v1);
24653 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24654 break;
24655 case OPC_DEXTR_W:
24656 tcg_gen_movi_tl(t0, v2);
24657 tcg_gen_movi_tl(t1, v1);
24658 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24659 break;
24660 case OPC_DEXTR_R_W:
24661 tcg_gen_movi_tl(t0, v2);
24662 tcg_gen_movi_tl(t1, v1);
24663 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24664 break;
24665 case OPC_DEXTR_RS_W:
24666 tcg_gen_movi_tl(t0, v2);
24667 tcg_gen_movi_tl(t1, v1);
24668 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24669 break;
24670 case OPC_DEXTR_S_H:
24671 tcg_gen_movi_tl(t0, v2);
24672 tcg_gen_movi_tl(t1, v1);
24673 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24674 break;
24675 case OPC_DEXTRV_S_H:
24676 tcg_gen_movi_tl(t0, v2);
24677 tcg_gen_movi_tl(t1, v1);
24678 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24679 break;
24680 case OPC_DEXTRV_L:
24681 tcg_gen_movi_tl(t0, v2);
24682 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24683 break;
24684 case OPC_DEXTRV_R_L:
24685 tcg_gen_movi_tl(t0, v2);
24686 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24687 break;
24688 case OPC_DEXTRV_RS_L:
24689 tcg_gen_movi_tl(t0, v2);
24690 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24691 break;
24692 case OPC_DEXTRV_W:
24693 tcg_gen_movi_tl(t0, v2);
24694 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24695 break;
24696 case OPC_DEXTRV_R_W:
24697 tcg_gen_movi_tl(t0, v2);
24698 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24699 break;
24700 case OPC_DEXTRV_RS_W:
24701 tcg_gen_movi_tl(t0, v2);
24702 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24703 break;
24704 }
24705 break;
24706#endif
24707 }
24708
24709 tcg_temp_free(t0);
24710 tcg_temp_free(t1);
24711 tcg_temp_free(v1_t);
24712 tcg_temp_free(v2_t);
b53371ed
JL
24713}
24714
9b1a1d68
JL
24715/* End MIPSDSP functions. */
24716
10dc65db
LA
24717static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24718{
4267d3e6 24719 int rs, rt, rd, sa;
b42ee5e1 24720 uint32_t op1, op2;
10dc65db
LA
24721
24722 rs = (ctx->opcode >> 21) & 0x1f;
24723 rt = (ctx->opcode >> 16) & 0x1f;
24724 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 24725 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24726
24727 op1 = MASK_SPECIAL(ctx->opcode);
24728 switch (op1) {
d4ea6acd 24729 case OPC_LSA:
1f1b4c00 24730 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24731 break;
c2e19f3c
AM
24732 case OPC_MULT:
24733 case OPC_MULTU:
24734 case OPC_DIV:
24735 case OPC_DIVU:
b42ee5e1
LA
24736 op2 = MASK_R6_MULDIV(ctx->opcode);
24737 switch (op2) {
24738 case R6_OPC_MUL:
24739 case R6_OPC_MUH:
24740 case R6_OPC_MULU:
24741 case R6_OPC_MUHU:
24742 case R6_OPC_DIV:
24743 case R6_OPC_MOD:
24744 case R6_OPC_DIVU:
24745 case R6_OPC_MODU:
24746 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24747 break;
24748 default:
24749 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24750 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24751 break;
24752 }
24753 break;
10dc65db
LA
24754 case OPC_SELEQZ:
24755 case OPC_SELNEZ:
24756 gen_cond_move(ctx, op1, rd, rs, rt);
24757 break;
4267d3e6
LA
24758 case R6_OPC_CLO:
24759 case R6_OPC_CLZ:
24760 if (rt == 0 && sa == 1) {
7480515f
AM
24761 /*
24762 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24763 * We need additionally to check other fields.
24764 */
4267d3e6
LA
24765 gen_cl(ctx, op1, rd, rs);
24766 } else {
9c708c7f 24767 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24768 }
24769 break;
24770 case R6_OPC_SDBBP:
3b3c1694
LA
24771 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24772 gen_helper_do_semihosting(cpu_env);
faf1f68b 24773 } else {
3b3c1694 24774 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 24775 generate_exception_end(ctx, EXCP_RI);
3b3c1694 24776 } else {
9c708c7f 24777 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24778 }
faf1f68b 24779 }
4267d3e6 24780 break;
b42ee5e1 24781#if defined(TARGET_MIPS64)
d4ea6acd
LA
24782 case OPC_DLSA:
24783 check_mips_64(ctx);
1f1b4c00 24784 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 24785 break;
4267d3e6
LA
24786 case R6_OPC_DCLO:
24787 case R6_OPC_DCLZ:
24788 if (rt == 0 && sa == 1) {
7480515f
AM
24789 /*
24790 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24791 * We need additionally to check other fields.
24792 */
4267d3e6
LA
24793 check_mips_64(ctx);
24794 gen_cl(ctx, op1, rd, rs);
24795 } else {
9c708c7f 24796 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24797 }
24798 break;
c2e19f3c
AM
24799 case OPC_DMULT:
24800 case OPC_DMULTU:
24801 case OPC_DDIV:
24802 case OPC_DDIVU:
24803
b42ee5e1
LA
24804 op2 = MASK_R6_MULDIV(ctx->opcode);
24805 switch (op2) {
24806 case R6_OPC_DMUL:
24807 case R6_OPC_DMUH:
24808 case R6_OPC_DMULU:
24809 case R6_OPC_DMUHU:
24810 case R6_OPC_DDIV:
24811 case R6_OPC_DMOD:
24812 case R6_OPC_DDIVU:
24813 case R6_OPC_DMODU:
24814 check_mips_64(ctx);
24815 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24816 break;
24817 default:
24818 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24819 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24820 break;
24821 }
24822 break;
24823#endif
10dc65db
LA
24824 default: /* Invalid */
24825 MIPS_INVAL("special_r6");
9c708c7f 24826 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24827 break;
24828 }
24829}
24830
9dc324ce
FN
24831static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24832{
24833 int rs = extract32(ctx->opcode, 21, 5);
24834 int rt = extract32(ctx->opcode, 16, 5);
24835 int rd = extract32(ctx->opcode, 11, 5);
24836 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24837
24838 switch (op1) {
24839 case OPC_MOVN: /* Conditional move */
24840 case OPC_MOVZ:
24841 gen_cond_move(ctx, op1, rd, rs, rt);
24842 break;
24843 case OPC_MFHI: /* Move from HI/LO */
24844 case OPC_MFLO:
24845 gen_HILO(ctx, op1, 0, rd);
24846 break;
24847 case OPC_MTHI:
24848 case OPC_MTLO: /* Move to HI/LO */
24849 gen_HILO(ctx, op1, 0, rs);
24850 break;
24851 case OPC_MULT:
24852 case OPC_MULTU:
24853 gen_mul_txx9(ctx, op1, rd, rs, rt);
24854 break;
24855 case OPC_DIV:
24856 case OPC_DIVU:
24857 gen_muldiv(ctx, op1, 0, rs, rt);
24858 break;
24859#if defined(TARGET_MIPS64)
24860 case OPC_DMULT:
24861 case OPC_DMULTU:
24862 case OPC_DDIV:
24863 case OPC_DDIVU:
24864 check_insn_opc_user_only(ctx, INSN_R5900);
24865 gen_muldiv(ctx, op1, 0, rs, rt);
24866 break;
24867#endif
24868 case OPC_JR:
24869 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24870 break;
24871 default: /* Invalid */
24872 MIPS_INVAL("special_tx79");
24873 generate_exception_end(ctx, EXCP_RI);
24874 break;
24875 }
24876}
24877
10dc65db
LA
24878static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24879{
b42ee5e1 24880 int rs, rt, rd, sa;
10dc65db
LA
24881 uint32_t op1;
24882
24883 rs = (ctx->opcode >> 21) & 0x1f;
24884 rt = (ctx->opcode >> 16) & 0x1f;
24885 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24886 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24887
24888 op1 = MASK_SPECIAL(ctx->opcode);
24889 switch (op1) {
24890 case OPC_MOVN: /* Conditional move */
24891 case OPC_MOVZ:
bbd5e4a2 24892 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
9dc324ce 24893 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24894 gen_cond_move(ctx, op1, rd, rs, rt);
24895 break;
24896 case OPC_MFHI: /* Move from HI/LO */
24897 case OPC_MFLO:
24898 gen_HILO(ctx, op1, rs & 3, rd);
24899 break;
24900 case OPC_MTHI:
24901 case OPC_MTLO: /* Move to HI/LO */
24902 gen_HILO(ctx, op1, rd & 3, rs);
24903 break;
24904 case OPC_MOVCI:
bbd5e4a2 24905 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10dc65db
LA
24906 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24907 check_cp1_enabled(ctx);
24908 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24909 (ctx->opcode >> 16) & 1);
24910 } else {
24911 generate_exception_err(ctx, EXCP_CpU, 1);
24912 }
24913 break;
b42ee5e1
LA
24914 case OPC_MULT:
24915 case OPC_MULTU:
24916 if (sa) {
24917 check_insn(ctx, INSN_VR54XX);
24918 op1 = MASK_MUL_VR54XX(ctx->opcode);
24919 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24920 } else {
24921 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24922 }
24923 break;
24924 case OPC_DIV:
24925 case OPC_DIVU:
24926 gen_muldiv(ctx, op1, 0, rs, rt);
24927 break;
24928#if defined(TARGET_MIPS64)
c2e19f3c
AM
24929 case OPC_DMULT:
24930 case OPC_DMULTU:
24931 case OPC_DDIV:
24932 case OPC_DDIVU:
b42ee5e1
LA
24933 check_insn(ctx, ISA_MIPS3);
24934 check_mips_64(ctx);
24935 gen_muldiv(ctx, op1, 0, rs, rt);
24936 break;
24937#endif
0aefa333 24938 case OPC_JR:
b231c103 24939 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24940 break;
4267d3e6
LA
24941 case OPC_SPIM:
24942#ifdef MIPS_STRICT_STANDARD
24943 MIPS_INVAL("SPIM");
9c708c7f 24944 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24945#else
24946 /* Implemented as RI exception for now. */
24947 MIPS_INVAL("spim (unofficial)");
9c708c7f 24948 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24949#endif
24950 break;
10dc65db
LA
24951 default: /* Invalid */
24952 MIPS_INVAL("special_legacy");
9c708c7f 24953 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24954 break;
24955 }
24956}
24957
099e5b4d 24958static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24959{
3c824109 24960 int rs, rt, rd, sa;
099e5b4d 24961 uint32_t op1;
3c824109 24962
3c824109
NF
24963 rs = (ctx->opcode >> 21) & 0x1f;
24964 rt = (ctx->opcode >> 16) & 0x1f;
24965 rd = (ctx->opcode >> 11) & 0x1f;
24966 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24967
24968 op1 = MASK_SPECIAL(ctx->opcode);
24969 switch (op1) {
24970 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24971 if (sa == 5 && rd == 0 &&
24972 rs == 0 && rt == 0) { /* PAUSE */
2e211e0a 24973 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 24974 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24975 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24976 break;
24977 }
24978 }
24979 /* Fallthrough */
099e5b4d
LA
24980 case OPC_SRA:
24981 gen_shift_imm(ctx, op1, rd, rt, sa);
24982 break;
24983 case OPC_SRL:
24984 switch ((ctx->opcode >> 21) & 0x1f) {
24985 case 1:
24986 /* rotr is decoded as srl on non-R2 CPUs */
7a47bae5 24987 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 24988 op1 = OPC_ROTR;
ea63e2c3 24989 }
099e5b4d
LA
24990 /* Fallthrough */
24991 case 0:
24992 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24993 break;
099e5b4d 24994 default:
9c708c7f 24995 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24996 break;
099e5b4d
LA
24997 }
24998 break;
c2e19f3c
AM
24999 case OPC_ADD:
25000 case OPC_ADDU:
25001 case OPC_SUB:
25002 case OPC_SUBU:
099e5b4d
LA
25003 gen_arith(ctx, op1, rd, rs, rt);
25004 break;
25005 case OPC_SLLV: /* Shifts */
25006 case OPC_SRAV:
25007 gen_shift(ctx, op1, rd, rs, rt);
25008 break;
25009 case OPC_SRLV:
25010 switch ((ctx->opcode >> 6) & 0x1f) {
25011 case 1:
25012 /* rotrv is decoded as srlv on non-R2 CPUs */
7a47bae5 25013 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 25014 op1 = OPC_ROTRV;
26135ead 25015 }
099e5b4d
LA
25016 /* Fallthrough */
25017 case 0:
25018 gen_shift(ctx, op1, rd, rs, rt);
26135ead 25019 break;
099e5b4d 25020 default:
9c708c7f 25021 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 25022 break;
099e5b4d
LA
25023 }
25024 break;
25025 case OPC_SLT: /* Set on less than */
25026 case OPC_SLTU:
25027 gen_slt(ctx, op1, rd, rs, rt);
25028 break;
25029 case OPC_AND: /* Logic*/
25030 case OPC_OR:
25031 case OPC_NOR:
25032 case OPC_XOR:
25033 gen_logic(ctx, op1, rd, rs, rt);
25034 break;
0aefa333 25035 case OPC_JALR:
b231c103 25036 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 25037 break;
c2e19f3c
AM
25038 case OPC_TGE: /* Traps */
25039 case OPC_TGEU:
25040 case OPC_TLT:
25041 case OPC_TLTU:
25042 case OPC_TEQ:
099e5b4d 25043 case OPC_TNE:
d9224450 25044 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
25045 gen_trap(ctx, op1, rs, rt, -1);
25046 break;
d4ea6acd 25047 case OPC_LSA: /* OPC_PMON */
2e211e0a 25048 if ((ctx->insn_flags & ISA_MIPS_R6) ||
f7685877 25049 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
25050 decode_opc_special_r6(env, ctx);
25051 } else {
25052 /* Pmon entry point, also R4010 selsl */
b48cfdff 25053#ifdef MIPS_STRICT_STANDARD
d4ea6acd 25054 MIPS_INVAL("PMON / selsl");
9c708c7f 25055 generate_exception_end(ctx, EXCP_RI);
b48cfdff 25056#else
d4ea6acd 25057 gen_helper_0e0i(pmon, sa);
b48cfdff 25058#endif
d4ea6acd 25059 }
099e5b4d
LA
25060 break;
25061 case OPC_SYSCALL:
9c708c7f 25062 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
25063 break;
25064 case OPC_BREAK:
9c708c7f 25065 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 25066 break;
099e5b4d 25067 case OPC_SYNC:
d9224450 25068 check_insn(ctx, ISA_MIPS2);
d208ac0c 25069 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 25070 break;
4ad40f36 25071
d26bc211 25072#if defined(TARGET_MIPS64)
099e5b4d
LA
25073 /* MIPS64 specific opcodes */
25074 case OPC_DSLL:
25075 case OPC_DSRA:
25076 case OPC_DSLL32:
25077 case OPC_DSRA32:
25078 check_insn(ctx, ISA_MIPS3);
25079 check_mips_64(ctx);
25080 gen_shift_imm(ctx, op1, rd, rt, sa);
25081 break;
25082 case OPC_DSRL:
25083 switch ((ctx->opcode >> 21) & 0x1f) {
25084 case 1:
25085 /* drotr is decoded as dsrl on non-R2 CPUs */
7a47bae5 25086 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 25087 op1 = OPC_DROTR;
ea63e2c3 25088 }
099e5b4d
LA
25089 /* Fallthrough */
25090 case 0:
d75c135e 25091 check_insn(ctx, ISA_MIPS3);
e189e748 25092 check_mips_64(ctx);
099e5b4d 25093 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 25094 break;
099e5b4d 25095 default:
9c708c7f 25096 generate_exception_end(ctx, EXCP_RI);
460f00c4 25097 break;
099e5b4d
LA
25098 }
25099 break;
25100 case OPC_DSRL32:
25101 switch ((ctx->opcode >> 21) & 0x1f) {
25102 case 1:
25103 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
7a47bae5 25104 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 25105 op1 = OPC_DROTR32;
ea63e2c3 25106 }
099e5b4d
LA
25107 /* Fallthrough */
25108 case 0:
d75c135e 25109 check_insn(ctx, ISA_MIPS3);
e189e748 25110 check_mips_64(ctx);
099e5b4d 25111 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 25112 break;
099e5b4d 25113 default:
9c708c7f 25114 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
25115 break;
25116 }
25117 break;
c2e19f3c
AM
25118 case OPC_DADD:
25119 case OPC_DADDU:
25120 case OPC_DSUB:
25121 case OPC_DSUBU:
099e5b4d
LA
25122 check_insn(ctx, ISA_MIPS3);
25123 check_mips_64(ctx);
25124 gen_arith(ctx, op1, rd, rs, rt);
25125 break;
25126 case OPC_DSLLV:
25127 case OPC_DSRAV:
25128 check_insn(ctx, ISA_MIPS3);
25129 check_mips_64(ctx);
25130 gen_shift(ctx, op1, rd, rs, rt);
25131 break;
25132 case OPC_DSRLV:
25133 switch ((ctx->opcode >> 6) & 0x1f) {
25134 case 1:
25135 /* drotrv is decoded as dsrlv on non-R2 CPUs */
7a47bae5 25136 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 25137 op1 = OPC_DROTRV;
6af0bf9c 25138 }
099e5b4d
LA
25139 /* Fallthrough */
25140 case 0:
25141 check_insn(ctx, ISA_MIPS3);
e189e748 25142 check_mips_64(ctx);
099e5b4d 25143 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 25144 break;
099e5b4d 25145 default:
9c708c7f 25146 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
25147 break;
25148 }
25149 break;
f7685877 25150 case OPC_DLSA:
2e211e0a 25151 if ((ctx->insn_flags & ISA_MIPS_R6) ||
f7685877
YK
25152 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25153 decode_opc_special_r6(env, ctx);
25154 }
25155 break;
099e5b4d 25156#endif
10dc65db 25157 default:
2e211e0a 25158 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db 25159 decode_opc_special_r6(env, ctx);
9dc324ce
FN
25160 } else if (ctx->insn_flags & INSN_R5900) {
25161 decode_opc_special_tx79(env, ctx);
10dc65db
LA
25162 } else {
25163 decode_opc_special_legacy(env, ctx);
25164 }
25165 }
25166}
25167
d67da337 25168
37b9aae2
MM
25169#if defined(TARGET_MIPS64)
25170
25171/*
25172 *
25173 * MMI (MultiMedia Interface) ASE instructions
25174 * ===========================================
25175 */
25176
25177/*
25178 * MMI instructions category: data communication
25179 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25180 *
25181 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25182 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25183 * PCPYUD PEXEH PEXTLW PPACW
25184 * PEXEW PEXTUB
25185 * PEXTUH
25186 * PEXTUW
25187 */
25188
d3434d9f
MM
25189/*
25190 * PCPYH rd, rt
25191 *
25192 * Parallel Copy Halfword
25193 *
25194 * 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
25195 * +-----------+---------+---------+---------+---------+-----------+
25196 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25197 * +-----------+---------+---------+---------+---------+-----------+
25198 */
25199static void gen_mmi_pcpyh(DisasContext *ctx)
25200{
25201 uint32_t pd, rt, rd;
25202 uint32_t opcode;
25203
25204 opcode = ctx->opcode;
25205
25206 pd = extract32(opcode, 21, 5);
25207 rt = extract32(opcode, 16, 5);
25208 rd = extract32(opcode, 11, 5);
25209
25210 if (unlikely(pd != 0)) {
25211 generate_exception_end(ctx, EXCP_RI);
25212 } else if (rd == 0) {
25213 /* nop */
25214 } else if (rt == 0) {
25215 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25216 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25217 } else {
25218 TCGv_i64 t0 = tcg_temp_new();
25219 TCGv_i64 t1 = tcg_temp_new();
25220 uint64_t mask = (1ULL << 16) - 1;
25221
25222 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25223 tcg_gen_movi_i64(t1, 0);
25224 tcg_gen_or_i64(t1, t0, t1);
25225 tcg_gen_shli_i64(t0, t0, 16);
25226 tcg_gen_or_i64(t1, t0, t1);
25227 tcg_gen_shli_i64(t0, t0, 16);
25228 tcg_gen_or_i64(t1, t0, t1);
25229 tcg_gen_shli_i64(t0, t0, 16);
25230 tcg_gen_or_i64(t1, t0, t1);
25231
25232 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25233
25234 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25235 tcg_gen_movi_i64(t1, 0);
25236 tcg_gen_or_i64(t1, t0, t1);
25237 tcg_gen_shli_i64(t0, t0, 16);
25238 tcg_gen_or_i64(t1, t0, t1);
25239 tcg_gen_shli_i64(t0, t0, 16);
25240 tcg_gen_or_i64(t1, t0, t1);
25241 tcg_gen_shli_i64(t0, t0, 16);
25242 tcg_gen_or_i64(t1, t0, t1);
25243
25244 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25245
25246 tcg_temp_free(t0);
25247 tcg_temp_free(t1);
25248 }
25249}
25250
b87eef31
MM
25251/*
25252 * PCPYLD rd, rs, rt
25253 *
25254 * Parallel Copy Lower Doubleword
25255 *
25256 * 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
25257 * +-----------+---------+---------+---------+---------+-----------+
25258 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25259 * +-----------+---------+---------+---------+---------+-----------+
25260 */
25261static void gen_mmi_pcpyld(DisasContext *ctx)
25262{
25263 uint32_t rs, rt, rd;
25264 uint32_t opcode;
25265
25266 opcode = ctx->opcode;
25267
25268 rs = extract32(opcode, 21, 5);
25269 rt = extract32(opcode, 16, 5);
25270 rd = extract32(opcode, 11, 5);
25271
25272 if (rd == 0) {
25273 /* nop */
25274 } else {
25275 if (rs == 0) {
25276 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25277 } else {
25278 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25279 }
25280 if (rt == 0) {
25281 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25282 } else {
25283 if (rd != rt) {
25284 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25285 }
25286 }
25287 }
25288}
25289
fd487f83
MM
25290/*
25291 * PCPYUD rd, rs, rt
25292 *
25293 * Parallel Copy Upper Doubleword
25294 *
25295 * 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
25296 * +-----------+---------+---------+---------+---------+-----------+
25297 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25298 * +-----------+---------+---------+---------+---------+-----------+
25299 */
25300static void gen_mmi_pcpyud(DisasContext *ctx)
25301{
25302 uint32_t rs, rt, rd;
25303 uint32_t opcode;
25304
25305 opcode = ctx->opcode;
25306
25307 rs = extract32(opcode, 21, 5);
25308 rt = extract32(opcode, 16, 5);
25309 rd = extract32(opcode, 11, 5);
25310
25311 if (rd == 0) {
25312 /* nop */
25313 } else {
25314 if (rs == 0) {
25315 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25316 } else {
25317 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25318 }
25319 if (rt == 0) {
25320 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25321 } else {
25322 if (rd != rt) {
25323 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25324 }
25325 }
25326 }
25327}
25328
37b9aae2
MM
25329#endif
25330
25331
b621f018
AM
25332#if !defined(TARGET_MIPS64)
25333
d67da337
AM
25334/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25335#define MXU_APTN1_A 0
25336#define MXU_APTN1_S 1
25337
b70bb918
CJ
25338/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25339#define MXU_APTN2_AA 0
25340#define MXU_APTN2_AS 1
25341#define MXU_APTN2_SA 2
25342#define MXU_APTN2_SS 3
25343
5bb29992
AM
25344/* MXU execute add/subtract 2-bit pattern 'eptn2' */
25345#define MXU_EPTN2_AA 0
25346#define MXU_EPTN2_AS 1
25347#define MXU_EPTN2_SA 2
25348#define MXU_EPTN2_SS 3
25349
a35723f4 25350/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
25351#define MXU_OPTN2_PTN0 0
25352#define MXU_OPTN2_PTN1 1
25353#define MXU_OPTN2_PTN2 2
25354#define MXU_OPTN2_PTN3 3
25355/* alternative naming scheme for 'optn2' */
a35723f4
CJ
25356#define MXU_OPTN2_WW 0
25357#define MXU_OPTN2_LW 1
25358#define MXU_OPTN2_HW 2
25359#define MXU_OPTN2_XW 3
25360
53f1131f
CJ
25361/* MXU operand getting pattern 'optn3' */
25362#define MXU_OPTN3_PTN0 0
25363#define MXU_OPTN3_PTN1 1
25364#define MXU_OPTN3_PTN2 2
25365#define MXU_OPTN3_PTN3 3
25366#define MXU_OPTN3_PTN4 4
25367#define MXU_OPTN3_PTN5 5
25368#define MXU_OPTN3_PTN6 6
25369#define MXU_OPTN3_PTN7 7
25370
d67da337 25371
96992d1a
CJ
25372/*
25373 * S32I2M XRa, rb - Register move from GRF to XRF
25374 */
25375static void gen_mxu_s32i2m(DisasContext *ctx)
25376{
25377 TCGv t0;
25378 uint32_t XRa, Rb;
25379
25380 t0 = tcg_temp_new();
25381
25382 XRa = extract32(ctx->opcode, 6, 5);
25383 Rb = extract32(ctx->opcode, 16, 5);
25384
25385 gen_load_gpr(t0, Rb);
25386 if (XRa <= 15) {
25387 gen_store_mxu_gpr(t0, XRa);
25388 } else if (XRa == 16) {
25389 gen_store_mxu_cr(t0);
25390 }
25391
25392 tcg_temp_free(t0);
25393}
25394
25395/*
25396 * S32M2I XRa, rb - Register move from XRF to GRF
25397 */
25398static void gen_mxu_s32m2i(DisasContext *ctx)
25399{
25400 TCGv t0;
25401 uint32_t XRa, Rb;
25402
25403 t0 = tcg_temp_new();
25404
25405 XRa = extract32(ctx->opcode, 6, 5);
25406 Rb = extract32(ctx->opcode, 16, 5);
25407
25408 if (XRa <= 15) {
25409 gen_load_mxu_gpr(t0, XRa);
25410 } else if (XRa == 16) {
25411 gen_load_mxu_cr(t0);
25412 }
25413
25414 gen_store_gpr(t0, Rb);
25415
25416 tcg_temp_free(t0);
25417}
25418
be57bcdb
CJ
25419/*
25420 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25421 */
25422static void gen_mxu_s8ldd(DisasContext *ctx)
25423{
25424 TCGv t0, t1;
be57bcdb
CJ
25425 uint32_t XRa, Rb, s8, optn3;
25426
25427 t0 = tcg_temp_new();
25428 t1 = tcg_temp_new();
25429
be57bcdb
CJ
25430 XRa = extract32(ctx->opcode, 6, 4);
25431 s8 = extract32(ctx->opcode, 10, 8);
25432 optn3 = extract32(ctx->opcode, 18, 3);
25433 Rb = extract32(ctx->opcode, 21, 5);
25434
be57bcdb
CJ
25435 gen_load_gpr(t0, Rb);
25436 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25437
25438 switch (optn3) {
25439 /* XRa[7:0] = tmp8 */
25440 case MXU_OPTN3_PTN0:
25441 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25442 gen_load_mxu_gpr(t0, XRa);
25443 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25444 break;
25445 /* XRa[15:8] = tmp8 */
25446 case MXU_OPTN3_PTN1:
25447 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25448 gen_load_mxu_gpr(t0, XRa);
25449 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25450 break;
25451 /* XRa[23:16] = tmp8 */
25452 case MXU_OPTN3_PTN2:
25453 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25454 gen_load_mxu_gpr(t0, XRa);
25455 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25456 break;
25457 /* XRa[31:24] = tmp8 */
25458 case MXU_OPTN3_PTN3:
25459 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25460 gen_load_mxu_gpr(t0, XRa);
25461 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25462 break;
25463 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25464 case MXU_OPTN3_PTN4:
25465 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25466 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25467 break;
25468 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25469 case MXU_OPTN3_PTN5:
25470 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25471 tcg_gen_shli_tl(t1, t1, 8);
25472 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25473 break;
25474 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25475 case MXU_OPTN3_PTN6:
25476 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25477 tcg_gen_mov_tl(t0, t1);
25478 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25479 tcg_gen_shli_tl(t1, t1, 16);
25480 tcg_gen_or_tl(t0, t0, t1);
25481 break;
25482 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25483 case MXU_OPTN3_PTN7:
25484 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25485 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25486 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25487 break;
25488 }
25489
25490 gen_store_mxu_gpr(t0, XRa);
25491
be57bcdb
CJ
25492 tcg_temp_free(t0);
25493 tcg_temp_free(t1);
25494}
25495
72c9bcf8
CJ
25496/*
25497 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25498 */
25499static void gen_mxu_d16mul(DisasContext *ctx)
25500{
25501 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
25502 uint32_t XRa, XRb, XRc, XRd, optn2;
25503
25504 t0 = tcg_temp_new();
25505 t1 = tcg_temp_new();
25506 t2 = tcg_temp_new();
25507 t3 = tcg_temp_new();
25508
72c9bcf8
CJ
25509 XRa = extract32(ctx->opcode, 6, 4);
25510 XRb = extract32(ctx->opcode, 10, 4);
25511 XRc = extract32(ctx->opcode, 14, 4);
25512 XRd = extract32(ctx->opcode, 18, 4);
25513 optn2 = extract32(ctx->opcode, 22, 2);
25514
72c9bcf8
CJ
25515 gen_load_mxu_gpr(t1, XRb);
25516 tcg_gen_sextract_tl(t0, t1, 0, 16);
25517 tcg_gen_sextract_tl(t1, t1, 16, 16);
25518 gen_load_mxu_gpr(t3, XRc);
25519 tcg_gen_sextract_tl(t2, t3, 0, 16);
25520 tcg_gen_sextract_tl(t3, t3, 16, 16);
25521
25522 switch (optn2) {
25523 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25524 tcg_gen_mul_tl(t3, t1, t3);
25525 tcg_gen_mul_tl(t2, t0, t2);
25526 break;
25527 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25528 tcg_gen_mul_tl(t3, t0, t3);
25529 tcg_gen_mul_tl(t2, t0, t2);
25530 break;
25531 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25532 tcg_gen_mul_tl(t3, t1, t3);
25533 tcg_gen_mul_tl(t2, t1, t2);
25534 break;
25535 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25536 tcg_gen_mul_tl(t3, t0, t3);
25537 tcg_gen_mul_tl(t2, t1, t2);
25538 break;
25539 }
25540 gen_store_mxu_gpr(t3, XRa);
25541 gen_store_mxu_gpr(t2, XRd);
25542
72c9bcf8
CJ
25543 tcg_temp_free(t0);
25544 tcg_temp_free(t1);
25545 tcg_temp_free(t2);
25546 tcg_temp_free(t3);
25547}
25548
e67915b4
CJ
25549/*
25550 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25551 * and accumulate
25552 */
25553static void gen_mxu_d16mac(DisasContext *ctx)
25554{
25555 TCGv t0, t1, t2, t3;
e67915b4
CJ
25556 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25557
25558 t0 = tcg_temp_new();
25559 t1 = tcg_temp_new();
25560 t2 = tcg_temp_new();
25561 t3 = tcg_temp_new();
25562
e67915b4
CJ
25563 XRa = extract32(ctx->opcode, 6, 4);
25564 XRb = extract32(ctx->opcode, 10, 4);
25565 XRc = extract32(ctx->opcode, 14, 4);
25566 XRd = extract32(ctx->opcode, 18, 4);
25567 optn2 = extract32(ctx->opcode, 22, 2);
25568 aptn2 = extract32(ctx->opcode, 24, 2);
25569
e67915b4
CJ
25570 gen_load_mxu_gpr(t1, XRb);
25571 tcg_gen_sextract_tl(t0, t1, 0, 16);
25572 tcg_gen_sextract_tl(t1, t1, 16, 16);
25573
25574 gen_load_mxu_gpr(t3, XRc);
25575 tcg_gen_sextract_tl(t2, t3, 0, 16);
25576 tcg_gen_sextract_tl(t3, t3, 16, 16);
25577
25578 switch (optn2) {
25579 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25580 tcg_gen_mul_tl(t3, t1, t3);
25581 tcg_gen_mul_tl(t2, t0, t2);
25582 break;
25583 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25584 tcg_gen_mul_tl(t3, t0, t3);
25585 tcg_gen_mul_tl(t2, t0, t2);
25586 break;
25587 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25588 tcg_gen_mul_tl(t3, t1, t3);
25589 tcg_gen_mul_tl(t2, t1, t2);
25590 break;
25591 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25592 tcg_gen_mul_tl(t3, t0, t3);
25593 tcg_gen_mul_tl(t2, t1, t2);
25594 break;
25595 }
25596 gen_load_mxu_gpr(t0, XRa);
25597 gen_load_mxu_gpr(t1, XRd);
25598
25599 switch (aptn2) {
25600 case MXU_APTN2_AA:
25601 tcg_gen_add_tl(t3, t0, t3);
25602 tcg_gen_add_tl(t2, t1, t2);
25603 break;
25604 case MXU_APTN2_AS:
25605 tcg_gen_add_tl(t3, t0, t3);
25606 tcg_gen_sub_tl(t2, t1, t2);
25607 break;
25608 case MXU_APTN2_SA:
25609 tcg_gen_sub_tl(t3, t0, t3);
25610 tcg_gen_add_tl(t2, t1, t2);
25611 break;
25612 case MXU_APTN2_SS:
25613 tcg_gen_sub_tl(t3, t0, t3);
25614 tcg_gen_sub_tl(t2, t1, t2);
25615 break;
25616 }
25617 gen_store_mxu_gpr(t3, XRa);
25618 gen_store_mxu_gpr(t2, XRd);
25619
e67915b4
CJ
25620 tcg_temp_free(t0);
25621 tcg_temp_free(t1);
25622 tcg_temp_free(t2);
25623 tcg_temp_free(t3);
25624}
25625
a9a4181b
CJ
25626/*
25627 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25628 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25629 */
25630static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25631{
25632 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
25633 uint32_t XRa, XRb, XRc, XRd, sel;
25634
25635 t0 = tcg_temp_new();
25636 t1 = tcg_temp_new();
25637 t2 = tcg_temp_new();
25638 t3 = tcg_temp_new();
25639 t4 = tcg_temp_new();
25640 t5 = tcg_temp_new();
25641 t6 = tcg_temp_new();
25642 t7 = tcg_temp_new();
25643
a9a4181b
CJ
25644 XRa = extract32(ctx->opcode, 6, 4);
25645 XRb = extract32(ctx->opcode, 10, 4);
25646 XRc = extract32(ctx->opcode, 14, 4);
25647 XRd = extract32(ctx->opcode, 18, 4);
25648 sel = extract32(ctx->opcode, 22, 2);
25649
a9a4181b
CJ
25650 gen_load_mxu_gpr(t3, XRb);
25651 gen_load_mxu_gpr(t7, XRc);
25652
25653 if (sel == 0x2) {
25654 /* Q8MULSU */
25655 tcg_gen_ext8s_tl(t0, t3);
25656 tcg_gen_shri_tl(t3, t3, 8);
25657 tcg_gen_ext8s_tl(t1, t3);
25658 tcg_gen_shri_tl(t3, t3, 8);
25659 tcg_gen_ext8s_tl(t2, t3);
25660 tcg_gen_shri_tl(t3, t3, 8);
25661 tcg_gen_ext8s_tl(t3, t3);
25662 } else {
25663 /* Q8MUL */
25664 tcg_gen_ext8u_tl(t0, t3);
25665 tcg_gen_shri_tl(t3, t3, 8);
25666 tcg_gen_ext8u_tl(t1, t3);
25667 tcg_gen_shri_tl(t3, t3, 8);
25668 tcg_gen_ext8u_tl(t2, t3);
25669 tcg_gen_shri_tl(t3, t3, 8);
25670 tcg_gen_ext8u_tl(t3, t3);
25671 }
25672
25673 tcg_gen_ext8u_tl(t4, t7);
25674 tcg_gen_shri_tl(t7, t7, 8);
25675 tcg_gen_ext8u_tl(t5, t7);
25676 tcg_gen_shri_tl(t7, t7, 8);
25677 tcg_gen_ext8u_tl(t6, t7);
25678 tcg_gen_shri_tl(t7, t7, 8);
25679 tcg_gen_ext8u_tl(t7, t7);
25680
25681 tcg_gen_mul_tl(t0, t0, t4);
25682 tcg_gen_mul_tl(t1, t1, t5);
25683 tcg_gen_mul_tl(t2, t2, t6);
25684 tcg_gen_mul_tl(t3, t3, t7);
25685
25686 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25687 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25688 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25689 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25690
25691 tcg_gen_shli_tl(t1, t1, 16);
25692 tcg_gen_shli_tl(t3, t3, 16);
25693
25694 tcg_gen_or_tl(t0, t0, t1);
25695 tcg_gen_or_tl(t1, t2, t3);
25696
25697 gen_store_mxu_gpr(t0, XRd);
25698 gen_store_mxu_gpr(t1, XRa);
25699
a9a4181b
CJ
25700 tcg_temp_free(t0);
25701 tcg_temp_free(t1);
25702 tcg_temp_free(t2);
25703 tcg_temp_free(t3);
25704 tcg_temp_free(t4);
25705 tcg_temp_free(t5);
25706 tcg_temp_free(t6);
25707 tcg_temp_free(t7);
25708}
25709
4ca83721
CJ
25710/*
25711 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25712 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25713 */
25714static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25715{
25716 TCGv t0, t1;
4ca83721
CJ
25717 uint32_t XRa, Rb, s12, sel;
25718
25719 t0 = tcg_temp_new();
25720 t1 = tcg_temp_new();
25721
4ca83721
CJ
25722 XRa = extract32(ctx->opcode, 6, 4);
25723 s12 = extract32(ctx->opcode, 10, 10);
25724 sel = extract32(ctx->opcode, 20, 1);
25725 Rb = extract32(ctx->opcode, 21, 5);
25726
4ca83721
CJ
25727 gen_load_gpr(t0, Rb);
25728
25729 tcg_gen_movi_tl(t1, s12);
25730 tcg_gen_shli_tl(t1, t1, 2);
25731 if (s12 & 0x200) {
25732 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25733 }
25734 tcg_gen_add_tl(t1, t0, t1);
25735 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25736
25737 if (sel == 1) {
25738 /* S32LDDR */
25739 tcg_gen_bswap32_tl(t1, t1);
25740 }
25741 gen_store_mxu_gpr(t1, XRa);
25742
4ca83721
CJ
25743 tcg_temp_free(t0);
25744 tcg_temp_free(t1);
25745}
25746
96992d1a 25747
b621f018
AM
25748/*
25749 * MXU instruction category: logic
25750 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25751 *
25752 * S32NOR S32AND S32OR S32XOR
25753 */
25754
25755/*
25756 * S32NOR XRa, XRb, XRc
25757 * Update XRa with the result of logical bitwise 'nor' operation
25758 * applied to the content of XRb and XRc.
25759 *
25760 * 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
25761 * +-----------+---------+-----+-------+-------+-------+-----------+
25762 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25763 * +-----------+---------+-----+-------+-------+-------+-----------+
25764 */
25765static void gen_mxu_S32NOR(DisasContext *ctx)
25766{
25767 uint32_t pad, XRc, XRb, XRa;
25768
25769 pad = extract32(ctx->opcode, 21, 5);
25770 XRc = extract32(ctx->opcode, 14, 4);
25771 XRb = extract32(ctx->opcode, 10, 4);
25772 XRa = extract32(ctx->opcode, 6, 4);
25773
25774 if (unlikely(pad != 0)) {
25775 /* opcode padding incorrect -> do nothing */
25776 } else if (unlikely(XRa == 0)) {
25777 /* destination is zero register -> do nothing */
25778 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25779 /* both operands zero registers -> just set destination to all 1s */
25780 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25781 } else if (unlikely(XRb == 0)) {
25782 /* XRb zero register -> just set destination to the negation of XRc */
25783 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25784 } else if (unlikely(XRc == 0)) {
25785 /* XRa zero register -> just set destination to the negation of XRb */
25786 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25787 } else if (unlikely(XRb == XRc)) {
25788 /* both operands same -> just set destination to the negation of XRb */
25789 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25790 } else {
25791 /* the most general case */
25792 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25793 }
25794}
25795
25796/*
25797 * S32AND XRa, XRb, XRc
25798 * Update XRa with the result of logical bitwise 'and' operation
25799 * applied to the content of XRb and XRc.
25800 *
25801 * 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
25802 * +-----------+---------+-----+-------+-------+-------+-----------+
25803 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25804 * +-----------+---------+-----+-------+-------+-------+-----------+
25805 */
25806static void gen_mxu_S32AND(DisasContext *ctx)
25807{
25808 uint32_t pad, XRc, XRb, XRa;
25809
25810 pad = extract32(ctx->opcode, 21, 5);
25811 XRc = extract32(ctx->opcode, 14, 4);
25812 XRb = extract32(ctx->opcode, 10, 4);
25813 XRa = extract32(ctx->opcode, 6, 4);
25814
25815 if (unlikely(pad != 0)) {
25816 /* opcode padding incorrect -> do nothing */
25817 } else if (unlikely(XRa == 0)) {
25818 /* destination is zero register -> do nothing */
25819 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25820 /* one of operands zero register -> just set destination to all 0s */
25821 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25822 } else if (unlikely(XRb == XRc)) {
25823 /* both operands same -> just set destination to one of them */
25824 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25825 } else {
25826 /* the most general case */
25827 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25828 }
25829}
25830
25831/*
25832 * S32OR XRa, XRb, XRc
25833 * Update XRa with the result of logical bitwise 'or' operation
25834 * applied to the content of XRb and XRc.
25835 *
25836 * 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
25837 * +-----------+---------+-----+-------+-------+-------+-----------+
25838 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25839 * +-----------+---------+-----+-------+-------+-------+-----------+
25840 */
25841static void gen_mxu_S32OR(DisasContext *ctx)
25842{
25843 uint32_t pad, XRc, XRb, XRa;
25844
25845 pad = extract32(ctx->opcode, 21, 5);
25846 XRc = extract32(ctx->opcode, 14, 4);
25847 XRb = extract32(ctx->opcode, 10, 4);
25848 XRa = extract32(ctx->opcode, 6, 4);
25849
25850 if (unlikely(pad != 0)) {
25851 /* opcode padding incorrect -> do nothing */
25852 } else if (unlikely(XRa == 0)) {
25853 /* destination is zero register -> do nothing */
25854 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25855 /* both operands zero registers -> just set destination to all 0s */
25856 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25857 } else if (unlikely(XRb == 0)) {
25858 /* XRb zero register -> just set destination to the content of XRc */
25859 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25860 } else if (unlikely(XRc == 0)) {
25861 /* XRc zero register -> just set destination to the content of XRb */
25862 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25863 } else if (unlikely(XRb == XRc)) {
25864 /* both operands same -> just set destination to one of them */
25865 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25866 } else {
25867 /* the most general case */
25868 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25869 }
25870}
25871
25872/*
25873 * S32XOR XRa, XRb, XRc
25874 * Update XRa with the result of logical bitwise 'xor' operation
25875 * applied to the content of XRb and XRc.
25876 *
25877 * 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
25878 * +-----------+---------+-----+-------+-------+-------+-----------+
25879 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25880 * +-----------+---------+-----+-------+-------+-------+-----------+
25881 */
25882static void gen_mxu_S32XOR(DisasContext *ctx)
25883{
25884 uint32_t pad, XRc, XRb, XRa;
25885
25886 pad = extract32(ctx->opcode, 21, 5);
25887 XRc = extract32(ctx->opcode, 14, 4);
25888 XRb = extract32(ctx->opcode, 10, 4);
25889 XRa = extract32(ctx->opcode, 6, 4);
25890
25891 if (unlikely(pad != 0)) {
25892 /* opcode padding incorrect -> do nothing */
25893 } else if (unlikely(XRa == 0)) {
25894 /* destination is zero register -> do nothing */
25895 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25896 /* both operands zero registers -> just set destination to all 0s */
25897 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25898 } else if (unlikely(XRb == 0)) {
25899 /* XRb zero register -> just set destination to the content of XRc */
25900 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25901 } else if (unlikely(XRc == 0)) {
25902 /* XRc zero register -> just set destination to the content of XRb */
25903 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25904 } else if (unlikely(XRb == XRc)) {
25905 /* both operands same -> just set destination to all 0s */
25906 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25907 } else {
25908 /* the most general case */
25909 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25910 }
25911}
25912
25913
bb84cbf3
AM
25914/*
25915 * MXU instruction category max/min
25916 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25917 *
25918 * S32MAX D16MAX Q8MAX
25919 * S32MIN D16MIN Q8MIN
25920 */
25921
25922/*
25923 * S32MAX XRa, XRb, XRc
25924 * Update XRa with the maximum of signed 32-bit integers contained
25925 * in XRb and XRc.
25926 *
25927 * S32MIN XRa, XRb, XRc
25928 * Update XRa with the minimum of signed 32-bit integers contained
25929 * in XRb and XRc.
25930 *
25931 * 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
25932 * +-----------+---------+-----+-------+-------+-------+-----------+
25933 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25934 * +-----------+---------+-----+-------+-------+-------+-----------+
25935 */
25936static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25937{
25938 uint32_t pad, opc, XRc, XRb, XRa;
25939
25940 pad = extract32(ctx->opcode, 21, 5);
25941 opc = extract32(ctx->opcode, 18, 3);
25942 XRc = extract32(ctx->opcode, 14, 4);
25943 XRb = extract32(ctx->opcode, 10, 4);
25944 XRa = extract32(ctx->opcode, 6, 4);
25945
25946 if (unlikely(pad != 0)) {
25947 /* opcode padding incorrect -> do nothing */
25948 } else if (unlikely(XRa == 0)) {
25949 /* destination is zero register -> do nothing */
25950 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25951 /* both operands zero registers -> just set destination to zero */
25952 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25953 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25954 /* exactly one operand is zero register - find which one is not...*/
25955 uint32_t XRx = XRb ? XRb : XRc;
25956 /* ...and do max/min operation with one operand 0 */
25957 if (opc == OPC_MXU_S32MAX) {
25958 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25959 } else {
25960 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25961 }
25962 } else if (unlikely(XRb == XRc)) {
25963 /* both operands same -> just set destination to one of them */
25964 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25965 } else {
25966 /* the most general case */
25967 if (opc == OPC_MXU_S32MAX) {
25968 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25969 mxu_gpr[XRc - 1]);
25970 } else {
25971 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25972 mxu_gpr[XRc - 1]);
25973 }
25974 }
25975}
25976
25977/*
25978 * D16MAX
25979 * Update XRa with the 16-bit-wise maximums of signed integers
25980 * contained in XRb and XRc.
25981 *
25982 * D16MIN
25983 * Update XRa with the 16-bit-wise minimums of signed integers
25984 * contained in XRb and XRc.
25985 *
25986 * 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
25987 * +-----------+---------+-----+-------+-------+-------+-----------+
25988 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25989 * +-----------+---------+-----+-------+-------+-------+-----------+
25990 */
25991static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25992{
25993 uint32_t pad, opc, XRc, XRb, XRa;
25994
25995 pad = extract32(ctx->opcode, 21, 5);
25996 opc = extract32(ctx->opcode, 18, 3);
25997 XRc = extract32(ctx->opcode, 14, 4);
25998 XRb = extract32(ctx->opcode, 10, 4);
25999 XRa = extract32(ctx->opcode, 6, 4);
26000
26001 if (unlikely(pad != 0)) {
26002 /* opcode padding incorrect -> do nothing */
26003 } else if (unlikely(XRc == 0)) {
26004 /* destination is zero register -> do nothing */
26005 } else if (unlikely((XRb == 0) && (XRa == 0))) {
26006 /* both operands zero registers -> just set destination to zero */
26007 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
26008 } else if (unlikely((XRb == 0) || (XRa == 0))) {
26009 /* exactly one operand is zero register - find which one is not...*/
26010 uint32_t XRx = XRb ? XRb : XRc;
26011 /* ...and do half-word-wise max/min with one operand 0 */
26012 TCGv_i32 t0 = tcg_temp_new();
26013 TCGv_i32 t1 = tcg_const_i32(0);
26014
26015 /* the left half-word first */
26016 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
26017 if (opc == OPC_MXU_D16MAX) {
26018 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26019 } else {
26020 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26021 }
26022
26023 /* the right half-word */
26024 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
26025 /* move half-words to the leftmost position */
26026 tcg_gen_shli_i32(t0, t0, 16);
26027 /* t0 will be max/min of t0 and t1 */
26028 if (opc == OPC_MXU_D16MAX) {
26029 tcg_gen_smax_i32(t0, t0, t1);
26030 } else {
26031 tcg_gen_smin_i32(t0, t0, t1);
26032 }
26033 /* return resulting half-words to its original position */
26034 tcg_gen_shri_i32(t0, t0, 16);
8cdf8869 26035 /* finally update the destination */
bb84cbf3
AM
26036 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26037
26038 tcg_temp_free(t1);
26039 tcg_temp_free(t0);
26040 } else if (unlikely(XRb == XRc)) {
26041 /* both operands same -> just set destination to one of them */
26042 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26043 } else {
26044 /* the most general case */
26045 TCGv_i32 t0 = tcg_temp_new();
26046 TCGv_i32 t1 = tcg_temp_new();
26047
26048 /* the left half-word first */
26049 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
26050 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26051 if (opc == OPC_MXU_D16MAX) {
26052 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26053 } else {
26054 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26055 }
26056
26057 /* the right half-word */
26058 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26059 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
26060 /* move half-words to the leftmost position */
26061 tcg_gen_shli_i32(t0, t0, 16);
26062 tcg_gen_shli_i32(t1, t1, 16);
26063 /* t0 will be max/min of t0 and t1 */
26064 if (opc == OPC_MXU_D16MAX) {
26065 tcg_gen_smax_i32(t0, t0, t1);
26066 } else {
26067 tcg_gen_smin_i32(t0, t0, t1);
26068 }
26069 /* return resulting half-words to its original position */
26070 tcg_gen_shri_i32(t0, t0, 16);
8cdf8869 26071 /* finally update the destination */
bb84cbf3
AM
26072 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26073
26074 tcg_temp_free(t1);
26075 tcg_temp_free(t0);
26076 }
26077}
26078
26079/*
26080 * Q8MAX
26081 * Update XRa with the 8-bit-wise maximums of signed integers
26082 * contained in XRb and XRc.
26083 *
26084 * Q8MIN
26085 * Update XRa with the 8-bit-wise minimums of signed integers
26086 * contained in XRb and XRc.
26087 *
26088 * 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
26089 * +-----------+---------+-----+-------+-------+-------+-----------+
26090 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
26091 * +-----------+---------+-----+-------+-------+-------+-----------+
26092 */
26093static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
26094{
26095 uint32_t pad, opc, XRc, XRb, XRa;
26096
26097 pad = extract32(ctx->opcode, 21, 5);
26098 opc = extract32(ctx->opcode, 18, 3);
26099 XRc = extract32(ctx->opcode, 14, 4);
26100 XRb = extract32(ctx->opcode, 10, 4);
26101 XRa = extract32(ctx->opcode, 6, 4);
26102
26103 if (unlikely(pad != 0)) {
26104 /* opcode padding incorrect -> do nothing */
26105 } else if (unlikely(XRa == 0)) {
26106 /* destination is zero register -> do nothing */
26107 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26108 /* both operands zero registers -> just set destination to zero */
26109 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26110 } else if (unlikely((XRb == 0) || (XRc == 0))) {
26111 /* exactly one operand is zero register - make it be the first...*/
26112 uint32_t XRx = XRb ? XRb : XRc;
26113 /* ...and do byte-wise max/min with one operand 0 */
26114 TCGv_i32 t0 = tcg_temp_new();
26115 TCGv_i32 t1 = tcg_const_i32(0);
26116 int32_t i;
26117
26118 /* the leftmost byte (byte 3) first */
26119 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
26120 if (opc == OPC_MXU_Q8MAX) {
26121 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26122 } else {
26123 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26124 }
26125
26126 /* bytes 2, 1, 0 */
26127 for (i = 2; i >= 0; i--) {
26128 /* extract the byte */
26129 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26130 /* move the byte to the leftmost position */
26131 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26132 /* t0 will be max/min of t0 and t1 */
26133 if (opc == OPC_MXU_Q8MAX) {
26134 tcg_gen_smax_i32(t0, t0, t1);
26135 } else {
26136 tcg_gen_smin_i32(t0, t0, t1);
26137 }
26138 /* return resulting byte to its original position */
26139 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
8cdf8869 26140 /* finally update the destination */
bb84cbf3
AM
26141 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26142 }
26143
26144 tcg_temp_free(t1);
26145 tcg_temp_free(t0);
26146 } else if (unlikely(XRb == XRc)) {
26147 /* both operands same -> just set destination to one of them */
26148 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26149 } else {
26150 /* the most general case */
26151 TCGv_i32 t0 = tcg_temp_new();
26152 TCGv_i32 t1 = tcg_temp_new();
26153 int32_t i;
26154
26155 /* the leftmost bytes (bytes 3) first */
26156 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26157 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26158 if (opc == OPC_MXU_Q8MAX) {
26159 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26160 } else {
26161 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26162 }
26163
26164 /* bytes 2, 1, 0 */
26165 for (i = 2; i >= 0; i--) {
26166 /* extract corresponding bytes */
26167 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26168 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26169 /* move the bytes to the leftmost position */
26170 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26171 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26172 /* t0 will be max/min of t0 and t1 */
26173 if (opc == OPC_MXU_Q8MAX) {
26174 tcg_gen_smax_i32(t0, t0, t1);
26175 } else {
26176 tcg_gen_smin_i32(t0, t0, t1);
26177 }
26178 /* return resulting byte to its original position */
26179 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
8cdf8869 26180 /* finally update the destination */
bb84cbf3
AM
26181 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26182 }
26183
26184 tcg_temp_free(t1);
26185 tcg_temp_free(t0);
26186 }
26187}
26188
26189
79f5fee7
AM
26190/*
26191 * MXU instruction category: align
26192 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26193 *
26194 * S32ALN S32ALNI
26195 */
26196
26197/*
26198 * S32ALNI XRc, XRb, XRa, optn3
26199 * Arrange bytes from XRb and XRc according to one of five sets of
26200 * rules determined by optn3, and place the result in XRa.
26201 *
26202 * 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
26203 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26204 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26205 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26206 *
26207 */
26208static void gen_mxu_S32ALNI(DisasContext *ctx)
26209{
26210 uint32_t optn3, pad, XRc, XRb, XRa;
26211
26212 optn3 = extract32(ctx->opcode, 23, 3);
26213 pad = extract32(ctx->opcode, 21, 2);
26214 XRc = extract32(ctx->opcode, 14, 4);
26215 XRb = extract32(ctx->opcode, 10, 4);
26216 XRa = extract32(ctx->opcode, 6, 4);
26217
26218 if (unlikely(pad != 0)) {
26219 /* opcode padding incorrect -> do nothing */
26220 } else if (unlikely(XRa == 0)) {
26221 /* destination is zero register -> do nothing */
26222 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26223 /* both operands zero registers -> just set destination to all 0s */
26224 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26225 } else if (unlikely(XRb == 0)) {
26226 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26227 switch (optn3) {
26228 case MXU_OPTN3_PTN0:
26229 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26230 break;
26231 case MXU_OPTN3_PTN1:
26232 case MXU_OPTN3_PTN2:
26233 case MXU_OPTN3_PTN3:
26234 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26235 8 * (4 - optn3));
26236 break;
26237 case MXU_OPTN3_PTN4:
26238 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26239 break;
26240 }
26241 } else if (unlikely(XRc == 0)) {
26242 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26243 switch (optn3) {
26244 case MXU_OPTN3_PTN0:
26245 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26246 break;
26247 case MXU_OPTN3_PTN1:
26248 case MXU_OPTN3_PTN2:
26249 case MXU_OPTN3_PTN3:
26250 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26251 break;
26252 case MXU_OPTN3_PTN4:
26253 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26254 break;
26255 }
26256 } else if (unlikely(XRb == XRc)) {
26257 /* both operands same -> just rotation or moving from any of them */
26258 switch (optn3) {
26259 case MXU_OPTN3_PTN0:
26260 case MXU_OPTN3_PTN4:
26261 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26262 break;
26263 case MXU_OPTN3_PTN1:
26264 case MXU_OPTN3_PTN2:
26265 case MXU_OPTN3_PTN3:
26266 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26267 break;
26268 }
26269 } else {
26270 /* the most general case */
26271 switch (optn3) {
26272 case MXU_OPTN3_PTN0:
26273 {
26274 /* */
26275 /* XRb XRc */
26276 /* +---------------+ */
26277 /* | A B C D | E F G H */
26278 /* +-------+-------+ */
26279 /* | */
26280 /* XRa */
26281 /* */
26282
26283 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26284 }
26285 break;
26286 case MXU_OPTN3_PTN1:
26287 {
26288 /* */
26289 /* XRb XRc */
26290 /* +-------------------+ */
26291 /* A | B C D E | F G H */
26292 /* +---------+---------+ */
26293 /* | */
26294 /* XRa */
26295 /* */
26296
26297 TCGv_i32 t0 = tcg_temp_new();
26298 TCGv_i32 t1 = tcg_temp_new();
26299
26300 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26301 tcg_gen_shli_i32(t0, t0, 8);
26302
26303 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26304 tcg_gen_shri_i32(t1, t1, 24);
26305
26306 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26307
26308 tcg_temp_free(t1);
26309 tcg_temp_free(t0);
26310 }
26311 break;
26312 case MXU_OPTN3_PTN2:
26313 {
26314 /* */
26315 /* XRb XRc */
26316 /* +-------------------+ */
26317 /* A B | C D E F | G H */
26318 /* +---------+---------+ */
26319 /* | */
26320 /* XRa */
26321 /* */
26322
26323 TCGv_i32 t0 = tcg_temp_new();
26324 TCGv_i32 t1 = tcg_temp_new();
26325
26326 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26327 tcg_gen_shli_i32(t0, t0, 16);
26328
26329 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26330 tcg_gen_shri_i32(t1, t1, 16);
26331
26332 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26333
26334 tcg_temp_free(t1);
26335 tcg_temp_free(t0);
26336 }
26337 break;
26338 case MXU_OPTN3_PTN3:
26339 {
26340 /* */
26341 /* XRb XRc */
26342 /* +-------------------+ */
26343 /* A B C | D E F G | H */
26344 /* +---------+---------+ */
26345 /* | */
26346 /* XRa */
26347 /* */
26348
26349 TCGv_i32 t0 = tcg_temp_new();
26350 TCGv_i32 t1 = tcg_temp_new();
26351
26352 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26353 tcg_gen_shli_i32(t0, t0, 24);
26354
26355 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26356 tcg_gen_shri_i32(t1, t1, 8);
26357
26358 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26359
26360 tcg_temp_free(t1);
26361 tcg_temp_free(t0);
26362 }
26363 break;
26364 case MXU_OPTN3_PTN4:
26365 {
26366 /* */
26367 /* XRb XRc */
26368 /* +---------------+ */
26369 /* A B C D | E F G H | */
26370 /* +-------+-------+ */
26371 /* | */
26372 /* XRa */
26373 /* */
26374
26375 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26376 }
26377 break;
26378 }
26379 }
26380}
26381
26382
96992d1a
CJ
26383/*
26384 * Decoding engine for MXU
26385 * =======================
26386 */
26387
03f40088
AM
26388/*
26389 *
26390 * Decode MXU pool00
26391 *
26392 * 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
26393 * +-----------+---------+-----+-------+-------+-------+-----------+
26394 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26395 * +-----------+---------+-----+-------+-------+-------+-----------+
26396 *
26397 */
26398static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26399{
26400 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26401
26402 switch (opcode) {
26403 case OPC_MXU_S32MAX:
03f40088 26404 case OPC_MXU_S32MIN:
bb84cbf3 26405 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
26406 break;
26407 case OPC_MXU_D16MAX:
03f40088 26408 case OPC_MXU_D16MIN:
bb84cbf3 26409 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
26410 break;
26411 case OPC_MXU_Q8MAX:
03f40088 26412 case OPC_MXU_Q8MIN:
bb84cbf3 26413 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
26414 break;
26415 case OPC_MXU_Q8SLT:
26416 /* TODO: Implement emulation of Q8SLT instruction. */
26417 MIPS_INVAL("OPC_MXU_Q8SLT");
26418 generate_exception_end(ctx, EXCP_RI);
26419 break;
26420 case OPC_MXU_Q8SLTU:
26421 /* TODO: Implement emulation of Q8SLTU instruction. */
26422 MIPS_INVAL("OPC_MXU_Q8SLTU");
26423 generate_exception_end(ctx, EXCP_RI);
26424 break;
26425 default:
26426 MIPS_INVAL("decode_opc_mxu");
26427 generate_exception_end(ctx, EXCP_RI);
26428 break;
26429 }
26430}
26431
26432/*
26433 *
26434 * Decode MXU pool01
26435 *
26436 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26437 * 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
26438 * +-----------+---------+-----+-------+-------+-------+-----------+
26439 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26440 * +-----------+---------+-----+-------+-------+-------+-----------+
26441 *
26442 * Q8ADD:
26443 * 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
26444 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26445 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26446 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26447 *
26448 */
26449static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26450{
26451 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26452
26453 switch (opcode) {
26454 case OPC_MXU_S32SLT:
26455 /* TODO: Implement emulation of S32SLT instruction. */
26456 MIPS_INVAL("OPC_MXU_S32SLT");
26457 generate_exception_end(ctx, EXCP_RI);
26458 break;
26459 case OPC_MXU_D16SLT:
26460 /* TODO: Implement emulation of D16SLT instruction. */
26461 MIPS_INVAL("OPC_MXU_D16SLT");
26462 generate_exception_end(ctx, EXCP_RI);
26463 break;
26464 case OPC_MXU_D16AVG:
26465 /* TODO: Implement emulation of D16AVG instruction. */
26466 MIPS_INVAL("OPC_MXU_D16AVG");
26467 generate_exception_end(ctx, EXCP_RI);
26468 break;
26469 case OPC_MXU_D16AVGR:
26470 /* TODO: Implement emulation of D16AVGR instruction. */
26471 MIPS_INVAL("OPC_MXU_D16AVGR");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 case OPC_MXU_Q8AVG:
26475 /* TODO: Implement emulation of Q8AVG instruction. */
26476 MIPS_INVAL("OPC_MXU_Q8AVG");
26477 generate_exception_end(ctx, EXCP_RI);
26478 break;
26479 case OPC_MXU_Q8AVGR:
26480 /* TODO: Implement emulation of Q8AVGR instruction. */
26481 MIPS_INVAL("OPC_MXU_Q8AVGR");
26482 generate_exception_end(ctx, EXCP_RI);
26483 break;
26484 case OPC_MXU_Q8ADD:
26485 /* TODO: Implement emulation of Q8ADD instruction. */
26486 MIPS_INVAL("OPC_MXU_Q8ADD");
26487 generate_exception_end(ctx, EXCP_RI);
26488 break;
26489 default:
26490 MIPS_INVAL("decode_opc_mxu");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 }
26494}
26495
26496/*
26497 *
26498 * Decode MXU pool02
26499 *
26500 * 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
26501 * +-----------+---------+-----+-------+-------+-------+-----------+
26502 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26503 * +-----------+---------+-----+-------+-------+-------+-----------+
26504 *
26505 */
26506static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26507{
26508 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26509
26510 switch (opcode) {
26511 case OPC_MXU_S32CPS:
26512 /* TODO: Implement emulation of S32CPS instruction. */
26513 MIPS_INVAL("OPC_MXU_S32CPS");
26514 generate_exception_end(ctx, EXCP_RI);
26515 break;
26516 case OPC_MXU_D16CPS:
26517 /* TODO: Implement emulation of D16CPS instruction. */
26518 MIPS_INVAL("OPC_MXU_D16CPS");
26519 generate_exception_end(ctx, EXCP_RI);
26520 break;
26521 case OPC_MXU_Q8ABD:
26522 /* TODO: Implement emulation of Q8ABD instruction. */
26523 MIPS_INVAL("OPC_MXU_Q8ABD");
26524 generate_exception_end(ctx, EXCP_RI);
26525 break;
26526 case OPC_MXU_Q16SAT:
26527 /* TODO: Implement emulation of Q16SAT instruction. */
26528 MIPS_INVAL("OPC_MXU_Q16SAT");
26529 generate_exception_end(ctx, EXCP_RI);
26530 break;
26531 default:
26532 MIPS_INVAL("decode_opc_mxu");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26535 }
26536}
26537
26538/*
26539 *
26540 * Decode MXU pool03
26541 *
26542 * D16MULF:
26543 * 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
26544 * +-----------+---+---+-------+-------+-------+-------+-----------+
26545 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26546 * +-----------+---+---+-------+-------+-------+-------+-----------+
26547 *
26548 * D16MULE:
26549 * 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
26550 * +-----------+---+---+-------+-------+-------+-------+-----------+
26551 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26552 * +-----------+---+---+-------+-------+-------+-------+-----------+
26553 *
26554 */
26555static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26556{
26557 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26558
26559 switch (opcode) {
26560 case OPC_MXU_D16MULF:
26561 /* TODO: Implement emulation of D16MULF instruction. */
26562 MIPS_INVAL("OPC_MXU_D16MULF");
26563 generate_exception_end(ctx, EXCP_RI);
26564 break;
26565 case OPC_MXU_D16MULE:
26566 /* TODO: Implement emulation of D16MULE instruction. */
26567 MIPS_INVAL("OPC_MXU_D16MULE");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 default:
26571 MIPS_INVAL("decode_opc_mxu");
26572 generate_exception_end(ctx, EXCP_RI);
26573 break;
26574 }
26575}
26576
26577/*
26578 *
26579 * Decode MXU pool04
26580 *
26581 * 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
26582 * +-----------+---------+-+-------------------+-------+-----------+
26583 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26584 * +-----------+---------+-+-------------------+-------+-----------+
26585 *
26586 */
26587static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26588{
26589 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26590
26591 switch (opcode) {
26592 case OPC_MXU_S32LDD:
03f40088 26593 case OPC_MXU_S32LDDR:
4ca83721 26594 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
26595 break;
26596 default:
26597 MIPS_INVAL("decode_opc_mxu");
26598 generate_exception_end(ctx, EXCP_RI);
26599 break;
26600 }
26601}
26602
26603/*
26604 *
26605 * Decode MXU pool05
26606 *
26607 * 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
26608 * +-----------+---------+-+-------------------+-------+-----------+
26609 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26610 * +-----------+---------+-+-------------------+-------+-----------+
26611 *
26612 */
26613static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26614{
26615 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26616
26617 switch (opcode) {
26618 case OPC_MXU_S32STD:
26619 /* TODO: Implement emulation of S32STD instruction. */
26620 MIPS_INVAL("OPC_MXU_S32STD");
26621 generate_exception_end(ctx, EXCP_RI);
26622 break;
26623 case OPC_MXU_S32STDR:
26624 /* TODO: Implement emulation of S32STDR instruction. */
26625 MIPS_INVAL("OPC_MXU_S32STDR");
26626 generate_exception_end(ctx, EXCP_RI);
26627 break;
26628 default:
26629 MIPS_INVAL("decode_opc_mxu");
26630 generate_exception_end(ctx, EXCP_RI);
26631 break;
26632 }
26633}
26634
26635/*
26636 *
26637 * Decode MXU pool06
26638 *
26639 * 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
26640 * +-----------+---------+---------+---+-------+-------+-----------+
26641 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26642 * +-----------+---------+---------+---+-------+-------+-----------+
26643 *
26644 */
26645static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26646{
26647 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26648
26649 switch (opcode) {
26650 case OPC_MXU_S32LDDV:
26651 /* TODO: Implement emulation of S32LDDV instruction. */
26652 MIPS_INVAL("OPC_MXU_S32LDDV");
26653 generate_exception_end(ctx, EXCP_RI);
26654 break;
26655 case OPC_MXU_S32LDDVR:
26656 /* TODO: Implement emulation of S32LDDVR instruction. */
26657 MIPS_INVAL("OPC_MXU_S32LDDVR");
26658 generate_exception_end(ctx, EXCP_RI);
26659 break;
26660 default:
26661 MIPS_INVAL("decode_opc_mxu");
26662 generate_exception_end(ctx, EXCP_RI);
26663 break;
26664 }
26665}
26666
26667/*
26668 *
26669 * Decode MXU pool07
26670 *
26671 * 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
26672 * +-----------+---------+---------+---+-------+-------+-----------+
26673 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26674 * +-----------+---------+---------+---+-------+-------+-----------+
26675 *
26676 */
26677static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26678{
26679 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26680
26681 switch (opcode) {
26682 case OPC_MXU_S32STDV:
26683 /* TODO: Implement emulation of S32TDV instruction. */
26684 MIPS_INVAL("OPC_MXU_S32TDV");
26685 generate_exception_end(ctx, EXCP_RI);
26686 break;
26687 case OPC_MXU_S32STDVR:
26688 /* TODO: Implement emulation of S32TDVR instruction. */
26689 MIPS_INVAL("OPC_MXU_S32TDVR");
26690 generate_exception_end(ctx, EXCP_RI);
26691 break;
26692 default:
26693 MIPS_INVAL("decode_opc_mxu");
26694 generate_exception_end(ctx, EXCP_RI);
26695 break;
26696 }
26697}
26698
26699/*
26700 *
26701 * Decode MXU pool08
26702 *
26703 * 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
26704 * +-----------+---------+-+-------------------+-------+-----------+
26705 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26706 * +-----------+---------+-+-------------------+-------+-----------+
26707 *
7480515f 26708 */
03f40088
AM
26709static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26710{
26711 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26712
26713 switch (opcode) {
26714 case OPC_MXU_S32LDI:
26715 /* TODO: Implement emulation of S32LDI instruction. */
26716 MIPS_INVAL("OPC_MXU_S32LDI");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_S32LDIR:
26720 /* TODO: Implement emulation of S32LDIR instruction. */
26721 MIPS_INVAL("OPC_MXU_S32LDIR");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 default:
26725 MIPS_INVAL("decode_opc_mxu");
26726 generate_exception_end(ctx, EXCP_RI);
26727 break;
26728 }
26729}
26730
26731/*
26732 *
26733 * Decode MXU pool09
26734 *
26735 * 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
26736 * +-----------+---------+-+-------------------+-------+-----------+
26737 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26738 * +-----------+---------+-+-------------------+-------+-----------+
26739 *
26740 */
26741static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26742{
26743 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26744
26745 switch (opcode) {
26746 case OPC_MXU_S32SDI:
26747 /* TODO: Implement emulation of S32SDI instruction. */
26748 MIPS_INVAL("OPC_MXU_S32SDI");
26749 generate_exception_end(ctx, EXCP_RI);
26750 break;
26751 case OPC_MXU_S32SDIR:
26752 /* TODO: Implement emulation of S32SDIR instruction. */
26753 MIPS_INVAL("OPC_MXU_S32SDIR");
26754 generate_exception_end(ctx, EXCP_RI);
26755 break;
26756 default:
26757 MIPS_INVAL("decode_opc_mxu");
26758 generate_exception_end(ctx, EXCP_RI);
26759 break;
26760 }
26761}
26762
26763/*
26764 *
26765 * Decode MXU pool10
26766 *
26767 * 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
26768 * +-----------+---------+---------+---+-------+-------+-----------+
26769 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26770 * +-----------+---------+---------+---+-------+-------+-----------+
26771 *
26772 */
26773static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26774{
26775 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26776
26777 switch (opcode) {
26778 case OPC_MXU_S32LDIV:
26779 /* TODO: Implement emulation of S32LDIV instruction. */
26780 MIPS_INVAL("OPC_MXU_S32LDIV");
26781 generate_exception_end(ctx, EXCP_RI);
26782 break;
26783 case OPC_MXU_S32LDIVR:
26784 /* TODO: Implement emulation of S32LDIVR instruction. */
26785 MIPS_INVAL("OPC_MXU_S32LDIVR");
26786 generate_exception_end(ctx, EXCP_RI);
26787 break;
26788 default:
26789 MIPS_INVAL("decode_opc_mxu");
26790 generate_exception_end(ctx, EXCP_RI);
26791 break;
26792 }
26793}
26794
26795/*
26796 *
26797 * Decode MXU pool11
26798 *
26799 * 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
26800 * +-----------+---------+---------+---+-------+-------+-----------+
26801 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26802 * +-----------+---------+---------+---+-------+-------+-----------+
26803 *
26804 */
26805static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26806{
26807 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26808
26809 switch (opcode) {
26810 case OPC_MXU_S32SDIV:
26811 /* TODO: Implement emulation of S32SDIV instruction. */
26812 MIPS_INVAL("OPC_MXU_S32SDIV");
26813 generate_exception_end(ctx, EXCP_RI);
26814 break;
26815 case OPC_MXU_S32SDIVR:
26816 /* TODO: Implement emulation of S32SDIVR instruction. */
26817 MIPS_INVAL("OPC_MXU_S32SDIVR");
26818 generate_exception_end(ctx, EXCP_RI);
26819 break;
26820 default:
26821 MIPS_INVAL("decode_opc_mxu");
26822 generate_exception_end(ctx, EXCP_RI);
26823 break;
26824 }
26825}
26826
26827/*
26828 *
26829 * Decode MXU pool12
26830 *
26831 * 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
26832 * +-----------+---+---+-------+-------+-------+-------+-----------+
26833 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26834 * +-----------+---+---+-------+-------+-------+-------+-----------+
26835 *
26836 */
26837static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26838{
26839 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26840
26841 switch (opcode) {
26842 case OPC_MXU_D32ACC:
26843 /* TODO: Implement emulation of D32ACC instruction. */
26844 MIPS_INVAL("OPC_MXU_D32ACC");
26845 generate_exception_end(ctx, EXCP_RI);
26846 break;
26847 case OPC_MXU_D32ACCM:
26848 /* TODO: Implement emulation of D32ACCM instruction. */
26849 MIPS_INVAL("OPC_MXU_D32ACCM");
26850 generate_exception_end(ctx, EXCP_RI);
26851 break;
26852 case OPC_MXU_D32ASUM:
26853 /* TODO: Implement emulation of D32ASUM instruction. */
26854 MIPS_INVAL("OPC_MXU_D32ASUM");
26855 generate_exception_end(ctx, EXCP_RI);
26856 break;
26857 default:
26858 MIPS_INVAL("decode_opc_mxu");
26859 generate_exception_end(ctx, EXCP_RI);
26860 break;
26861 }
26862}
26863
26864/*
26865 *
26866 * Decode MXU pool13
26867 *
26868 * 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
26869 * +-----------+---+---+-------+-------+-------+-------+-----------+
26870 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26871 * +-----------+---+---+-------+-------+-------+-------+-----------+
26872 *
26873 */
26874static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26875{
26876 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26877
26878 switch (opcode) {
26879 case OPC_MXU_Q16ACC:
26880 /* TODO: Implement emulation of Q16ACC instruction. */
26881 MIPS_INVAL("OPC_MXU_Q16ACC");
26882 generate_exception_end(ctx, EXCP_RI);
26883 break;
26884 case OPC_MXU_Q16ACCM:
26885 /* TODO: Implement emulation of Q16ACCM instruction. */
26886 MIPS_INVAL("OPC_MXU_Q16ACCM");
26887 generate_exception_end(ctx, EXCP_RI);
26888 break;
26889 case OPC_MXU_Q16ASUM:
26890 /* TODO: Implement emulation of Q16ASUM instruction. */
26891 MIPS_INVAL("OPC_MXU_Q16ASUM");
26892 generate_exception_end(ctx, EXCP_RI);
26893 break;
26894 default:
26895 MIPS_INVAL("decode_opc_mxu");
26896 generate_exception_end(ctx, EXCP_RI);
26897 break;
26898 }
26899}
26900
26901/*
26902 *
26903 * Decode MXU pool14
26904 *
26905 * Q8ADDE, Q8ACCE:
26906 * 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
26907 * +-----------+---+---+-------+-------+-------+-------+-----------+
26908 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26909 * +-----------+---+---+-------+-------+-------+-------+-----------+
26910 *
26911 * D8SUM, D8SUMC:
26912 * 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
26913 * +-----------+---+---+-------+-------+-------+-------+-----------+
26914 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26915 * +-----------+---+---+-------+-------+-------+-------+-----------+
26916 *
26917 */
26918static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26919{
26920 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26921
26922 switch (opcode) {
26923 case OPC_MXU_Q8ADDE:
26924 /* TODO: Implement emulation of Q8ADDE instruction. */
26925 MIPS_INVAL("OPC_MXU_Q8ADDE");
26926 generate_exception_end(ctx, EXCP_RI);
26927 break;
26928 case OPC_MXU_D8SUM:
26929 /* TODO: Implement emulation of D8SUM instruction. */
26930 MIPS_INVAL("OPC_MXU_D8SUM");
26931 generate_exception_end(ctx, EXCP_RI);
26932 break;
26933 case OPC_MXU_D8SUMC:
26934 /* TODO: Implement emulation of D8SUMC instruction. */
26935 MIPS_INVAL("OPC_MXU_D8SUMC");
26936 generate_exception_end(ctx, EXCP_RI);
26937 break;
26938 default:
26939 MIPS_INVAL("decode_opc_mxu");
26940 generate_exception_end(ctx, EXCP_RI);
26941 break;
26942 }
26943}
26944
26945/*
26946 *
26947 * Decode MXU pool15
26948 *
26949 * S32MUL, S32MULU, S32EXTRV:
26950 * 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
26951 * +-----------+---------+---------+---+-------+-------+-----------+
26952 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26953 * +-----------+---------+---------+---+-------+-------+-----------+
26954 *
26955 * S32EXTR:
26956 * 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
26957 * +-----------+---------+---------+---+-------+-------+-----------+
26958 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26959 * +-----------+---------+---------+---+-------+-------+-----------+
26960 *
26961 */
26962static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26963{
26964 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26965
26966 switch (opcode) {
26967 case OPC_MXU_S32MUL:
26968 /* TODO: Implement emulation of S32MUL instruction. */
26969 MIPS_INVAL("OPC_MXU_S32MUL");
26970 generate_exception_end(ctx, EXCP_RI);
26971 break;
26972 case OPC_MXU_S32MULU:
26973 /* TODO: Implement emulation of S32MULU instruction. */
26974 MIPS_INVAL("OPC_MXU_S32MULU");
26975 generate_exception_end(ctx, EXCP_RI);
26976 break;
26977 case OPC_MXU_S32EXTR:
26978 /* TODO: Implement emulation of S32EXTR instruction. */
26979 MIPS_INVAL("OPC_MXU_S32EXTR");
26980 generate_exception_end(ctx, EXCP_RI);
26981 break;
26982 case OPC_MXU_S32EXTRV:
26983 /* TODO: Implement emulation of S32EXTRV instruction. */
26984 MIPS_INVAL("OPC_MXU_S32EXTRV");
26985 generate_exception_end(ctx, EXCP_RI);
26986 break;
26987 default:
26988 MIPS_INVAL("decode_opc_mxu");
26989 generate_exception_end(ctx, EXCP_RI);
26990 break;
26991 }
26992}
26993
26994/*
26995 *
26996 * Decode MXU pool16
26997 *
26998 * D32SARW:
26999 * 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
27000 * +-----------+---------+-----+-------+-------+-------+-----------+
27001 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
27002 * +-----------+---------+-----+-------+-------+-------+-----------+
27003 *
27004 * S32ALN:
27005 * 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
27006 * +-----------+---------+-----+-------+-------+-------+-----------+
27007 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
27008 * +-----------+---------+-----+-------+-------+-------+-----------+
27009 *
27010 * S32ALNI:
27011 * 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
27012 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27013 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27014 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27015 *
03f40088
AM
27016 * S32LUI:
27017 * 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
27018 * +-----------+-----+---+-----+-------+---------------+-----------+
27019 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
27020 * +-----------+-----+---+-----+-------+---------------+-----------+
27021 *
b621f018
AM
27022 * S32NOR, S32AND, S32OR, S32XOR:
27023 * 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
27024 * +-----------+---------+-----+-------+-------+-------+-----------+
27025 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27026 * +-----------+---------+-----+-------+-------+-------+-----------+
27027 *
03f40088
AM
27028 */
27029static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
27030{
27031 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27032
27033 switch (opcode) {
27034 case OPC_MXU_D32SARW:
27035 /* TODO: Implement emulation of D32SARW instruction. */
27036 MIPS_INVAL("OPC_MXU_D32SARW");
27037 generate_exception_end(ctx, EXCP_RI);
27038 break;
27039 case OPC_MXU_S32ALN:
27040 /* TODO: Implement emulation of S32ALN instruction. */
27041 MIPS_INVAL("OPC_MXU_S32ALN");
27042 generate_exception_end(ctx, EXCP_RI);
27043 break;
27044 case OPC_MXU_S32ALNI:
79f5fee7 27045 gen_mxu_S32ALNI(ctx);
03f40088 27046 break;
b621f018
AM
27047 case OPC_MXU_S32LUI:
27048 /* TODO: Implement emulation of S32LUI instruction. */
27049 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
27050 generate_exception_end(ctx, EXCP_RI);
27051 break;
b621f018
AM
27052 case OPC_MXU_S32NOR:
27053 gen_mxu_S32NOR(ctx);
27054 break;
03f40088 27055 case OPC_MXU_S32AND:
b621f018 27056 gen_mxu_S32AND(ctx);
03f40088
AM
27057 break;
27058 case OPC_MXU_S32OR:
b621f018 27059 gen_mxu_S32OR(ctx);
03f40088
AM
27060 break;
27061 case OPC_MXU_S32XOR:
b621f018 27062 gen_mxu_S32XOR(ctx);
03f40088
AM
27063 break;
27064 default:
27065 MIPS_INVAL("decode_opc_mxu");
27066 generate_exception_end(ctx, EXCP_RI);
27067 break;
27068 }
27069}
27070
27071/*
27072 *
27073 * Decode MXU pool17
27074 *
27075 * 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
27076 * +-----------+---------+---------+---+---------+-----+-----------+
27077 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
27078 * +-----------+---------+---------+---+---------+-----+-----------+
27079 *
27080 */
27081static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
27082{
27083 uint32_t opcode = extract32(ctx->opcode, 6, 2);
27084
27085 switch (opcode) {
27086 case OPC_MXU_LXW:
27087 /* TODO: Implement emulation of LXW instruction. */
27088 MIPS_INVAL("OPC_MXU_LXW");
27089 generate_exception_end(ctx, EXCP_RI);
27090 break;
27091 case OPC_MXU_LXH:
27092 /* TODO: Implement emulation of LXH instruction. */
27093 MIPS_INVAL("OPC_MXU_LXH");
27094 generate_exception_end(ctx, EXCP_RI);
27095 break;
27096 case OPC_MXU_LXHU:
27097 /* TODO: Implement emulation of LXHU instruction. */
27098 MIPS_INVAL("OPC_MXU_LXHU");
27099 generate_exception_end(ctx, EXCP_RI);
27100 break;
27101 case OPC_MXU_LXB:
27102 /* TODO: Implement emulation of LXB instruction. */
27103 MIPS_INVAL("OPC_MXU_LXB");
27104 generate_exception_end(ctx, EXCP_RI);
27105 break;
27106 case OPC_MXU_LXBU:
27107 /* TODO: Implement emulation of LXBU instruction. */
27108 MIPS_INVAL("OPC_MXU_LXBU");
27109 generate_exception_end(ctx, EXCP_RI);
27110 break;
27111 default:
27112 MIPS_INVAL("decode_opc_mxu");
27113 generate_exception_end(ctx, EXCP_RI);
27114 break;
27115 }
27116}
27117/*
27118 *
27119 * Decode MXU pool18
27120 *
27121 * 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 27122 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 27123 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
27124 * +-----------+---------+-----+-------+-------+-------+-----------+
27125 *
27126 */
c233bf07 27127static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
27128{
27129 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27130
27131 switch (opcode) {
27132 case OPC_MXU_D32SLLV:
27133 /* TODO: Implement emulation of D32SLLV instruction. */
27134 MIPS_INVAL("OPC_MXU_D32SLLV");
27135 generate_exception_end(ctx, EXCP_RI);
27136 break;
27137 case OPC_MXU_D32SLRV:
27138 /* TODO: Implement emulation of D32SLRV instruction. */
27139 MIPS_INVAL("OPC_MXU_D32SLRV");
27140 generate_exception_end(ctx, EXCP_RI);
27141 break;
27142 case OPC_MXU_D32SARV:
27143 /* TODO: Implement emulation of D32SARV instruction. */
27144 MIPS_INVAL("OPC_MXU_D32SARV");
27145 generate_exception_end(ctx, EXCP_RI);
27146 break;
27147 case OPC_MXU_Q16SLLV:
27148 /* TODO: Implement emulation of Q16SLLV instruction. */
27149 MIPS_INVAL("OPC_MXU_Q16SLLV");
27150 generate_exception_end(ctx, EXCP_RI);
27151 break;
27152 case OPC_MXU_Q16SLRV:
27153 /* TODO: Implement emulation of Q16SLRV instruction. */
27154 MIPS_INVAL("OPC_MXU_Q16SLRV");
27155 generate_exception_end(ctx, EXCP_RI);
27156 break;
27157 case OPC_MXU_Q16SARV:
27158 /* TODO: Implement emulation of Q16SARV instruction. */
27159 MIPS_INVAL("OPC_MXU_Q16SARV");
27160 generate_exception_end(ctx, EXCP_RI);
27161 break;
27162 default:
27163 MIPS_INVAL("decode_opc_mxu");
27164 generate_exception_end(ctx, EXCP_RI);
27165 break;
27166 }
27167}
27168
27169/*
27170 *
c233bf07 27171 * Decode MXU pool19
03f40088
AM
27172 *
27173 * 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
27174 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 27175 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
27176 * +-----------+---+---+-------+-------+-------+-------+-----------+
27177 *
27178 */
c233bf07 27179static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
27180{
27181 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27182
27183 switch (opcode) {
27184 case OPC_MXU_Q8MUL:
03f40088 27185 case OPC_MXU_Q8MULSU:
a9a4181b 27186 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
27187 break;
27188 default:
27189 MIPS_INVAL("decode_opc_mxu");
27190 generate_exception_end(ctx, EXCP_RI);
27191 break;
27192 }
27193}
27194
27195/*
27196 *
c233bf07 27197 * Decode MXU pool20
03f40088
AM
27198 *
27199 * 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
27200 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 27201 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
27202 * +-----------+---------+-----+-------+-------+-------+-----------+
27203 *
27204 */
c233bf07 27205static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
27206{
27207 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27208
27209 switch (opcode) {
27210 case OPC_MXU_Q8MOVZ:
27211 /* TODO: Implement emulation of Q8MOVZ instruction. */
27212 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27213 generate_exception_end(ctx, EXCP_RI);
27214 break;
27215 case OPC_MXU_Q8MOVN:
27216 /* TODO: Implement emulation of Q8MOVN instruction. */
27217 MIPS_INVAL("OPC_MXU_Q8MOVN");
27218 generate_exception_end(ctx, EXCP_RI);
27219 break;
27220 case OPC_MXU_D16MOVZ:
27221 /* TODO: Implement emulation of D16MOVZ instruction. */
27222 MIPS_INVAL("OPC_MXU_D16MOVZ");
27223 generate_exception_end(ctx, EXCP_RI);
27224 break;
27225 case OPC_MXU_D16MOVN:
27226 /* TODO: Implement emulation of D16MOVN instruction. */
27227 MIPS_INVAL("OPC_MXU_D16MOVN");
27228 generate_exception_end(ctx, EXCP_RI);
27229 break;
27230 case OPC_MXU_S32MOVZ:
27231 /* TODO: Implement emulation of S32MOVZ instruction. */
27232 MIPS_INVAL("OPC_MXU_S32MOVZ");
27233 generate_exception_end(ctx, EXCP_RI);
27234 break;
27235 case OPC_MXU_S32MOVN:
27236 /* TODO: Implement emulation of S32MOVN instruction. */
27237 MIPS_INVAL("OPC_MXU_S32MOVN");
27238 generate_exception_end(ctx, EXCP_RI);
27239 break;
27240 default:
27241 MIPS_INVAL("decode_opc_mxu");
27242 generate_exception_end(ctx, EXCP_RI);
27243 break;
27244 }
27245}
27246
27247/*
27248 *
c233bf07 27249 * Decode MXU pool21
03f40088
AM
27250 *
27251 * 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
27252 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 27253 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
27254 * +-----------+---+---+-------+-------+-------+-------+-----------+
27255 *
27256 */
c233bf07 27257static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
27258{
27259 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27260
27261 switch (opcode) {
27262 case OPC_MXU_Q8MAC:
27263 /* TODO: Implement emulation of Q8MAC instruction. */
27264 MIPS_INVAL("OPC_MXU_Q8MAC");
27265 generate_exception_end(ctx, EXCP_RI);
27266 break;
27267 case OPC_MXU_Q8MACSU:
27268 /* TODO: Implement emulation of Q8MACSU instruction. */
27269 MIPS_INVAL("OPC_MXU_Q8MACSU");
27270 generate_exception_end(ctx, EXCP_RI);
27271 break;
27272 default:
27273 MIPS_INVAL("decode_opc_mxu");
27274 generate_exception_end(ctx, EXCP_RI);
27275 break;
27276 }
27277}
27278
27279
27280/*
27281 * Main MXU decoding function
27282 *
27283 * 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
27284 * +-----------+---------------------------------------+-----------+
27285 * | SPECIAL2 | |x x x x x x|
27286 * +-----------+---------------------------------------+-----------+
27287 *
27288 */
0a348b9a
AM
27289static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27290{
11d56f61
CJ
27291 /*
27292 * TODO: Investigate necessity of including handling of
27293 * CLZ, CLO, SDBB in this function, as they belong to
27294 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27295 */
03f40088
AM
27296 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27297
87860df5
AM
27298 if (opcode == OPC__MXU_MUL) {
27299 uint32_t rs, rt, rd, op1;
27300
27301 rs = extract32(ctx->opcode, 21, 5);
27302 rt = extract32(ctx->opcode, 16, 5);
27303 rd = extract32(ctx->opcode, 11, 5);
27304 op1 = MASK_SPECIAL2(ctx->opcode);
27305
27306 gen_arith(ctx, op1, rd, rs, rt);
27307
27308 return;
27309 }
27310
27311 if (opcode == OPC_MXU_S32M2I) {
27312 gen_mxu_s32m2i(ctx);
27313 return;
27314 }
27315
27316 if (opcode == OPC_MXU_S32I2M) {
27317 gen_mxu_s32i2m(ctx);
27318 return;
27319 }
27320
e5bf8a08
AM
27321 {
27322 TCGv t_mxu_cr = tcg_temp_new();
27323 TCGLabel *l_exit = gen_new_label();
27324
27325 gen_load_mxu_cr(t_mxu_cr);
27326 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27327 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27328
27329 switch (opcode) {
27330 case OPC_MXU_S32MADD:
27331 /* TODO: Implement emulation of S32MADD instruction. */
27332 MIPS_INVAL("OPC_MXU_S32MADD");
27333 generate_exception_end(ctx, EXCP_RI);
27334 break;
27335 case OPC_MXU_S32MADDU:
27336 /* TODO: Implement emulation of S32MADDU instruction. */
27337 MIPS_INVAL("OPC_MXU_S32MADDU");
27338 generate_exception_end(ctx, EXCP_RI);
27339 break;
27340 case OPC_MXU__POOL00:
27341 decode_opc_mxu__pool00(env, ctx);
27342 break;
27343 case OPC_MXU_S32MSUB:
27344 /* TODO: Implement emulation of S32MSUB instruction. */
27345 MIPS_INVAL("OPC_MXU_S32MSUB");
27346 generate_exception_end(ctx, EXCP_RI);
27347 break;
27348 case OPC_MXU_S32MSUBU:
27349 /* TODO: Implement emulation of S32MSUBU instruction. */
27350 MIPS_INVAL("OPC_MXU_S32MSUBU");
27351 generate_exception_end(ctx, EXCP_RI);
27352 break;
27353 case OPC_MXU__POOL01:
27354 decode_opc_mxu__pool01(env, ctx);
27355 break;
27356 case OPC_MXU__POOL02:
27357 decode_opc_mxu__pool02(env, ctx);
27358 break;
27359 case OPC_MXU_D16MUL:
27360 gen_mxu_d16mul(ctx);
27361 break;
27362 case OPC_MXU__POOL03:
27363 decode_opc_mxu__pool03(env, ctx);
27364 break;
27365 case OPC_MXU_D16MAC:
27366 gen_mxu_d16mac(ctx);
27367 break;
27368 case OPC_MXU_D16MACF:
27369 /* TODO: Implement emulation of D16MACF instruction. */
27370 MIPS_INVAL("OPC_MXU_D16MACF");
27371 generate_exception_end(ctx, EXCP_RI);
27372 break;
27373 case OPC_MXU_D16MADL:
27374 /* TODO: Implement emulation of D16MADL instruction. */
27375 MIPS_INVAL("OPC_MXU_D16MADL");
27376 generate_exception_end(ctx, EXCP_RI);
27377 break;
27378 case OPC_MXU_S16MAD:
27379 /* TODO: Implement emulation of S16MAD instruction. */
27380 MIPS_INVAL("OPC_MXU_S16MAD");
27381 generate_exception_end(ctx, EXCP_RI);
27382 break;
27383 case OPC_MXU_Q16ADD:
27384 /* TODO: Implement emulation of Q16ADD instruction. */
27385 MIPS_INVAL("OPC_MXU_Q16ADD");
27386 generate_exception_end(ctx, EXCP_RI);
27387 break;
27388 case OPC_MXU_D16MACE:
27389 /* TODO: Implement emulation of D16MACE instruction. */
27390 MIPS_INVAL("OPC_MXU_D16MACE");
27391 generate_exception_end(ctx, EXCP_RI);
27392 break;
27393 case OPC_MXU__POOL04:
27394 decode_opc_mxu__pool04(env, ctx);
27395 break;
27396 case OPC_MXU__POOL05:
27397 decode_opc_mxu__pool05(env, ctx);
27398 break;
27399 case OPC_MXU__POOL06:
27400 decode_opc_mxu__pool06(env, ctx);
27401 break;
27402 case OPC_MXU__POOL07:
27403 decode_opc_mxu__pool07(env, ctx);
27404 break;
27405 case OPC_MXU__POOL08:
27406 decode_opc_mxu__pool08(env, ctx);
27407 break;
27408 case OPC_MXU__POOL09:
27409 decode_opc_mxu__pool09(env, ctx);
27410 break;
27411 case OPC_MXU__POOL10:
27412 decode_opc_mxu__pool10(env, ctx);
27413 break;
27414 case OPC_MXU__POOL11:
27415 decode_opc_mxu__pool11(env, ctx);
27416 break;
27417 case OPC_MXU_D32ADD:
27418 /* TODO: Implement emulation of D32ADD instruction. */
27419 MIPS_INVAL("OPC_MXU_D32ADD");
27420 generate_exception_end(ctx, EXCP_RI);
27421 break;
27422 case OPC_MXU__POOL12:
27423 decode_opc_mxu__pool12(env, ctx);
27424 break;
27425 case OPC_MXU__POOL13:
27426 decode_opc_mxu__pool13(env, ctx);
27427 break;
27428 case OPC_MXU__POOL14:
27429 decode_opc_mxu__pool14(env, ctx);
27430 break;
27431 case OPC_MXU_Q8ACCE:
27432 /* TODO: Implement emulation of Q8ACCE instruction. */
27433 MIPS_INVAL("OPC_MXU_Q8ACCE");
27434 generate_exception_end(ctx, EXCP_RI);
27435 break;
27436 case OPC_MXU_S8LDD:
27437 gen_mxu_s8ldd(ctx);
27438 break;
27439 case OPC_MXU_S8STD:
27440 /* TODO: Implement emulation of S8STD instruction. */
27441 MIPS_INVAL("OPC_MXU_S8STD");
27442 generate_exception_end(ctx, EXCP_RI);
27443 break;
27444 case OPC_MXU_S8LDI:
27445 /* TODO: Implement emulation of S8LDI instruction. */
27446 MIPS_INVAL("OPC_MXU_S8LDI");
27447 generate_exception_end(ctx, EXCP_RI);
27448 break;
27449 case OPC_MXU_S8SDI:
27450 /* TODO: Implement emulation of S8SDI instruction. */
27451 MIPS_INVAL("OPC_MXU_S8SDI");
27452 generate_exception_end(ctx, EXCP_RI);
27453 break;
27454 case OPC_MXU__POOL15:
27455 decode_opc_mxu__pool15(env, ctx);
27456 break;
27457 case OPC_MXU__POOL16:
27458 decode_opc_mxu__pool16(env, ctx);
27459 break;
c233bf07
AM
27460 case OPC_MXU__POOL17:
27461 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
27462 break;
27463 case OPC_MXU_S16LDD:
27464 /* TODO: Implement emulation of S16LDD instruction. */
27465 MIPS_INVAL("OPC_MXU_S16LDD");
27466 generate_exception_end(ctx, EXCP_RI);
27467 break;
27468 case OPC_MXU_S16STD:
27469 /* TODO: Implement emulation of S16STD instruction. */
27470 MIPS_INVAL("OPC_MXU_S16STD");
27471 generate_exception_end(ctx, EXCP_RI);
27472 break;
27473 case OPC_MXU_S16LDI:
27474 /* TODO: Implement emulation of S16LDI instruction. */
27475 MIPS_INVAL("OPC_MXU_S16LDI");
27476 generate_exception_end(ctx, EXCP_RI);
27477 break;
27478 case OPC_MXU_S16SDI:
27479 /* TODO: Implement emulation of S16SDI instruction. */
27480 MIPS_INVAL("OPC_MXU_S16SDI");
27481 generate_exception_end(ctx, EXCP_RI);
27482 break;
27483 case OPC_MXU_D32SLL:
27484 /* TODO: Implement emulation of D32SLL instruction. */
27485 MIPS_INVAL("OPC_MXU_D32SLL");
27486 generate_exception_end(ctx, EXCP_RI);
27487 break;
27488 case OPC_MXU_D32SLR:
27489 /* TODO: Implement emulation of D32SLR instruction. */
27490 MIPS_INVAL("OPC_MXU_D32SLR");
27491 generate_exception_end(ctx, EXCP_RI);
27492 break;
27493 case OPC_MXU_D32SARL:
27494 /* TODO: Implement emulation of D32SARL instruction. */
27495 MIPS_INVAL("OPC_MXU_D32SARL");
27496 generate_exception_end(ctx, EXCP_RI);
27497 break;
27498 case OPC_MXU_D32SAR:
27499 /* TODO: Implement emulation of D32SAR instruction. */
27500 MIPS_INVAL("OPC_MXU_D32SAR");
27501 generate_exception_end(ctx, EXCP_RI);
27502 break;
27503 case OPC_MXU_Q16SLL:
27504 /* TODO: Implement emulation of Q16SLL instruction. */
27505 MIPS_INVAL("OPC_MXU_Q16SLL");
27506 generate_exception_end(ctx, EXCP_RI);
27507 break;
27508 case OPC_MXU_Q16SLR:
27509 /* TODO: Implement emulation of Q16SLR instruction. */
27510 MIPS_INVAL("OPC_MXU_Q16SLR");
27511 generate_exception_end(ctx, EXCP_RI);
27512 break;
c233bf07
AM
27513 case OPC_MXU__POOL18:
27514 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
27515 break;
27516 case OPC_MXU_Q16SAR:
27517 /* TODO: Implement emulation of Q16SAR instruction. */
27518 MIPS_INVAL("OPC_MXU_Q16SAR");
27519 generate_exception_end(ctx, EXCP_RI);
27520 break;
e5bf8a08
AM
27521 case OPC_MXU__POOL19:
27522 decode_opc_mxu__pool19(env, ctx);
27523 break;
27524 case OPC_MXU__POOL20:
27525 decode_opc_mxu__pool20(env, ctx);
27526 break;
c233bf07
AM
27527 case OPC_MXU__POOL21:
27528 decode_opc_mxu__pool21(env, ctx);
27529 break;
e5bf8a08
AM
27530 case OPC_MXU_Q16SCOP:
27531 /* TODO: Implement emulation of Q16SCOP instruction. */
27532 MIPS_INVAL("OPC_MXU_Q16SCOP");
27533 generate_exception_end(ctx, EXCP_RI);
27534 break;
27535 case OPC_MXU_Q8MADL:
27536 /* TODO: Implement emulation of Q8MADL instruction. */
27537 MIPS_INVAL("OPC_MXU_Q8MADL");
27538 generate_exception_end(ctx, EXCP_RI);
27539 break;
27540 case OPC_MXU_S32SFL:
27541 /* TODO: Implement emulation of S32SFL instruction. */
27542 MIPS_INVAL("OPC_MXU_S32SFL");
27543 generate_exception_end(ctx, EXCP_RI);
27544 break;
27545 case OPC_MXU_Q8SAD:
27546 /* TODO: Implement emulation of Q8SAD instruction. */
27547 MIPS_INVAL("OPC_MXU_Q8SAD");
27548 generate_exception_end(ctx, EXCP_RI);
27549 break;
27550 default:
27551 MIPS_INVAL("decode_opc_mxu");
27552 generate_exception_end(ctx, EXCP_RI);
27553 }
27554
27555 gen_set_label(l_exit);
27556 tcg_temp_free(t_mxu_cr);
03f40088 27557 }
0a348b9a
AM
27558}
27559
b621f018
AM
27560#endif /* !defined(TARGET_MIPS64) */
27561
03f40088 27562
10dc65db 27563static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
27564{
27565 int rs, rt, rd;
27566 uint32_t op1;
6c5c1e20 27567
2e211e0a 27568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
4267d3e6 27569
099e5b4d
LA
27570 rs = (ctx->opcode >> 21) & 0x1f;
27571 rt = (ctx->opcode >> 16) & 0x1f;
27572 rd = (ctx->opcode >> 11) & 0x1f;
27573
27574 op1 = MASK_SPECIAL2(ctx->opcode);
27575 switch (op1) {
c2e19f3c
AM
27576 case OPC_MADD: /* Multiply and add/sub */
27577 case OPC_MADDU:
27578 case OPC_MSUB:
27579 case OPC_MSUBU:
bbd5e4a2 27580 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
27581 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27582 break;
27583 case OPC_MUL:
099e5b4d
LA
27584 gen_arith(ctx, op1, rd, rs, rt);
27585 break;
fac5a073
LA
27586 case OPC_DIV_G_2F:
27587 case OPC_DIVU_G_2F:
27588 case OPC_MULT_G_2F:
27589 case OPC_MULTU_G_2F:
27590 case OPC_MOD_G_2F:
27591 case OPC_MODU_G_2F:
8e2d5831 27592 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
fac5a073
LA
27593 gen_loongson_integer(ctx, op1, rd, rs, rt);
27594 break;
099e5b4d
LA
27595 case OPC_CLO:
27596 case OPC_CLZ:
bbd5e4a2 27597 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
27598 gen_cl(ctx, op1, rd, rs);
27599 break;
27600 case OPC_SDBBP:
3b3c1694
LA
27601 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27602 gen_helper_do_semihosting(cpu_env);
27603 } else {
7480515f
AM
27604 /*
27605 * XXX: not clear which exception should be raised
3b3c1694
LA
27606 * when in debug mode...
27607 */
bbd5e4a2 27608 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 27609 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 27610 }
099e5b4d 27611 break;
9b1a1d68 27612#if defined(TARGET_MIPS64)
099e5b4d
LA
27613 case OPC_DCLO:
27614 case OPC_DCLZ:
bbd5e4a2 27615 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
27616 check_mips_64(ctx);
27617 gen_cl(ctx, op1, rd, rs);
27618 break;
4267d3e6
LA
27619 case OPC_DMULT_G_2F:
27620 case OPC_DMULTU_G_2F:
27621 case OPC_DDIV_G_2F:
27622 case OPC_DDIVU_G_2F:
27623 case OPC_DMOD_G_2F:
27624 case OPC_DMODU_G_2F:
8e2d5831 27625 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
4267d3e6
LA
27626 gen_loongson_integer(ctx, op1, rd, rs, rt);
27627 break;
10dc65db 27628#endif
4267d3e6
LA
27629 default: /* Invalid */
27630 MIPS_INVAL("special2_legacy");
9c708c7f 27631 generate_exception_end(ctx, EXCP_RI);
4267d3e6 27632 break;
10dc65db
LA
27633 }
27634}
27635
27636static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27637{
15eacb9b
YK
27638 int rs, rt, rd, sa;
27639 uint32_t op1, op2;
10dc65db
LA
27640 int16_t imm;
27641
27642 rs = (ctx->opcode >> 21) & 0x1f;
27643 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
27644 rd = (ctx->opcode >> 11) & 0x1f;
27645 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
27646 imm = (int16_t)ctx->opcode >> 7;
27647
27648 op1 = MASK_SPECIAL3(ctx->opcode);
27649 switch (op1) {
bf7910c6
LA
27650 case R6_OPC_PREF:
27651 if (rt >= 24) {
27652 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 27653 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
27654 }
27655 /* Treat as NOP. */
27656 break;
27657 case R6_OPC_CACHE:
40d48212 27658 check_cp0_enabled(ctx);
0d74a222
LA
27659 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27660 gen_cache_operation(ctx, rt, rs, imm);
27661 }
bf7910c6 27662 break;
10dc65db 27663 case R6_OPC_SC:
33a07fa2 27664 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
27665 break;
27666 case R6_OPC_LL:
27667 gen_ld(ctx, op1, rt, rs, imm);
27668 break;
15eacb9b
YK
27669 case OPC_BSHFL:
27670 {
27671 if (rd == 0) {
27672 /* Treat as NOP. */
27673 break;
27674 }
15eacb9b
YK
27675 op2 = MASK_BSHFL(ctx->opcode);
27676 switch (op2) {
c2e19f3c 27677 case OPC_ALIGN:
373ecd38
AM
27678 case OPC_ALIGN_1:
27679 case OPC_ALIGN_2:
27680 case OPC_ALIGN_3:
821f2008 27681 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
27682 break;
27683 case OPC_BITSWAP:
1f1b4c00 27684 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27685 break;
27686 }
15eacb9b
YK
27687 }
27688 break;
99029be1
YK
27689#ifndef CONFIG_USER_ONLY
27690 case OPC_GINV:
27691 if (unlikely(ctx->gi <= 1)) {
27692 generate_exception_end(ctx, EXCP_RI);
27693 }
27694 check_cp0_enabled(ctx);
27695 switch ((ctx->opcode >> 6) & 3) {
27696 case 0: /* GINVI */
27697 /* Treat as NOP. */
27698 break;
27699 case 2: /* GINVT */
27700 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27701 break;
27702 default:
27703 generate_exception_end(ctx, EXCP_RI);
27704 break;
27705 }
27706 break;
27707#endif
bf7910c6
LA
27708#if defined(TARGET_MIPS64)
27709 case R6_OPC_SCD:
33a07fa2 27710 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
27711 break;
27712 case R6_OPC_LLD:
27713 gen_ld(ctx, op1, rt, rs, imm);
27714 break;
15eacb9b
YK
27715 case OPC_DBSHFL:
27716 check_mips_64(ctx);
27717 {
27718 if (rd == 0) {
27719 /* Treat as NOP. */
27720 break;
27721 }
15eacb9b
YK
27722 op2 = MASK_DBSHFL(ctx->opcode);
27723 switch (op2) {
c2e19f3c 27724 case OPC_DALIGN:
373ecd38
AM
27725 case OPC_DALIGN_1:
27726 case OPC_DALIGN_2:
27727 case OPC_DALIGN_3:
27728 case OPC_DALIGN_4:
27729 case OPC_DALIGN_5:
27730 case OPC_DALIGN_6:
27731 case OPC_DALIGN_7:
821f2008 27732 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
27733 break;
27734 case OPC_DBITSWAP:
1f1b4c00 27735 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
27736 break;
27737 }
1f1b4c00 27738
15eacb9b
YK
27739 }
27740 break;
bf7910c6 27741#endif
10dc65db
LA
27742 default: /* Invalid */
27743 MIPS_INVAL("special3_r6");
9c708c7f 27744 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
27745 break;
27746 }
27747}
27748
27749static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27750{
fac5a073 27751 int rs, rt, rd;
099e5b4d 27752 uint32_t op1, op2;
099e5b4d
LA
27753
27754 rs = (ctx->opcode >> 21) & 0x1f;
27755 rt = (ctx->opcode >> 16) & 0x1f;
27756 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
27757
27758 op1 = MASK_SPECIAL3(ctx->opcode);
27759 switch (op1) {
c2e19f3c
AM
27760 case OPC_DIV_G_2E:
27761 case OPC_DIVU_G_2E:
27762 case OPC_MOD_G_2E:
27763 case OPC_MODU_G_2E:
27764 case OPC_MULT_G_2E:
27765 case OPC_MULTU_G_2E:
7480515f
AM
27766 /*
27767 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27768 * the same mask and op1.
27769 */
908f6be1 27770 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 27771 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 27772 switch (op2) {
099e5b4d
LA
27773 case OPC_ADDUH_QB:
27774 case OPC_ADDUH_R_QB:
27775 case OPC_ADDQH_PH:
27776 case OPC_ADDQH_R_PH:
27777 case OPC_ADDQH_W:
27778 case OPC_ADDQH_R_W:
27779 case OPC_SUBUH_QB:
27780 case OPC_SUBUH_R_QB:
27781 case OPC_SUBQH_PH:
27782 case OPC_SUBQH_R_PH:
27783 case OPC_SUBQH_W:
27784 case OPC_SUBQH_R_W:
461c08df
JL
27785 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27786 break;
099e5b4d
LA
27787 case OPC_MUL_PH:
27788 case OPC_MUL_S_PH:
27789 case OPC_MULQ_S_W:
27790 case OPC_MULQ_RS_W:
27791 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27792 break;
461c08df 27793 default:
099e5b4d 27794 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 27795 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
27796 break;
27797 }
099e5b4d
LA
27798 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27799 gen_loongson_integer(ctx, op1, rd, rs, rt);
27800 } else {
9c708c7f 27801 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27802 }
27803 break;
27804 case OPC_LX_DSP:
27805 op2 = MASK_LX(ctx->opcode);
27806 switch (op2) {
27807#if defined(TARGET_MIPS64)
27808 case OPC_LDX:
27809#endif
27810 case OPC_LBUX:
27811 case OPC_LHX:
27812 case OPC_LWX:
27813 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27814 break;
27815 default: /* Invalid */
27816 MIPS_INVAL("MASK LX");
9c708c7f 27817 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27818 break;
27819 }
27820 break;
27821 case OPC_ABSQ_S_PH_DSP:
27822 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27823 switch (op2) {
27824 case OPC_ABSQ_S_QB:
27825 case OPC_ABSQ_S_PH:
27826 case OPC_ABSQ_S_W:
27827 case OPC_PRECEQ_W_PHL:
27828 case OPC_PRECEQ_W_PHR:
27829 case OPC_PRECEQU_PH_QBL:
27830 case OPC_PRECEQU_PH_QBR:
27831 case OPC_PRECEQU_PH_QBLA:
27832 case OPC_PRECEQU_PH_QBRA:
27833 case OPC_PRECEU_PH_QBL:
27834 case OPC_PRECEU_PH_QBR:
27835 case OPC_PRECEU_PH_QBLA:
27836 case OPC_PRECEU_PH_QBRA:
27837 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27838 break;
27839 case OPC_BITREV:
27840 case OPC_REPL_QB:
27841 case OPC_REPLV_QB:
27842 case OPC_REPL_PH:
27843 case OPC_REPLV_PH:
27844 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27845 break;
27846 default:
27847 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 27848 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27849 break;
27850 }
27851 break;
27852 case OPC_ADDU_QB_DSP:
27853 op2 = MASK_ADDU_QB(ctx->opcode);
27854 switch (op2) {
27855 case OPC_ADDQ_PH:
27856 case OPC_ADDQ_S_PH:
27857 case OPC_ADDQ_S_W:
27858 case OPC_ADDU_QB:
27859 case OPC_ADDU_S_QB:
27860 case OPC_ADDU_PH:
27861 case OPC_ADDU_S_PH:
27862 case OPC_SUBQ_PH:
27863 case OPC_SUBQ_S_PH:
27864 case OPC_SUBQ_S_W:
27865 case OPC_SUBU_QB:
27866 case OPC_SUBU_S_QB:
27867 case OPC_SUBU_PH:
27868 case OPC_SUBU_S_PH:
27869 case OPC_ADDSC:
27870 case OPC_ADDWC:
27871 case OPC_MODSUB:
27872 case OPC_RADDU_W_QB:
27873 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27874 break;
27875 case OPC_MULEU_S_PH_QBL:
27876 case OPC_MULEU_S_PH_QBR:
27877 case OPC_MULQ_RS_PH:
27878 case OPC_MULEQ_S_W_PHL:
27879 case OPC_MULEQ_S_W_PHR:
27880 case OPC_MULQ_S_PH:
27881 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27882 break;
27883 default: /* Invalid */
27884 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 27885 generate_exception_end(ctx, EXCP_RI);
461c08df 27886 break;
461c08df 27887
099e5b4d
LA
27888 }
27889 break;
27890 case OPC_CMPU_EQ_QB_DSP:
27891 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27892 switch (op2) {
27893 case OPC_PRECR_SRA_PH_W:
27894 case OPC_PRECR_SRA_R_PH_W:
27895 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 27896 break;
099e5b4d
LA
27897 case OPC_PRECR_QB_PH:
27898 case OPC_PRECRQ_QB_PH:
27899 case OPC_PRECRQ_PH_W:
27900 case OPC_PRECRQ_RS_PH_W:
27901 case OPC_PRECRQU_S_QB_PH:
27902 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 27903 break;
099e5b4d
LA
27904 case OPC_CMPU_EQ_QB:
27905 case OPC_CMPU_LT_QB:
27906 case OPC_CMPU_LE_QB:
27907 case OPC_CMP_EQ_PH:
27908 case OPC_CMP_LT_PH:
27909 case OPC_CMP_LE_PH:
27910 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 27911 break;
099e5b4d
LA
27912 case OPC_CMPGU_EQ_QB:
27913 case OPC_CMPGU_LT_QB:
27914 case OPC_CMPGU_LE_QB:
27915 case OPC_CMPGDU_EQ_QB:
27916 case OPC_CMPGDU_LT_QB:
27917 case OPC_CMPGDU_LE_QB:
27918 case OPC_PICK_QB:
27919 case OPC_PICK_PH:
27920 case OPC_PACKRL_PH:
27921 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27922 break;
27923 default: /* Invalid */
27924 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 27925 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27926 break;
27927 }
27928 break;
27929 case OPC_SHLL_QB_DSP:
27930 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27931 break;
27932 case OPC_DPA_W_PH_DSP:
27933 op2 = MASK_DPA_W_PH(ctx->opcode);
27934 switch (op2) {
27935 case OPC_DPAU_H_QBL:
27936 case OPC_DPAU_H_QBR:
27937 case OPC_DPSU_H_QBL:
27938 case OPC_DPSU_H_QBR:
27939 case OPC_DPA_W_PH:
27940 case OPC_DPAX_W_PH:
27941 case OPC_DPAQ_S_W_PH:
27942 case OPC_DPAQX_S_W_PH:
27943 case OPC_DPAQX_SA_W_PH:
27944 case OPC_DPS_W_PH:
27945 case OPC_DPSX_W_PH:
27946 case OPC_DPSQ_S_W_PH:
27947 case OPC_DPSQX_S_W_PH:
27948 case OPC_DPSQX_SA_W_PH:
27949 case OPC_MULSAQ_S_W_PH:
27950 case OPC_DPAQ_SA_L_W:
27951 case OPC_DPSQ_SA_L_W:
27952 case OPC_MAQ_S_W_PHL:
27953 case OPC_MAQ_S_W_PHR:
27954 case OPC_MAQ_SA_W_PHL:
27955 case OPC_MAQ_SA_W_PHR:
27956 case OPC_MULSA_W_PH:
27957 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27958 break;
27959 default: /* Invalid */
27960 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 27961 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27962 break;
27963 }
27964 break;
27965 case OPC_INSV_DSP:
27966 op2 = MASK_INSV(ctx->opcode);
27967 switch (op2) {
27968 case OPC_INSV:
27969 check_dsp(ctx);
27970 {
27971 TCGv t0, t1;
27972
27973 if (rt == 0) {
099e5b4d
LA
27974 break;
27975 }
27976
27977 t0 = tcg_temp_new();
27978 t1 = tcg_temp_new();
27979
27980 gen_load_gpr(t0, rt);
27981 gen_load_gpr(t1, rs);
27982
27983 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27984
27985 tcg_temp_free(t0);
27986 tcg_temp_free(t1);
a22260ae
JL
27987 break;
27988 }
099e5b4d
LA
27989 default: /* Invalid */
27990 MIPS_INVAL("MASK INSV");
9c708c7f 27991 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27992 break;
27993 }
27994 break;
27995 case OPC_APPEND_DSP:
27996 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27997 break;
27998 case OPC_EXTR_W_DSP:
27999 op2 = MASK_EXTR_W(ctx->opcode);
28000 switch (op2) {
28001 case OPC_EXTR_W:
28002 case OPC_EXTR_R_W:
28003 case OPC_EXTR_RS_W:
28004 case OPC_EXTR_S_H:
28005 case OPC_EXTRV_S_H:
28006 case OPC_EXTRV_W:
28007 case OPC_EXTRV_R_W:
28008 case OPC_EXTRV_RS_W:
28009 case OPC_EXTP:
28010 case OPC_EXTPV:
28011 case OPC_EXTPDP:
28012 case OPC_EXTPDPV:
28013 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28014 break;
28015 case OPC_RDDSP:
28016 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
28017 break;
28018 case OPC_SHILO:
28019 case OPC_SHILOV:
28020 case OPC_MTHLIP:
28021 case OPC_WRDSP:
28022 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28023 break;
28024 default: /* Invalid */
28025 MIPS_INVAL("MASK EXTR.W");
9c708c7f 28026 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
28027 break;
28028 }
28029 break;
099e5b4d 28030#if defined(TARGET_MIPS64)
c2e19f3c
AM
28031 case OPC_DDIV_G_2E:
28032 case OPC_DDIVU_G_2E:
28033 case OPC_DMULT_G_2E:
28034 case OPC_DMULTU_G_2E:
28035 case OPC_DMOD_G_2E:
28036 case OPC_DMODU_G_2E:
fac5a073
LA
28037 check_insn(ctx, INSN_LOONGSON2E);
28038 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 28039 break;
099e5b4d
LA
28040 case OPC_ABSQ_S_QH_DSP:
28041 op2 = MASK_ABSQ_S_QH(ctx->opcode);
28042 switch (op2) {
28043 case OPC_PRECEQ_L_PWL:
28044 case OPC_PRECEQ_L_PWR:
28045 case OPC_PRECEQ_PW_QHL:
28046 case OPC_PRECEQ_PW_QHR:
28047 case OPC_PRECEQ_PW_QHLA:
28048 case OPC_PRECEQ_PW_QHRA:
28049 case OPC_PRECEQU_QH_OBL:
28050 case OPC_PRECEQU_QH_OBR:
28051 case OPC_PRECEQU_QH_OBLA:
28052 case OPC_PRECEQU_QH_OBRA:
28053 case OPC_PRECEU_QH_OBL:
28054 case OPC_PRECEU_QH_OBR:
28055 case OPC_PRECEU_QH_OBLA:
28056 case OPC_PRECEU_QH_OBRA:
28057 case OPC_ABSQ_S_OB:
28058 case OPC_ABSQ_S_PW:
28059 case OPC_ABSQ_S_QH:
28060 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28061 break;
28062 case OPC_REPL_OB:
28063 case OPC_REPL_PW:
28064 case OPC_REPL_QH:
28065 case OPC_REPLV_OB:
28066 case OPC_REPLV_PW:
28067 case OPC_REPLV_QH:
28068 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
28069 break;
28070 default: /* Invalid */
28071 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 28072 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
28073 break;
28074 }
28075 break;
28076 case OPC_ADDU_OB_DSP:
28077 op2 = MASK_ADDU_OB(ctx->opcode);
28078 switch (op2) {
28079 case OPC_RADDU_L_OB:
28080 case OPC_SUBQ_PW:
28081 case OPC_SUBQ_S_PW:
28082 case OPC_SUBQ_QH:
28083 case OPC_SUBQ_S_QH:
28084 case OPC_SUBU_OB:
28085 case OPC_SUBU_S_OB:
28086 case OPC_SUBU_QH:
28087 case OPC_SUBU_S_QH:
28088 case OPC_SUBUH_OB:
28089 case OPC_SUBUH_R_OB:
28090 case OPC_ADDQ_PW:
28091 case OPC_ADDQ_S_PW:
28092 case OPC_ADDQ_QH:
28093 case OPC_ADDQ_S_QH:
28094 case OPC_ADDU_OB:
28095 case OPC_ADDU_S_OB:
28096 case OPC_ADDU_QH:
28097 case OPC_ADDU_S_QH:
28098 case OPC_ADDUH_OB:
28099 case OPC_ADDUH_R_OB:
28100 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 28101 break;
099e5b4d
LA
28102 case OPC_MULEQ_S_PW_QHL:
28103 case OPC_MULEQ_S_PW_QHR:
28104 case OPC_MULEU_S_QH_OBL:
28105 case OPC_MULEU_S_QH_OBR:
28106 case OPC_MULQ_RS_QH:
28107 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 28108 break;
099e5b4d
LA
28109 default: /* Invalid */
28110 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 28111 generate_exception_end(ctx, EXCP_RI);
26690560 28112 break;
099e5b4d
LA
28113 }
28114 break;
28115 case OPC_CMPU_EQ_OB_DSP:
28116 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
28117 switch (op2) {
28118 case OPC_PRECR_SRA_QH_PW:
28119 case OPC_PRECR_SRA_R_QH_PW:
28120 /* Return value is rt. */
28121 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 28122 break;
099e5b4d
LA
28123 case OPC_PRECR_OB_QH:
28124 case OPC_PRECRQ_OB_QH:
28125 case OPC_PRECRQ_PW_L:
28126 case OPC_PRECRQ_QH_PW:
28127 case OPC_PRECRQ_RS_QH_PW:
28128 case OPC_PRECRQU_S_OB_QH:
28129 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 28130 break;
099e5b4d
LA
28131 case OPC_CMPU_EQ_OB:
28132 case OPC_CMPU_LT_OB:
28133 case OPC_CMPU_LE_OB:
28134 case OPC_CMP_EQ_QH:
28135 case OPC_CMP_LT_QH:
28136 case OPC_CMP_LE_QH:
28137 case OPC_CMP_EQ_PW:
28138 case OPC_CMP_LT_PW:
28139 case OPC_CMP_LE_PW:
28140 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 28141 break;
099e5b4d
LA
28142 case OPC_CMPGDU_EQ_OB:
28143 case OPC_CMPGDU_LT_OB:
28144 case OPC_CMPGDU_LE_OB:
28145 case OPC_CMPGU_EQ_OB:
28146 case OPC_CMPGU_LT_OB:
28147 case OPC_CMPGU_LE_OB:
28148 case OPC_PACKRL_PW:
28149 case OPC_PICK_OB:
28150 case OPC_PICK_PW:
28151 case OPC_PICK_QH:
28152 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 28153 break;
099e5b4d
LA
28154 default: /* Invalid */
28155 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 28156 generate_exception_end(ctx, EXCP_RI);
161f85e6 28157 break;
099e5b4d
LA
28158 }
28159 break;
28160 case OPC_DAPPEND_DSP:
28161 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28162 break;
28163 case OPC_DEXTR_W_DSP:
28164 op2 = MASK_DEXTR_W(ctx->opcode);
28165 switch (op2) {
28166 case OPC_DEXTP:
28167 case OPC_DEXTPDP:
28168 case OPC_DEXTPDPV:
28169 case OPC_DEXTPV:
28170 case OPC_DEXTR_L:
28171 case OPC_DEXTR_R_L:
28172 case OPC_DEXTR_RS_L:
28173 case OPC_DEXTR_W:
28174 case OPC_DEXTR_R_W:
28175 case OPC_DEXTR_RS_W:
28176 case OPC_DEXTR_S_H:
28177 case OPC_DEXTRV_L:
28178 case OPC_DEXTRV_R_L:
28179 case OPC_DEXTRV_RS_L:
28180 case OPC_DEXTRV_S_H:
28181 case OPC_DEXTRV_W:
28182 case OPC_DEXTRV_R_W:
28183 case OPC_DEXTRV_RS_W:
28184 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 28185 break;
099e5b4d
LA
28186 case OPC_DMTHLIP:
28187 case OPC_DSHILO:
28188 case OPC_DSHILOV:
28189 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 28190 break;
099e5b4d
LA
28191 default: /* Invalid */
28192 MIPS_INVAL("MASK EXTR.W");
9c708c7f 28193 generate_exception_end(ctx, EXCP_RI);
461c08df 28194 break;
099e5b4d
LA
28195 }
28196 break;
28197 case OPC_DPAQ_W_QH_DSP:
28198 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28199 switch (op2) {
28200 case OPC_DPAU_H_OBL:
28201 case OPC_DPAU_H_OBR:
28202 case OPC_DPSU_H_OBL:
28203 case OPC_DPSU_H_OBR:
28204 case OPC_DPA_W_QH:
28205 case OPC_DPAQ_S_W_QH:
28206 case OPC_DPS_W_QH:
28207 case OPC_DPSQ_S_W_QH:
28208 case OPC_MULSAQ_S_W_QH:
28209 case OPC_DPAQ_SA_L_PW:
28210 case OPC_DPSQ_SA_L_PW:
28211 case OPC_MULSAQ_S_L_PW:
28212 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28213 break;
28214 case OPC_MAQ_S_W_QHLL:
28215 case OPC_MAQ_S_W_QHLR:
28216 case OPC_MAQ_S_W_QHRL:
28217 case OPC_MAQ_S_W_QHRR:
28218 case OPC_MAQ_SA_W_QHLL:
28219 case OPC_MAQ_SA_W_QHLR:
28220 case OPC_MAQ_SA_W_QHRL:
28221 case OPC_MAQ_SA_W_QHRR:
28222 case OPC_MAQ_S_L_PWL:
28223 case OPC_MAQ_S_L_PWR:
28224 case OPC_DMADD:
28225 case OPC_DMADDU:
28226 case OPC_DMSUB:
28227 case OPC_DMSUBU:
28228 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 28229 break;
099e5b4d
LA
28230 default: /* Invalid */
28231 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 28232 generate_exception_end(ctx, EXCP_RI);
b53371ed 28233 break;
099e5b4d
LA
28234 }
28235 break;
28236 case OPC_DINSV_DSP:
28237 op2 = MASK_INSV(ctx->opcode);
28238 switch (op2) {
28239 case OPC_DINSV:
28240 {
28241 TCGv t0, t1;
28242
28243 if (rt == 0) {
a22260ae
JL
28244 break;
28245 }
099e5b4d 28246 check_dsp(ctx);
1cb6686c 28247
099e5b4d
LA
28248 t0 = tcg_temp_new();
28249 t1 = tcg_temp_new();
1cb6686c 28250
099e5b4d
LA
28251 gen_load_gpr(t0, rt);
28252 gen_load_gpr(t1, rs);
1cb6686c 28253
099e5b4d 28254 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 28255
099e5b4d
LA
28256 tcg_temp_free(t0);
28257 tcg_temp_free(t1);
77c5fa8b 28258 break;
099e5b4d 28259 }
7a387fff 28260 default: /* Invalid */
099e5b4d 28261 MIPS_INVAL("MASK DINSV");
9c708c7f 28262 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
28263 break;
28264 }
28265 break;
099e5b4d
LA
28266 case OPC_SHLL_OB_DSP:
28267 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28268 break;
28269#endif
fac5a073
LA
28270 default: /* Invalid */
28271 MIPS_INVAL("special3_legacy");
9c708c7f 28272 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
28273 break;
28274 }
28275}
28276
37b9aae2
MM
28277
28278#if defined(TARGET_MIPS64)
28279
874b2879 28280static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 28281{
c8341e00 28282 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
28283
28284 switch (opc) {
baa609db
AM
28285 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28286 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28287 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28288 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28289 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28290 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28291 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28292 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28293 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28294 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28295 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28296 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28297 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28298 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28299 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28300 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28301 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28302 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28303 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28304 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28305 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28306 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28307 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28308 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28309 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28310 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
28311 break;
28312 default:
28313 MIPS_INVAL("TX79 MMI class MMI0");
28314 generate_exception_end(ctx, EXCP_RI);
28315 break;
28316 }
28317}
28318
874b2879 28319static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 28320{
c8341e00 28321 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
28322
28323 switch (opc) {
baa609db
AM
28324 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28325 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28326 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28327 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28328 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28329 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28330 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28331 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28332 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28333 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28334 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28335 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28336 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28337 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28338 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28339 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28340 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28341 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28342 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
28343 break;
28344 default:
28345 MIPS_INVAL("TX79 MMI class MMI1");
28346 generate_exception_end(ctx, EXCP_RI);
28347 break;
28348 }
28349}
28350
874b2879 28351static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 28352{
c8341e00 28353 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
28354
28355 switch (opc) {
baa609db
AM
28356 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28357 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28358 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28359 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28360 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28361 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28362 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28363 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28364 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
baa609db
AM
28365 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28366 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28367 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28368 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28369 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28370 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28371 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28372 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28373 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28374 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28375 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28376 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28377 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3 28378 break;
b87eef31
MM
28379 case MMI_OPC_2_PCPYLD:
28380 gen_mmi_pcpyld(ctx);
28381 break;
6c1e48d3
FN
28382 default:
28383 MIPS_INVAL("TX79 MMI class MMI2");
28384 generate_exception_end(ctx, EXCP_RI);
28385 break;
28386 }
28387}
28388
874b2879 28389static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 28390{
c8341e00 28391 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
28392
28393 switch (opc) {
baa609db
AM
28394 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28395 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28396 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28397 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28398 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28399 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28400 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
baa609db
AM
28401 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28402 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28403 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
baa609db
AM
28404 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28405 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc 28406 break;
d3434d9f
MM
28407 case MMI_OPC_3_PCPYH:
28408 gen_mmi_pcpyh(ctx);
28409 break;
fd487f83
MM
28410 case MMI_OPC_3_PCPYUD:
28411 gen_mmi_pcpyud(ctx);
28412 break;
ec1944fc
FN
28413 default:
28414 MIPS_INVAL("TX79 MMI class MMI3");
28415 generate_exception_end(ctx, EXCP_RI);
28416 break;
28417 }
28418}
28419
874b2879 28420static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 28421{
c8341e00 28422 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
28423 int rs = extract32(ctx->opcode, 21, 5);
28424 int rt = extract32(ctx->opcode, 16, 5);
28425 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
28426
28427 switch (opc) {
baa609db 28428 case MMI_OPC_CLASS_MMI0:
874b2879 28429 decode_mmi0(env, ctx);
88eafe0b 28430 break;
baa609db 28431 case MMI_OPC_CLASS_MMI1:
874b2879 28432 decode_mmi1(env, ctx);
7a803ca2 28433 break;
baa609db 28434 case MMI_OPC_CLASS_MMI2:
874b2879 28435 decode_mmi2(env, ctx);
6c1e48d3 28436 break;
baa609db 28437 case MMI_OPC_CLASS_MMI3:
874b2879 28438 decode_mmi3(env, ctx);
ec1944fc 28439 break;
baa609db
AM
28440 case MMI_OPC_MULT1:
28441 case MMI_OPC_MULTU1:
3b948f05
PMD
28442 case MMI_OPC_MADD:
28443 case MMI_OPC_MADDU:
a95c4c26
FN
28444 case MMI_OPC_MADD1:
28445 case MMI_OPC_MADDU1:
06de726b
FN
28446 gen_mul_txx9(ctx, opc, rd, rs, rt);
28447 break;
baa609db
AM
28448 case MMI_OPC_DIV1:
28449 case MMI_OPC_DIVU1:
c42171c3 28450 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 28451 break;
baa609db
AM
28452 case MMI_OPC_MTLO1:
28453 case MMI_OPC_MTHI1:
86efbfb6 28454 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 28455 break;
baa609db
AM
28456 case MMI_OPC_MFLO1:
28457 case MMI_OPC_MFHI1:
86efbfb6 28458 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 28459 break;
baa609db 28460 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
28461 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28462 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28463 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28464 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28465 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28466 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28467 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28468 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28469 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
28470 break;
28471 default:
28472 MIPS_INVAL("TX79 MMI class");
28473 generate_exception_end(ctx, EXCP_RI);
28474 break;
28475 }
28476}
28477
874b2879 28478static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 28479{
baa609db 28480 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
28481}
28482
874b2879 28483static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 28484{
baa609db 28485 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
28486}
28487
28488/*
28489 * The TX79-specific instruction Store Quadword
28490 *
28491 * +--------+-------+-------+------------------------+
28492 * | 011111 | base | rt | offset | SQ
28493 * +--------+-------+-------+------------------------+
28494 * 6 5 5 16
28495 *
28496 * has the same opcode as the Read Hardware Register instruction
28497 *
28498 * +--------+-------+-------+-------+-------+--------+
28499 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28500 * +--------+-------+-------+-------+-------+--------+
28501 * 6 5 5 5 5 6
28502 *
28503 * that is required, trapped and emulated by the Linux kernel. However, all
28504 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28505 * offset is odd. Therefore all valid SQ instructions can execute normally.
28506 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28507 * between SQ and RDHWR, as the Linux kernel does.
28508 */
874b2879 28509static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
28510{
28511 int base = extract32(ctx->opcode, 21, 5);
28512 int rt = extract32(ctx->opcode, 16, 5);
28513 int offset = extract32(ctx->opcode, 0, 16);
28514
28515#ifdef CONFIG_USER_ONLY
28516 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28517 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28518
28519 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28520 int rd = extract32(ctx->opcode, 11, 5);
28521
28522 gen_rdhwr(ctx, rt, rd, 0);
28523 return;
28524 }
28525#endif
28526
874b2879 28527 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
28528}
28529
37b9aae2
MM
28530#endif
28531
fac5a073
LA
28532static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28533{
28534 int rs, rt, rd, sa;
28535 uint32_t op1, op2;
76964147 28536 int16_t imm;
fac5a073
LA
28537
28538 rs = (ctx->opcode >> 21) & 0x1f;
28539 rt = (ctx->opcode >> 16) & 0x1f;
28540 rd = (ctx->opcode >> 11) & 0x1f;
28541 sa = (ctx->opcode >> 6) & 0x1f;
76964147 28542 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
28543
28544 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
28545
28546 /*
28547 * EVA loads and stores overlap Loongson 2E instructions decoded by
28548 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28549 * EVA is absent.
28550 */
28551 if (ctx->eva) {
28552 switch (op1) {
c2e19f3c
AM
28553 case OPC_LWLE:
28554 case OPC_LWRE:
2e211e0a 28555 check_insn_opc_removed(ctx, ISA_MIPS_R6);
76964147 28556 /* fall through */
c2e19f3c
AM
28557 case OPC_LBUE:
28558 case OPC_LHUE:
28559 case OPC_LBE:
28560 case OPC_LHE:
28561 case OPC_LLE:
28562 case OPC_LWE:
76964147
JH
28563 check_cp0_enabled(ctx);
28564 gen_ld(ctx, op1, rt, rs, imm);
28565 return;
c2e19f3c
AM
28566 case OPC_SWLE:
28567 case OPC_SWRE:
2e211e0a 28568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
76964147 28569 /* fall through */
c2e19f3c
AM
28570 case OPC_SBE:
28571 case OPC_SHE:
76964147
JH
28572 case OPC_SWE:
28573 check_cp0_enabled(ctx);
28574 gen_st(ctx, op1, rt, rs, imm);
28575 return;
28576 case OPC_SCE:
28577 check_cp0_enabled(ctx);
33a07fa2 28578 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
28579 return;
28580 case OPC_CACHEE:
28581 check_cp0_enabled(ctx);
28582 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28583 gen_cache_operation(ctx, rt, rs, imm);
28584 }
28585 /* Treat as NOP. */
28586 return;
28587 case OPC_PREFE:
28588 check_cp0_enabled(ctx);
28589 /* Treat as NOP. */
28590 return;
28591 }
28592 }
28593
fac5a073
LA
28594 switch (op1) {
28595 case OPC_EXT:
28596 case OPC_INS:
7a47bae5 28597 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
28598 gen_bitops(ctx, op1, rt, rs, sa, rd);
28599 break;
28600 case OPC_BSHFL:
fac5a073 28601 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 28602 switch (op2) {
c2e19f3c 28603 case OPC_ALIGN:
373ecd38
AM
28604 case OPC_ALIGN_1:
28605 case OPC_ALIGN_2:
28606 case OPC_ALIGN_3:
15eacb9b 28607 case OPC_BITSWAP:
2e211e0a 28608 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
28609 decode_opc_special3_r6(env, ctx);
28610 break;
28611 default:
7a47bae5 28612 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
28613 gen_bshfl(ctx, op2, rt, rd);
28614 break;
28615 }
fac5a073
LA
28616 break;
28617#if defined(TARGET_MIPS64)
c2e19f3c
AM
28618 case OPC_DEXTM:
28619 case OPC_DEXTU:
28620 case OPC_DEXT:
28621 case OPC_DINSM:
28622 case OPC_DINSU:
28623 case OPC_DINS:
7a47bae5 28624 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
28625 check_mips_64(ctx);
28626 gen_bitops(ctx, op1, rt, rs, sa, rd);
28627 break;
28628 case OPC_DBSHFL:
fac5a073 28629 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 28630 switch (op2) {
c2e19f3c 28631 case OPC_DALIGN:
373ecd38
AM
28632 case OPC_DALIGN_1:
28633 case OPC_DALIGN_2:
28634 case OPC_DALIGN_3:
28635 case OPC_DALIGN_4:
28636 case OPC_DALIGN_5:
28637 case OPC_DALIGN_6:
28638 case OPC_DALIGN_7:
15eacb9b 28639 case OPC_DBITSWAP:
2e211e0a 28640 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
28641 decode_opc_special3_r6(env, ctx);
28642 break;
28643 default:
7a47bae5 28644 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
28645 check_mips_64(ctx);
28646 op2 = MASK_DBSHFL(ctx->opcode);
28647 gen_bshfl(ctx, op2, rt, rd);
28648 break;
28649 }
fac5a073
LA
28650 break;
28651#endif
28652 case OPC_RDHWR:
b00c7218 28653 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
28654 break;
28655 case OPC_FORK:
9affc1c5 28656 check_mt(ctx);
fac5a073
LA
28657 {
28658 TCGv t0 = tcg_temp_new();
28659 TCGv t1 = tcg_temp_new();
28660
28661 gen_load_gpr(t0, rt);
28662 gen_load_gpr(t1, rs);
28663 gen_helper_fork(t0, t1);
28664 tcg_temp_free(t0);
28665 tcg_temp_free(t1);
28666 }
28667 break;
28668 case OPC_YIELD:
9affc1c5 28669 check_mt(ctx);
fac5a073
LA
28670 {
28671 TCGv t0 = tcg_temp_new();
28672
fac5a073
LA
28673 gen_load_gpr(t0, rs);
28674 gen_helper_yield(t0, cpu_env, t0);
28675 gen_store_gpr(t0, rd);
28676 tcg_temp_free(t0);
28677 }
28678 break;
10dc65db 28679 default:
2e211e0a 28680 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db
LA
28681 decode_opc_special3_r6(env, ctx);
28682 } else {
28683 decode_opc_special3_legacy(env, ctx);
28684 }
099e5b4d
LA
28685 }
28686}
28687
863f264d
YK
28688/* MIPS SIMD Architecture (MSA) */
28689static inline int check_msa_access(DisasContext *ctx)
28690{
28691 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28692 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 28693 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28694 return 0;
28695 }
28696
28697 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28698 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 28699 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
28700 return 0;
28701 } else {
9c708c7f 28702 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
28703 return 0;
28704 }
28705 }
28706 return 1;
28707}
28708
5692c6e1
YK
28709static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28710{
28711 /* generates tcg ops to check if any element is 0 */
28712 /* Note this function only works with MSA_WRLEN = 128 */
28713 uint64_t eval_zero_or_big = 0;
28714 uint64_t eval_big = 0;
28715 TCGv_i64 t0 = tcg_temp_new_i64();
28716 TCGv_i64 t1 = tcg_temp_new_i64();
28717 switch (df) {
28718 case DF_BYTE:
28719 eval_zero_or_big = 0x0101010101010101ULL;
28720 eval_big = 0x8080808080808080ULL;
28721 break;
28722 case DF_HALF:
28723 eval_zero_or_big = 0x0001000100010001ULL;
28724 eval_big = 0x8000800080008000ULL;
28725 break;
28726 case DF_WORD:
28727 eval_zero_or_big = 0x0000000100000001ULL;
28728 eval_big = 0x8000000080000000ULL;
28729 break;
28730 case DF_DOUBLE:
28731 eval_zero_or_big = 0x0000000000000001ULL;
28732 eval_big = 0x8000000000000000ULL;
28733 break;
28734 }
235785e8
AM
28735 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28736 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
5692c6e1 28737 tcg_gen_andi_i64(t0, t0, eval_big);
235785e8
AM
28738 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28739 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28740 tcg_gen_andi_i64(t1, t1, eval_big);
28741 tcg_gen_or_i64(t0, t0, t1);
28742 /* if all bits are zero then all elements are not zero */
28743 /* if some bit is non-zero then some element is zero */
28744 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28745 tcg_gen_trunc_i64_tl(tresult, t0);
28746 tcg_temp_free_i64(t0);
28747 tcg_temp_free_i64(t1);
28748}
28749
28750static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28751{
28752 uint8_t df = (ctx->opcode >> 21) & 0x3;
28753 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28754 int64_t s16 = (int16_t)ctx->opcode;
28755
28756 check_msa_access(ctx);
28757
075a1fe7 28758 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 28759 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
28760 return;
28761 }
28762 switch (op1) {
28763 case OPC_BZ_V:
28764 case OPC_BNZ_V:
28765 {
28766 TCGv_i64 t0 = tcg_temp_new_i64();
235785e8 28767 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
5692c6e1
YK
28768 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28769 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28770 tcg_gen_trunc_i64_tl(bcond, t0);
28771 tcg_temp_free_i64(t0);
28772 }
28773 break;
28774 case OPC_BZ_B:
28775 case OPC_BZ_H:
28776 case OPC_BZ_W:
28777 case OPC_BZ_D:
28778 gen_check_zero_element(bcond, df, wt);
28779 break;
28780 case OPC_BNZ_B:
28781 case OPC_BNZ_H:
28782 case OPC_BNZ_W:
28783 case OPC_BNZ_D:
28784 gen_check_zero_element(bcond, df, wt);
28785 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28786 break;
28787 }
28788
eeb3bba8 28789 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
28790
28791 ctx->hflags |= MIPS_HFLAG_BC;
28792 ctx->hflags |= MIPS_HFLAG_BDS32;
28793}
28794
4c789546
YK
28795static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28796{
28797#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28798 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28799 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28800 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28801
28802 TCGv_i32 twd = tcg_const_i32(wd);
28803 TCGv_i32 tws = tcg_const_i32(ws);
28804 TCGv_i32 ti8 = tcg_const_i32(i8);
28805
28806 switch (MASK_MSA_I8(ctx->opcode)) {
28807 case OPC_ANDI_B:
28808 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28809 break;
28810 case OPC_ORI_B:
28811 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28812 break;
28813 case OPC_NORI_B:
28814 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28815 break;
28816 case OPC_XORI_B:
28817 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28818 break;
28819 case OPC_BMNZI_B:
28820 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28821 break;
28822 case OPC_BMZI_B:
28823 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28824 break;
28825 case OPC_BSELI_B:
28826 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28827 break;
28828 case OPC_SHF_B:
28829 case OPC_SHF_H:
28830 case OPC_SHF_W:
28831 {
28832 uint8_t df = (ctx->opcode >> 24) & 0x3;
28833 if (df == DF_DOUBLE) {
9c708c7f 28834 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28835 } else {
28836 TCGv_i32 tdf = tcg_const_i32(df);
28837 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28838 tcg_temp_free_i32(tdf);
28839 }
28840 }
28841 break;
28842 default:
28843 MIPS_INVAL("MSA instruction");
9c708c7f 28844 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28845 break;
28846 }
28847
28848 tcg_temp_free_i32(twd);
28849 tcg_temp_free_i32(tws);
28850 tcg_temp_free_i32(ti8);
28851}
28852
80e71591
YK
28853static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28854{
28855#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28856 uint8_t df = (ctx->opcode >> 21) & 0x3;
28857 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28858 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28859 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28860 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28861
28862 TCGv_i32 tdf = tcg_const_i32(df);
28863 TCGv_i32 twd = tcg_const_i32(wd);
28864 TCGv_i32 tws = tcg_const_i32(ws);
28865 TCGv_i32 timm = tcg_temp_new_i32();
28866 tcg_gen_movi_i32(timm, u5);
28867
28868 switch (MASK_MSA_I5(ctx->opcode)) {
28869 case OPC_ADDVI_df:
28870 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28871 break;
28872 case OPC_SUBVI_df:
28873 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28874 break;
28875 case OPC_MAXI_S_df:
28876 tcg_gen_movi_i32(timm, s5);
28877 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28878 break;
28879 case OPC_MAXI_U_df:
28880 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28881 break;
28882 case OPC_MINI_S_df:
28883 tcg_gen_movi_i32(timm, s5);
28884 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28885 break;
28886 case OPC_MINI_U_df:
28887 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28888 break;
28889 case OPC_CEQI_df:
28890 tcg_gen_movi_i32(timm, s5);
28891 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28892 break;
28893 case OPC_CLTI_S_df:
28894 tcg_gen_movi_i32(timm, s5);
28895 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28896 break;
28897 case OPC_CLTI_U_df:
28898 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28899 break;
28900 case OPC_CLEI_S_df:
28901 tcg_gen_movi_i32(timm, s5);
28902 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28903 break;
28904 case OPC_CLEI_U_df:
28905 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28906 break;
28907 case OPC_LDI_df:
28908 {
28909 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28910 tcg_gen_movi_i32(timm, s10);
28911 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28912 }
28913 break;
28914 default:
28915 MIPS_INVAL("MSA instruction");
9c708c7f 28916 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
28917 break;
28918 }
28919
28920 tcg_temp_free_i32(tdf);
28921 tcg_temp_free_i32(twd);
28922 tcg_temp_free_i32(tws);
28923 tcg_temp_free_i32(timm);
28924}
28925
d4cf28de
YK
28926static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28927{
28928#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28929 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28930 uint32_t df = 0, m = 0;
28931 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28932 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28933
28934 TCGv_i32 tdf;
28935 TCGv_i32 tm;
28936 TCGv_i32 twd;
28937 TCGv_i32 tws;
28938
28939 if ((dfm & 0x40) == 0x00) {
28940 m = dfm & 0x3f;
28941 df = DF_DOUBLE;
28942 } else if ((dfm & 0x60) == 0x40) {
28943 m = dfm & 0x1f;
28944 df = DF_WORD;
28945 } else if ((dfm & 0x70) == 0x60) {
28946 m = dfm & 0x0f;
28947 df = DF_HALF;
28948 } else if ((dfm & 0x78) == 0x70) {
28949 m = dfm & 0x7;
28950 df = DF_BYTE;
28951 } else {
9c708c7f 28952 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
28953 return;
28954 }
28955
28956 tdf = tcg_const_i32(df);
28957 tm = tcg_const_i32(m);
28958 twd = tcg_const_i32(wd);
28959 tws = tcg_const_i32(ws);
28960
28961 switch (MASK_MSA_BIT(ctx->opcode)) {
28962 case OPC_SLLI_df:
28963 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28964 break;
28965 case OPC_SRAI_df:
28966 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28967 break;
28968 case OPC_SRLI_df:
28969 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28970 break;
28971 case OPC_BCLRI_df:
28972 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28973 break;
28974 case OPC_BSETI_df:
28975 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28976 break;
28977 case OPC_BNEGI_df:
28978 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28979 break;
28980 case OPC_BINSLI_df:
28981 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28982 break;
28983 case OPC_BINSRI_df:
28984 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28985 break;
28986 case OPC_SAT_S_df:
28987 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28988 break;
28989 case OPC_SAT_U_df:
28990 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28991 break;
28992 case OPC_SRARI_df:
28993 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28994 break;
28995 case OPC_SRLRI_df:
28996 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28997 break;
28998 default:
28999 MIPS_INVAL("MSA instruction");
9c708c7f 29000 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
29001 break;
29002 }
29003
29004 tcg_temp_free_i32(tdf);
29005 tcg_temp_free_i32(tm);
29006 tcg_temp_free_i32(twd);
29007 tcg_temp_free_i32(tws);
29008}
29009
28f99f08
YK
29010static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
29011{
29012#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
29013 uint8_t df = (ctx->opcode >> 21) & 0x3;
29014 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29015 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29016 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29017
29018 TCGv_i32 tdf = tcg_const_i32(df);
29019 TCGv_i32 twd = tcg_const_i32(wd);
29020 TCGv_i32 tws = tcg_const_i32(ws);
29021 TCGv_i32 twt = tcg_const_i32(wt);
29022
29023 switch (MASK_MSA_3R(ctx->opcode)) {
2e3eddb0
AM
29024 case OPC_BINSL_df:
29025 switch (df) {
29026 case DF_BYTE:
29027 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_HALF:
29030 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
29031 break;
29032 case DF_WORD:
29033 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
29034 break;
29035 case DF_DOUBLE:
29036 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
29037 break;
29038 }
29039 break;
29040 case OPC_BINSR_df:
29041 switch (df) {
29042 case DF_BYTE:
29043 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_HALF:
29046 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
29047 break;
29048 case DF_WORD:
29049 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
29050 break;
29051 case DF_DOUBLE:
29052 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
29053 break;
29054 }
29055 break;
a44d6d14
AM
29056 case OPC_BCLR_df:
29057 switch (df) {
29058 case DF_BYTE:
29059 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_HALF:
29062 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
29063 break;
29064 case DF_WORD:
29065 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
29066 break;
29067 case DF_DOUBLE:
29068 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
29069 break;
29070 }
29071 break;
29072 case OPC_BNEG_df:
29073 switch (df) {
29074 case DF_BYTE:
29075 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_HALF:
29078 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
29079 break;
29080 case DF_WORD:
29081 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
29082 break;
29083 case DF_DOUBLE:
29084 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
29085 break;
29086 }
29087 break;
29088 case OPC_BSET_df:
29089 switch (df) {
29090 case DF_BYTE:
29091 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_HALF:
29094 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
29095 break;
29096 case DF_WORD:
29097 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
29098 break;
29099 case DF_DOUBLE:
29100 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
29101 break;
29102 }
29103 break;
c65ca134
AM
29104 case OPC_ADD_A_df:
29105 switch (df) {
29106 case DF_BYTE:
29107 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_HALF:
29110 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
29111 break;
29112 case DF_WORD:
29113 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
29114 break;
29115 case DF_DOUBLE:
29116 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
29117 break;
29118 }
29119 break;
29120 case OPC_ADDS_A_df:
29121 switch (df) {
29122 case DF_BYTE:
29123 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_HALF:
29126 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
29127 break;
29128 case DF_WORD:
29129 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29130 break;
29131 case DF_DOUBLE:
29132 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29133 break;
29134 }
29135 break;
29136 case OPC_ADDS_S_df:
29137 switch (df) {
29138 case DF_BYTE:
29139 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_HALF:
29142 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29143 break;
29144 case DF_WORD:
29145 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29146 break;
29147 case DF_DOUBLE:
29148 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29149 break;
29150 }
29151 break;
29152 case OPC_ADDS_U_df:
29153 switch (df) {
29154 case DF_BYTE:
29155 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_HALF:
29158 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29159 break;
29160 case DF_WORD:
29161 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29162 break;
29163 case DF_DOUBLE:
29164 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29165 break;
29166 }
29167 break;
29168 case OPC_ADDV_df:
29169 switch (df) {
29170 case DF_BYTE:
29171 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_HALF:
29174 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29175 break;
29176 case DF_WORD:
29177 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29178 break;
29179 case DF_DOUBLE:
29180 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29181 break;
29182 }
29183 break;
7672edc4
AM
29184 case OPC_AVE_S_df:
29185 switch (df) {
29186 case DF_BYTE:
29187 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_HALF:
29190 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29191 break;
29192 case DF_WORD:
29193 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29194 break;
29195 case DF_DOUBLE:
29196 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29197 break;
29198 }
29199 break;
29200 case OPC_AVE_U_df:
29201 switch (df) {
29202 case DF_BYTE:
29203 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29204 break;
29205 case DF_HALF:
29206 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29207 break;
29208 case DF_WORD:
29209 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29210 break;
29211 case DF_DOUBLE:
29212 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29213 break;
29214 }
29215 break;
755107e2
AM
29216 case OPC_AVER_S_df:
29217 switch (df) {
29218 case DF_BYTE:
29219 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29220 break;
29221 case DF_HALF:
29222 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29223 break;
29224 case DF_WORD:
29225 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29226 break;
29227 case DF_DOUBLE:
29228 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29229 break;
29230 }
29231 break;
29232 case OPC_AVER_U_df:
29233 switch (df) {
29234 case DF_BYTE:
29235 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29236 break;
29237 case DF_HALF:
29238 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29239 break;
29240 case DF_WORD:
29241 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29242 break;
29243 case DF_DOUBLE:
29244 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29245 break;
29246 }
29247 break;
ade7e788
AM
29248 case OPC_CEQ_df:
29249 switch (df) {
29250 case DF_BYTE:
29251 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29252 break;
29253 case DF_HALF:
29254 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29255 break;
29256 case DF_WORD:
29257 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29258 break;
29259 case DF_DOUBLE:
29260 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29261 break;
29262 }
29263 break;
0501bb1a
AM
29264 case OPC_CLE_S_df:
29265 switch (df) {
29266 case DF_BYTE:
29267 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29268 break;
29269 case DF_HALF:
29270 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29271 break;
29272 case DF_WORD:
29273 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29274 break;
29275 case DF_DOUBLE:
29276 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29277 break;
29278 }
29279 break;
29280 case OPC_CLE_U_df:
29281 switch (df) {
29282 case DF_BYTE:
29283 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29284 break;
29285 case DF_HALF:
29286 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29287 break;
29288 case DF_WORD:
29289 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29290 break;
29291 case DF_DOUBLE:
29292 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29293 break;
29294 }
29295 break;
11656699
AM
29296 case OPC_CLT_S_df:
29297 switch (df) {
29298 case DF_BYTE:
29299 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29300 break;
29301 case DF_HALF:
29302 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29303 break;
29304 case DF_WORD:
29305 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29306 break;
29307 case DF_DOUBLE:
29308 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29309 break;
29310 }
29311 break;
29312 case OPC_CLT_U_df:
29313 switch (df) {
29314 case DF_BYTE:
29315 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29316 break;
29317 case DF_HALF:
29318 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29319 break;
29320 case DF_WORD:
29321 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29322 break;
29323 case DF_DOUBLE:
29324 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29325 break;
29326 }
29327 break;
64a0257f
AM
29328 case OPC_DIV_S_df:
29329 switch (df) {
29330 case DF_BYTE:
29331 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29332 break;
29333 case DF_HALF:
29334 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29335 break;
29336 case DF_WORD:
29337 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29338 break;
29339 case DF_DOUBLE:
29340 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29341 break;
29342 }
29343 break;
29344 case OPC_DIV_U_df:
29345 switch (df) {
29346 case DF_BYTE:
29347 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29348 break;
29349 case DF_HALF:
29350 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29351 break;
29352 case DF_WORD:
29353 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29354 break;
29355 case DF_DOUBLE:
29356 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29357 break;
29358 }
29359 break;
e8e01ef0
AM
29360 case OPC_MAX_A_df:
29361 switch (df) {
29362 case DF_BYTE:
29363 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29364 break;
29365 case DF_HALF:
29366 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29367 break;
29368 case DF_WORD:
29369 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29370 break;
29371 case DF_DOUBLE:
29372 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29373 break;
29374 }
29375 break;
2db26305
AM
29376 case OPC_MAX_S_df:
29377 switch (df) {
29378 case DF_BYTE:
29379 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29380 break;
29381 case DF_HALF:
29382 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29383 break;
29384 case DF_WORD:
29385 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29386 break;
29387 case DF_DOUBLE:
29388 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29389 break;
29390 }
29391 break;
29392 case OPC_MAX_U_df:
29393 switch (df) {
29394 case DF_BYTE:
29395 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29396 break;
29397 case DF_HALF:
29398 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29399 break;
29400 case DF_WORD:
29401 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29402 break;
29403 case DF_DOUBLE:
29404 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29405 break;
29406 }
29407 break;
e8e01ef0
AM
29408 case OPC_MIN_A_df:
29409 switch (df) {
29410 case DF_BYTE:
29411 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29412 break;
29413 case DF_HALF:
29414 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29415 break;
29416 case DF_WORD:
29417 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29418 break;
29419 case DF_DOUBLE:
29420 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29421 break;
29422 }
29423 break;
2db26305
AM
29424 case OPC_MIN_S_df:
29425 switch (df) {
29426 case DF_BYTE:
29427 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29428 break;
29429 case DF_HALF:
29430 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29431 break;
29432 case DF_WORD:
29433 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29434 break;
29435 case DF_DOUBLE:
29436 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29437 break;
29438 }
29439 break;
29440 case OPC_MIN_U_df:
29441 switch (df) {
29442 case DF_BYTE:
29443 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29444 break;
29445 case DF_HALF:
29446 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29447 break;
29448 case DF_WORD:
29449 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29450 break;
29451 case DF_DOUBLE:
29452 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29453 break;
29454 }
29455 break;
a6387ea5
AM
29456 case OPC_MOD_S_df:
29457 switch (df) {
29458 case DF_BYTE:
29459 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29460 break;
29461 case DF_HALF:
29462 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29463 break;
29464 case DF_WORD:
29465 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29466 break;
29467 case DF_DOUBLE:
29468 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29469 break;
29470 }
29471 break;
29472 case OPC_MOD_U_df:
29473 switch (df) {
29474 case DF_BYTE:
29475 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29476 break;
29477 case DF_HALF:
29478 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29479 break;
29480 case DF_WORD:
29481 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29482 break;
29483 case DF_DOUBLE:
29484 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29485 break;
29486 }
29487 break;
7a7a162a
AM
29488 case OPC_MADDV_df:
29489 switch (df) {
29490 case DF_BYTE:
29491 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29492 break;
29493 case DF_HALF:
29494 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29495 break;
29496 case DF_WORD:
29497 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29498 break;
29499 case DF_DOUBLE:
29500 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29501 break;
29502 }
29503 break;
5f148a02
AM
29504 case OPC_MSUBV_df:
29505 switch (df) {
29506 case DF_BYTE:
29507 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29508 break;
29509 case DF_HALF:
29510 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29511 break;
29512 case DF_WORD:
29513 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29514 break;
29515 case DF_DOUBLE:
29516 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29517 break;
29518 }
29519 break;
f392d134
AM
29520 case OPC_ASUB_S_df:
29521 switch (df) {
29522 case DF_BYTE:
29523 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29524 break;
29525 case DF_HALF:
29526 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29527 break;
29528 case DF_WORD:
29529 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29530 break;
29531 case DF_DOUBLE:
29532 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29533 break;
29534 }
29535 break;
29536 case OPC_ASUB_U_df:
29537 switch (df) {
29538 case DF_BYTE:
29539 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29540 break;
29541 case DF_HALF:
29542 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29543 break;
29544 case DF_WORD:
29545 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29546 break;
29547 case DF_DOUBLE:
29548 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29549 break;
29550 }
29551 break;
fb5f59b4
AM
29552 case OPC_ILVEV_df:
29553 switch (df) {
29554 case DF_BYTE:
29555 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29556 break;
29557 case DF_HALF:
29558 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29559 break;
29560 case DF_WORD:
29561 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29562 break;
29563 case DF_DOUBLE:
29564 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29565 break;
29566 }
29567 break;
29568 case OPC_ILVOD_df:
29569 switch (df) {
29570 case DF_BYTE:
29571 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29572 break;
29573 case DF_HALF:
29574 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29575 break;
29576 case DF_WORD:
29577 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29578 break;
29579 case DF_DOUBLE:
29580 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29581 break;
29582 }
29583 break;
29584 case OPC_ILVL_df:
29585 switch (df) {
29586 case DF_BYTE:
29587 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29588 break;
29589 case DF_HALF:
29590 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29591 break;
29592 case DF_WORD:
29593 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29594 break;
29595 case DF_DOUBLE:
29596 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29597 break;
29598 }
29599 break;
29600 case OPC_ILVR_df:
29601 switch (df) {
29602 case DF_BYTE:
29603 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29604 break;
29605 case DF_HALF:
29606 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29607 break;
29608 case DF_WORD:
29609 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29610 break;
29611 case DF_DOUBLE:
29612 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29613 break;
29614 }
29615 break;
8a0ee380
AM
29616 case OPC_PCKEV_df:
29617 switch (df) {
29618 case DF_BYTE:
29619 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29620 break;
29621 case DF_HALF:
29622 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29623 break;
29624 case DF_WORD:
29625 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29626 break;
29627 case DF_DOUBLE:
29628 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29629 break;
29630 }
29631 break;
29632 case OPC_PCKOD_df:
29633 switch (df) {
29634 case DF_BYTE:
29635 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29636 break;
29637 case DF_HALF:
29638 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29639 break;
29640 case DF_WORD:
29641 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29642 break;
29643 case DF_DOUBLE:
29644 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29645 break;
29646 }
29647 break;
28f99f08 29648 case OPC_SLL_df:
4d52cc2b
AM
29649 switch (df) {
29650 case DF_BYTE:
29651 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29652 break;
29653 case DF_HALF:
29654 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29655 break;
29656 case DF_WORD:
29657 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29658 break;
29659 case DF_DOUBLE:
29660 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29661 break;
29662 }
29663 break;
29664 case OPC_SRA_df:
29665 switch (df) {
29666 case DF_BYTE:
29667 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29668 break;
29669 case DF_HALF:
29670 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29671 break;
29672 case DF_WORD:
29673 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29674 break;
29675 case DF_DOUBLE:
29676 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29677 break;
29678 }
29679 break;
29680 case OPC_SRAR_df:
29681 switch (df) {
29682 case DF_BYTE:
29683 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29684 break;
29685 case DF_HALF:
29686 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29687 break;
29688 case DF_WORD:
29689 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29690 break;
29691 case DF_DOUBLE:
29692 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29693 break;
29694 }
29695 break;
29696 case OPC_SRL_df:
29697 switch (df) {
29698 case DF_BYTE:
29699 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29700 break;
29701 case DF_HALF:
29702 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29703 break;
29704 case DF_WORD:
29705 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29706 break;
29707 case DF_DOUBLE:
29708 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29709 break;
29710 }
29711 break;
29712 case OPC_SRLR_df:
29713 switch (df) {
29714 case DF_BYTE:
29715 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29716 break;
29717 case DF_HALF:
29718 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29719 break;
29720 case DF_WORD:
29721 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29722 break;
29723 case DF_DOUBLE:
29724 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29725 break;
29726 }
28f99f08 29727 break;
28f99f08 29728 case OPC_SUBS_S_df:
534e4001
AM
29729 switch (df) {
29730 case DF_BYTE:
29731 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29732 break;
29733 case DF_HALF:
29734 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29735 break;
29736 case DF_WORD:
29737 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29738 break;
29739 case DF_DOUBLE:
29740 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29741 break;
29742 }
28f99f08
YK
29743 break;
29744 case OPC_MULV_df:
05135034
AM
29745 switch (df) {
29746 case DF_BYTE:
29747 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29748 break;
29749 case DF_HALF:
29750 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29751 break;
29752 case DF_WORD:
29753 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29754 break;
29755 case DF_DOUBLE:
29756 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29757 break;
29758 }
28f99f08
YK
29759 break;
29760 case OPC_SLD_df:
29761 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29762 break;
29763 case OPC_VSHF_df:
29764 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29765 break;
28f99f08 29766 case OPC_SUBV_df:
83b2e79a
AM
29767 switch (df) {
29768 case DF_BYTE:
29769 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29770 break;
29771 case DF_HALF:
29772 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29773 break;
29774 case DF_WORD:
29775 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29776 break;
29777 case DF_DOUBLE:
29778 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29779 break;
29780 }
28f99f08 29781 break;
28f99f08 29782 case OPC_SUBS_U_df:
81b53858
AM
29783 switch (df) {
29784 case DF_BYTE:
29785 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29786 break;
29787 case DF_HALF:
29788 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29789 break;
29790 case DF_WORD:
29791 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29792 break;
29793 case DF_DOUBLE:
29794 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29795 break;
29796 }
28f99f08 29797 break;
28f99f08
YK
29798 case OPC_SPLAT_df:
29799 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29800 break;
28f99f08 29801 case OPC_SUBSUS_U_df:
55a04640
AM
29802 switch (df) {
29803 case DF_BYTE:
29804 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29805 break;
29806 case DF_HALF:
29807 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29808 break;
29809 case DF_WORD:
29810 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29811 break;
29812 case DF_DOUBLE:
29813 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29814 break;
29815 }
28f99f08 29816 break;
28f99f08 29817 case OPC_SUBSUU_S_df:
cb4ac991
AM
29818 switch (df) {
29819 case DF_BYTE:
29820 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29821 break;
29822 case DF_HALF:
29823 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29824 break;
29825 case DF_WORD:
29826 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29827 break;
29828 case DF_DOUBLE:
29829 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29830 break;
29831 }
28f99f08 29832 break;
28f99f08
YK
29833
29834 case OPC_DOTP_S_df:
29835 case OPC_DOTP_U_df:
29836 case OPC_DPADD_S_df:
29837 case OPC_DPADD_U_df:
29838 case OPC_DPSUB_S_df:
29839 case OPC_HADD_S_df:
29840 case OPC_DPSUB_U_df:
29841 case OPC_HADD_U_df:
29842 case OPC_HSUB_S_df:
29843 case OPC_HSUB_U_df:
29844 if (df == DF_BYTE) {
9c708c7f
PD
29845 generate_exception_end(ctx, EXCP_RI);
29846 break;
28f99f08
YK
29847 }
29848 switch (MASK_MSA_3R(ctx->opcode)) {
dc0af931
AM
29849 case OPC_HADD_S_df:
29850 switch (df) {
29851 case DF_HALF:
29852 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29853 break;
29854 case DF_WORD:
29855 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29856 break;
29857 case DF_DOUBLE:
29858 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29859 break;
29860 }
29861 break;
29862 case OPC_HADD_U_df:
29863 switch (df) {
29864 case DF_HALF:
29865 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29866 break;
29867 case DF_WORD:
29868 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29869 break;
29870 case DF_DOUBLE:
29871 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29872 break;
29873 }
29874 break;
b24b9aec
AM
29875 case OPC_HSUB_S_df:
29876 switch (df) {
29877 case DF_HALF:
29878 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29879 break;
29880 case DF_WORD:
29881 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29882 break;
29883 case DF_DOUBLE:
29884 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29885 break;
29886 }
29887 break;
29888 case OPC_HSUB_U_df:
29889 switch (df) {
29890 case DF_HALF:
29891 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29892 break;
29893 case DF_WORD:
29894 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29895 break;
29896 case DF_DOUBLE:
29897 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29898 break;
29899 }
29900 break;
28f99f08 29901 case OPC_DOTP_S_df:
165cacb6
AM
29902 switch (df) {
29903 case DF_HALF:
29904 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29905 break;
29906 case DF_WORD:
29907 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29908 break;
29909 case DF_DOUBLE:
29910 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29911 break;
29912 }
28f99f08
YK
29913 break;
29914 case OPC_DOTP_U_df:
72c6a6e2
AM
29915 switch (df) {
29916 case DF_HALF:
29917 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29918 break;
29919 case DF_WORD:
29920 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29921 break;
29922 case DF_DOUBLE:
29923 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29924 break;
29925 }
28f99f08
YK
29926 break;
29927 case OPC_DPADD_S_df:
9f5840a6
AM
29928 switch (df) {
29929 case DF_HALF:
29930 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29931 break;
29932 case DF_WORD:
29933 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29934 break;
29935 case DF_DOUBLE:
29936 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29937 break;
29938 }
28f99f08
YK
29939 break;
29940 case OPC_DPADD_U_df:
e5e0777e
AM
29941 switch (df) {
29942 case DF_HALF:
29943 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29944 break;
29945 case DF_WORD:
29946 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29947 break;
29948 case DF_DOUBLE:
29949 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29950 break;
29951 }
28f99f08
YK
29952 break;
29953 case OPC_DPSUB_S_df:
8ed86716
AM
29954 switch (df) {
29955 case DF_HALF:
29956 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29957 break;
29958 case DF_WORD:
29959 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29960 break;
29961 case DF_DOUBLE:
29962 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29963 break;
29964 }
28f99f08 29965 break;
28f99f08 29966 case OPC_DPSUB_U_df:
0c8c76ac
AM
29967 switch (df) {
29968 case DF_HALF:
29969 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29970 break;
29971 case DF_WORD:
29972 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29973 break;
29974 case DF_DOUBLE:
29975 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29976 break;
29977 }
28f99f08 29978 break;
28f99f08
YK
29979 }
29980 break;
29981 default:
29982 MIPS_INVAL("MSA instruction");
9c708c7f 29983 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
29984 break;
29985 }
29986 tcg_temp_free_i32(twd);
29987 tcg_temp_free_i32(tws);
29988 tcg_temp_free_i32(twt);
29989 tcg_temp_free_i32(tdf);
29990}
29991
1e608ec1
YK
29992static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29993{
29994#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29995 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29996 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29997 TCGv telm = tcg_temp_new();
29998 TCGv_i32 tsr = tcg_const_i32(source);
29999 TCGv_i32 tdt = tcg_const_i32(dest);
30000
30001 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
30002 case OPC_CTCMSA:
30003 gen_load_gpr(telm, source);
30004 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
30005 break;
30006 case OPC_CFCMSA:
30007 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
30008 gen_store_gpr(telm, dest);
30009 break;
30010 case OPC_MOVE_V:
30011 gen_helper_msa_move_v(cpu_env, tdt, tsr);
30012 break;
30013 default:
30014 MIPS_INVAL("MSA instruction");
9c708c7f 30015 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
30016 break;
30017 }
30018
30019 tcg_temp_free(telm);
30020 tcg_temp_free_i32(tdt);
30021 tcg_temp_free_i32(tsr);
30022}
30023
30024static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
30025 uint32_t n)
30026{
30027#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30028 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30029 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30030
30031 TCGv_i32 tws = tcg_const_i32(ws);
30032 TCGv_i32 twd = tcg_const_i32(wd);
30033 TCGv_i32 tn = tcg_const_i32(n);
30034 TCGv_i32 tdf = tcg_const_i32(df);
30035
30036 switch (MASK_MSA_ELM(ctx->opcode)) {
30037 case OPC_SLDI_df:
30038 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
30039 break;
30040 case OPC_SPLATI_df:
30041 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
30042 break;
30043 case OPC_INSVE_df:
30044 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
30045 break;
30046 case OPC_COPY_S_df:
30047 case OPC_COPY_U_df:
30048 case OPC_INSERT_df:
30049#if !defined(TARGET_MIPS64)
30050 /* Double format valid only for MIPS64 */
30051 if (df == DF_DOUBLE) {
9c708c7f 30052 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
30053 break;
30054 }
41d28858
MM
30055 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
30056 (df == DF_WORD)) {
30057 generate_exception_end(ctx, EXCP_RI);
30058 break;
30059 }
1e608ec1
YK
30060#endif
30061 switch (MASK_MSA_ELM(ctx->opcode)) {
30062 case OPC_COPY_S_df:
cab48881 30063 if (likely(wd != 0)) {
631c4674
MM
30064 switch (df) {
30065 case DF_BYTE:
30066 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
30067 break;
30068 case DF_HALF:
30069 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
30070 break;
30071 case DF_WORD:
30072 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
30073 break;
30074#if defined(TARGET_MIPS64)
30075 case DF_DOUBLE:
30076 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
30077 break;
30078#endif
30079 default:
30080 assert(0);
30081 }
cab48881 30082 }
1e608ec1
YK
30083 break;
30084 case OPC_COPY_U_df:
cab48881 30085 if (likely(wd != 0)) {
41d28858
MM
30086 switch (df) {
30087 case DF_BYTE:
30088 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
30089 break;
30090 case DF_HALF:
30091 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
30092 break;
30093#if defined(TARGET_MIPS64)
30094 case DF_WORD:
30095 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
30096 break;
30097#endif
30098 default:
30099 assert(0);
30100 }
cab48881 30101 }
1e608ec1
YK
30102 break;
30103 case OPC_INSERT_df:
c1c9a10f
MM
30104 switch (df) {
30105 case DF_BYTE:
30106 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
30107 break;
30108 case DF_HALF:
30109 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
30110 break;
30111 case DF_WORD:
30112 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
30113 break;
30114#if defined(TARGET_MIPS64)
30115 case DF_DOUBLE:
30116 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
30117 break;
30118#endif
30119 default:
30120 assert(0);
30121 }
1e608ec1
YK
30122 break;
30123 }
30124 break;
30125 default:
30126 MIPS_INVAL("MSA instruction");
9c708c7f 30127 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
30128 }
30129 tcg_temp_free_i32(twd);
30130 tcg_temp_free_i32(tws);
30131 tcg_temp_free_i32(tn);
30132 tcg_temp_free_i32(tdf);
30133}
30134
30135static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30136{
30137 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30138 uint32_t df = 0, n = 0;
30139
30140 if ((dfn & 0x30) == 0x00) {
30141 n = dfn & 0x0f;
30142 df = DF_BYTE;
30143 } else if ((dfn & 0x38) == 0x20) {
30144 n = dfn & 0x07;
30145 df = DF_HALF;
30146 } else if ((dfn & 0x3c) == 0x30) {
30147 n = dfn & 0x03;
30148 df = DF_WORD;
30149 } else if ((dfn & 0x3e) == 0x38) {
30150 n = dfn & 0x01;
30151 df = DF_DOUBLE;
30152 } else if (dfn == 0x3E) {
30153 /* CTCMSA, CFCMSA, MOVE.V */
30154 gen_msa_elm_3e(env, ctx);
30155 return;
30156 } else {
9c708c7f 30157 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
30158 return;
30159 }
30160
30161 gen_msa_elm_df(env, ctx, df, n);
30162}
30163
7d05b9c8
YK
30164static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30165{
30166#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30167 uint8_t df = (ctx->opcode >> 21) & 0x1;
30168 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30169 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30170 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30171
30172 TCGv_i32 twd = tcg_const_i32(wd);
30173 TCGv_i32 tws = tcg_const_i32(ws);
30174 TCGv_i32 twt = tcg_const_i32(wt);
30175 TCGv_i32 tdf = tcg_temp_new_i32();
30176
30177 /* adjust df value for floating-point instruction */
30178 tcg_gen_movi_i32(tdf, df + 2);
30179
30180 switch (MASK_MSA_3RF(ctx->opcode)) {
30181 case OPC_FCAF_df:
30182 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30183 break;
30184 case OPC_FADD_df:
30185 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30186 break;
30187 case OPC_FCUN_df:
30188 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30189 break;
30190 case OPC_FSUB_df:
30191 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30192 break;
30193 case OPC_FCOR_df:
30194 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30195 break;
30196 case OPC_FCEQ_df:
30197 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30198 break;
30199 case OPC_FMUL_df:
30200 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30201 break;
30202 case OPC_FCUNE_df:
30203 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30204 break;
30205 case OPC_FCUEQ_df:
30206 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30207 break;
30208 case OPC_FDIV_df:
30209 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30210 break;
30211 case OPC_FCNE_df:
30212 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30213 break;
30214 case OPC_FCLT_df:
30215 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30216 break;
30217 case OPC_FMADD_df:
30218 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30219 break;
30220 case OPC_MUL_Q_df:
30221 tcg_gen_movi_i32(tdf, df + 1);
30222 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30223 break;
30224 case OPC_FCULT_df:
30225 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30226 break;
30227 case OPC_FMSUB_df:
30228 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30229 break;
30230 case OPC_MADD_Q_df:
30231 tcg_gen_movi_i32(tdf, df + 1);
30232 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30233 break;
30234 case OPC_FCLE_df:
30235 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30236 break;
30237 case OPC_MSUB_Q_df:
30238 tcg_gen_movi_i32(tdf, df + 1);
30239 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30240 break;
30241 case OPC_FCULE_df:
30242 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30243 break;
30244 case OPC_FEXP2_df:
30245 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30246 break;
30247 case OPC_FSAF_df:
30248 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30249 break;
30250 case OPC_FEXDO_df:
30251 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30252 break;
30253 case OPC_FSUN_df:
30254 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30255 break;
30256 case OPC_FSOR_df:
30257 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30258 break;
30259 case OPC_FSEQ_df:
30260 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30261 break;
30262 case OPC_FTQ_df:
30263 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30264 break;
30265 case OPC_FSUNE_df:
30266 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30267 break;
30268 case OPC_FSUEQ_df:
30269 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30270 break;
30271 case OPC_FSNE_df:
30272 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30273 break;
30274 case OPC_FSLT_df:
30275 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30276 break;
30277 case OPC_FMIN_df:
30278 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30279 break;
30280 case OPC_MULR_Q_df:
30281 tcg_gen_movi_i32(tdf, df + 1);
30282 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30283 break;
30284 case OPC_FSULT_df:
30285 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30286 break;
30287 case OPC_FMIN_A_df:
30288 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30289 break;
30290 case OPC_MADDR_Q_df:
30291 tcg_gen_movi_i32(tdf, df + 1);
30292 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30293 break;
30294 case OPC_FSLE_df:
30295 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30296 break;
30297 case OPC_FMAX_df:
30298 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30299 break;
30300 case OPC_MSUBR_Q_df:
30301 tcg_gen_movi_i32(tdf, df + 1);
30302 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30303 break;
30304 case OPC_FSULE_df:
30305 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30306 break;
30307 case OPC_FMAX_A_df:
30308 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30309 break;
30310 default:
30311 MIPS_INVAL("MSA instruction");
9c708c7f 30312 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
30313 break;
30314 }
30315
30316 tcg_temp_free_i32(twd);
30317 tcg_temp_free_i32(tws);
30318 tcg_temp_free_i32(twt);
30319 tcg_temp_free_i32(tdf);
30320}
30321
cbe50b9a
YK
30322static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30323{
30324#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30325 (op & (0x7 << 18)))
30326 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30327 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30328 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30329 uint8_t df = (ctx->opcode >> 16) & 0x3;
30330 TCGv_i32 twd = tcg_const_i32(wd);
30331 TCGv_i32 tws = tcg_const_i32(ws);
30332 TCGv_i32 twt = tcg_const_i32(wt);
30333 TCGv_i32 tdf = tcg_const_i32(df);
30334
30335 switch (MASK_MSA_2R(ctx->opcode)) {
30336 case OPC_FILL_df:
30337#if !defined(TARGET_MIPS64)
30338 /* Double format valid only for MIPS64 */
30339 if (df == DF_DOUBLE) {
9c708c7f 30340 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30341 break;
30342 }
30343#endif
30344 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30345 break;
cbe50b9a 30346 case OPC_NLOC_df:
81c4b059
AM
30347 switch (df) {
30348 case DF_BYTE:
30349 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30350 break;
30351 case DF_HALF:
30352 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30353 break;
30354 case DF_WORD:
30355 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30356 break;
30357 case DF_DOUBLE:
30358 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30359 break;
30360 }
cbe50b9a
YK
30361 break;
30362 case OPC_NLZC_df:
81c4b059
AM
30363 switch (df) {
30364 case DF_BYTE:
30365 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30366 break;
30367 case DF_HALF:
30368 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30369 break;
30370 case DF_WORD:
30371 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30372 break;
30373 case DF_DOUBLE:
30374 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30375 break;
30376 }
cbe50b9a 30377 break;
4c5daf38
AM
30378 case OPC_PCNT_df:
30379 switch (df) {
30380 case DF_BYTE:
30381 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30382 break;
30383 case DF_HALF:
30384 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30385 break;
30386 case DF_WORD:
30387 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30388 break;
30389 case DF_DOUBLE:
30390 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30391 break;
30392 }
30393 break;
cbe50b9a
YK
30394 default:
30395 MIPS_INVAL("MSA instruction");
9c708c7f 30396 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30397 break;
30398 }
30399
30400 tcg_temp_free_i32(twd);
30401 tcg_temp_free_i32(tws);
30402 tcg_temp_free_i32(twt);
30403 tcg_temp_free_i32(tdf);
30404}
30405
3bdeb688
YK
30406static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30407{
30408#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30409 (op & (0xf << 17)))
30410 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30411 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30412 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30413 uint8_t df = (ctx->opcode >> 16) & 0x1;
30414 TCGv_i32 twd = tcg_const_i32(wd);
30415 TCGv_i32 tws = tcg_const_i32(ws);
30416 TCGv_i32 twt = tcg_const_i32(wt);
30417 /* adjust df value for floating-point instruction */
30418 TCGv_i32 tdf = tcg_const_i32(df + 2);
30419
30420 switch (MASK_MSA_2RF(ctx->opcode)) {
30421 case OPC_FCLASS_df:
30422 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30423 break;
30424 case OPC_FTRUNC_S_df:
30425 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30426 break;
30427 case OPC_FTRUNC_U_df:
30428 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30429 break;
30430 case OPC_FSQRT_df:
30431 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30432 break;
30433 case OPC_FRSQRT_df:
30434 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30435 break;
30436 case OPC_FRCP_df:
30437 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30438 break;
30439 case OPC_FRINT_df:
30440 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30441 break;
30442 case OPC_FLOG2_df:
30443 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30444 break;
30445 case OPC_FEXUPL_df:
30446 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30447 break;
30448 case OPC_FEXUPR_df:
30449 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30450 break;
30451 case OPC_FFQL_df:
30452 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30453 break;
30454 case OPC_FFQR_df:
30455 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30456 break;
30457 case OPC_FTINT_S_df:
30458 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30459 break;
30460 case OPC_FTINT_U_df:
30461 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30462 break;
30463 case OPC_FFINT_S_df:
30464 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30465 break;
30466 case OPC_FFINT_U_df:
30467 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30468 break;
30469 }
30470
30471 tcg_temp_free_i32(twd);
30472 tcg_temp_free_i32(tws);
30473 tcg_temp_free_i32(twt);
30474 tcg_temp_free_i32(tdf);
30475}
30476
cbe50b9a
YK
30477static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30478{
30479#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30480 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30481 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30482 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30483 TCGv_i32 twd = tcg_const_i32(wd);
30484 TCGv_i32 tws = tcg_const_i32(ws);
30485 TCGv_i32 twt = tcg_const_i32(wt);
30486
30487 switch (MASK_MSA_VEC(ctx->opcode)) {
30488 case OPC_AND_V:
30489 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30490 break;
30491 case OPC_OR_V:
30492 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30493 break;
30494 case OPC_NOR_V:
30495 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30496 break;
30497 case OPC_XOR_V:
30498 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30499 break;
30500 case OPC_BMNZ_V:
30501 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30502 break;
30503 case OPC_BMZ_V:
30504 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30505 break;
30506 case OPC_BSEL_V:
30507 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30508 break;
30509 default:
30510 MIPS_INVAL("MSA instruction");
9c708c7f 30511 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30512 break;
30513 }
30514
30515 tcg_temp_free_i32(twd);
30516 tcg_temp_free_i32(tws);
30517 tcg_temp_free_i32(twt);
30518}
30519
30520static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30521{
30522 switch (MASK_MSA_VEC(ctx->opcode)) {
30523 case OPC_AND_V:
30524 case OPC_OR_V:
30525 case OPC_NOR_V:
30526 case OPC_XOR_V:
30527 case OPC_BMNZ_V:
30528 case OPC_BMZ_V:
30529 case OPC_BSEL_V:
30530 gen_msa_vec_v(env, ctx);
30531 break;
30532 case OPC_MSA_2R:
30533 gen_msa_2r(env, ctx);
30534 break;
3bdeb688
YK
30535 case OPC_MSA_2RF:
30536 gen_msa_2rf(env, ctx);
30537 break;
cbe50b9a
YK
30538 default:
30539 MIPS_INVAL("MSA instruction");
9c708c7f 30540 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
30541 break;
30542 }
30543}
30544
4c789546
YK
30545static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30546{
30547 uint32_t opcode = ctx->opcode;
30548 check_insn(ctx, ASE_MSA);
30549 check_msa_access(ctx);
30550
30551 switch (MASK_MSA_MINOR(opcode)) {
30552 case OPC_MSA_I8_00:
30553 case OPC_MSA_I8_01:
30554 case OPC_MSA_I8_02:
30555 gen_msa_i8(env, ctx);
30556 break;
80e71591
YK
30557 case OPC_MSA_I5_06:
30558 case OPC_MSA_I5_07:
30559 gen_msa_i5(env, ctx);
30560 break;
d4cf28de
YK
30561 case OPC_MSA_BIT_09:
30562 case OPC_MSA_BIT_0A:
30563 gen_msa_bit(env, ctx);
30564 break;
28f99f08
YK
30565 case OPC_MSA_3R_0D:
30566 case OPC_MSA_3R_0E:
30567 case OPC_MSA_3R_0F:
30568 case OPC_MSA_3R_10:
30569 case OPC_MSA_3R_11:
30570 case OPC_MSA_3R_12:
30571 case OPC_MSA_3R_13:
30572 case OPC_MSA_3R_14:
30573 case OPC_MSA_3R_15:
30574 gen_msa_3r(env, ctx);
30575 break;
1e608ec1
YK
30576 case OPC_MSA_ELM:
30577 gen_msa_elm(env, ctx);
30578 break;
7d05b9c8
YK
30579 case OPC_MSA_3RF_1A:
30580 case OPC_MSA_3RF_1B:
30581 case OPC_MSA_3RF_1C:
30582 gen_msa_3rf(env, ctx);
30583 break;
cbe50b9a
YK
30584 case OPC_MSA_VEC:
30585 gen_msa_vec(env, ctx);
30586 break;
f7685877
YK
30587 case OPC_LD_B:
30588 case OPC_LD_H:
30589 case OPC_LD_W:
30590 case OPC_LD_D:
30591 case OPC_ST_B:
30592 case OPC_ST_H:
30593 case OPC_ST_W:
30594 case OPC_ST_D:
30595 {
30596 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30597 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30598 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30599 uint8_t df = (ctx->opcode >> 0) & 0x3;
30600
f7685877 30601 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
30602 TCGv taddr = tcg_temp_new();
30603 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
30604
30605 switch (MASK_MSA_MINOR(opcode)) {
30606 case OPC_LD_B:
adc370a4
YK
30607 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30608 break;
f7685877 30609 case OPC_LD_H:
adc370a4
YK
30610 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30611 break;
f7685877 30612 case OPC_LD_W:
adc370a4
YK
30613 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30614 break;
f7685877 30615 case OPC_LD_D:
adc370a4 30616 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
30617 break;
30618 case OPC_ST_B:
adc370a4
YK
30619 gen_helper_msa_st_b(cpu_env, twd, taddr);
30620 break;
f7685877 30621 case OPC_ST_H:
adc370a4
YK
30622 gen_helper_msa_st_h(cpu_env, twd, taddr);
30623 break;
f7685877 30624 case OPC_ST_W:
adc370a4
YK
30625 gen_helper_msa_st_w(cpu_env, twd, taddr);
30626 break;
f7685877 30627 case OPC_ST_D:
adc370a4 30628 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
30629 break;
30630 }
30631
30632 tcg_temp_free_i32(twd);
adc370a4 30633 tcg_temp_free(taddr);
f7685877
YK
30634 }
30635 break;
4c789546
YK
30636 default:
30637 MIPS_INVAL("MSA instruction");
9c708c7f 30638 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
30639 break;
30640 }
30641
30642}
30643
d2bfa6e6 30644static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
30645{
30646 int32_t offset;
30647 int rs, rt, rd, sa;
30648 uint32_t op, op1;
30649 int16_t imm;
30650
30651 /* make sure instructions are on a word boundary */
eeb3bba8
EC
30652 if (ctx->base.pc_next & 0x3) {
30653 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 30654 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
30655 return;
30656 }
30657
30658 /* Handle blikely not taken case */
30659 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 30660 TCGLabel *l1 = gen_new_label();
099e5b4d 30661
099e5b4d
LA
30662 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30663 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 30664 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
30665 gen_set_label(l1);
30666 }
30667
099e5b4d
LA
30668 op = MASK_OP_MAJOR(ctx->opcode);
30669 rs = (ctx->opcode >> 21) & 0x1f;
30670 rt = (ctx->opcode >> 16) & 0x1f;
30671 rd = (ctx->opcode >> 11) & 0x1f;
30672 sa = (ctx->opcode >> 6) & 0x1f;
30673 imm = (int16_t)ctx->opcode;
30674 switch (op) {
30675 case OPC_SPECIAL:
30676 decode_opc_special(env, ctx);
30677 break;
30678 case OPC_SPECIAL2:
37b9aae2 30679#if defined(TARGET_MIPS64)
71b8a6b3 30680 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 30681 decode_mmi(env, ctx);
37b9aae2
MM
30682#else
30683 if (ctx->insn_flags & ASE_MXU) {
0a348b9a 30684 decode_opc_mxu(env, ctx);
b621f018 30685#endif
71b8a6b3
FN
30686 } else {
30687 decode_opc_special2_legacy(env, ctx);
30688 }
099e5b4d
LA
30689 break;
30690 case OPC_SPECIAL3:
37b9aae2 30691#if defined(TARGET_MIPS64)
bb41e74b 30692 if (ctx->insn_flags & INSN_R5900) {
874b2879 30693 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
30694 } else {
30695 decode_opc_special3(env, ctx);
30696 }
37b9aae2
MM
30697#else
30698 decode_opc_special3(env, ctx);
30699#endif
099e5b4d 30700 break;
7a387fff
TS
30701 case OPC_REGIMM:
30702 op1 = MASK_REGIMM(ctx->opcode);
30703 switch (op1) {
fecd2646
LA
30704 case OPC_BLTZL: /* REGIMM branches */
30705 case OPC_BGEZL:
30706 case OPC_BLTZALL:
30707 case OPC_BGEZALL:
d9224450 30708 check_insn(ctx, ISA_MIPS2);
2e211e0a 30709 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 30710 /* Fallthrough */
fecd2646
LA
30711 case OPC_BLTZ:
30712 case OPC_BGEZ:
b231c103 30713 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30714 break;
fecd2646
LA
30715 case OPC_BLTZAL:
30716 case OPC_BGEZAL:
2e211e0a 30717 if (ctx->insn_flags & ISA_MIPS_R6) {
0aefa333
YK
30718 if (rs == 0) {
30719 /* OPC_NAL, OPC_BAL */
b231c103 30720 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 30721 } else {
9c708c7f 30722 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
30723 }
30724 } else {
b231c103 30725 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 30726 }
c9602061 30727 break;
c2e19f3c
AM
30728 case OPC_TGEI: /* REGIMM traps */
30729 case OPC_TGEIU:
30730 case OPC_TLTI:
30731 case OPC_TLTIU:
30732 case OPC_TEQI:
30733
7a387fff 30734 case OPC_TNEI:
d9224450 30735 check_insn(ctx, ISA_MIPS2);
2e211e0a 30736 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7a387fff
TS
30737 gen_trap(ctx, op1, rs, -1, imm);
30738 break;
bb238210 30739 case OPC_SIGRIE:
2e211e0a 30740 check_insn(ctx, ISA_MIPS_R6);
bb238210
YK
30741 generate_exception_end(ctx, EXCP_RI);
30742 break;
7a387fff 30743 case OPC_SYNCI:
7a47bae5 30744 check_insn(ctx, ISA_MIPS_R2);
7480515f
AM
30745 /*
30746 * Break the TB to be able to sync copied instructions
30747 * immediately.
30748 */
eeb3bba8 30749 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 30750 break;
e45a93e2
JL
30751 case OPC_BPOSGE32: /* MIPS DSP branch */
30752#if defined(TARGET_MIPS64)
30753 case OPC_BPOSGE64:
30754#endif
30755 check_dsp(ctx);
b231c103 30756 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 30757 break;
d4ea6acd
LA
30758#if defined(TARGET_MIPS64)
30759 case OPC_DAHI:
2e211e0a 30760 check_insn(ctx, ISA_MIPS_R6);
d4ea6acd
LA
30761 check_mips_64(ctx);
30762 if (rs != 0) {
30763 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30764 }
d4ea6acd
LA
30765 break;
30766 case OPC_DATI:
2e211e0a 30767 check_insn(ctx, ISA_MIPS_R6);
d4ea6acd
LA
30768 check_mips_64(ctx);
30769 if (rs != 0) {
30770 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30771 }
d4ea6acd
LA
30772 break;
30773#endif
6af0bf9c 30774 default: /* Invalid */
923617a3 30775 MIPS_INVAL("regimm");
9c708c7f 30776 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30777 break;
30778 }
30779 break;
7a387fff 30780 case OPC_CP0:
387a8fe5 30781 check_cp0_enabled(ctx);
7a387fff 30782 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 30783 switch (op1) {
7a387fff
TS
30784 case OPC_MFC0:
30785 case OPC_MTC0:
ead9360e
TS
30786 case OPC_MFTR:
30787 case OPC_MTTR:
5204ea79
LA
30788 case OPC_MFHC0:
30789 case OPC_MTHC0:
d26bc211 30790#if defined(TARGET_MIPS64)
7a387fff
TS
30791 case OPC_DMFC0:
30792 case OPC_DMTC0:
30793#endif
f1aa6320 30794#ifndef CONFIG_USER_ONLY
932e71cd 30795 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 30796#endif /* !CONFIG_USER_ONLY */
7a387fff 30797 break;
c38a1d52
AR
30798 case OPC_C0:
30799 case OPC_C0_1:
30800 case OPC_C0_2:
30801 case OPC_C0_3:
30802 case OPC_C0_4:
30803 case OPC_C0_5:
30804 case OPC_C0_6:
30805 case OPC_C0_7:
30806 case OPC_C0_8:
30807 case OPC_C0_9:
30808 case OPC_C0_A:
30809 case OPC_C0_B:
30810 case OPC_C0_C:
30811 case OPC_C0_D:
30812 case OPC_C0_E:
30813 case OPC_C0_F:
f1aa6320 30814#ifndef CONFIG_USER_ONLY
932e71cd 30815 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 30816#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
30817 break;
30818 case OPC_MFMC0:
8706c382 30819#ifndef CONFIG_USER_ONLY
932e71cd 30820 {
099e5b4d 30821 uint32_t op2;
35fbce2c 30822 TCGv t0 = tcg_temp_new();
6c5c1e20 30823
0eaef5aa 30824 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
30825 switch (op2) {
30826 case OPC_DMT:
9affc1c5 30827 check_cp0_mt(ctx);
9ed5726c 30828 gen_helper_dmt(t0);
35fbce2c 30829 gen_store_gpr(t0, rt);
6c5c1e20
TS
30830 break;
30831 case OPC_EMT:
9affc1c5 30832 check_cp0_mt(ctx);
9ed5726c 30833 gen_helper_emt(t0);
35fbce2c 30834 gen_store_gpr(t0, rt);
da80682b 30835 break;
6c5c1e20 30836 case OPC_DVPE:
9affc1c5 30837 check_cp0_mt(ctx);
895c2d04 30838 gen_helper_dvpe(t0, cpu_env);
35fbce2c 30839 gen_store_gpr(t0, rt);
6c5c1e20
TS
30840 break;
30841 case OPC_EVPE:
9affc1c5 30842 check_cp0_mt(ctx);
895c2d04 30843 gen_helper_evpe(t0, cpu_env);
35fbce2c 30844 gen_store_gpr(t0, rt);
6c5c1e20 30845 break;
01bc435b 30846 case OPC_DVP:
2e211e0a 30847 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
30848 if (ctx->vp) {
30849 gen_helper_dvp(t0, cpu_env);
30850 gen_store_gpr(t0, rt);
30851 }
30852 break;
30853 case OPC_EVP:
2e211e0a 30854 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
30855 if (ctx->vp) {
30856 gen_helper_evp(t0, cpu_env);
30857 gen_store_gpr(t0, rt);
30858 }
30859 break;
6c5c1e20 30860 case OPC_DI:
7a47bae5 30861 check_insn(ctx, ISA_MIPS_R2);
867abc7e 30862 save_cpu_state(ctx, 1);
895c2d04 30863 gen_helper_di(t0, cpu_env);
35fbce2c 30864 gen_store_gpr(t0, rt);
7480515f
AM
30865 /*
30866 * Stop translation as we may have switched
30867 * the execution mode.
30868 */
eeb3bba8 30869 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
30870 break;
30871 case OPC_EI:
7a47bae5 30872 check_insn(ctx, ISA_MIPS_R2);
867abc7e 30873 save_cpu_state(ctx, 1);
895c2d04 30874 gen_helper_ei(t0, cpu_env);
35fbce2c 30875 gen_store_gpr(t0, rt);
7480515f
AM
30876 /*
30877 * DISAS_STOP isn't sufficient, we need to ensure we break
30878 * out of translated code to check for pending interrupts.
30879 */
eeb3bba8
EC
30880 gen_save_pc(ctx->base.pc_next + 4);
30881 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
30882 break;
30883 default: /* Invalid */
30884 MIPS_INVAL("mfmc0");
9c708c7f 30885 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
30886 break;
30887 }
6c5c1e20 30888 tcg_temp_free(t0);
7a387fff 30889 }
0eaef5aa 30890#endif /* !CONFIG_USER_ONLY */
6af0bf9c 30891 break;
7a387fff 30892 case OPC_RDPGPR:
7a47bae5 30893 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 30894 gen_load_srsgpr(rt, rd);
ead9360e 30895 break;
7a387fff 30896 case OPC_WRPGPR:
7a47bae5 30897 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 30898 gen_store_srsgpr(rt, rd);
38121543 30899 break;
6af0bf9c 30900 default:
923617a3 30901 MIPS_INVAL("cp0");
9c708c7f 30902 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
30903 break;
30904 }
30905 break;
31837be3 30906 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
2e211e0a 30907 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
30908 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30909 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30910 } else {
30911 /* OPC_ADDI */
30912 /* Arithmetic with immediate opcode */
30913 gen_arith_imm(ctx, op, rt, rs, imm);
30914 }
30915 break;
324d9e32 30916 case OPC_ADDIU:
d75c135e 30917 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 30918 break;
324d9e32
AJ
30919 case OPC_SLTI: /* Set on less than with immediate opcode */
30920 case OPC_SLTIU:
d75c135e 30921 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
30922 break;
30923 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 30924 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
30925 case OPC_ORI:
30926 case OPC_XORI:
d75c135e 30927 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 30928 break;
c2e19f3c
AM
30929 case OPC_J: /* Jump */
30930 case OPC_JAL:
7a387fff 30931 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 30932 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 30933 break;
31837be3
YK
30934 /* Branch */
30935 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
2e211e0a 30936 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 30937 if (rt == 0) {
9c708c7f 30938 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30939 break;
30940 }
30941 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30942 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30943 } else {
30944 /* OPC_BLEZL */
b231c103 30945 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30946 }
30947 break;
30948 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
2e211e0a 30949 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 30950 if (rt == 0) {
9c708c7f 30951 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
30952 break;
30953 }
30954 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30955 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30956 } else {
30957 /* OPC_BGTZL */
b231c103 30958 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
30959 }
30960 break;
30961 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30962 if (rt == 0) {
30963 /* OPC_BLEZ */
b231c103 30964 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 30965 } else {
2e211e0a 30966 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
30967 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30968 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30969 }
30970 break;
30971 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30972 if (rt == 0) {
30973 /* OPC_BGTZ */
b231c103 30974 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 30975 } else {
2e211e0a 30976 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
30977 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30978 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30979 }
30980 break;
30981 case OPC_BEQL:
30982 case OPC_BNEL:
d9224450 30983 check_insn(ctx, ISA_MIPS2);
2e211e0a 30984 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 30985 /* Fallthrough */
31837be3
YK
30986 case OPC_BEQ:
30987 case OPC_BNE:
b231c103 30988 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 30989 break;
d9224450
MR
30990 case OPC_LL: /* Load and stores */
30991 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
30992 if (ctx->insn_flags & INSN_R5900) {
30993 check_insn_opc_user_only(ctx, INSN_R5900);
30994 }
d9224450
MR
30995 /* Fallthrough */
30996 case OPC_LWL:
fecd2646 30997 case OPC_LWR:
2e211e0a 30998 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 30999 /* Fallthrough */
c2e19f3c
AM
31000 case OPC_LB:
31001 case OPC_LH:
31002 case OPC_LW:
31003 case OPC_LWPC:
31004 case OPC_LBU:
31005 case OPC_LHU:
d75c135e 31006 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 31007 break;
fecd2646 31008 case OPC_SWL:
7a387fff 31009 case OPC_SWR:
2e211e0a 31010 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6f3b233 31011 /* fall through */
c2e19f3c
AM
31012 case OPC_SB:
31013 case OPC_SH:
fecd2646 31014 case OPC_SW:
5c13fdfd 31015 gen_st(ctx, op, rt, rs, imm);
7a387fff 31016 break;
d66c7132 31017 case OPC_SC:
d9224450 31018 check_insn(ctx, ISA_MIPS2);
2e211e0a 31019 check_insn_opc_removed(ctx, ISA_MIPS_R6);
55fc7a69
FN
31020 if (ctx->insn_flags & INSN_R5900) {
31021 check_insn_opc_user_only(ctx, INSN_R5900);
31022 }
33a07fa2
LA
31023 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
31024 break;
7a387fff 31025 case OPC_CACHE:
2e211e0a 31026 check_insn_opc_removed(ctx, ISA_MIPS_R6);
2e15497c 31027 check_cp0_enabled(ctx);
bbd5e4a2 31028 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
0d74a222
LA
31029 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
31030 gen_cache_operation(ctx, rt, rs, imm);
31031 }
ead9360e 31032 /* Treat as NOP. */
34ae7b51 31033 break;
7a387fff 31034 case OPC_PREF:
2e211e0a 31035 check_insn_opc_removed(ctx, ISA_MIPS_R6);
992e8176
FN
31036 if (ctx->insn_flags & INSN_R5900) {
31037 /* Treat as NOP. */
31038 } else {
bbd5e4a2 31039 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
992e8176
FN
31040 /* Treat as NOP. */
31041 }
6af0bf9c 31042 break;
4ad40f36 31043
923617a3 31044 /* Floating point (COP1). */
7a387fff
TS
31045 case OPC_LWC1:
31046 case OPC_LDC1:
31047 case OPC_SWC1:
31048 case OPC_SDC1:
5ab5c041 31049 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
31050 break;
31051
7a387fff 31052 case OPC_CP1:
5692c6e1
YK
31053 op1 = MASK_CP1(ctx->opcode);
31054
31055 switch (op1) {
31056 case OPC_MFHC1:
31057 case OPC_MTHC1:
5e755519 31058 check_cp1_enabled(ctx);
7a47bae5 31059 check_insn(ctx, ISA_MIPS_R2);
146dd620 31060 /* fall through */
5692c6e1
YK
31061 case OPC_MFC1:
31062 case OPC_CFC1:
31063 case OPC_MTC1:
31064 case OPC_CTC1:
31065 check_cp1_enabled(ctx);
31066 gen_cp1(ctx, op1, rt, rd);
31067 break;
d26bc211 31068#if defined(TARGET_MIPS64)
5692c6e1
YK
31069 case OPC_DMFC1:
31070 case OPC_DMTC1:
31071 check_cp1_enabled(ctx);
31072 check_insn(ctx, ISA_MIPS3);
d9224450 31073 check_mips_64(ctx);
5692c6e1
YK
31074 gen_cp1(ctx, op1, rt, rd);
31075 break;
e189e748 31076#endif
5692c6e1
YK
31077 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
31078 check_cp1_enabled(ctx);
2e211e0a 31079 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1 31080 /* OPC_BC1EQZ */
31837be3 31081 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 31082 rt, imm << 2, 4);
5692c6e1
YK
31083 } else {
31084 /* OPC_BC1ANY2 */
b8aa4598 31085 check_cop1x(ctx);
d75c135e 31086 check_insn(ctx, ASE_MIPS3D);
d75c135e 31087 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 31088 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
31089 }
31090 break;
31091 case OPC_BC1NEZ:
31092 check_cp1_enabled(ctx);
2e211e0a 31093 check_insn(ctx, ISA_MIPS_R6);
5692c6e1 31094 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 31095 rt, imm << 2, 4);
5692c6e1
YK
31096 break;
31097 case OPC_BC1ANY4:
31098 check_cp1_enabled(ctx);
2e211e0a 31099 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
31100 check_cop1x(ctx);
31101 check_insn(ctx, ASE_MIPS3D);
31102 /* fall through */
31103 case OPC_BC1:
31104 check_cp1_enabled(ctx);
2e211e0a 31105 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
31106 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31107 (rt >> 2) & 0x7, imm << 2);
31108 break;
31109 case OPC_PS_FMT:
e29c9628 31110 check_ps(ctx);
b6f3b233 31111 /* fall through */
5692c6e1
YK
31112 case OPC_S_FMT:
31113 case OPC_D_FMT:
31114 check_cp1_enabled(ctx);
31115 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31116 (imm >> 8) & 0x7);
31117 break;
31118 case OPC_W_FMT:
31119 case OPC_L_FMT:
31120 {
31121 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
31122 check_cp1_enabled(ctx);
2e211e0a 31123 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1
YK
31124 switch (r6_op) {
31125 case R6_OPC_CMP_AF_S:
31126 case R6_OPC_CMP_UN_S:
31127 case R6_OPC_CMP_EQ_S:
31128 case R6_OPC_CMP_UEQ_S:
31129 case R6_OPC_CMP_LT_S:
31130 case R6_OPC_CMP_ULT_S:
31131 case R6_OPC_CMP_LE_S:
31132 case R6_OPC_CMP_ULE_S:
31133 case R6_OPC_CMP_SAF_S:
31134 case R6_OPC_CMP_SUN_S:
31135 case R6_OPC_CMP_SEQ_S:
31136 case R6_OPC_CMP_SEUQ_S:
31137 case R6_OPC_CMP_SLT_S:
31138 case R6_OPC_CMP_SULT_S:
31139 case R6_OPC_CMP_SLE_S:
31140 case R6_OPC_CMP_SULE_S:
31141 case R6_OPC_CMP_OR_S:
31142 case R6_OPC_CMP_UNE_S:
31143 case R6_OPC_CMP_NE_S:
31144 case R6_OPC_CMP_SOR_S:
31145 case R6_OPC_CMP_SUNE_S:
31146 case R6_OPC_CMP_SNE_S:
31147 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31148 break;
31149 case R6_OPC_CMP_AF_D:
31150 case R6_OPC_CMP_UN_D:
31151 case R6_OPC_CMP_EQ_D:
31152 case R6_OPC_CMP_UEQ_D:
31153 case R6_OPC_CMP_LT_D:
31154 case R6_OPC_CMP_ULT_D:
31155 case R6_OPC_CMP_LE_D:
31156 case R6_OPC_CMP_ULE_D:
31157 case R6_OPC_CMP_SAF_D:
31158 case R6_OPC_CMP_SUN_D:
31159 case R6_OPC_CMP_SEQ_D:
31160 case R6_OPC_CMP_SEUQ_D:
31161 case R6_OPC_CMP_SLT_D:
31162 case R6_OPC_CMP_SULT_D:
31163 case R6_OPC_CMP_SLE_D:
31164 case R6_OPC_CMP_SULE_D:
31165 case R6_OPC_CMP_OR_D:
31166 case R6_OPC_CMP_UNE_D:
31167 case R6_OPC_CMP_NE_D:
31168 case R6_OPC_CMP_SOR_D:
31169 case R6_OPC_CMP_SUNE_D:
31170 case R6_OPC_CMP_SNE_D:
31171 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31172 break;
31173 default:
d2bfa6e6
MR
31174 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31175 rt, rd, sa, (imm >> 8) & 0x7);
31176
5692c6e1 31177 break;
3f493883 31178 }
5692c6e1
YK
31179 } else {
31180 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31181 (imm >> 8) & 0x7);
36d23958 31182 }
5692c6e1
YK
31183 break;
31184 }
31185 case OPC_BZ_V:
31186 case OPC_BNZ_V:
31187 case OPC_BZ_B:
31188 case OPC_BZ_H:
31189 case OPC_BZ_W:
31190 case OPC_BZ_D:
31191 case OPC_BNZ_B:
31192 case OPC_BNZ_H:
31193 case OPC_BNZ_W:
31194 case OPC_BNZ_D:
31195 check_insn(ctx, ASE_MSA);
31196 gen_msa_branch(env, ctx, op1);
31197 break;
31198 default:
31199 MIPS_INVAL("cp1");
9c708c7f 31200 generate_exception_end(ctx, EXCP_RI);
5692c6e1 31201 break;
6ea83fed 31202 }
4ad40f36
FB
31203 break;
31204
31837be3
YK
31205 /* Compact branches [R6] and COP2 [non-R6] */
31206 case OPC_BC: /* OPC_LWC2 */
31207 case OPC_BALC: /* OPC_SWC2 */
2e211e0a 31208 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
31209 /* OPC_BC, OPC_BALC */
31210 gen_compute_compact_branch(ctx, op, 0, 0,
31211 sextract32(ctx->opcode << 2, 0, 28));
e10a0ca1
JY
31212 } else if (ctx->insn_flags & ASE_LEXT) {
31213 gen_loongson_lswc2(ctx, rt, rs, rd);
31837be3
YK
31214 } else {
31215 /* OPC_LWC2, OPC_SWC2 */
31216 /* COP2: Not implemented. */
31217 generate_exception_err(ctx, EXCP_CpU, 2);
31218 }
31219 break;
31220 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31221 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
2e211e0a 31222 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
31223 if (rs != 0) {
31224 /* OPC_BEQZC, OPC_BNEZC */
31225 gen_compute_compact_branch(ctx, op, rs, 0,
31226 sextract32(ctx->opcode << 2, 0, 23));
31227 } else {
31228 /* OPC_JIC, OPC_JIALC */
31229 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31230 }
90e22a57
JY
31231 } else if (ctx->insn_flags & ASE_LEXT) {
31232 gen_loongson_lsdc2(ctx, rt, rs, rd);
31837be3
YK
31233 } else {
31234 /* OPC_LWC2, OPC_SWC2 */
31235 /* COP2: Not implemented. */
31236 generate_exception_err(ctx, EXCP_CpU, 2);
31237 }
4ad40f36 31238 break;
bd277fa1 31239 case OPC_CP2:
8e2d5831 31240 check_insn(ctx, ASE_LMMI);
bd277fa1
RH
31241 /* Note that these instructions use different fields. */
31242 gen_loongson_multimedia(ctx, sa, rd, rt);
31243 break;
4ad40f36 31244
7a387fff 31245 case OPC_CP3:
2e211e0a 31246 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5ab5c041 31247 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 31248 check_cp1_enabled(ctx);
36d23958
TS
31249 op1 = MASK_CP3(ctx->opcode);
31250 switch (op1) {
d9224450
MR
31251 case OPC_LUXC1:
31252 case OPC_SUXC1:
7a47bae5 31253 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 31254 /* Fallthrough */
5a5012ec
TS
31255 case OPC_LWXC1:
31256 case OPC_LDXC1:
5a5012ec
TS
31257 case OPC_SWXC1:
31258 case OPC_SDXC1:
7a47bae5 31259 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
93b12ccc 31260 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 31261 break;
e0c84da7 31262 case OPC_PREFX:
7a47bae5 31263 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
ead9360e 31264 /* Treat as NOP. */
e0c84da7 31265 break;
5a5012ec 31266 case OPC_ALNV_PS:
7a47bae5 31267 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 31268 /* Fallthrough */
5a5012ec
TS
31269 case OPC_MADD_S:
31270 case OPC_MADD_D:
31271 case OPC_MADD_PS:
31272 case OPC_MSUB_S:
31273 case OPC_MSUB_D:
31274 case OPC_MSUB_PS:
31275 case OPC_NMADD_S:
31276 case OPC_NMADD_D:
31277 case OPC_NMADD_PS:
31278 case OPC_NMSUB_S:
31279 case OPC_NMSUB_D:
31280 case OPC_NMSUB_PS:
7a47bae5 31281 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
5a5012ec
TS
31282 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31283 break;
36d23958 31284 default:
923617a3 31285 MIPS_INVAL("cp3");
9c708c7f 31286 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
31287 break;
31288 }
31289 } else {
e397ee33 31290 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 31291 }
4ad40f36
FB
31292 break;
31293
d26bc211 31294#if defined(TARGET_MIPS64)
7a387fff 31295 /* MIPS64 opcodes */
96631327 31296 case OPC_LLD:
55fc7a69
FN
31297 if (ctx->insn_flags & INSN_R5900) {
31298 check_insn_opc_user_only(ctx, INSN_R5900);
31299 }
96631327 31300 /* fall through */
c2e19f3c
AM
31301 case OPC_LDL:
31302 case OPC_LDR:
2e211e0a 31303 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6f3b233 31304 /* fall through */
fecd2646 31305 case OPC_LWU:
7a387fff 31306 case OPC_LD:
d75c135e 31307 check_insn(ctx, ISA_MIPS3);
5c13fdfd 31308 check_mips_64(ctx);
d75c135e 31309 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 31310 break;
c2e19f3c
AM
31311 case OPC_SDL:
31312 case OPC_SDR:
2e211e0a 31313 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6f3b233 31314 /* fall through */
7a387fff 31315 case OPC_SD:
d75c135e 31316 check_insn(ctx, ISA_MIPS3);
e189e748 31317 check_mips_64(ctx);
5c13fdfd 31318 gen_st(ctx, op, rt, rs, imm);
7a387fff 31319 break;
d66c7132 31320 case OPC_SCD:
2e211e0a 31321 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d75c135e 31322 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
31323 if (ctx->insn_flags & INSN_R5900) {
31324 check_insn_opc_user_only(ctx, INSN_R5900);
31325 }
d66c7132 31326 check_mips_64(ctx);
33a07fa2 31327 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 31328 break;
31837be3 31329 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
2e211e0a 31330 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
31331 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31332 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31333 } else {
31334 /* OPC_DADDI */
31335 check_insn(ctx, ISA_MIPS3);
31336 check_mips_64(ctx);
31337 gen_arith_imm(ctx, op, rt, rs, imm);
31338 }
31339 break;
324d9e32 31340 case OPC_DADDIU:
d75c135e 31341 check_insn(ctx, ISA_MIPS3);
e189e748 31342 check_mips_64(ctx);
d75c135e 31343 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 31344 break;
31837be3
YK
31345#else
31346 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
2e211e0a 31347 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
31348 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31349 } else {
31350 MIPS_INVAL("major opcode");
9c708c7f 31351 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
31352 }
31353 break;
6af0bf9c 31354#endif
d4ea6acd 31355 case OPC_DAUI: /* OPC_JALX */
2e211e0a 31356 if (ctx->insn_flags & ISA_MIPS_R6) {
d4ea6acd
LA
31357#if defined(TARGET_MIPS64)
31358 /* OPC_DAUI */
31359 check_mips_64(ctx);
db77d852
LA
31360 if (rs == 0) {
31361 generate_exception(ctx, EXCP_RI);
31362 } else if (rt != 0) {
d4ea6acd
LA
31363 TCGv t0 = tcg_temp_new();
31364 gen_load_gpr(t0, rs);
31365 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31366 tcg_temp_free(t0);
31367 }
d4ea6acd 31368#else
9c708c7f 31369 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
31370 MIPS_INVAL("major opcode");
31371#endif
31372 } else {
31373 /* OPC_JALX */
31374 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31375 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 31376 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 31377 }
364d4831 31378 break;
4c789546 31379 case OPC_MSA: /* OPC_MDMX */
f08099ad 31380 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 31381#if defined(TARGET_MIPS64)
874b2879 31382 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
37b9aae2 31383#endif
f08099ad
FN
31384 } else {
31385 /* MDMX: Not implemented. */
31386 gen_msa(env, ctx);
31387 }
d4ea6acd
LA
31388 break;
31389 case OPC_PCREL:
2e211e0a 31390 check_insn(ctx, ISA_MIPS_R6);
eeb3bba8 31391 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 31392 break;
6af0bf9c 31393 default: /* Invalid */
923617a3 31394 MIPS_INVAL("major opcode");
9c708c7f 31395 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
31396 break;
31397 }
6af0bf9c
FB
31398}
31399
18f440ed 31400static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 31401{
18f440ed 31402 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 31403 CPUMIPSState *env = cs->env_ptr;
12be9258 31404
18f440ed 31405 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
31406 ctx->saved_pc = -1;
31407 ctx->insn_flags = env->insn_flags;
31408 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 31409 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
31410 ctx->CP0_Config3 = env->CP0_Config3;
31411 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
31412 ctx->btarget = 0;
31413 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31414 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31415 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31416 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31417 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31418 ctx->PAMask = env->PAMask;
31419 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31420 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31421 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31422 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31423 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 31424 /* Restore delay slot state from the tb context. */
12be9258
EC
31425 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31426 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31427 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 31428 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
31429 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31430 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31431 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31432 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 31433 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
99029be1 31434 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
12be9258 31435 restore_cpu_state(env, ctx);
932e71cd 31436#ifdef CONFIG_USER_ONLY
12be9258 31437 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 31438#else
12be9258 31439 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 31440#endif
2e211e0a 31441 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
8a805609 31442 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
190ce7fb 31443
18f440ed
EC
31444 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31445 ctx->hflags);
31446}
12be9258 31447
18f440ed
EC
31448static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31449{
31450}
b933066a 31451
18f440ed
EC
31452static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31453{
31454 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 31455
18f440ed
EC
31456 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31457 ctx->btarget);
31458}
31837be3 31459
18f440ed
EC
31460static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31461 const CPUBreakpoint *bp)
31462{
31463 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 31464
18f440ed
EC
31465 save_cpu_state(ctx, 1);
31466 ctx->base.is_jmp = DISAS_NORETURN;
31467 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
31468 /*
31469 * The address covered by the breakpoint must be included in
31470 * [tb->pc, tb->pc + tb->size) in order to for it to be
31471 * properly cleared -- thus we increment the PC here so that
31472 * the logic setting tb->size below does the right thing.
31473 */
18f440ed
EC
31474 ctx->base.pc_next += 4;
31475 return true;
31476}
4ad40f36 31477
18f440ed
EC
31478static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31479{
31480 CPUMIPSState *env = cs->env_ptr;
31481 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31482 int insn_bytes;
31483 int is_slot;
4ad40f36 31484
18f440ed 31485 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
31486 if (ctx->insn_flags & ISA_NANOMIPS32) {
31487 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31488 insn_bytes = decode_nanomips_opc(env, ctx);
31489 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
31490 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31491 insn_bytes = 4;
31492 decode_opc(env, ctx);
31493 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31494 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31495 insn_bytes = decode_micromips_opc(env, ctx);
31496 } else if (ctx->insn_flags & ASE_MIPS16) {
31497 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31498 insn_bytes = decode_mips16_opc(env, ctx);
31499 } else {
31500 generate_exception_end(ctx, EXCP_RI);
31501 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31502 return;
31503 }
faf7aaa9 31504
18f440ed
EC
31505 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31506 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31507 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
31508 /*
31509 * Force to generate branch as there is neither delay nor
31510 * forbidden slot.
31511 */
18f440ed
EC
31512 is_slot = 1;
31513 }
31514 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31515 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
31516 /*
31517 * Force to generate branch as microMIPS R6 doesn't restrict
31518 * branches in the forbidden slot.
31519 */
18f440ed 31520 is_slot = 1;
eeb3bba8 31521 }
18f440ed
EC
31522 }
31523 if (is_slot) {
31524 gen_branch(ctx, insn_bytes);
31525 }
31526 ctx->base.pc_next += insn_bytes;
1b530a6d 31527
18f440ed
EC
31528 if (ctx->base.is_jmp != DISAS_NEXT) {
31529 return;
6af0bf9c 31530 }
7480515f
AM
31531 /*
31532 * Execute a branch and its delay slot as a single instruction.
31533 * This is what GDB expects and is consistent with what the
31534 * hardware does (e.g. if a delay slot instruction faults, the
31535 * reported PC is the PC of the branch).
31536 */
18f440ed
EC
31537 if (ctx->base.singlestep_enabled &&
31538 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31539 ctx->base.is_jmp = DISAS_TOO_MANY;
31540 }
31541 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31542 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 31543 }
18f440ed
EC
31544}
31545
31546static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31547{
31548 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31549
12be9258
EC
31550 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31551 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 31552 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 31553 } else {
12be9258 31554 switch (ctx->base.is_jmp) {
b28425ba 31555 case DISAS_STOP:
12be9258 31556 gen_save_pc(ctx->base.pc_next);
cd314a7d 31557 tcg_gen_lookup_and_goto_ptr();
df1561e2 31558 break;
b28425ba 31559 case DISAS_NEXT:
18f440ed 31560 case DISAS_TOO_MANY:
12be9258
EC
31561 save_cpu_state(ctx, 0);
31562 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 31563 break;
b28425ba 31564 case DISAS_EXIT:
07ea28b4 31565 tcg_gen_exit_tb(NULL, 0);
16c00cb2 31566 break;
b28425ba 31567 case DISAS_NORETURN:
5a5012ec 31568 break;
18f440ed
EC
31569 default:
31570 g_assert_not_reached();
6958549d 31571 }
6af0bf9c 31572 }
18f440ed
EC
31573}
31574
31575static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31576{
31577 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31578 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31579}
31580
31581static const TranslatorOps mips_tr_ops = {
31582 .init_disas_context = mips_tr_init_disas_context,
31583 .tb_start = mips_tr_tb_start,
31584 .insn_start = mips_tr_insn_start,
31585 .breakpoint_check = mips_tr_breakpoint_check,
31586 .translate_insn = mips_tr_translate_insn,
31587 .tb_stop = mips_tr_tb_stop,
31588 .disas_log = mips_tr_disas_log,
31589};
31590
8b86d6d2 31591void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
31592{
31593 DisasContext ctx;
31594
8b86d6d2 31595 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
31596}
31597
71375b59 31598static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
31599{
31600 int i;
5e755519 31601 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 31602
2a5612e6
SW
31603#define printfpr(fp) \
31604 do { \
31605 if (is_fpu64) \
90c84c56
MA
31606 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31607 " fd:%13g fs:%13g psu: %13g\n", \
31608 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31609 (double)(fp)->fd, \
31610 (double)(fp)->fs[FP_ENDIAN_IDX], \
31611 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
31612 else { \
31613 fpr_t tmp; \
31614 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31615 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
31616 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31617 " fd:%13g fs:%13g psu:%13g\n", \
31618 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31619 (double)tmp.fd, \
31620 (double)tmp.fs[FP_ENDIAN_IDX], \
31621 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 31622 } \
71375b59 31623 } while (0)
6ea83fed 31624
5a5012ec 31625
90c84c56
MA
31626 qemu_fprintf(f,
31627 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31628 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31629 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 31630 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 31631 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 31632 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
31633 }
31634
31635#undef printfpr
31636}
31637
90c84c56 31638void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 31639{
878096ee
AF
31640 MIPSCPU *cpu = MIPS_CPU(cs);
31641 CPUMIPSState *env = &cpu->env;
6af0bf9c 31642 int i;
3b46e624 31643
90c84c56
MA
31644 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31645 " LO=0x" TARGET_FMT_lx " ds %04x "
31646 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31647 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31648 env->hflags, env->btarget, env->bcond);
6af0bf9c 31649 for (i = 0; i < 32; i++) {
1f8929d2 31650 if ((i & 3) == 0) {
90c84c56 31651 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 31652 }
90c84c56
MA
31653 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31654 regnames[i], env->active_tc.gpr[i]);
1f8929d2 31655 if ((i & 3) == 3) {
90c84c56 31656 qemu_fprintf(f, "\n");
1f8929d2 31657 }
90c84c56
MA
31658 }
31659
71375b59
AM
31660 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31661 TARGET_FMT_lx "\n",
90c84c56
MA
31662 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31663 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31664 PRIx64 "\n",
31665 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31666 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31667 env->CP0_Config2, env->CP0_Config3);
31668 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31669 env->CP0_Config4, env->CP0_Config5);
1cc5af69 31670 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 31671 fpu_dump_state(env, f, flags);
1cc5af69 31672 }
6af0bf9c
FB
31673}
31674
78ce64f4 31675void mips_tcg_init(void)
39454628 31676{
f01be154 31677 int i;
39454628 31678
f764718d 31679 cpu_gpr[0] = NULL;
bb928dbe 31680 for (i = 1; i < 32; i++)
e1ccc054 31681 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
71375b59
AM
31682 offsetof(CPUMIPSState,
31683 active_tc.gpr[i]),
4b2eb8d2 31684 regnames[i]);
d73ee8a2 31685
863f264d
YK
31686 for (i = 0; i < 32; i++) {
31687 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31688 msa_wr_d[i * 2] =
e1ccc054 31689 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
7480515f
AM
31690 /*
31691 * The scalar floating-point unit (FPU) registers are mapped on
31692 * the MSA vector registers.
31693 */
cb269f27 31694 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
31695 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31696 msa_wr_d[i * 2 + 1] =
e1ccc054 31697 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
31698 }
31699
e1ccc054 31700 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 31701 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 31702 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 31703 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 31704 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 31705 regnames_HI[i]);
e1ccc054 31706 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 31707 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 31708 regnames_LO[i]);
4b2eb8d2 31709 }
e1ccc054 31710 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
31711 offsetof(CPUMIPSState,
31712 active_tc.DSPControl),
4b2eb8d2 31713 "DSPControl");
e1ccc054 31714 bcond = tcg_global_mem_new(cpu_env,
7db13fae 31715 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 31716 btarget = tcg_global_mem_new(cpu_env,
7db13fae 31717 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 31718 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 31719 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 31720
e1ccc054 31721 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31722 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 31723 "fcr0");
e1ccc054 31724 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 31725 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 31726 "fcr31");
33a07fa2
LA
31727 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31728 "lladdr");
31729 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31730 "llval");
a168a796
FN
31731
31732#if defined(TARGET_MIPS64)
31733 cpu_mmr[0] = NULL;
31734 for (i = 1; i < 32; i++) {
31735 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31736 offsetof(CPUMIPSState,
31737 active_tc.mmr[i]),
31738 regnames[i]);
31739 }
31740#endif
31741
b621f018 31742#if !defined(TARGET_MIPS64)
eb5559f6
CJ
31743 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31744 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31745 offsetof(CPUMIPSState,
31746 active_tc.mxu_gpr[i]),
31747 mxuregnames[i]);
31748 }
31749
31750 mxu_CR = tcg_global_mem_new(cpu_env,
31751 offsetof(CPUMIPSState, active_tc.mxu_cr),
31752 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 31753#endif
39454628
TS
31754}
31755
bad729e2
RH
31756void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31757 target_ulong *data)
d2856f1a 31758{
bad729e2 31759 env->active_tc.PC = data[0];
d2856f1a 31760 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 31761 env->hflags |= data[1];
4636401d
AJ
31762 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31763 case MIPS_HFLAG_BR:
31764 break;
31765 case MIPS_HFLAG_BC:
31766 case MIPS_HFLAG_BL:
31767 case MIPS_HFLAG_B:
bad729e2 31768 env->btarget = data[2];
4636401d
AJ
31769 break;
31770 }
d2856f1a 31771}
This page took 7.401888 seconds and 4 git commands to generate.