]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
target/mips: Make check_cp0_enabled() return a boolean
[mirror_qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c 1/*
ab99e0e4 2 * MIPS emulation for QEMU - main translation routines
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
96e5b4c7 9 * Copyright (c) 2020 Philippe Mathieu-Daudé
6af0bf9c
FB
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
89975214 14 * version 2.1 of the License, or (at your option) any later version.
6af0bf9c
FB
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
8167ee88 22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
23 */
24
c684822a 25#include "qemu/osdep.h"
6af0bf9c 26#include "cpu.h"
26aa3d9a 27#include "internal.h"
dcb32f1d 28#include "tcg/tcg-op.h"
0ab8e33a 29#include "exec/translator.h"
2ef6175a
RH
30#include "exec/helper-proto.h"
31#include "exec/helper-gen.h"
6b5fe137 32#include "semihosting/semihost.h"
a7812ae4 33
b44a7fb1 34#include "target/mips/trace.h"
a7e30d84 35#include "trace-tcg.h"
b28425ba 36#include "exec/translator.h"
508127e2 37#include "exec/log.h"
0442428a 38#include "qemu/qemu-print.h"
81ddae7c 39#include "fpu_helper.h"
e3130936 40#include "translate.h"
a7e30d84 41
e37e863f
FB
42enum {
43 /* indirect opcode tables */
7a387fff
TS
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
7a387fff
TS
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 51 /* arithmetic with immediate */
7a387fff
TS
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
324d9e32 56 /* logic with immediate */
7a387fff
TS
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
324d9e32 61 /* arithmetic with immediate */
7a387fff
TS
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
e37e863f 64 /* Jump and branches */
7a387fff
TS
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
b231c103 75 OPC_JALX = (0x1D << 26),
d4ea6acd 76 OPC_DAUI = (0x1D << 26),
e37e863f 77 /* Load and stores */
7a387fff
TS
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
364d4831 84 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
364d4831 99 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
e37e863f 103 /* Floating point load/store */
7a387fff
TS
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
31837be3
YK
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
7a387fff
TS
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
e37e863f 139 /* Cache and prefetch */
7a387fff
TS
140 OPC_CACHE = (0x2F << 26),
141 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
142 /* PC-relative address computation / loads */
143 OPC_PCREL = (0x3B << 26),
144};
145
146/* PC-relative address computation / loads */
71375b59
AM
147#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
148#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
149enum {
150 /* Instructions determined by bits 19 and 20 */
151 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
152 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
153 OPC_LWUPC = OPC_PCREL | (2 << 19),
154
155 /* Instructions determined by bits 16 ... 20 */
156 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
157 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
158
159 /* Other */
160 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
161};
162
163/* MIPS special opcodes */
71375b59 164#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 165
e37e863f
FB
166enum {
167 /* Shifts */
7a387fff 168 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
169 /* NOP is SLL r0, r0, 0 */
170 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
171 /* EHB is SLL r0, r0, 3 */
172 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 173 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
174 OPC_SRA = 0x03 | OPC_SPECIAL,
175 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 176 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 177 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
178 OPC_SRAV = 0x07 | OPC_SPECIAL,
179 OPC_DSLLV = 0x14 | OPC_SPECIAL,
180 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 181 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
182 OPC_DSRAV = 0x17 | OPC_SPECIAL,
183 OPC_DSLL = 0x38 | OPC_SPECIAL,
184 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 185 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
186 OPC_DSRA = 0x3B | OPC_SPECIAL,
187 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
188 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 189 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 190 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 191 /* Multiplication / division */
7a387fff
TS
192 OPC_MULT = 0x18 | OPC_SPECIAL,
193 OPC_MULTU = 0x19 | OPC_SPECIAL,
194 OPC_DIV = 0x1A | OPC_SPECIAL,
195 OPC_DIVU = 0x1B | OPC_SPECIAL,
196 OPC_DMULT = 0x1C | OPC_SPECIAL,
197 OPC_DMULTU = 0x1D | OPC_SPECIAL,
198 OPC_DDIV = 0x1E | OPC_SPECIAL,
199 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 200
e37e863f 201 /* 2 registers arithmetic / logic */
7a387fff
TS
202 OPC_ADD = 0x20 | OPC_SPECIAL,
203 OPC_ADDU = 0x21 | OPC_SPECIAL,
204 OPC_SUB = 0x22 | OPC_SPECIAL,
205 OPC_SUBU = 0x23 | OPC_SPECIAL,
206 OPC_AND = 0x24 | OPC_SPECIAL,
207 OPC_OR = 0x25 | OPC_SPECIAL,
208 OPC_XOR = 0x26 | OPC_SPECIAL,
209 OPC_NOR = 0x27 | OPC_SPECIAL,
210 OPC_SLT = 0x2A | OPC_SPECIAL,
211 OPC_SLTU = 0x2B | OPC_SPECIAL,
212 OPC_DADD = 0x2C | OPC_SPECIAL,
213 OPC_DADDU = 0x2D | OPC_SPECIAL,
214 OPC_DSUB = 0x2E | OPC_SPECIAL,
215 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 216 /* Jumps */
7a387fff
TS
217 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
218 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 219 /* Traps */
7a387fff
TS
220 OPC_TGE = 0x30 | OPC_SPECIAL,
221 OPC_TGEU = 0x31 | OPC_SPECIAL,
222 OPC_TLT = 0x32 | OPC_SPECIAL,
223 OPC_TLTU = 0x33 | OPC_SPECIAL,
224 OPC_TEQ = 0x34 | OPC_SPECIAL,
225 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 226 /* HI / LO registers load & stores */
7a387fff
TS
227 OPC_MFHI = 0x10 | OPC_SPECIAL,
228 OPC_MTHI = 0x11 | OPC_SPECIAL,
229 OPC_MFLO = 0x12 | OPC_SPECIAL,
230 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 231 /* Conditional moves */
7a387fff
TS
232 OPC_MOVZ = 0x0A | OPC_SPECIAL,
233 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 234
b691d9d2
LA
235 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
236 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
237
7a387fff 238 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
239
240 /* Special */
a0d700e4 241 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
242 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
243 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 244 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
245 OPC_SYNC = 0x0F | OPC_SPECIAL,
246
7a387fff
TS
247 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
248 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
249 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
250 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
251};
252
7480515f
AM
253/*
254 * R6 Multiply and Divide instructions have the same opcode
255 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
256 */
71375b59 257#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
258
259enum {
260 R6_OPC_MUL = OPC_MULT | (2 << 6),
261 R6_OPC_MUH = OPC_MULT | (3 << 6),
262 R6_OPC_MULU = OPC_MULTU | (2 << 6),
263 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
264 R6_OPC_DIV = OPC_DIV | (2 << 6),
265 R6_OPC_MOD = OPC_DIV | (3 << 6),
266 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
267 R6_OPC_MODU = OPC_DIVU | (3 << 6),
268
269 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
270 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
271 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
272 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
273 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
274 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
275 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
276 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
277
278 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
279 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
280 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
281 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
282 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
b42ee5e1
LA
283};
284
e9c71dd1 285/* Multiplication variants of the vr54xx. */
71375b59 286#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
287
288enum {
289 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
290 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
291 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
292 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
293 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
294 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
295 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
296 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
298 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
299 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
300 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
301 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
302 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
303};
304
7a387fff 305/* REGIMM (rt field) opcodes */
71375b59 306#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
307
308enum {
309 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
310 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
311 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
312 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
313 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
314 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
315 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
316 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
317 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
318 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
319 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
320 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
321 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
322 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 323 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 324 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
325
326 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
327 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
328};
329
7a387fff 330/* Special2 opcodes */
71375b59 331#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 332
e37e863f 333enum {
7a387fff
TS
334 /* Multiply & xxx operations */
335 OPC_MADD = 0x00 | OPC_SPECIAL2,
336 OPC_MADDU = 0x01 | OPC_SPECIAL2,
337 OPC_MUL = 0x02 | OPC_SPECIAL2,
338 OPC_MSUB = 0x04 | OPC_SPECIAL2,
339 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
340 /* Loongson 2F */
341 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
342 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
343 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
344 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
345 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
346 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
347 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
348 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
349 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
350 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
351 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
352 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 353 /* Misc */
7a387fff
TS
354 OPC_CLZ = 0x20 | OPC_SPECIAL2,
355 OPC_CLO = 0x21 | OPC_SPECIAL2,
356 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
357 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 358 /* Special */
7a387fff
TS
359 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
360};
361
362/* Special3 opcodes */
71375b59 363#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
364
365enum {
366 OPC_EXT = 0x00 | OPC_SPECIAL3,
367 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
368 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
369 OPC_DEXT = 0x03 | OPC_SPECIAL3,
370 OPC_INS = 0x04 | OPC_SPECIAL3,
371 OPC_DINSM = 0x05 | OPC_SPECIAL3,
372 OPC_DINSU = 0x06 | OPC_SPECIAL3,
373 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
374 OPC_FORK = 0x08 | OPC_SPECIAL3,
375 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
376 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
377 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
378 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
99029be1 379 OPC_GINV = 0x3D | OPC_SPECIAL3,
161f85e6
AJ
380
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
394
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 417 /* MIPS DSP Append Sub-class */
26690560 418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 423
76964147
JH
424 /* EVA */
425 OPC_LWLE = 0x19 | OPC_SPECIAL3,
426 OPC_LWRE = 0x1A | OPC_SPECIAL3,
427 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
428 OPC_SBE = 0x1C | OPC_SPECIAL3,
429 OPC_SHE = 0x1D | OPC_SPECIAL3,
430 OPC_SCE = 0x1E | OPC_SPECIAL3,
431 OPC_SWE = 0x1F | OPC_SPECIAL3,
432 OPC_SWLE = 0x21 | OPC_SPECIAL3,
433 OPC_SWRE = 0x22 | OPC_SPECIAL3,
434 OPC_PREFE = 0x23 | OPC_SPECIAL3,
435 OPC_LBUE = 0x28 | OPC_SPECIAL3,
436 OPC_LHUE = 0x29 | OPC_SPECIAL3,
437 OPC_LBE = 0x2C | OPC_SPECIAL3,
438 OPC_LHE = 0x2D | OPC_SPECIAL3,
439 OPC_LLE = 0x2E | OPC_SPECIAL3,
440 OPC_LWE = 0x2F | OPC_SPECIAL3,
441
4368b29a 442 /* R6 */
bf7910c6
LA
443 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
444 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
445 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
446 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
447 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
448 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
449};
450
e10a0ca1
JY
451/* Loongson EXT load/store quad word opcodes */
452#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
453enum {
454 OPC_GSLQ = 0x0020 | OPC_LWC2,
455 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
456 OPC_GSSHFL = OPC_LWC2,
457 OPC_GSSQ = 0x0020 | OPC_SWC2,
458 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
459 OPC_GSSHFS = OPC_SWC2,
460};
461
fd723105
JY
462/* Loongson EXT shifted load/store opcodes */
463#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
464enum {
465 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
466 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
467 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
468 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
469 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
470 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
471 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
472 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
473};
474
90e22a57
JY
475/* Loongson EXT LDC2/SDC2 opcodes */
476#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
477
478enum {
479 OPC_GSLBX = 0x0 | OPC_LDC2,
480 OPC_GSLHX = 0x1 | OPC_LDC2,
481 OPC_GSLWX = 0x2 | OPC_LDC2,
482 OPC_GSLDX = 0x3 | OPC_LDC2,
483 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
484 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
485 OPC_GSSBX = 0x0 | OPC_SDC2,
486 OPC_GSSHX = 0x1 | OPC_SDC2,
487 OPC_GSSWX = 0x2 | OPC_SDC2,
488 OPC_GSSDX = 0x3 | OPC_SDC2,
489 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
490 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
491};
492
7a387fff 493/* BSHFL opcodes */
71375b59 494#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 495
e37e863f 496enum {
15eacb9b
YK
497 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
498 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
499 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
500 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
501 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
502 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
503 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 504 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
505};
506
7a387fff 507/* DBSHFL opcodes */
71375b59 508#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 509
e37e863f 510enum {
15eacb9b
YK
511 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
512 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
513 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
514 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
515 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
516 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
517 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
518 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
519 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
520 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 521 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
522};
523
e45a93e2
JL
524/* MIPS DSP REGIMM opcodes */
525enum {
526 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 527 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
528};
529
71375b59 530#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
531/* MIPS DSP Load */
532enum {
533 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
534 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
535 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 536 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
537};
538
71375b59 539#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
540enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
543 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
544 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
545 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
546 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
549 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
550 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
551 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
552 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
558 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
559 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
560 /* MIPS DSP Multiply Sub-class insns */
561 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
564 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
565 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
567};
568
569#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 570#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
571enum {
572 /* MIPS DSP Arithmetic Sub-class */
573 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
577 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
585 /* MIPS DSP Multiply Sub-class insns */
586 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
587 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
588 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
590};
591
71375b59 592#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
593enum {
594 /* MIPS DSP Arithmetic Sub-class */
595 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
608 /* DSP Bit/Manipulation Sub-class */
609 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
614};
615
71375b59 616#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
617enum {
618 /* MIPS DSP Arithmetic Sub-class */
619 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
626 /* DSP Compare-Pick Sub-class */
627 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 642};
a22260ae 643
71375b59 644#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
645enum {
646 /* MIPS DSP GPR-Based Shift Sub-class */
647 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
669};
461c08df 670
71375b59 671#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
672enum {
673 /* MIPS DSP Multiply Sub-class insns */
674 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
688 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
691 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
696};
697
71375b59 698#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
699enum {
700 /* DSP Bit/Manipulation Sub-class */
701 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
702};
703
71375b59 704#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 705enum {
df6126a7 706 /* MIPS DSP Append Sub-class */
26690560
JL
707 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
708 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
709 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
710};
711
71375b59 712#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
713enum {
714 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
715 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
719 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
727 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
728 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
729 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
730 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
731 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
732};
733
71375b59 734#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
735enum {
736 /* MIPS DSP Arithmetic Sub-class */
737 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
754 /* DSP Bit/Manipulation Sub-class */
755 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 761};
461c08df 762
71375b59 763#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 764enum {
a22260ae
JL
765 /* MIPS DSP Multiply Sub-class insns */
766 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
767 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
768 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
769 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
770 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
771 /* MIPS DSP Arithmetic Sub-class */
772 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
775 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
776 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
785 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
786 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
793};
461c08df 794
71375b59 795#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 796enum {
26690560
JL
797 /* DSP Compare-Pick Sub-class */
798 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
817 /* MIPS DSP Arithmetic Sub-class */
818 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
826};
461c08df 827
71375b59 828#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 829enum {
df6126a7 830 /* DSP Append Sub-class */
26690560
JL
831 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
832 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
833 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
834 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
835};
26690560 836
71375b59 837#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
838enum {
839 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
840 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
841 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
861};
862
71375b59 863#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
864enum {
865 /* DSP Bit/Manipulation Sub-class */
866 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
867};
1cb6686c 868
71375b59 869#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
870enum {
871 /* MIPS DSP Multiply Sub-class insns */
872 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
898};
a22260ae 899
71375b59 900#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
901enum {
902 /* MIPS DSP GPR-Based Shift Sub-class */
903 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
929};
77c5fa8b 930
7a387fff 931/* Coprocessor 0 (rs field) */
71375b59 932#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 933
6ea83fed 934enum {
7a387fff
TS
935 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
936 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 937 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
938 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
939 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 940 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 941 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
942 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
943 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 944 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
945 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
946 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
947 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
948 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
949 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
950 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
951 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
952 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
953 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
954 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
955 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
956 OPC_C0_A = (0x1A << 21) | OPC_CP0,
957 OPC_C0_B = (0x1B << 21) | OPC_CP0,
958 OPC_C0_C = (0x1C << 21) | OPC_CP0,
959 OPC_C0_D = (0x1D << 21) | OPC_CP0,
960 OPC_C0_E = (0x1E << 21) | OPC_CP0,
961 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 962};
7a387fff
TS
963
964/* MFMC0 opcodes */
71375b59 965#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
966
967enum {
ead9360e
TS
968 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
969 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
970 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
971 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
972 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
973 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
974 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
975 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
976};
977
978/* Coprocessor 0 (with rs == C0) */
71375b59 979#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
980
981enum {
982 OPC_TLBR = 0x01 | OPC_C0,
983 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
984 OPC_TLBINV = 0x03 | OPC_C0,
985 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
986 OPC_TLBWR = 0x06 | OPC_C0,
987 OPC_TLBP = 0x08 | OPC_C0,
988 OPC_RFE = 0x10 | OPC_C0,
989 OPC_ERET = 0x18 | OPC_C0,
990 OPC_DERET = 0x1F | OPC_C0,
991 OPC_WAIT = 0x20 | OPC_C0,
992};
993
71375b59 994#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
995
996enum {
997 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
998 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
999 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1000 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1001 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1002 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1003 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1004 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1005 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1006 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1007 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1008};
1009
8e2d5831 1010#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1011
1012enum {
71375b59
AM
1013 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1015 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1016 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1017 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1021
1022 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1026 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1030
1031 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1032 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1033 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1034 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1035 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1036 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1037 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1038 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1039
1040 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1041 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1042 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1043 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1044 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1045 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1046 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1047 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1048
1049 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1050 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1051 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1052 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1053 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1054 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1055
1056 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1057 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1058 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1059 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1060 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1062
1063 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1065 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1066 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1067 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1069
1070 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1071 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1072 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1073 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1074 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1076
1077 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1078 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1079 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1080 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1081 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1082 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1083
1084 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1085 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1086 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1087 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1088 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1089 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1090
1091 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1092 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1093 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1094 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1095 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1096 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1097
1098 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1099 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1100 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1101 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1102 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1103 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1104};
1105
1106
71375b59 1107#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1108
1109enum {
71375b59
AM
1110 OPC_LWXC1 = 0x00 | OPC_CP3,
1111 OPC_LDXC1 = 0x01 | OPC_CP3,
1112 OPC_LUXC1 = 0x05 | OPC_CP3,
1113 OPC_SWXC1 = 0x08 | OPC_CP3,
1114 OPC_SDXC1 = 0x09 | OPC_CP3,
1115 OPC_SUXC1 = 0x0D | OPC_CP3,
1116 OPC_PREFX = 0x0F | OPC_CP3,
1117 OPC_ALNV_PS = 0x1E | OPC_CP3,
1118 OPC_MADD_S = 0x20 | OPC_CP3,
1119 OPC_MADD_D = 0x21 | OPC_CP3,
1120 OPC_MADD_PS = 0x26 | OPC_CP3,
1121 OPC_MSUB_S = 0x28 | OPC_CP3,
1122 OPC_MSUB_D = 0x29 | OPC_CP3,
1123 OPC_MSUB_PS = 0x2E | OPC_CP3,
1124 OPC_NMADD_S = 0x30 | OPC_CP3,
1125 OPC_NMADD_D = 0x31 | OPC_CP3,
1126 OPC_NMADD_PS = 0x36 | OPC_CP3,
1127 OPC_NMSUB_S = 0x38 | OPC_CP3,
1128 OPC_NMSUB_D = 0x39 | OPC_CP3,
1129 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1130};
1131
497f072b 1132/*
baa609db
AM
1133 * MMI (MultiMedia Instruction) encodings
1134 * ======================================
f99c0d6d 1135 *
baa609db 1136 * MMI instructions encoding table keys:
f99c0d6d
FN
1137 *
1138 * * This code is reserved for future use. An attempt to execute it
1139 * causes a Reserved Instruction exception.
1140 * % This code indicates an instruction class. The instruction word
1141 * must be further decoded by examining additional tables that show
1142 * the values for other instruction fields.
1143 * # This code is reserved for the unsupported instructions DMULT,
1144 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1145 * to execute it causes a Reserved Instruction exception.
1146 *
baa609db 1147 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
1148 *
1149 * 31 26 0
1150 * +--------+----------------------------------------+
1151 * | opcode | |
1152 * +--------+----------------------------------------+
1153 *
1154 * opcode bits 28..26
1155 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1156 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1157 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1158 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1159 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1160 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1161 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1162 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1163 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1164 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1165 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 1166 */
b158d449 1167
f99c0d6d 1168enum {
baa609db
AM
1169 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1170 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1171 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
1172};
1173
d3297211 1174/*
baa609db 1175 * MMI instructions with opcode field = MMI:
d3297211
FN
1176 *
1177 * 31 26 5 0
1178 * +--------+-------------------------------+--------+
1179 * | MMI | |function|
1180 * +--------+-------------------------------+--------+
1181 *
1182 * function bits 2..0
1183 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1184 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1185 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1186 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1187 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1188 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1189 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1190 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1191 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1192 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1193 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1194 */
1195
c8341e00 1196#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 1197enum {
baa609db
AM
1198 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1199 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
baa609db
AM
1200 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1201 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1202 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1203 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1204 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1205 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
dd581bf9
FN
1206};
1207
39454628 1208/* global register indices */
46c9e2b3 1209TCGv cpu_gpr[32], cpu_PC;
cefd68f6
PMD
1210/*
1211 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1212 * and the upper halves in cpu_gpr_hi[].
1213 */
1214TCGv_i64 cpu_gpr_hi[32];
9f5f7691 1215TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
46c9e2b3
PMD
1216static TCGv cpu_dspctrl, btarget;
1217TCGv bcond;
33a07fa2 1218static TCGv cpu_lladdr, cpu_llval;
41db4607 1219static TCGv_i32 hflags;
8758d1b8
PMD
1220TCGv_i32 fpu_fcr0, fpu_fcr31;
1221TCGv_i64 fpu_f64[32];
aa0bf00b 1222
022c62cb 1223#include "exec/gen-icount.h"
2e70f6ef 1224
895c2d04 1225#define gen_helper_0e0i(name, arg) do { \
a7812ae4 1226 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 1227 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 1228 tcg_temp_free_i32(helper_tmp); \
71375b59 1229 } while (0)
be24bb4f 1230
895c2d04 1231#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 1232 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 1233 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 1234 tcg_temp_free_i32(helper_tmp); \
71375b59 1235 } while (0)
be24bb4f 1236
895c2d04
BS
1237#define gen_helper_1e0i(name, ret, arg1) do { \
1238 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1239 gen_helper_##name(ret, cpu_env, helper_tmp); \
1240 tcg_temp_free_i32(helper_tmp); \
71375b59 1241 } while (0)
895c2d04
BS
1242
1243#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1244 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1245 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1246 tcg_temp_free_i32(helper_tmp); \
71375b59 1247 } while (0)
895c2d04
BS
1248
1249#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1250 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1251 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1252 tcg_temp_free_i32(helper_tmp); \
71375b59 1253 } while (0)
895c2d04
BS
1254
1255#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 1256 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 1257 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 1258 tcg_temp_free_i32(helper_tmp); \
71375b59 1259 } while (0)
be24bb4f 1260
895c2d04 1261#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 1262 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 1263 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 1264 tcg_temp_free_i32(helper_tmp); \
71375b59 1265 } while (0)
c239529e 1266
b28425ba
EC
1267#define DISAS_STOP DISAS_TARGET_0
1268#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 1269
d73ee8a2
RH
1270static const char * const regnames[] = {
1271 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1272 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1273 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1274 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1275};
6af0bf9c 1276
d73ee8a2
RH
1277static const char * const regnames_HI[] = {
1278 "HI0", "HI1", "HI2", "HI3",
1279};
4b2eb8d2 1280
d73ee8a2
RH
1281static const char * const regnames_LO[] = {
1282 "LO0", "LO1", "LO2", "LO3",
1283};
4b2eb8d2 1284
d73ee8a2
RH
1285static const char * const fregnames[] = {
1286 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1287 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1288 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1289 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1290};
958fb4a9 1291
8e9ade68 1292/* General purpose registers moves. */
46c9e2b3 1293void gen_load_gpr(TCGv t, int reg)
aaa9128a 1294{
1f8929d2 1295 if (reg == 0) {
8e9ade68 1296 tcg_gen_movi_tl(t, 0);
1f8929d2 1297 } else {
4b2eb8d2 1298 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 1299 }
aaa9128a
TS
1300}
1301
46c9e2b3 1302void gen_store_gpr(TCGv t, int reg)
aaa9128a 1303{
1f8929d2 1304 if (reg != 0) {
4b2eb8d2 1305 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 1306 }
aaa9128a
TS
1307}
1308
61f4e0ec
PMD
1309#if defined(TARGET_MIPS64)
1310void gen_load_gpr_hi(TCGv_i64 t, int reg)
1311{
1312 if (reg == 0) {
1313 tcg_gen_movi_i64(t, 0);
1314 } else {
1315 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1316 }
1317}
1318
1319void gen_store_gpr_hi(TCGv_i64 t, int reg)
1320{
1321 if (reg != 0) {
1322 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1323 }
1324}
1325#endif /* TARGET_MIPS64 */
1326
8e9ade68 1327/* Moves to/from shadow registers. */
235785e8 1328static inline void gen_load_srsgpr(int from, int to)
aaa9128a 1329{
d9bea114 1330 TCGv t0 = tcg_temp_new();
be24bb4f 1331
1f8929d2 1332 if (from == 0) {
d9bea114 1333 tcg_gen_movi_tl(t0, 0);
1f8929d2 1334 } else {
d9bea114 1335 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1336 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1337
7db13fae 1338 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1339 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1340 tcg_gen_andi_i32(t2, t2, 0xf);
1341 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1342 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1343 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1344
d9bea114 1345 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1346 tcg_temp_free_ptr(addr);
d9bea114 1347 tcg_temp_free_i32(t2);
8e9ade68 1348 }
d9bea114
AJ
1349 gen_store_gpr(t0, to);
1350 tcg_temp_free(t0);
aaa9128a
TS
1351}
1352
71375b59 1353static inline void gen_store_srsgpr(int from, int to)
aaa9128a 1354{
be24bb4f 1355 if (to != 0) {
d9bea114
AJ
1356 TCGv t0 = tcg_temp_new();
1357 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1358 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1359
d9bea114 1360 gen_load_gpr(t0, from);
7db13fae 1361 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1362 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1363 tcg_gen_andi_i32(t2, t2, 0xf);
1364 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1365 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1366 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1367
d9bea114 1368 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1369 tcg_temp_free_ptr(addr);
d9bea114
AJ
1370 tcg_temp_free_i32(t2);
1371 tcg_temp_free(t0);
8e9ade68 1372 }
aaa9128a
TS
1373}
1374
eab9944c
LA
1375/* Tests */
1376static inline void gen_save_pc(target_ulong pc)
1377{
1378 tcg_gen_movi_tl(cpu_PC, pc);
1379}
1380
1381static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1382{
1383 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
1384 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1385 gen_save_pc(ctx->base.pc_next);
1386 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
1387 }
1388 if (ctx->hflags != ctx->saved_hflags) {
1389 tcg_gen_movi_i32(hflags, ctx->hflags);
1390 ctx->saved_hflags = ctx->hflags;
1391 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1392 case MIPS_HFLAG_BR:
1393 break;
1394 case MIPS_HFLAG_BC:
1395 case MIPS_HFLAG_BL:
1396 case MIPS_HFLAG_B:
1397 tcg_gen_movi_tl(btarget, ctx->btarget);
1398 break;
1399 }
1400 }
1401}
1402
1403static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1404{
1405 ctx->saved_hflags = ctx->hflags;
1406 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1407 case MIPS_HFLAG_BR:
1408 break;
1409 case MIPS_HFLAG_BC:
1410 case MIPS_HFLAG_BL:
1411 case MIPS_HFLAG_B:
1412 ctx->btarget = env->btarget;
1413 break;
1414 }
1415}
1416
46c9e2b3 1417void generate_exception_err(DisasContext *ctx, int excp, int err)
eab9944c
LA
1418{
1419 TCGv_i32 texcp = tcg_const_i32(excp);
1420 TCGv_i32 terr = tcg_const_i32(err);
1421 save_cpu_state(ctx, 1);
1422 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1423 tcg_temp_free_i32(terr);
1424 tcg_temp_free_i32(texcp);
eeb3bba8 1425 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
1426}
1427
46c9e2b3 1428void generate_exception(DisasContext *ctx, int excp)
eab9944c 1429{
eab9944c
LA
1430 gen_helper_0e0i(raise_exception, excp);
1431}
1432
46c9e2b3 1433void generate_exception_end(DisasContext *ctx, int excp)
9c708c7f
PD
1434{
1435 generate_exception_err(ctx, excp, 0);
1436}
1437
3a4ef3b7
PMD
1438void gen_reserved_instruction(DisasContext *ctx)
1439{
1440 generate_exception_end(ctx, EXCP_RI);
1441}
1442
aaa9128a 1443/* Floating point register moves. */
8758d1b8 1444void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1445{
7c979afd
LA
1446 if (ctx->hflags & MIPS_HFLAG_FRE) {
1447 generate_exception(ctx, EXCP_RI);
1448 }
ecc7b3aa 1449 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1450}
1451
8758d1b8 1452void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1453{
7c979afd
LA
1454 TCGv_i64 t64;
1455 if (ctx->hflags & MIPS_HFLAG_FRE) {
1456 generate_exception(ctx, EXCP_RI);
1457 }
1458 t64 = tcg_temp_new_i64();
d73ee8a2
RH
1459 tcg_gen_extu_i32_i64(t64, t);
1460 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1461 tcg_temp_free_i64(t64);
6d066274
AJ
1462}
1463
7f6613ce 1464static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1465{
7f6613ce 1466 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 1467 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 1468 } else {
7c979afd 1469 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 1470 }
6d066274
AJ
1471}
1472
7f6613ce 1473static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1474{
7f6613ce
PJ
1475 if (ctx->hflags & MIPS_HFLAG_F64) {
1476 TCGv_i64 t64 = tcg_temp_new_i64();
1477 tcg_gen_extu_i32_i64(t64, t);
1478 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1479 tcg_temp_free_i64(t64);
1480 } else {
7c979afd 1481 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 1482 }
aa0bf00b 1483}
6ea83fed 1484
8758d1b8 1485void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1486{
f364515c 1487 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1488 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1489 } else {
d73ee8a2 1490 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1491 }
1492}
6ea83fed 1493
8758d1b8 1494void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1495{
f364515c 1496 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1497 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1498 } else {
d73ee8a2
RH
1499 TCGv_i64 t0;
1500 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1501 t0 = tcg_temp_new_i64();
6d066274 1502 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1503 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1504 tcg_temp_free_i64(t0);
aa0bf00b
TS
1505 }
1506}
6ea83fed 1507
8758d1b8 1508int get_fp_bit(int cc)
a16336e4 1509{
1f8929d2 1510 if (cc) {
d94536f4 1511 return 24 + cc;
1f8929d2 1512 } else {
d94536f4 1513 return 23;
1f8929d2 1514 }
a16336e4
TS
1515}
1516
48d38ca5 1517/* Addresses computation */
46c9e2b3 1518void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1519{
941694d0 1520 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1521
1522#if defined(TARGET_MIPS64)
01f72885 1523 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 1524 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1525 }
1526#endif
4ad40f36
FB
1527}
1528
bf0718c5
SM
1529static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1530 target_long ofs)
1531{
1532 tcg_gen_addi_tl(ret, base, ofs);
1533
1534#if defined(TARGET_MIPS64)
1535 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1536 tcg_gen_ext32s_i64(ret, ret);
1537 }
1538#endif
1539}
1540
31837be3
YK
1541/* Addresses computation (translation time) */
1542static target_long addr_add(DisasContext *ctx, target_long base,
1543 target_long offset)
1544{
1545 target_long sum = base + offset;
1546
1547#if defined(TARGET_MIPS64)
1548 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1549 sum = (int32_t)sum;
1550 }
1551#endif
1552 return sum;
1553}
1554
71f303cd 1555/* Sign-extract the low 32-bits to a target_long. */
46c9e2b3 1556void gen_move_low32(TCGv ret, TCGv_i64 arg)
1f1b4c00
YK
1557{
1558#if defined(TARGET_MIPS64)
71f303cd
RH
1559 tcg_gen_ext32s_i64(ret, arg);
1560#else
1561 tcg_gen_extrl_i64_i32(ret, arg);
1562#endif
1563}
1564
1565/* Sign-extract the high 32-bits to a target_long. */
46c9e2b3 1566void gen_move_high32(TCGv ret, TCGv_i64 arg)
71f303cd
RH
1567{
1568#if defined(TARGET_MIPS64)
1569 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 1570#else
71f303cd 1571 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
1572#endif
1573}
1574
905bdf72 1575bool check_cp0_enabled(DisasContext *ctx)
387a8fe5 1576{
1f8929d2 1577 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1578 generate_exception_end(ctx, EXCP_CpU);
905bdf72 1579 return false;
1f8929d2 1580 }
905bdf72 1581 return true;
387a8fe5
TS
1582}
1583
8758d1b8 1584void check_cp1_enabled(DisasContext *ctx)
5e755519 1585{
1f8929d2 1586 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 1587 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 1588 }
5e755519
TS
1589}
1590
7480515f
AM
1591/*
1592 * Verify that the processor is running with COP1X instructions enabled.
1593 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1594 * opcode tables.
1595 */
8758d1b8 1596void check_cop1x(DisasContext *ctx)
b8aa4598 1597{
1f8929d2 1598 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
3a4ef3b7 1599 gen_reserved_instruction(ctx);
1f8929d2 1600 }
b8aa4598
TS
1601}
1602
7480515f
AM
1603/*
1604 * Verify that the processor is running with 64-bit floating-point
1605 * operations enabled.
1606 */
8758d1b8 1607void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1608{
1f8929d2 1609 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
3a4ef3b7 1610 gen_reserved_instruction(ctx);
1f8929d2 1611 }
5e755519
TS
1612}
1613
1614/*
1615 * Verify if floating point register is valid; an operation is not defined
1616 * if bit 0 of any register specification is set and the FR bit in the
1617 * Status register equals zero, since the register numbers specify an
1618 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1619 * in the Status register equals one, both even and odd register numbers
1620 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1621 *
1622 * Multiple 64 bit wide registers can be checked by calling
1623 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1624 */
8758d1b8 1625void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1626{
1f8929d2 1627 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
3a4ef3b7 1628 gen_reserved_instruction(ctx);
1f8929d2 1629 }
5e755519
TS
1630}
1631
7480515f
AM
1632/*
1633 * Verify that the processor is running with DSP instructions enabled.
1634 * This is enabled by CP0 Status register MX(24) bit.
853c3240 1635 */
853c3240
JL
1636static inline void check_dsp(DisasContext *ctx)
1637{
1638 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 1639 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1640 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1641 } else {
3a4ef3b7 1642 gen_reserved_instruction(ctx);
ad153f15 1643 }
853c3240
JL
1644 }
1645}
1646
908f6be1 1647static inline void check_dsp_r2(DisasContext *ctx)
853c3240 1648{
908f6be1 1649 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 1650 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1651 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1652 } else {
3a4ef3b7 1653 gen_reserved_instruction(ctx);
ad153f15 1654 }
853c3240
JL
1655 }
1656}
1657
908f6be1 1658static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 1659{
908f6be1 1660 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
1661 if (ctx->insn_flags & ASE_DSP) {
1662 generate_exception_end(ctx, EXCP_DSPDIS);
1663 } else {
3a4ef3b7 1664 gen_reserved_instruction(ctx);
59e781fb
SM
1665 }
1666 }
1667}
1668
7480515f
AM
1669/*
1670 * This code generates a "reserved instruction" exception if the
1671 * CPU does not support the instruction set corresponding to flags.
1672 */
46c9e2b3 1673void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 1674{
d75c135e 1675 if (unlikely(!(ctx->insn_flags & flags))) {
3a4ef3b7 1676 gen_reserved_instruction(ctx);
d75c135e 1677 }
3a95e3a7
TS
1678}
1679
7480515f
AM
1680/*
1681 * This code generates a "reserved instruction" exception if the
1682 * CPU has corresponding flag set which indicates that the instruction
1683 * has been removed.
1684 */
f9c9cd63 1685static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
1686{
1687 if (unlikely(ctx->insn_flags & flags)) {
3a4ef3b7 1688 gen_reserved_instruction(ctx);
fecd2646
LA
1689 }
1690}
1691
96631327
FN
1692/*
1693 * The Linux kernel traps certain reserved instruction exceptions to
1694 * emulate the corresponding instructions. QEMU is the kernel in user
1695 * mode, so those traps are emulated by accepting the instructions.
1696 *
1697 * A reserved instruction exception is generated for flagged CPUs if
1698 * QEMU runs in system mode.
1699 */
1700static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1701{
1702#ifndef CONFIG_USER_ONLY
1703 check_insn_opc_removed(ctx, flags);
1704#endif
1705}
1706
7480515f
AM
1707/*
1708 * This code generates a "reserved instruction" exception if the
1709 * CPU does not support 64-bit paired-single (PS) floating point data type.
1710 */
e29c9628
YK
1711static inline void check_ps(DisasContext *ctx)
1712{
1713 if (unlikely(!ctx->ps)) {
1714 generate_exception(ctx, EXCP_RI);
1715 }
1716 check_cp1_64bitmode(ctx);
1717}
1718
7480515f 1719/*
d7efb693
PMD
1720 * This code generates a "reserved instruction" exception if cpu is not
1721 * 64-bit or 64-bit instructions are not enabled.
7480515f 1722 */
46c9e2b3 1723void check_mips_64(DisasContext *ctx)
e189e748 1724{
d7efb693 1725 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
3a4ef3b7 1726 gen_reserved_instruction(ctx);
1f8929d2 1727 }
e189e748
TS
1728}
1729
5204ea79
LA
1730#ifndef CONFIG_USER_ONLY
1731static inline void check_mvh(DisasContext *ctx)
1732{
1733 if (unlikely(!ctx->mvh)) {
1734 generate_exception(ctx, EXCP_RI);
1735 }
1736}
1737#endif
1738
0b16dcd1
AR
1739/*
1740 * This code generates a "reserved instruction" exception if the
1741 * Config5 XNP bit is set.
1742 */
1743static inline void check_xnp(DisasContext *ctx)
1744{
1745 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3a4ef3b7 1746 gen_reserved_instruction(ctx);
0b16dcd1
AR
1747 }
1748}
1749
5e31fdd5
YK
1750#ifndef CONFIG_USER_ONLY
1751/*
1752 * This code generates a "reserved instruction" exception if the
1753 * Config3 PW bit is NOT set.
1754 */
1755static inline void check_pw(DisasContext *ctx)
1756{
1757 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3a4ef3b7 1758 gen_reserved_instruction(ctx);
5e31fdd5
YK
1759 }
1760}
1761#endif
1762
9affc1c5
AR
1763/*
1764 * This code generates a "reserved instruction" exception if the
1765 * Config3 MT bit is NOT set.
1766 */
1767static inline void check_mt(DisasContext *ctx)
1768{
1769 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1770 gen_reserved_instruction(ctx);
9affc1c5
AR
1771 }
1772}
1773
1774#ifndef CONFIG_USER_ONLY
1775/*
1776 * This code generates a "coprocessor unusable" exception if CP0 is not
1777 * available, and, if that is not the case, generates a "reserved instruction"
1778 * exception if the Config5 MT bit is NOT set. This is needed for availability
1779 * control of some of MT ASE instructions.
1780 */
1781static inline void check_cp0_mt(DisasContext *ctx)
1782{
1783 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1784 generate_exception_end(ctx, EXCP_CpU);
9affc1c5
AR
1785 } else {
1786 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1787 gen_reserved_instruction(ctx);
9affc1c5
AR
1788 }
1789 }
1790}
1791#endif
1792
fb32f8c8
DN
1793/*
1794 * This code generates a "reserved instruction" exception if the
1795 * Config5 NMS bit is set.
1796 */
1797static inline void check_nms(DisasContext *ctx)
1798{
1799 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3a4ef3b7 1800 gen_reserved_instruction(ctx);
fb32f8c8
DN
1801 }
1802}
1803
d046a9ea
DN
1804/*
1805 * This code generates a "reserved instruction" exception if the
1806 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1807 * Config2 TL, and Config5 L2C are unset.
1808 */
1809static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1810{
1f8929d2
AM
1811 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1812 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1813 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1814 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1815 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1816 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3a4ef3b7 1817 gen_reserved_instruction(ctx);
d046a9ea
DN
1818 }
1819}
1820
1821/*
1822 * This code generates a "reserved instruction" exception if the
1823 * Config5 EVA bit is NOT set.
1824 */
1825static inline void check_eva(DisasContext *ctx)
1826{
1827 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3a4ef3b7 1828 gen_reserved_instruction(ctx);
d046a9ea
DN
1829 }
1830}
1831
0b16dcd1 1832
7480515f
AM
1833/*
1834 * Define small wrappers for gen_load_fpr* so that we have a uniform
1835 * calling interface for 32 and 64-bit FPRs. No sense in changing
1836 * all callers for gen_load_fpr32 when we need the CTX parameter for
1837 * this one use.
1838 */
7c979afd 1839#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
1840#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1841#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1842static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1843 int ft, int fs, int cc) \
1844{ \
71375b59
AM
1845 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1846 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
1847 switch (ifmt) { \
1848 case FMT_PS: \
e29c9628 1849 check_ps(ctx); \
8153667c
NF
1850 break; \
1851 case FMT_D: \
1852 if (abs) { \
1853 check_cop1x(ctx); \
1854 } \
1855 check_cp1_registers(ctx, fs | ft); \
1856 break; \
1857 case FMT_S: \
1858 if (abs) { \
1859 check_cop1x(ctx); \
1860 } \
1861 break; \
1862 } \
71375b59
AM
1863 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1864 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 1865 switch (n) { \
1f8929d2
AM
1866 case 0: \
1867 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1868 break; \
1869 case 1: \
1870 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1871 break; \
1872 case 2: \
1873 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1874 break; \
1875 case 3: \
1876 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1877 break; \
1878 case 4: \
1879 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1880 break; \
1881 case 5: \
1882 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1883 break; \
1884 case 6: \
1885 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1886 break; \
1887 case 7: \
1888 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1889 break; \
1890 case 8: \
1891 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1892 break; \
1893 case 9: \
1894 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1895 break; \
1896 case 10: \
1897 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1898 break; \
1899 case 11: \
1900 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1901 break; \
1902 case 12: \
1903 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1904 break; \
1905 case 13: \
1906 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1907 break; \
1908 case 14: \
1909 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1910 break; \
1911 case 15: \
1912 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1913 break; \
1914 default: \
1915 abort(); \
8153667c 1916 } \
71375b59
AM
1917 tcg_temp_free_i##bits(fp0); \
1918 tcg_temp_free_i##bits(fp1); \
8153667c
NF
1919}
1920
1921FOP_CONDS(, 0, d, FMT_D, 64)
1922FOP_CONDS(abs, 1, d, FMT_D, 64)
1923FOP_CONDS(, 0, s, FMT_S, 32)
1924FOP_CONDS(abs, 1, s, FMT_S, 32)
1925FOP_CONDS(, 0, ps, FMT_PS, 64)
1926FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1927#undef FOP_CONDS
3f493883
YK
1928
1929#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 1930static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
1931 int ft, int fs, int fd) \
1932{ \
1933 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1934 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 1935 if (ifmt == FMT_D) { \
3f493883 1936 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
1937 } \
1938 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1939 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1940 switch (n) { \
1941 case 0: \
1942 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 1: \
1945 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 2: \
1948 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 3: \
1951 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 4: \
1954 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 5: \
1957 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 6: \
1960 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 7: \
1963 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 8: \
1966 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 9: \
1969 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 10: \
1972 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 11: \
1975 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 case 12: \
1978 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1979 break; \
1980 case 13: \
1981 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1982 break; \
1983 case 14: \
1984 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1985 break; \
1986 case 15: \
1987 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1988 break; \
1989 case 17: \
1990 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1991 break; \
1992 case 18: \
1993 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1994 break; \
1995 case 19: \
1996 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1997 break; \
1998 case 25: \
1999 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2000 break; \
2001 case 26: \
2002 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2003 break; \
2004 case 27: \
2005 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2006 break; \
2007 default: \
2008 abort(); \
2009 } \
2010 STORE; \
71375b59
AM
2011 tcg_temp_free_i ## bits(fp0); \
2012 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
2013}
2014
2015FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 2016FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 2017#undef FOP_CONDNS
8153667c
NF
2018#undef gen_ldcmp_fpr32
2019#undef gen_ldcmp_fpr64
2020
958fb4a9 2021/* load/store instructions. */
e7139c44 2022#ifdef CONFIG_USER_ONLY
71375b59 2023#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
2024static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2025 DisasContext *ctx) \
d9bea114
AJ
2026{ \
2027 TCGv t0 = tcg_temp_new(); \
2028 tcg_gen_mov_tl(t0, arg1); \
2029 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
2030 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2031 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 2032 tcg_temp_free(t0); \
aaa9128a 2033}
e7139c44 2034#else
71375b59 2035#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
2036static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2037 DisasContext *ctx) \
e7139c44 2038{ \
dd4096cd 2039 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
2040}
2041#endif
71375b59 2042OP_LD_ATOMIC(ll, ld32s);
aaa9128a 2043#if defined(TARGET_MIPS64)
71375b59 2044OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
2045#endif
2046#undef OP_LD_ATOMIC
2047
46c9e2b3 2048void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
662d7485
NF
2049{
2050 if (base == 0) {
2051 tcg_gen_movi_tl(addr, offset);
2052 } else if (offset == 0) {
2053 gen_load_gpr(addr, base);
2054 } else {
2055 tcg_gen_movi_tl(addr, offset);
2056 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2057 }
2058}
2059
235785e8 2060static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 2061{
eeb3bba8 2062 target_ulong pc = ctx->base.pc_next;
364d4831
NF
2063
2064 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2065 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2066
2067 pc -= branch_bytes;
2068 }
2069
2070 pc &= ~(target_ulong)3;
2071 return pc;
2072}
2073
5c13fdfd 2074/* Load */
d75c135e 2075static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 2076 int rt, int base, int offset)
6af0bf9c 2077{
fc40787a 2078 TCGv t0, t1, t2;
dd4096cd 2079 int mem_idx = ctx->mem_idx;
afa88c3a 2080
8e2d5831
JY
2081 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2082 INSN_LOONGSON3A)) {
7480515f
AM
2083 /*
2084 * Loongson CPU uses a load to zero register for prefetch.
2085 * We emulate it as a NOP. On other CPU we must perform the
2086 * actual memory access.
2087 */
afa88c3a
AJ
2088 return;
2089 }
6af0bf9c 2090
afa88c3a 2091 t0 = tcg_temp_new();
662d7485 2092 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 2093
6af0bf9c 2094 switch (opc) {
d26bc211 2095#if defined(TARGET_MIPS64)
6e473128 2096 case OPC_LWU:
dd4096cd 2097 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 2098 ctx->default_tcg_memop_mask);
78723684 2099 gen_store_gpr(t0, rt);
6e473128 2100 break;
6af0bf9c 2101 case OPC_LD:
dd4096cd 2102 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 2103 ctx->default_tcg_memop_mask);
78723684 2104 gen_store_gpr(t0, rt);
6af0bf9c 2105 break;
7a387fff 2106 case OPC_LLD:
bf7910c6 2107 case R6_OPC_LLD:
dd4096cd 2108 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 2109 gen_store_gpr(t0, rt);
7a387fff 2110 break;
6af0bf9c 2111 case OPC_LDL:
3cee3050 2112 t1 = tcg_temp_new();
7480515f
AM
2113 /*
2114 * Do a byte access to possibly trigger a page
2115 * fault with the unaligned address.
2116 */
dd4096cd 2117 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2118 tcg_gen_andi_tl(t1, t0, 7);
2119#ifndef TARGET_WORDS_BIGENDIAN
2120 tcg_gen_xori_tl(t1, t1, 7);
2121#endif
2122 tcg_gen_shli_tl(t1, t1, 3);
2123 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2124 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 2125 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2126 t2 = tcg_const_tl(-1);
2127 tcg_gen_shl_tl(t2, t2, t1);
78723684 2128 gen_load_gpr(t1, rt);
eb02cc3f 2129 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2130 tcg_temp_free(t2);
2131 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2132 tcg_temp_free(t1);
fc40787a 2133 gen_store_gpr(t0, rt);
6af0bf9c 2134 break;
6af0bf9c 2135 case OPC_LDR:
3cee3050 2136 t1 = tcg_temp_new();
7480515f
AM
2137 /*
2138 * Do a byte access to possibly trigger a page
2139 * fault with the unaligned address.
2140 */
dd4096cd 2141 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2142 tcg_gen_andi_tl(t1, t0, 7);
2143#ifdef TARGET_WORDS_BIGENDIAN
2144 tcg_gen_xori_tl(t1, t1, 7);
2145#endif
2146 tcg_gen_shli_tl(t1, t1, 3);
2147 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2148 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
2149 tcg_gen_shr_tl(t0, t0, t1);
2150 tcg_gen_xori_tl(t1, t1, 63);
2151 t2 = tcg_const_tl(0xfffffffffffffffeull);
2152 tcg_gen_shl_tl(t2, t2, t1);
78723684 2153 gen_load_gpr(t1, rt);
fc40787a
AJ
2154 tcg_gen_and_tl(t1, t1, t2);
2155 tcg_temp_free(t2);
2156 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2157 tcg_temp_free(t1);
fc40787a 2158 gen_store_gpr(t0, rt);
6af0bf9c 2159 break;
364d4831 2160 case OPC_LDPC:
3cee3050 2161 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2162 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2163 tcg_temp_free(t1);
dd4096cd 2164 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
2165 gen_store_gpr(t0, rt);
2166 break;
6af0bf9c 2167#endif
364d4831 2168 case OPC_LWPC:
3cee3050 2169 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2170 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2171 tcg_temp_free(t1);
dd4096cd 2172 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
2173 gen_store_gpr(t0, rt);
2174 break;
76964147
JH
2175 case OPC_LWE:
2176 mem_idx = MIPS_HFLAG_UM;
2177 /* fall through */
6af0bf9c 2178 case OPC_LW:
dd4096cd 2179 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 2180 ctx->default_tcg_memop_mask);
78723684 2181 gen_store_gpr(t0, rt);
6af0bf9c 2182 break;
76964147
JH
2183 case OPC_LHE:
2184 mem_idx = MIPS_HFLAG_UM;
2185 /* fall through */
6af0bf9c 2186 case OPC_LH:
dd4096cd 2187 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 2188 ctx->default_tcg_memop_mask);
78723684 2189 gen_store_gpr(t0, rt);
6af0bf9c 2190 break;
76964147
JH
2191 case OPC_LHUE:
2192 mem_idx = MIPS_HFLAG_UM;
2193 /* fall through */
6af0bf9c 2194 case OPC_LHU:
dd4096cd 2195 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 2196 ctx->default_tcg_memop_mask);
78723684 2197 gen_store_gpr(t0, rt);
6af0bf9c 2198 break;
76964147
JH
2199 case OPC_LBE:
2200 mem_idx = MIPS_HFLAG_UM;
2201 /* fall through */
6af0bf9c 2202 case OPC_LB:
dd4096cd 2203 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 2204 gen_store_gpr(t0, rt);
6af0bf9c 2205 break;
76964147
JH
2206 case OPC_LBUE:
2207 mem_idx = MIPS_HFLAG_UM;
2208 /* fall through */
6af0bf9c 2209 case OPC_LBU:
dd4096cd 2210 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 2211 gen_store_gpr(t0, rt);
6af0bf9c 2212 break;
76964147
JH
2213 case OPC_LWLE:
2214 mem_idx = MIPS_HFLAG_UM;
2215 /* fall through */
6af0bf9c 2216 case OPC_LWL:
3cee3050 2217 t1 = tcg_temp_new();
7480515f
AM
2218 /*
2219 * Do a byte access to possibly trigger a page
2220 * fault with the unaligned address.
2221 */
dd4096cd 2222 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2223 tcg_gen_andi_tl(t1, t0, 3);
2224#ifndef TARGET_WORDS_BIGENDIAN
2225 tcg_gen_xori_tl(t1, t1, 3);
2226#endif
2227 tcg_gen_shli_tl(t1, t1, 3);
2228 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2229 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 2230 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2231 t2 = tcg_const_tl(-1);
2232 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2233 gen_load_gpr(t1, rt);
eb02cc3f 2234 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2235 tcg_temp_free(t2);
2236 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2237 tcg_temp_free(t1);
fc40787a
AJ
2238 tcg_gen_ext32s_tl(t0, t0);
2239 gen_store_gpr(t0, rt);
6af0bf9c 2240 break;
76964147
JH
2241 case OPC_LWRE:
2242 mem_idx = MIPS_HFLAG_UM;
2243 /* fall through */
6af0bf9c 2244 case OPC_LWR:
3cee3050 2245 t1 = tcg_temp_new();
7480515f
AM
2246 /*
2247 * Do a byte access to possibly trigger a page
2248 * fault with the unaligned address.
2249 */
dd4096cd 2250 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2251 tcg_gen_andi_tl(t1, t0, 3);
2252#ifdef TARGET_WORDS_BIGENDIAN
2253 tcg_gen_xori_tl(t1, t1, 3);
2254#endif
2255 tcg_gen_shli_tl(t1, t1, 3);
2256 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2257 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
2258 tcg_gen_shr_tl(t0, t0, t1);
2259 tcg_gen_xori_tl(t1, t1, 31);
2260 t2 = tcg_const_tl(0xfffffffeull);
2261 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2262 gen_load_gpr(t1, rt);
fc40787a
AJ
2263 tcg_gen_and_tl(t1, t1, t2);
2264 tcg_temp_free(t2);
2265 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2266 tcg_temp_free(t1);
c728154b 2267 tcg_gen_ext32s_tl(t0, t0);
fc40787a 2268 gen_store_gpr(t0, rt);
6af0bf9c 2269 break;
76964147
JH
2270 case OPC_LLE:
2271 mem_idx = MIPS_HFLAG_UM;
2272 /* fall through */
6af0bf9c 2273 case OPC_LL:
4368b29a 2274 case R6_OPC_LL:
dd4096cd 2275 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 2276 gen_store_gpr(t0, rt);
6af0bf9c 2277 break;
d66c7132 2278 }
d66c7132 2279 tcg_temp_free(t0);
d66c7132
AJ
2280}
2281
0b16dcd1
AR
2282static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2283 uint32_t reg1, uint32_t reg2)
2284{
2285 TCGv taddr = tcg_temp_new();
2286 TCGv_i64 tval = tcg_temp_new_i64();
2287 TCGv tmp1 = tcg_temp_new();
2288 TCGv tmp2 = tcg_temp_new();
2289
2290 gen_base_offset_addr(ctx, taddr, base, offset);
2291 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2292#ifdef TARGET_WORDS_BIGENDIAN
2293 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2294#else
2295 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2296#endif
2297 gen_store_gpr(tmp1, reg1);
2298 tcg_temp_free(tmp1);
2299 gen_store_gpr(tmp2, reg2);
2300 tcg_temp_free(tmp2);
2301 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2302 tcg_temp_free_i64(tval);
2303 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2304 tcg_temp_free(taddr);
2305}
2306
5c13fdfd 2307/* Store */
235785e8
AM
2308static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2309 int base, int offset)
5c13fdfd 2310{
5c13fdfd
AJ
2311 TCGv t0 = tcg_temp_new();
2312 TCGv t1 = tcg_temp_new();
dd4096cd 2313 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
2314
2315 gen_base_offset_addr(ctx, t0, base, offset);
2316 gen_load_gpr(t1, rt);
2317 switch (opc) {
2318#if defined(TARGET_MIPS64)
2319 case OPC_SD:
dd4096cd 2320 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 2321 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
2322 break;
2323 case OPC_SDL:
dd4096cd 2324 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
2325 break;
2326 case OPC_SDR:
dd4096cd 2327 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
2328 break;
2329#endif
76964147
JH
2330 case OPC_SWE:
2331 mem_idx = MIPS_HFLAG_UM;
2332 /* fall through */
5c13fdfd 2333 case OPC_SW:
dd4096cd 2334 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 2335 ctx->default_tcg_memop_mask);
5c13fdfd 2336 break;
76964147
JH
2337 case OPC_SHE:
2338 mem_idx = MIPS_HFLAG_UM;
2339 /* fall through */
5c13fdfd 2340 case OPC_SH:
dd4096cd 2341 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 2342 ctx->default_tcg_memop_mask);
5c13fdfd 2343 break;
76964147
JH
2344 case OPC_SBE:
2345 mem_idx = MIPS_HFLAG_UM;
2346 /* fall through */
5c13fdfd 2347 case OPC_SB:
dd4096cd 2348 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 2349 break;
76964147
JH
2350 case OPC_SWLE:
2351 mem_idx = MIPS_HFLAG_UM;
2352 /* fall through */
5c13fdfd 2353 case OPC_SWL:
dd4096cd 2354 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 2355 break;
76964147
JH
2356 case OPC_SWRE:
2357 mem_idx = MIPS_HFLAG_UM;
2358 /* fall through */
5c13fdfd 2359 case OPC_SWR:
dd4096cd 2360 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
2361 break;
2362 }
5c13fdfd
AJ
2363 tcg_temp_free(t0);
2364 tcg_temp_free(t1);
2365}
2366
2367
d66c7132 2368/* Store conditional */
33a07fa2 2369static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 2370 MemOp tcg_mo, bool eva)
d66c7132 2371{
33a07fa2
LA
2372 TCGv addr, t0, val;
2373 TCGLabel *l1 = gen_new_label();
2374 TCGLabel *done = gen_new_label();
d66c7132 2375
2d2826b9 2376 t0 = tcg_temp_new();
33a07fa2 2377 addr = tcg_temp_new();
8cdf8869 2378 /* compare the address against that of the preceding LL */
33a07fa2
LA
2379 gen_base_offset_addr(ctx, addr, base, offset);
2380 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2381 tcg_temp_free(addr);
2382 tcg_gen_movi_tl(t0, 0);
2383 gen_store_gpr(t0, rt);
2384 tcg_gen_br(done);
2385
2386 gen_set_label(l1);
2387 /* generate cmpxchg */
2388 val = tcg_temp_new();
2389 gen_load_gpr(val, rt);
2390 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2391 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2392 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2393 gen_store_gpr(t0, rt);
2394 tcg_temp_free(val);
2395
2396 gen_set_label(done);
d66c7132 2397 tcg_temp_free(t0);
6af0bf9c
FB
2398}
2399
33a07fa2 2400
0b16dcd1 2401static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 2402 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
2403{
2404 TCGv taddr = tcg_temp_local_new();
2405 TCGv lladdr = tcg_temp_local_new();
2406 TCGv_i64 tval = tcg_temp_new_i64();
2407 TCGv_i64 llval = tcg_temp_new_i64();
2408 TCGv_i64 val = tcg_temp_new_i64();
2409 TCGv tmp1 = tcg_temp_new();
2410 TCGv tmp2 = tcg_temp_new();
2411 TCGLabel *lab_fail = gen_new_label();
2412 TCGLabel *lab_done = gen_new_label();
2413
2414 gen_base_offset_addr(ctx, taddr, base, offset);
2415
2416 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2417 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2418
2419 gen_load_gpr(tmp1, reg1);
2420 gen_load_gpr(tmp2, reg2);
2421
2422#ifdef TARGET_WORDS_BIGENDIAN
2423 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2424#else
2425 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2426#endif
2427
2428 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2429 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 2430 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
2431 if (reg1 != 0) {
2432 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2433 }
2434 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2435
2436 gen_set_label(lab_fail);
2437
2438 if (reg1 != 0) {
2439 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2440 }
2441 gen_set_label(lab_done);
2442 tcg_gen_movi_tl(lladdr, -1);
2443 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2444}
2445
6ea83fed 2446/* Load and store */
235785e8
AM
2447static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2448 TCGv t0)
6ea83fed 2449{
7480515f
AM
2450 /*
2451 * Don't do NOP if destination is zero: we must perform the actual
2452 * memory access.
2453 */
6ea83fed
FB
2454 switch (opc) {
2455 case OPC_LWC1:
b6d96bed 2456 {
a7812ae4 2457 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
2458 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2459 ctx->default_tcg_memop_mask);
7c979afd 2460 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 2461 tcg_temp_free_i32(fp0);
b6d96bed 2462 }
6ea83fed
FB
2463 break;
2464 case OPC_SWC1:
b6d96bed 2465 {
a7812ae4 2466 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 2467 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
2468 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2469 ctx->default_tcg_memop_mask);
a7812ae4 2470 tcg_temp_free_i32(fp0);
b6d96bed 2471 }
6ea83fed
FB
2472 break;
2473 case OPC_LDC1:
b6d96bed 2474 {
a7812ae4 2475 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
2476 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2477 ctx->default_tcg_memop_mask);
b6d96bed 2478 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 2479 tcg_temp_free_i64(fp0);
b6d96bed 2480 }
6ea83fed
FB
2481 break;
2482 case OPC_SDC1:
b6d96bed 2483 {
a7812ae4 2484 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2485 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
2486 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2487 ctx->default_tcg_memop_mask);
a7812ae4 2488 tcg_temp_free_i64(fp0);
b6d96bed 2489 }
6ea83fed
FB
2490 break;
2491 default:
9d68ac14 2492 MIPS_INVAL("flt_ldst");
3a4ef3b7 2493 gen_reserved_instruction(ctx);
b52d3bfa 2494 break;
6ea83fed 2495 }
6ea83fed 2496}
6ea83fed 2497
5ab5c041
AJ
2498static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2499 int rs, int16_t imm)
26ebe468 2500{
b52d3bfa
YK
2501 TCGv t0 = tcg_temp_new();
2502
5ab5c041 2503 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 2504 check_cp1_enabled(ctx);
d9224450
MR
2505 switch (op) {
2506 case OPC_LDC1:
2507 case OPC_SDC1:
2508 check_insn(ctx, ISA_MIPS2);
2509 /* Fallthrough */
2510 default:
b52d3bfa
YK
2511 gen_base_offset_addr(ctx, t0, rs, imm);
2512 gen_flt_ldst(ctx, op, rt, t0);
d9224450 2513 }
26ebe468
NF
2514 } else {
2515 generate_exception_err(ctx, EXCP_CpU, 1);
2516 }
b52d3bfa 2517 tcg_temp_free(t0);
26ebe468
NF
2518}
2519
6af0bf9c 2520/* Arithmetic with immediate operand */
d75c135e 2521static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 2522 int rt, int rs, int imm)
6af0bf9c 2523{
324d9e32 2524 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 2525
7a387fff 2526 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
2527 /*
2528 * If no destination, treat it as a NOP.
2529 * For addi, we must generate the overflow exception when needed.
2530 */
324d9e32 2531 return;
6af0bf9c
FB
2532 }
2533 switch (opc) {
2534 case OPC_ADDI:
48d38ca5 2535 {
324d9e32
AJ
2536 TCGv t0 = tcg_temp_local_new();
2537 TCGv t1 = tcg_temp_new();
2538 TCGv t2 = tcg_temp_new();
42a268c2 2539 TCGLabel *l1 = gen_new_label();
48d38ca5 2540
324d9e32
AJ
2541 gen_load_gpr(t1, rs);
2542 tcg_gen_addi_tl(t0, t1, uimm);
2543 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2544
324d9e32
AJ
2545 tcg_gen_xori_tl(t1, t1, ~uimm);
2546 tcg_gen_xori_tl(t2, t0, uimm);
2547 tcg_gen_and_tl(t1, t1, t2);
2548 tcg_temp_free(t2);
2549 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2550 tcg_temp_free(t1);
48d38ca5
TS
2551 /* operands of same sign, result different sign */
2552 generate_exception(ctx, EXCP_OVERFLOW);
2553 gen_set_label(l1);
78723684 2554 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
2555 gen_store_gpr(t0, rt);
2556 tcg_temp_free(t0);
48d38ca5 2557 }
6af0bf9c
FB
2558 break;
2559 case OPC_ADDIU:
324d9e32
AJ
2560 if (rs != 0) {
2561 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2562 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2563 } else {
2564 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2565 }
6af0bf9c 2566 break;
d26bc211 2567#if defined(TARGET_MIPS64)
7a387fff 2568 case OPC_DADDI:
48d38ca5 2569 {
324d9e32
AJ
2570 TCGv t0 = tcg_temp_local_new();
2571 TCGv t1 = tcg_temp_new();
2572 TCGv t2 = tcg_temp_new();
42a268c2 2573 TCGLabel *l1 = gen_new_label();
48d38ca5 2574
324d9e32
AJ
2575 gen_load_gpr(t1, rs);
2576 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2577
324d9e32
AJ
2578 tcg_gen_xori_tl(t1, t1, ~uimm);
2579 tcg_gen_xori_tl(t2, t0, uimm);
2580 tcg_gen_and_tl(t1, t1, t2);
2581 tcg_temp_free(t2);
2582 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2583 tcg_temp_free(t1);
48d38ca5
TS
2584 /* operands of same sign, result different sign */
2585 generate_exception(ctx, EXCP_OVERFLOW);
2586 gen_set_label(l1);
324d9e32
AJ
2587 gen_store_gpr(t0, rt);
2588 tcg_temp_free(t0);
48d38ca5 2589 }
7a387fff
TS
2590 break;
2591 case OPC_DADDIU:
324d9e32
AJ
2592 if (rs != 0) {
2593 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2594 } else {
2595 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2596 }
7a387fff
TS
2597 break;
2598#endif
324d9e32 2599 }
324d9e32
AJ
2600}
2601
2602/* Logic with immediate operand */
d75c135e 2603static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2604 int rt, int rs, int16_t imm)
324d9e32
AJ
2605{
2606 target_ulong uimm;
324d9e32
AJ
2607
2608 if (rt == 0) {
2609 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2610 return;
2611 }
2612 uimm = (uint16_t)imm;
2613 switch (opc) {
6af0bf9c 2614 case OPC_ANDI:
1f8929d2 2615 if (likely(rs != 0)) {
324d9e32 2616 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2617 } else {
324d9e32 2618 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 2619 }
6af0bf9c
FB
2620 break;
2621 case OPC_ORI:
1f8929d2 2622 if (rs != 0) {
324d9e32 2623 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2624 } else {
324d9e32 2625 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2626 }
6af0bf9c
FB
2627 break;
2628 case OPC_XORI:
1f8929d2 2629 if (likely(rs != 0)) {
324d9e32 2630 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2631 } else {
324d9e32 2632 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2633 }
6af0bf9c
FB
2634 break;
2635 case OPC_LUI:
2e211e0a 2636 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
d4ea6acd
LA
2637 /* OPC_AUI */
2638 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2639 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
2640 } else {
2641 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 2642 }
7c2c3ea3
EJ
2643 break;
2644
2645 default:
6af0bf9c 2646 break;
324d9e32 2647 }
324d9e32
AJ
2648}
2649
2650/* Set on less than with immediate operand */
d75c135e 2651static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2652 int rt, int rs, int16_t imm)
324d9e32
AJ
2653{
2654 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
2655 TCGv t0;
2656
2657 if (rt == 0) {
2658 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2659 return;
2660 }
2661 t0 = tcg_temp_new();
2662 gen_load_gpr(t0, rs);
2663 switch (opc) {
2664 case OPC_SLTI:
e68dd28f 2665 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2666 break;
2667 case OPC_SLTIU:
e68dd28f 2668 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2669 break;
2670 }
324d9e32
AJ
2671 tcg_temp_free(t0);
2672}
2673
2674/* Shifts with immediate operand */
d75c135e 2675static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
2676 int rt, int rs, int16_t imm)
2677{
2678 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
2679 TCGv t0;
2680
2681 if (rt == 0) {
2682 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2683 return;
2684 }
2685
2686 t0 = tcg_temp_new();
2687 gen_load_gpr(t0, rs);
2688 switch (opc) {
6af0bf9c 2689 case OPC_SLL:
78723684 2690 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 2691 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
2692 break;
2693 case OPC_SRA:
324d9e32 2694 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
2695 break;
2696 case OPC_SRL:
ea63e2c3
NF
2697 if (uimm != 0) {
2698 tcg_gen_ext32u_tl(t0, t0);
2699 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2700 } else {
2701 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 2702 }
ea63e2c3
NF
2703 break;
2704 case OPC_ROTR:
2705 if (uimm != 0) {
2706 TCGv_i32 t1 = tcg_temp_new_i32();
2707
2708 tcg_gen_trunc_tl_i32(t1, t0);
2709 tcg_gen_rotri_i32(t1, t1, uimm);
2710 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2711 tcg_temp_free_i32(t1);
3399e30f
NF
2712 } else {
2713 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 2714 }
7a387fff 2715 break;
d26bc211 2716#if defined(TARGET_MIPS64)
7a387fff 2717 case OPC_DSLL:
324d9e32 2718 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2719 break;
2720 case OPC_DSRA:
324d9e32 2721 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2722 break;
2723 case OPC_DSRL:
ea63e2c3 2724 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
2725 break;
2726 case OPC_DROTR:
2727 if (uimm != 0) {
2728 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2729 } else {
2730 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2731 }
7a387fff
TS
2732 break;
2733 case OPC_DSLL32:
324d9e32 2734 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2735 break;
2736 case OPC_DSRA32:
324d9e32 2737 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2738 break;
2739 case OPC_DSRL32:
ea63e2c3 2740 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
2741 break;
2742 case OPC_DROTR32:
2743 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 2744 break;
7a387fff 2745#endif
6af0bf9c 2746 }
78723684 2747 tcg_temp_free(t0);
6af0bf9c
FB
2748}
2749
2750/* Arithmetic */
d75c135e
AJ
2751static void gen_arith(DisasContext *ctx, uint32_t opc,
2752 int rd, int rs, int rt)
6af0bf9c 2753{
7a387fff
TS
2754 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2755 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
2756 /*
2757 * If no destination, treat it as a NOP.
2758 * For add & sub, we must generate the overflow exception when needed.
2759 */
460f00c4 2760 return;
185f0762 2761 }
460f00c4 2762
6af0bf9c
FB
2763 switch (opc) {
2764 case OPC_ADD:
48d38ca5 2765 {
460f00c4
AJ
2766 TCGv t0 = tcg_temp_local_new();
2767 TCGv t1 = tcg_temp_new();
2768 TCGv t2 = tcg_temp_new();
42a268c2 2769 TCGLabel *l1 = gen_new_label();
48d38ca5 2770
460f00c4
AJ
2771 gen_load_gpr(t1, rs);
2772 gen_load_gpr(t2, rt);
2773 tcg_gen_add_tl(t0, t1, t2);
2774 tcg_gen_ext32s_tl(t0, t0);
2775 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2776 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2777 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2778 tcg_temp_free(t2);
2779 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2780 tcg_temp_free(t1);
48d38ca5
TS
2781 /* operands of same sign, result different sign */
2782 generate_exception(ctx, EXCP_OVERFLOW);
2783 gen_set_label(l1);
460f00c4
AJ
2784 gen_store_gpr(t0, rd);
2785 tcg_temp_free(t0);
48d38ca5 2786 }
6af0bf9c
FB
2787 break;
2788 case OPC_ADDU:
460f00c4
AJ
2789 if (rs != 0 && rt != 0) {
2790 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2791 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2792 } else if (rs == 0 && rt != 0) {
2793 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2794 } else if (rs != 0 && rt == 0) {
2795 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2796 } else {
2797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2798 }
6af0bf9c
FB
2799 break;
2800 case OPC_SUB:
48d38ca5 2801 {
460f00c4
AJ
2802 TCGv t0 = tcg_temp_local_new();
2803 TCGv t1 = tcg_temp_new();
2804 TCGv t2 = tcg_temp_new();
42a268c2 2805 TCGLabel *l1 = gen_new_label();
48d38ca5 2806
460f00c4
AJ
2807 gen_load_gpr(t1, rs);
2808 gen_load_gpr(t2, rt);
2809 tcg_gen_sub_tl(t0, t1, t2);
2810 tcg_gen_ext32s_tl(t0, t0);
2811 tcg_gen_xor_tl(t2, t1, t2);
2812 tcg_gen_xor_tl(t1, t0, t1);
2813 tcg_gen_and_tl(t1, t1, t2);
2814 tcg_temp_free(t2);
2815 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2816 tcg_temp_free(t1);
7480515f
AM
2817 /*
2818 * operands of different sign, first operand and the result
2819 * of different sign
2820 */
48d38ca5
TS
2821 generate_exception(ctx, EXCP_OVERFLOW);
2822 gen_set_label(l1);
460f00c4
AJ
2823 gen_store_gpr(t0, rd);
2824 tcg_temp_free(t0);
48d38ca5 2825 }
6af0bf9c
FB
2826 break;
2827 case OPC_SUBU:
460f00c4
AJ
2828 if (rs != 0 && rt != 0) {
2829 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2830 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2831 } else if (rs == 0 && rt != 0) {
2832 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2833 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2834 } else if (rs != 0 && rt == 0) {
2835 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2836 } else {
2837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2838 }
6af0bf9c 2839 break;
d26bc211 2840#if defined(TARGET_MIPS64)
7a387fff 2841 case OPC_DADD:
48d38ca5 2842 {
460f00c4
AJ
2843 TCGv t0 = tcg_temp_local_new();
2844 TCGv t1 = tcg_temp_new();
2845 TCGv t2 = tcg_temp_new();
42a268c2 2846 TCGLabel *l1 = gen_new_label();
48d38ca5 2847
460f00c4
AJ
2848 gen_load_gpr(t1, rs);
2849 gen_load_gpr(t2, rt);
2850 tcg_gen_add_tl(t0, t1, t2);
2851 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2852 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2853 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2854 tcg_temp_free(t2);
2855 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2856 tcg_temp_free(t1);
48d38ca5
TS
2857 /* operands of same sign, result different sign */
2858 generate_exception(ctx, EXCP_OVERFLOW);
2859 gen_set_label(l1);
460f00c4
AJ
2860 gen_store_gpr(t0, rd);
2861 tcg_temp_free(t0);
48d38ca5 2862 }
7a387fff
TS
2863 break;
2864 case OPC_DADDU:
460f00c4
AJ
2865 if (rs != 0 && rt != 0) {
2866 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2867 } else if (rs == 0 && rt != 0) {
2868 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2869 } else if (rs != 0 && rt == 0) {
2870 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2871 } else {
2872 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2873 }
7a387fff
TS
2874 break;
2875 case OPC_DSUB:
48d38ca5 2876 {
460f00c4
AJ
2877 TCGv t0 = tcg_temp_local_new();
2878 TCGv t1 = tcg_temp_new();
2879 TCGv t2 = tcg_temp_new();
42a268c2 2880 TCGLabel *l1 = gen_new_label();
48d38ca5 2881
460f00c4
AJ
2882 gen_load_gpr(t1, rs);
2883 gen_load_gpr(t2, rt);
2884 tcg_gen_sub_tl(t0, t1, t2);
2885 tcg_gen_xor_tl(t2, t1, t2);
2886 tcg_gen_xor_tl(t1, t0, t1);
2887 tcg_gen_and_tl(t1, t1, t2);
2888 tcg_temp_free(t2);
2889 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2890 tcg_temp_free(t1);
71375b59
AM
2891 /*
2892 * Operands of different sign, first operand and result different
2893 * sign.
2894 */
48d38ca5
TS
2895 generate_exception(ctx, EXCP_OVERFLOW);
2896 gen_set_label(l1);
460f00c4
AJ
2897 gen_store_gpr(t0, rd);
2898 tcg_temp_free(t0);
48d38ca5 2899 }
7a387fff
TS
2900 break;
2901 case OPC_DSUBU:
460f00c4
AJ
2902 if (rs != 0 && rt != 0) {
2903 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2904 } else if (rs == 0 && rt != 0) {
2905 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2906 } else if (rs != 0 && rt == 0) {
2907 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2908 } else {
2909 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2910 }
7a387fff
TS
2911 break;
2912#endif
460f00c4
AJ
2913 case OPC_MUL:
2914 if (likely(rs != 0 && rt != 0)) {
2915 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2916 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2917 } else {
2918 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2919 }
6af0bf9c 2920 break;
460f00c4 2921 }
460f00c4
AJ
2922}
2923
2924/* Conditional move */
d75c135e 2925static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 2926 int rd, int rs, int rt)
460f00c4 2927{
acf12465 2928 TCGv t0, t1, t2;
460f00c4
AJ
2929
2930 if (rd == 0) {
acf12465 2931 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2932 return;
2933 }
2934
acf12465
AJ
2935 t0 = tcg_temp_new();
2936 gen_load_gpr(t0, rt);
2937 t1 = tcg_const_tl(0);
2938 t2 = tcg_temp_new();
2939 gen_load_gpr(t2, rs);
460f00c4
AJ
2940 switch (opc) {
2941 case OPC_MOVN:
acf12465 2942 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 2943 break;
460f00c4 2944 case OPC_MOVZ:
acf12465 2945 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 2946 break;
b691d9d2
LA
2947 case OPC_SELNEZ:
2948 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
2949 break;
2950 case OPC_SELEQZ:
2951 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 2952 break;
460f00c4 2953 }
acf12465
AJ
2954 tcg_temp_free(t2);
2955 tcg_temp_free(t1);
2956 tcg_temp_free(t0);
460f00c4
AJ
2957}
2958
2959/* Logic */
d75c135e 2960static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 2961 int rd, int rs, int rt)
460f00c4 2962{
460f00c4
AJ
2963 if (rd == 0) {
2964 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2965 return;
2966 }
2967
2968 switch (opc) {
6af0bf9c 2969 case OPC_AND:
460f00c4
AJ
2970 if (likely(rs != 0 && rt != 0)) {
2971 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2972 } else {
2973 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2974 }
6af0bf9c
FB
2975 break;
2976 case OPC_NOR:
460f00c4
AJ
2977 if (rs != 0 && rt != 0) {
2978 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2979 } else if (rs == 0 && rt != 0) {
2980 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2981 } else if (rs != 0 && rt == 0) {
2982 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2983 } else {
2984 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2985 }
6af0bf9c
FB
2986 break;
2987 case OPC_OR:
460f00c4
AJ
2988 if (likely(rs != 0 && rt != 0)) {
2989 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2990 } else if (rs == 0 && rt != 0) {
2991 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2992 } else if (rs != 0 && rt == 0) {
2993 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2994 } else {
2995 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2996 }
6af0bf9c
FB
2997 break;
2998 case OPC_XOR:
460f00c4
AJ
2999 if (likely(rs != 0 && rt != 0)) {
3000 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3001 } else if (rs == 0 && rt != 0) {
3002 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3003 } else if (rs != 0 && rt == 0) {
3004 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3005 } else {
3006 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3007 }
6af0bf9c 3008 break;
460f00c4 3009 }
460f00c4
AJ
3010}
3011
3012/* Set on lower than */
d75c135e 3013static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 3014 int rd, int rs, int rt)
460f00c4 3015{
460f00c4
AJ
3016 TCGv t0, t1;
3017
3018 if (rd == 0) {
3019 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3020 return;
3021 }
3022
3023 t0 = tcg_temp_new();
3024 t1 = tcg_temp_new();
3025 gen_load_gpr(t0, rs);
3026 gen_load_gpr(t1, rt);
3027 switch (opc) {
3028 case OPC_SLT:
e68dd28f 3029 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 3030 break;
460f00c4 3031 case OPC_SLTU:
e68dd28f 3032 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
3033 break;
3034 }
460f00c4
AJ
3035 tcg_temp_free(t0);
3036 tcg_temp_free(t1);
3037}
20c4c97c 3038
460f00c4 3039/* Shifts */
d75c135e
AJ
3040static void gen_shift(DisasContext *ctx, uint32_t opc,
3041 int rd, int rs, int rt)
460f00c4 3042{
460f00c4 3043 TCGv t0, t1;
20c4c97c 3044
460f00c4 3045 if (rd == 0) {
7480515f
AM
3046 /*
3047 * If no destination, treat it as a NOP.
3048 * For add & sub, we must generate the overflow exception when needed.
3049 */
460f00c4
AJ
3050 return;
3051 }
3052
3053 t0 = tcg_temp_new();
3054 t1 = tcg_temp_new();
3055 gen_load_gpr(t0, rs);
3056 gen_load_gpr(t1, rt);
3057 switch (opc) {
6af0bf9c 3058 case OPC_SLLV:
78723684
TS
3059 tcg_gen_andi_tl(t0, t0, 0x1f);
3060 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 3061 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
3062 break;
3063 case OPC_SRAV:
78723684 3064 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 3065 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
3066 break;
3067 case OPC_SRLV:
ea63e2c3
NF
3068 tcg_gen_ext32u_tl(t1, t1);
3069 tcg_gen_andi_tl(t0, t0, 0x1f);
3070 tcg_gen_shr_tl(t0, t1, t0);
3071 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
3072 break;
3073 case OPC_ROTRV:
3074 {
3075 TCGv_i32 t2 = tcg_temp_new_i32();
3076 TCGv_i32 t3 = tcg_temp_new_i32();
3077
3078 tcg_gen_trunc_tl_i32(t2, t0);
3079 tcg_gen_trunc_tl_i32(t3, t1);
3080 tcg_gen_andi_i32(t2, t2, 0x1f);
3081 tcg_gen_rotr_i32(t2, t3, t2);
3082 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3083 tcg_temp_free_i32(t2);
3084 tcg_temp_free_i32(t3);
5a63bcb2 3085 }
7a387fff 3086 break;
d26bc211 3087#if defined(TARGET_MIPS64)
7a387fff 3088 case OPC_DSLLV:
78723684 3089 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3090 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3091 break;
3092 case OPC_DSRAV:
78723684 3093 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3094 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3095 break;
3096 case OPC_DSRLV:
ea63e2c3
NF
3097 tcg_gen_andi_tl(t0, t0, 0x3f);
3098 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
3099 break;
3100 case OPC_DROTRV:
3101 tcg_gen_andi_tl(t0, t0, 0x3f);
3102 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 3103 break;
7a387fff 3104#endif
6af0bf9c 3105 }
78723684
TS
3106 tcg_temp_free(t0);
3107 tcg_temp_free(t1);
6af0bf9c
FB
3108}
3109
3110/* Arithmetic on HI/LO registers */
26135ead 3111static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 3112{
86efbfb6 3113 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 3114 /* Treat as NOP. */
a1f6684d 3115 return;
6af0bf9c 3116 }
4133498f 3117
4133498f 3118 if (acc != 0) {
86efbfb6 3119 check_dsp(ctx);
4133498f
JL
3120 }
3121
6af0bf9c
FB
3122 switch (opc) {
3123 case OPC_MFHI:
4133498f
JL
3124#if defined(TARGET_MIPS64)
3125 if (acc != 0) {
3126 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3127 } else
3128#endif
3129 {
3130 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3131 }
6af0bf9c
FB
3132 break;
3133 case OPC_MFLO:
4133498f
JL
3134#if defined(TARGET_MIPS64)
3135 if (acc != 0) {
3136 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3137 } else
3138#endif
3139 {
3140 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3141 }
6af0bf9c
FB
3142 break;
3143 case OPC_MTHI:
4133498f
JL
3144 if (reg != 0) {
3145#if defined(TARGET_MIPS64)
3146 if (acc != 0) {
3147 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3148 } else
3149#endif
3150 {
3151 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3152 }
3153 } else {
3154 tcg_gen_movi_tl(cpu_HI[acc], 0);
3155 }
6af0bf9c
FB
3156 break;
3157 case OPC_MTLO:
4133498f
JL
3158 if (reg != 0) {
3159#if defined(TARGET_MIPS64)
3160 if (acc != 0) {
3161 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3162 } else
3163#endif
3164 {
3165 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3166 }
3167 } else {
3168 tcg_gen_movi_tl(cpu_LO[acc], 0);
3169 }
6af0bf9c 3170 break;
6af0bf9c 3171 }
6af0bf9c
FB
3172}
3173
d4ea6acd 3174static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 3175 MemOp memop)
d4ea6acd
LA
3176{
3177 TCGv t0 = tcg_const_tl(addr);
3178 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3179 gen_store_gpr(t0, reg);
3180 tcg_temp_free(t0);
3181}
3182
ab39ee45
YK
3183static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3184 int rs)
d4ea6acd
LA
3185{
3186 target_long offset;
3187 target_long addr;
3188
ab39ee45 3189 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
3190 case OPC_ADDIUPC:
3191 if (rs != 0) {
3192 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3193 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3194 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3195 }
3196 break;
3197 case R6_OPC_LWPC:
3198 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3199 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3200 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3201 break;
3202#if defined(TARGET_MIPS64)
3203 case OPC_LWUPC:
3204 check_mips_64(ctx);
3205 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3206 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3207 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3208 break;
3209#endif
3210 default:
ab39ee45 3211 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
3212 case OPC_AUIPC:
3213 if (rs != 0) {
ab39ee45
YK
3214 offset = sextract32(ctx->opcode, 0, 16) << 16;
3215 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3216 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3217 }
3218 break;
3219 case OPC_ALUIPC:
3220 if (rs != 0) {
ab39ee45
YK
3221 offset = sextract32(ctx->opcode, 0, 16) << 16;
3222 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
3223 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3224 }
3225 break;
3226#if defined(TARGET_MIPS64)
3227 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3228 case R6_OPC_LDPC + (1 << 16):
3229 case R6_OPC_LDPC + (2 << 16):
3230 case R6_OPC_LDPC + (3 << 16):
3231 check_mips_64(ctx);
3232 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 3233 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
3234 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3235 break;
3236#endif
3237 default:
3238 MIPS_INVAL("OPC_PCREL");
3a4ef3b7 3239 gen_reserved_instruction(ctx);
d4ea6acd
LA
3240 break;
3241 }
3242 break;
3243 }
3244}
3245
b42ee5e1
LA
3246static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3247{
b42ee5e1
LA
3248 TCGv t0, t1;
3249
3250 if (rd == 0) {
3251 /* Treat as NOP. */
b42ee5e1
LA
3252 return;
3253 }
3254
3255 t0 = tcg_temp_new();
3256 t1 = tcg_temp_new();
3257
3258 gen_load_gpr(t0, rs);
3259 gen_load_gpr(t1, rt);
3260
3261 switch (opc) {
3262 case R6_OPC_DIV:
3263 {
3264 TCGv t2 = tcg_temp_new();
3265 TCGv t3 = tcg_temp_new();
3266 tcg_gen_ext32s_tl(t0, t0);
3267 tcg_gen_ext32s_tl(t1, t1);
3268 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3269 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3270 tcg_gen_and_tl(t2, t2, t3);
3271 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3272 tcg_gen_or_tl(t2, t2, t3);
3273 tcg_gen_movi_tl(t3, 0);
3274 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3275 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3276 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3277 tcg_temp_free(t3);
3278 tcg_temp_free(t2);
3279 }
b42ee5e1
LA
3280 break;
3281 case R6_OPC_MOD:
3282 {
3283 TCGv t2 = tcg_temp_new();
3284 TCGv t3 = tcg_temp_new();
3285 tcg_gen_ext32s_tl(t0, t0);
3286 tcg_gen_ext32s_tl(t1, t1);
3287 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3288 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3289 tcg_gen_and_tl(t2, t2, t3);
3290 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3291 tcg_gen_or_tl(t2, t2, t3);
3292 tcg_gen_movi_tl(t3, 0);
3293 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3294 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3295 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3296 tcg_temp_free(t3);
3297 tcg_temp_free(t2);
3298 }
b42ee5e1
LA
3299 break;
3300 case R6_OPC_DIVU:
3301 {
3302 TCGv t2 = tcg_const_tl(0);
3303 TCGv t3 = tcg_const_tl(1);
3304 tcg_gen_ext32u_tl(t0, t0);
3305 tcg_gen_ext32u_tl(t1, t1);
3306 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3307 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3308 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3309 tcg_temp_free(t3);
3310 tcg_temp_free(t2);
3311 }
b42ee5e1
LA
3312 break;
3313 case R6_OPC_MODU:
3314 {
3315 TCGv t2 = tcg_const_tl(0);
3316 TCGv t3 = tcg_const_tl(1);
3317 tcg_gen_ext32u_tl(t0, t0);
3318 tcg_gen_ext32u_tl(t1, t1);
3319 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3320 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3321 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3322 tcg_temp_free(t3);
3323 tcg_temp_free(t2);
3324 }
b42ee5e1
LA
3325 break;
3326 case R6_OPC_MUL:
3327 {
3328 TCGv_i32 t2 = tcg_temp_new_i32();
3329 TCGv_i32 t3 = tcg_temp_new_i32();
3330 tcg_gen_trunc_tl_i32(t2, t0);
3331 tcg_gen_trunc_tl_i32(t3, t1);
3332 tcg_gen_mul_i32(t2, t2, t3);
3333 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3334 tcg_temp_free_i32(t2);
3335 tcg_temp_free_i32(t3);
3336 }
b42ee5e1
LA
3337 break;
3338 case R6_OPC_MUH:
3339 {
3340 TCGv_i32 t2 = tcg_temp_new_i32();
3341 TCGv_i32 t3 = tcg_temp_new_i32();
3342 tcg_gen_trunc_tl_i32(t2, t0);
3343 tcg_gen_trunc_tl_i32(t3, t1);
3344 tcg_gen_muls2_i32(t2, t3, t2, t3);
3345 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3346 tcg_temp_free_i32(t2);
3347 tcg_temp_free_i32(t3);
3348 }
b42ee5e1
LA
3349 break;
3350 case R6_OPC_MULU:
3351 {
3352 TCGv_i32 t2 = tcg_temp_new_i32();
3353 TCGv_i32 t3 = tcg_temp_new_i32();
3354 tcg_gen_trunc_tl_i32(t2, t0);
3355 tcg_gen_trunc_tl_i32(t3, t1);
3356 tcg_gen_mul_i32(t2, t2, t3);
3357 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3358 tcg_temp_free_i32(t2);
3359 tcg_temp_free_i32(t3);
3360 }
b42ee5e1
LA
3361 break;
3362 case R6_OPC_MUHU:
3363 {
3364 TCGv_i32 t2 = tcg_temp_new_i32();
3365 TCGv_i32 t3 = tcg_temp_new_i32();
3366 tcg_gen_trunc_tl_i32(t2, t0);
3367 tcg_gen_trunc_tl_i32(t3, t1);
3368 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3369 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3370 tcg_temp_free_i32(t2);
3371 tcg_temp_free_i32(t3);
3372 }
b42ee5e1
LA
3373 break;
3374#if defined(TARGET_MIPS64)
3375 case R6_OPC_DDIV:
3376 {
3377 TCGv t2 = tcg_temp_new();
3378 TCGv t3 = tcg_temp_new();
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3380 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3381 tcg_gen_and_tl(t2, t2, t3);
3382 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3383 tcg_gen_or_tl(t2, t2, t3);
3384 tcg_gen_movi_tl(t3, 0);
3385 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3386 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3387 tcg_temp_free(t3);
3388 tcg_temp_free(t2);
3389 }
b42ee5e1
LA
3390 break;
3391 case R6_OPC_DMOD:
3392 {
3393 TCGv t2 = tcg_temp_new();
3394 TCGv t3 = tcg_temp_new();
3395 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3396 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3397 tcg_gen_and_tl(t2, t2, t3);
3398 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3399 tcg_gen_or_tl(t2, t2, t3);
3400 tcg_gen_movi_tl(t3, 0);
3401 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3402 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3403 tcg_temp_free(t3);
3404 tcg_temp_free(t2);
3405 }
b42ee5e1
LA
3406 break;
3407 case R6_OPC_DDIVU:
3408 {
3409 TCGv t2 = tcg_const_tl(0);
3410 TCGv t3 = tcg_const_tl(1);
3411 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3412 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3413 tcg_temp_free(t3);
3414 tcg_temp_free(t2);
3415 }
b42ee5e1
LA
3416 break;
3417 case R6_OPC_DMODU:
3418 {
3419 TCGv t2 = tcg_const_tl(0);
3420 TCGv t3 = tcg_const_tl(1);
3421 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3422 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3423 tcg_temp_free(t3);
3424 tcg_temp_free(t2);
3425 }
b42ee5e1
LA
3426 break;
3427 case R6_OPC_DMUL:
3428 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3429 break;
3430 case R6_OPC_DMUH:
3431 {
3432 TCGv t2 = tcg_temp_new();
3433 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3434 tcg_temp_free(t2);
3435 }
b42ee5e1
LA
3436 break;
3437 case R6_OPC_DMULU:
3438 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3439 break;
3440 case R6_OPC_DMUHU:
3441 {
3442 TCGv t2 = tcg_temp_new();
3443 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3444 tcg_temp_free(t2);
3445 }
b42ee5e1
LA
3446 break;
3447#endif
3448 default:
9d68ac14 3449 MIPS_INVAL("r6 mul/div");
3a4ef3b7 3450 gen_reserved_instruction(ctx);
b42ee5e1
LA
3451 goto out;
3452 }
b42ee5e1
LA
3453 out:
3454 tcg_temp_free(t0);
3455 tcg_temp_free(t1);
3456}
3457
37b9aae2 3458#if defined(TARGET_MIPS64)
c42171c3
FN
3459static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3460{
3461 TCGv t0, t1;
3462
3463 t0 = tcg_temp_new();
3464 t1 = tcg_temp_new();
3465
3466 gen_load_gpr(t0, rs);
3467 gen_load_gpr(t1, rt);
3468
3469 switch (opc) {
baa609db 3470 case MMI_OPC_DIV1:
c42171c3
FN
3471 {
3472 TCGv t2 = tcg_temp_new();
3473 TCGv t3 = tcg_temp_new();
3474 tcg_gen_ext32s_tl(t0, t0);
3475 tcg_gen_ext32s_tl(t1, t1);
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3477 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3478 tcg_gen_and_tl(t2, t2, t3);
3479 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3480 tcg_gen_or_tl(t2, t2, t3);
3481 tcg_gen_movi_tl(t3, 0);
3482 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3483 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3484 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3485 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3486 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3487 tcg_temp_free(t3);
3488 tcg_temp_free(t2);
3489 }
3490 break;
baa609db 3491 case MMI_OPC_DIVU1:
c42171c3
FN
3492 {
3493 TCGv t2 = tcg_const_tl(0);
3494 TCGv t3 = tcg_const_tl(1);
3495 tcg_gen_ext32u_tl(t0, t0);
3496 tcg_gen_ext32u_tl(t1, t1);
3497 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3498 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3499 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3500 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3501 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3502 tcg_temp_free(t3);
3503 tcg_temp_free(t2);
3504 }
3505 break;
3506 default:
3507 MIPS_INVAL("div1 TX79");
3a4ef3b7 3508 gen_reserved_instruction(ctx);
c42171c3
FN
3509 goto out;
3510 }
3511 out:
3512 tcg_temp_free(t0);
3513 tcg_temp_free(t1);
3514}
37b9aae2 3515#endif
c42171c3 3516
26135ead
RS
3517static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3518 int acc, int rs, int rt)
6af0bf9c 3519{
d45f89f4
AJ
3520 TCGv t0, t1;
3521
51127181
AJ
3522 t0 = tcg_temp_new();
3523 t1 = tcg_temp_new();
6af0bf9c 3524
78723684
TS
3525 gen_load_gpr(t0, rs);
3526 gen_load_gpr(t1, rt);
51127181 3527
26135ead 3528 if (acc != 0) {
c42171c3 3529 check_dsp(ctx);
26135ead
RS
3530 }
3531
6af0bf9c
FB
3532 switch (opc) {
3533 case OPC_DIV:
48d38ca5 3534 {
51127181
AJ
3535 TCGv t2 = tcg_temp_new();
3536 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3537 tcg_gen_ext32s_tl(t0, t0);
3538 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3539 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3540 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3541 tcg_gen_and_tl(t2, t2, t3);
3542 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3543 tcg_gen_or_tl(t2, t2, t3);
3544 tcg_gen_movi_tl(t3, 0);
3545 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3546 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3547 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3548 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3549 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3550 tcg_temp_free(t3);
3551 tcg_temp_free(t2);
48d38ca5 3552 }
6af0bf9c
FB
3553 break;
3554 case OPC_DIVU:
48d38ca5 3555 {
51127181
AJ
3556 TCGv t2 = tcg_const_tl(0);
3557 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
3558 tcg_gen_ext32u_tl(t0, t0);
3559 tcg_gen_ext32u_tl(t1, t1);
51127181 3560 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3561 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3562 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3563 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3564 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3565 tcg_temp_free(t3);
3566 tcg_temp_free(t2);
48d38ca5 3567 }
6af0bf9c
FB
3568 break;
3569 case OPC_MULT:
214c465f 3570 {
ce1dd5d1
RH
3571 TCGv_i32 t2 = tcg_temp_new_i32();
3572 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3573 tcg_gen_trunc_tl_i32(t2, t0);
3574 tcg_gen_trunc_tl_i32(t3, t1);
3575 tcg_gen_muls2_i32(t2, t3, t2, t3);
3576 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3577 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3578 tcg_temp_free_i32(t2);
3579 tcg_temp_free_i32(t3);
214c465f 3580 }
6af0bf9c
FB
3581 break;
3582 case OPC_MULTU:
214c465f 3583 {
ce1dd5d1
RH
3584 TCGv_i32 t2 = tcg_temp_new_i32();
3585 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3586 tcg_gen_trunc_tl_i32(t2, t0);
3587 tcg_gen_trunc_tl_i32(t3, t1);
3588 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3589 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3590 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3591 tcg_temp_free_i32(t2);
3592 tcg_temp_free_i32(t3);
214c465f 3593 }
6af0bf9c 3594 break;
d26bc211 3595#if defined(TARGET_MIPS64)
7a387fff 3596 case OPC_DDIV:
48d38ca5 3597 {
51127181
AJ
3598 TCGv t2 = tcg_temp_new();
3599 TCGv t3 = tcg_temp_new();
3600 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3601 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3602 tcg_gen_and_tl(t2, t2, t3);
3603 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3604 tcg_gen_or_tl(t2, t2, t3);
3605 tcg_gen_movi_tl(t3, 0);
3606 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3607 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3608 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
3609 tcg_temp_free(t3);
3610 tcg_temp_free(t2);
48d38ca5 3611 }
7a387fff
TS
3612 break;
3613 case OPC_DDIVU:
48d38ca5 3614 {
51127181
AJ
3615 TCGv t2 = tcg_const_tl(0);
3616 TCGv t3 = tcg_const_tl(1);
3617 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3618 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3619 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
3620 tcg_temp_free(t3);
3621 tcg_temp_free(t2);
48d38ca5 3622 }
7a387fff
TS
3623 break;
3624 case OPC_DMULT:
26135ead 3625 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3626 break;
3627 case OPC_DMULTU:
26135ead 3628 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3629 break;
3630#endif
6af0bf9c 3631 case OPC_MADD:
214c465f 3632 {
d45f89f4
AJ
3633 TCGv_i64 t2 = tcg_temp_new_i64();
3634 TCGv_i64 t3 = tcg_temp_new_i64();
3635
3636 tcg_gen_ext_tl_i64(t2, t0);
3637 tcg_gen_ext_tl_i64(t3, t1);
3638 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3639 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3640 tcg_gen_add_i64(t2, t2, t3);
3641 tcg_temp_free_i64(t3);
71f303cd
RH
3642 gen_move_low32(cpu_LO[acc], t2);
3643 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3644 tcg_temp_free_i64(t2);
214c465f 3645 }
6af0bf9c
FB
3646 break;
3647 case OPC_MADDU:
4133498f 3648 {
d45f89f4
AJ
3649 TCGv_i64 t2 = tcg_temp_new_i64();
3650 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3651
78723684
TS
3652 tcg_gen_ext32u_tl(t0, t0);
3653 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3654 tcg_gen_extu_tl_i64(t2, t0);
3655 tcg_gen_extu_tl_i64(t3, t1);
3656 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3657 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3658 tcg_gen_add_i64(t2, t2, t3);
3659 tcg_temp_free_i64(t3);
71f303cd
RH
3660 gen_move_low32(cpu_LO[acc], t2);
3661 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3662 tcg_temp_free_i64(t2);
214c465f 3663 }
6af0bf9c
FB
3664 break;
3665 case OPC_MSUB:
214c465f 3666 {
d45f89f4
AJ
3667 TCGv_i64 t2 = tcg_temp_new_i64();
3668 TCGv_i64 t3 = tcg_temp_new_i64();
3669
3670 tcg_gen_ext_tl_i64(t2, t0);
3671 tcg_gen_ext_tl_i64(t3, t1);
3672 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3673 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3674 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3675 tcg_temp_free_i64(t3);
71f303cd
RH
3676 gen_move_low32(cpu_LO[acc], t2);
3677 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3678 tcg_temp_free_i64(t2);
214c465f 3679 }
6af0bf9c
FB
3680 break;
3681 case OPC_MSUBU:
214c465f 3682 {
d45f89f4
AJ
3683 TCGv_i64 t2 = tcg_temp_new_i64();
3684 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3685
78723684
TS
3686 tcg_gen_ext32u_tl(t0, t0);
3687 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3688 tcg_gen_extu_tl_i64(t2, t0);
3689 tcg_gen_extu_tl_i64(t3, t1);
3690 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3691 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3692 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3693 tcg_temp_free_i64(t3);
71f303cd
RH
3694 gen_move_low32(cpu_LO[acc], t2);
3695 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3696 tcg_temp_free_i64(t2);
214c465f 3697 }
6af0bf9c
FB
3698 break;
3699 default:
9d68ac14 3700 MIPS_INVAL("mul/div");
3a4ef3b7 3701 gen_reserved_instruction(ctx);
78723684 3702 goto out;
6af0bf9c 3703 }
78723684
TS
3704 out:
3705 tcg_temp_free(t0);
3706 tcg_temp_free(t1);
6af0bf9c
FB
3707}
3708
21e8e8b2 3709/*
3b948f05
PMD
3710 * These MULT[U] and MADD[U] instructions implemented in for example
3711 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
3712 * architectures are special three-operand variants with the syntax
3713 *
06de726b 3714 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
3715 *
3716 * such that
3717 *
3718 * (rd, LO, HI) <- rs * rt
3719 *
3b948f05
PMD
3720 * and
3721 *
a95c4c26 3722 * MADD[U][1] rd, rs, rt
3b948f05
PMD
3723 *
3724 * such that
3725 *
3726 * (rd, LO, HI) <- (LO, HI) + rs * rt
3727 *
21e8e8b2
FN
3728 * where the low-order 32-bits of the result is placed into both the
3729 * GPR rd and the special register LO. The high-order 32-bits of the
3730 * result is placed into the special register HI.
3731 *
3732 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3733 * which is the zero register that always reads as 0.
3734 */
3735static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3736 int rd, int rs, int rt)
3737{
3738 TCGv t0 = tcg_temp_new();
3739 TCGv t1 = tcg_temp_new();
3740 int acc = 0;
3741
3742 gen_load_gpr(t0, rs);
3743 gen_load_gpr(t1, rt);
3744
3745 switch (opc) {
baa609db 3746 case MMI_OPC_MULT1:
06de726b
FN
3747 acc = 1;
3748 /* Fall through */
21e8e8b2
FN
3749 case OPC_MULT:
3750 {
3751 TCGv_i32 t2 = tcg_temp_new_i32();
3752 TCGv_i32 t3 = tcg_temp_new_i32();
3753 tcg_gen_trunc_tl_i32(t2, t0);
3754 tcg_gen_trunc_tl_i32(t3, t1);
3755 tcg_gen_muls2_i32(t2, t3, t2, t3);
3756 if (rd) {
3757 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3758 }
3759 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3760 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3761 tcg_temp_free_i32(t2);
3762 tcg_temp_free_i32(t3);
3763 }
3764 break;
baa609db 3765 case MMI_OPC_MULTU1:
06de726b
FN
3766 acc = 1;
3767 /* Fall through */
21e8e8b2
FN
3768 case OPC_MULTU:
3769 {
3770 TCGv_i32 t2 = tcg_temp_new_i32();
3771 TCGv_i32 t3 = tcg_temp_new_i32();
3772 tcg_gen_trunc_tl_i32(t2, t0);
3773 tcg_gen_trunc_tl_i32(t3, t1);
3774 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3775 if (rd) {
3776 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3777 }
3778 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3779 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3780 tcg_temp_free_i32(t2);
3781 tcg_temp_free_i32(t3);
3782 }
3783 break;
a95c4c26
FN
3784 case MMI_OPC_MADD1:
3785 acc = 1;
3786 /* Fall through */
3b948f05
PMD
3787 case MMI_OPC_MADD:
3788 {
3789 TCGv_i64 t2 = tcg_temp_new_i64();
3790 TCGv_i64 t3 = tcg_temp_new_i64();
3791
3792 tcg_gen_ext_tl_i64(t2, t0);
3793 tcg_gen_ext_tl_i64(t3, t1);
3794 tcg_gen_mul_i64(t2, t2, t3);
3795 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3796 tcg_gen_add_i64(t2, t2, t3);
3797 tcg_temp_free_i64(t3);
3798 gen_move_low32(cpu_LO[acc], t2);
3799 gen_move_high32(cpu_HI[acc], t2);
3800 if (rd) {
3801 gen_move_low32(cpu_gpr[rd], t2);
3802 }
3803 tcg_temp_free_i64(t2);
3804 }
3805 break;
a95c4c26
FN
3806 case MMI_OPC_MADDU1:
3807 acc = 1;
3808 /* Fall through */
3b948f05
PMD
3809 case MMI_OPC_MADDU:
3810 {
3811 TCGv_i64 t2 = tcg_temp_new_i64();
3812 TCGv_i64 t3 = tcg_temp_new_i64();
3813
3814 tcg_gen_ext32u_tl(t0, t0);
3815 tcg_gen_ext32u_tl(t1, t1);
3816 tcg_gen_extu_tl_i64(t2, t0);
3817 tcg_gen_extu_tl_i64(t3, t1);
3818 tcg_gen_mul_i64(t2, t2, t3);
3819 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3820 tcg_gen_add_i64(t2, t2, t3);
3821 tcg_temp_free_i64(t3);
3822 gen_move_low32(cpu_LO[acc], t2);
3823 gen_move_high32(cpu_HI[acc], t2);
3824 if (rd) {
3825 gen_move_low32(cpu_gpr[rd], t2);
3826 }
3827 tcg_temp_free_i64(t2);
3828 }
3829 break;
21e8e8b2 3830 default:
3b948f05 3831 MIPS_INVAL("mul/madd TXx9");
3a4ef3b7 3832 gen_reserved_instruction(ctx);
21e8e8b2
FN
3833 goto out;
3834 }
3835
3836 out:
3837 tcg_temp_free(t0);
3838 tcg_temp_free(t1);
3839}
3840
235785e8
AM
3841static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3842 int rd, int rs, int rt)
e9c71dd1 3843{
f157bfe1
AJ
3844 TCGv t0 = tcg_temp_new();
3845 TCGv t1 = tcg_temp_new();
e9c71dd1 3846
6c5c1e20
TS
3847 gen_load_gpr(t0, rs);
3848 gen_load_gpr(t1, rt);
e9c71dd1
TS
3849
3850 switch (opc) {
3851 case OPC_VR54XX_MULS:
895c2d04 3852 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 3853 break;
e9c71dd1 3854 case OPC_VR54XX_MULSU:
895c2d04 3855 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 3856 break;
e9c71dd1 3857 case OPC_VR54XX_MACC:
895c2d04 3858 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 3859 break;
e9c71dd1 3860 case OPC_VR54XX_MACCU:
895c2d04 3861 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 3862 break;
e9c71dd1 3863 case OPC_VR54XX_MSAC:
895c2d04 3864 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 3865 break;
e9c71dd1 3866 case OPC_VR54XX_MSACU:
895c2d04 3867 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 3868 break;
e9c71dd1 3869 case OPC_VR54XX_MULHI:
895c2d04 3870 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 3871 break;
e9c71dd1 3872 case OPC_VR54XX_MULHIU:
895c2d04 3873 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 3874 break;
e9c71dd1 3875 case OPC_VR54XX_MULSHI:
895c2d04 3876 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 3877 break;
e9c71dd1 3878 case OPC_VR54XX_MULSHIU:
895c2d04 3879 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 3880 break;
e9c71dd1 3881 case OPC_VR54XX_MACCHI:
895c2d04 3882 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 3883 break;
e9c71dd1 3884 case OPC_VR54XX_MACCHIU:
895c2d04 3885 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 3886 break;
e9c71dd1 3887 case OPC_VR54XX_MSACHI:
895c2d04 3888 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 3889 break;
e9c71dd1 3890 case OPC_VR54XX_MSACHIU:
895c2d04 3891 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 3892 break;
e9c71dd1
TS
3893 default:
3894 MIPS_INVAL("mul vr54xx");
3a4ef3b7 3895 gen_reserved_instruction(ctx);
6c5c1e20 3896 goto out;
e9c71dd1 3897 }
6c5c1e20 3898 gen_store_gpr(t0, rd);
6c5c1e20
TS
3899
3900 out:
3901 tcg_temp_free(t0);
3902 tcg_temp_free(t1);
e9c71dd1
TS
3903}
3904
235785e8
AM
3905static void gen_cl(DisasContext *ctx, uint32_t opc,
3906 int rd, int rs)
6af0bf9c 3907{
20e1fb52 3908 TCGv t0;
6c5c1e20 3909
6af0bf9c 3910 if (rd == 0) {
ead9360e 3911 /* Treat as NOP. */
20e1fb52 3912 return;
6af0bf9c 3913 }
1a0196c5 3914 t0 = cpu_gpr[rd];
6c5c1e20 3915 gen_load_gpr(t0, rs);
1a0196c5 3916
6af0bf9c
FB
3917 switch (opc) {
3918 case OPC_CLO:
4267d3e6 3919 case R6_OPC_CLO:
1a0196c5
RH
3920#if defined(TARGET_MIPS64)
3921 case OPC_DCLO:
3922 case R6_OPC_DCLO:
3923#endif
3924 tcg_gen_not_tl(t0, t0);
6af0bf9c 3925 break;
1a0196c5
RH
3926 }
3927
3928 switch (opc) {
3929 case OPC_CLO:
3930 case R6_OPC_CLO:
6af0bf9c 3931 case OPC_CLZ:
4267d3e6 3932 case R6_OPC_CLZ:
1a0196c5
RH
3933 tcg_gen_ext32u_tl(t0, t0);
3934 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3935 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 3936 break;
d26bc211 3937#if defined(TARGET_MIPS64)
7a387fff 3938 case OPC_DCLO:
4267d3e6 3939 case R6_OPC_DCLO:
7a387fff 3940 case OPC_DCLZ:
4267d3e6 3941 case R6_OPC_DCLZ:
1a0196c5 3942 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
3943 break;
3944#endif
6af0bf9c 3945 }
6af0bf9c
FB
3946}
3947
161f85e6 3948/* Godson integer instructions */
bd277fa1
RH
3949static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3950 int rd, int rs, int rt)
161f85e6 3951{
161f85e6
AJ
3952 TCGv t0, t1;
3953
3954 if (rd == 0) {
3955 /* Treat as NOP. */
161f85e6
AJ
3956 return;
3957 }
3958
3959 switch (opc) {
3960 case OPC_MULT_G_2E:
3961 case OPC_MULT_G_2F:
3962 case OPC_MULTU_G_2E:
3963 case OPC_MULTU_G_2F:
3964#if defined(TARGET_MIPS64)
3965 case OPC_DMULT_G_2E:
3966 case OPC_DMULT_G_2F:
3967 case OPC_DMULTU_G_2E:
3968 case OPC_DMULTU_G_2F:
3969#endif
3970 t0 = tcg_temp_new();
3971 t1 = tcg_temp_new();
3972 break;
3973 default:
3974 t0 = tcg_temp_local_new();
3975 t1 = tcg_temp_local_new();
3976 break;
3977 }
3978
3979 gen_load_gpr(t0, rs);
3980 gen_load_gpr(t1, rt);
3981
3982 switch (opc) {
3983 case OPC_MULT_G_2E:
3984 case OPC_MULT_G_2F:
3985 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3986 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3987 break;
3988 case OPC_MULTU_G_2E:
3989 case OPC_MULTU_G_2F:
3990 tcg_gen_ext32u_tl(t0, t0);
3991 tcg_gen_ext32u_tl(t1, t1);
3992 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3993 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3994 break;
3995 case OPC_DIV_G_2E:
3996 case OPC_DIV_G_2F:
3997 {
42a268c2
RH
3998 TCGLabel *l1 = gen_new_label();
3999 TCGLabel *l2 = gen_new_label();
4000 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4001 tcg_gen_ext32s_tl(t0, t0);
4002 tcg_gen_ext32s_tl(t1, t1);
4003 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4004 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4005 tcg_gen_br(l3);
4006 gen_set_label(l1);
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4008 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4009 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4010 tcg_gen_br(l3);
4011 gen_set_label(l2);
4012 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4013 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4014 gen_set_label(l3);
4015 }
161f85e6
AJ
4016 break;
4017 case OPC_DIVU_G_2E:
4018 case OPC_DIVU_G_2F:
4019 {
42a268c2
RH
4020 TCGLabel *l1 = gen_new_label();
4021 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4022 tcg_gen_ext32u_tl(t0, t0);
4023 tcg_gen_ext32u_tl(t1, t1);
4024 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4025 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4026 tcg_gen_br(l2);
4027 gen_set_label(l1);
4028 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4029 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4030 gen_set_label(l2);
4031 }
161f85e6
AJ
4032 break;
4033 case OPC_MOD_G_2E:
4034 case OPC_MOD_G_2F:
4035 {
42a268c2
RH
4036 TCGLabel *l1 = gen_new_label();
4037 TCGLabel *l2 = gen_new_label();
4038 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4039 tcg_gen_ext32u_tl(t0, t0);
4040 tcg_gen_ext32u_tl(t1, t1);
4041 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4042 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4044 gen_set_label(l1);
4045 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4046 tcg_gen_br(l3);
4047 gen_set_label(l2);
4048 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4049 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4050 gen_set_label(l3);
4051 }
161f85e6
AJ
4052 break;
4053 case OPC_MODU_G_2E:
4054 case OPC_MODU_G_2F:
4055 {
42a268c2
RH
4056 TCGLabel *l1 = gen_new_label();
4057 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4058 tcg_gen_ext32u_tl(t0, t0);
4059 tcg_gen_ext32u_tl(t1, t1);
4060 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4061 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4062 tcg_gen_br(l2);
4063 gen_set_label(l1);
4064 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4065 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4066 gen_set_label(l2);
4067 }
161f85e6
AJ
4068 break;
4069#if defined(TARGET_MIPS64)
4070 case OPC_DMULT_G_2E:
4071 case OPC_DMULT_G_2F:
4072 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4073 break;
4074 case OPC_DMULTU_G_2E:
4075 case OPC_DMULTU_G_2F:
4076 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4077 break;
4078 case OPC_DDIV_G_2E:
4079 case OPC_DDIV_G_2F:
4080 {
42a268c2
RH
4081 TCGLabel *l1 = gen_new_label();
4082 TCGLabel *l2 = gen_new_label();
4083 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4084 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4085 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4086 tcg_gen_br(l3);
4087 gen_set_label(l1);
4088 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4089 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4090 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4091 tcg_gen_br(l3);
4092 gen_set_label(l2);
4093 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4094 gen_set_label(l3);
4095 }
161f85e6
AJ
4096 break;
4097 case OPC_DDIVU_G_2E:
4098 case OPC_DDIVU_G_2F:
4099 {
42a268c2
RH
4100 TCGLabel *l1 = gen_new_label();
4101 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4102 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4103 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4104 tcg_gen_br(l2);
4105 gen_set_label(l1);
4106 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4107 gen_set_label(l2);
4108 }
161f85e6
AJ
4109 break;
4110 case OPC_DMOD_G_2E:
4111 case OPC_DMOD_G_2F:
4112 {
42a268c2
RH
4113 TCGLabel *l1 = gen_new_label();
4114 TCGLabel *l2 = gen_new_label();
4115 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4116 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4117 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4118 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4119 gen_set_label(l1);
4120 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4121 tcg_gen_br(l3);
4122 gen_set_label(l2);
4123 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4124 gen_set_label(l3);
4125 }
161f85e6
AJ
4126 break;
4127 case OPC_DMODU_G_2E:
4128 case OPC_DMODU_G_2F:
4129 {
42a268c2
RH
4130 TCGLabel *l1 = gen_new_label();
4131 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4132 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4133 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4134 tcg_gen_br(l2);
4135 gen_set_label(l1);
4136 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4137 gen_set_label(l2);
4138 }
161f85e6
AJ
4139 break;
4140#endif
4141 }
4142
161f85e6
AJ
4143 tcg_temp_free(t0);
4144 tcg_temp_free(t1);
4145}
4146
bd277fa1
RH
4147/* Loongson multimedia instructions */
4148static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4149{
bd277fa1
RH
4150 uint32_t opc, shift_max;
4151 TCGv_i64 t0, t1;
84878f4c 4152 TCGCond cond;
bd277fa1 4153
8e2d5831 4154 opc = MASK_LMMI(ctx->opcode);
bd277fa1
RH
4155 switch (opc) {
4156 case OPC_ADD_CP2:
4157 case OPC_SUB_CP2:
4158 case OPC_DADD_CP2:
4159 case OPC_DSUB_CP2:
4160 t0 = tcg_temp_local_new_i64();
4161 t1 = tcg_temp_local_new_i64();
4162 break;
4163 default:
4164 t0 = tcg_temp_new_i64();
4165 t1 = tcg_temp_new_i64();
4166 break;
4167 }
4168
b5a587b6 4169 check_cp1_enabled(ctx);
bd277fa1
RH
4170 gen_load_fpr64(ctx, t0, rs);
4171 gen_load_fpr64(ctx, t1, rt);
4172
bd277fa1 4173 switch (opc) {
b1cf82f0
AM
4174 case OPC_PADDSH:
4175 gen_helper_paddsh(t0, t0, t1);
4176 break;
4177 case OPC_PADDUSH:
4178 gen_helper_paddush(t0, t0, t1);
4179 break;
4180 case OPC_PADDH:
4181 gen_helper_paddh(t0, t0, t1);
4182 break;
4183 case OPC_PADDW:
4184 gen_helper_paddw(t0, t0, t1);
4185 break;
4186 case OPC_PADDSB:
4187 gen_helper_paddsb(t0, t0, t1);
4188 break;
4189 case OPC_PADDUSB:
4190 gen_helper_paddusb(t0, t0, t1);
4191 break;
4192 case OPC_PADDB:
4193 gen_helper_paddb(t0, t0, t1);
4194 break;
4195
4196 case OPC_PSUBSH:
4197 gen_helper_psubsh(t0, t0, t1);
4198 break;
4199 case OPC_PSUBUSH:
4200 gen_helper_psubush(t0, t0, t1);
4201 break;
4202 case OPC_PSUBH:
4203 gen_helper_psubh(t0, t0, t1);
4204 break;
4205 case OPC_PSUBW:
4206 gen_helper_psubw(t0, t0, t1);
4207 break;
4208 case OPC_PSUBSB:
4209 gen_helper_psubsb(t0, t0, t1);
4210 break;
4211 case OPC_PSUBUSB:
4212 gen_helper_psubusb(t0, t0, t1);
4213 break;
4214 case OPC_PSUBB:
4215 gen_helper_psubb(t0, t0, t1);
4216 break;
4217
4218 case OPC_PSHUFH:
4219 gen_helper_pshufh(t0, t0, t1);
4220 break;
4221 case OPC_PACKSSWH:
4222 gen_helper_packsswh(t0, t0, t1);
4223 break;
4224 case OPC_PACKSSHB:
4225 gen_helper_packsshb(t0, t0, t1);
4226 break;
4227 case OPC_PACKUSHB:
4228 gen_helper_packushb(t0, t0, t1);
4229 break;
4230
4231 case OPC_PUNPCKLHW:
4232 gen_helper_punpcklhw(t0, t0, t1);
4233 break;
4234 case OPC_PUNPCKHHW:
4235 gen_helper_punpckhhw(t0, t0, t1);
4236 break;
4237 case OPC_PUNPCKLBH:
4238 gen_helper_punpcklbh(t0, t0, t1);
4239 break;
4240 case OPC_PUNPCKHBH:
4241 gen_helper_punpckhbh(t0, t0, t1);
4242 break;
4243 case OPC_PUNPCKLWD:
4244 gen_helper_punpcklwd(t0, t0, t1);
4245 break;
4246 case OPC_PUNPCKHWD:
4247 gen_helper_punpckhwd(t0, t0, t1);
4248 break;
4249
4250 case OPC_PAVGH:
4251 gen_helper_pavgh(t0, t0, t1);
4252 break;
4253 case OPC_PAVGB:
4254 gen_helper_pavgb(t0, t0, t1);
4255 break;
4256 case OPC_PMAXSH:
4257 gen_helper_pmaxsh(t0, t0, t1);
4258 break;
4259 case OPC_PMINSH:
4260 gen_helper_pminsh(t0, t0, t1);
4261 break;
4262 case OPC_PMAXUB:
4263 gen_helper_pmaxub(t0, t0, t1);
4264 break;
4265 case OPC_PMINUB:
4266 gen_helper_pminub(t0, t0, t1);
4267 break;
4268
4269 case OPC_PCMPEQW:
4270 gen_helper_pcmpeqw(t0, t0, t1);
4271 break;
4272 case OPC_PCMPGTW:
4273 gen_helper_pcmpgtw(t0, t0, t1);
4274 break;
4275 case OPC_PCMPEQH:
4276 gen_helper_pcmpeqh(t0, t0, t1);
4277 break;
4278 case OPC_PCMPGTH:
4279 gen_helper_pcmpgth(t0, t0, t1);
4280 break;
4281 case OPC_PCMPEQB:
4282 gen_helper_pcmpeqb(t0, t0, t1);
4283 break;
4284 case OPC_PCMPGTB:
4285 gen_helper_pcmpgtb(t0, t0, t1);
4286 break;
4287
4288 case OPC_PSLLW:
4289 gen_helper_psllw(t0, t0, t1);
4290 break;
4291 case OPC_PSLLH:
4292 gen_helper_psllh(t0, t0, t1);
4293 break;
4294 case OPC_PSRLW:
4295 gen_helper_psrlw(t0, t0, t1);
4296 break;
4297 case OPC_PSRLH:
4298 gen_helper_psrlh(t0, t0, t1);
4299 break;
4300 case OPC_PSRAW:
4301 gen_helper_psraw(t0, t0, t1);
4302 break;
4303 case OPC_PSRAH:
4304 gen_helper_psrah(t0, t0, t1);
4305 break;
4306
4307 case OPC_PMULLH:
4308 gen_helper_pmullh(t0, t0, t1);
4309 break;
4310 case OPC_PMULHH:
4311 gen_helper_pmulhh(t0, t0, t1);
4312 break;
4313 case OPC_PMULHUH:
4314 gen_helper_pmulhuh(t0, t0, t1);
4315 break;
4316 case OPC_PMADDHW:
4317 gen_helper_pmaddhw(t0, t0, t1);
4318 break;
4319
4320 case OPC_PASUBUB:
4321 gen_helper_pasubub(t0, t0, t1);
4322 break;
4323 case OPC_BIADD:
4324 gen_helper_biadd(t0, t0);
4325 break;
4326 case OPC_PMOVMSKB:
4327 gen_helper_pmovmskb(t0, t0);
4328 break;
4329
4330 case OPC_PADDD:
4331 tcg_gen_add_i64(t0, t0, t1);
4332 break;
4333 case OPC_PSUBD:
4334 tcg_gen_sub_i64(t0, t0, t1);
4335 break;
4336 case OPC_XOR_CP2:
4337 tcg_gen_xor_i64(t0, t0, t1);
4338 break;
4339 case OPC_NOR_CP2:
4340 tcg_gen_nor_i64(t0, t0, t1);
4341 break;
4342 case OPC_AND_CP2:
4343 tcg_gen_and_i64(t0, t0, t1);
4344 break;
4345 case OPC_OR_CP2:
4346 tcg_gen_or_i64(t0, t0, t1);
4347 break;
bd277fa1 4348
9099a36b
H
4349 case OPC_PANDN:
4350 tcg_gen_andc_i64(t0, t1, t0);
4351 break;
4352
bd277fa1
RH
4353 case OPC_PINSRH_0:
4354 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
4355 break;
4356 case OPC_PINSRH_1:
4357 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
4358 break;
4359 case OPC_PINSRH_2:
4360 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
4361 break;
4362 case OPC_PINSRH_3:
4363 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
4364 break;
4365
4366 case OPC_PEXTRH:
4367 tcg_gen_andi_i64(t1, t1, 3);
4368 tcg_gen_shli_i64(t1, t1, 4);
4369 tcg_gen_shr_i64(t0, t0, t1);
4370 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
4371 break;
4372
4373 case OPC_ADDU_CP2:
4374 tcg_gen_add_i64(t0, t0, t1);
4375 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4376 break;
4377 case OPC_SUBU_CP2:
4378 tcg_gen_sub_i64(t0, t0, t1);
4379 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4380 break;
4381
4382 case OPC_SLL_CP2:
bd277fa1
RH
4383 shift_max = 32;
4384 goto do_shift;
4385 case OPC_SRL_CP2:
bd277fa1
RH
4386 shift_max = 32;
4387 goto do_shift;
4388 case OPC_SRA_CP2:
bd277fa1
RH
4389 shift_max = 32;
4390 goto do_shift;
4391 case OPC_DSLL_CP2:
bd277fa1
RH
4392 shift_max = 64;
4393 goto do_shift;
4394 case OPC_DSRL_CP2:
bd277fa1
RH
4395 shift_max = 64;
4396 goto do_shift;
4397 case OPC_DSRA_CP2:
bd277fa1
RH
4398 shift_max = 64;
4399 goto do_shift;
4400 do_shift:
4401 /* Make sure shift count isn't TCG undefined behaviour. */
4402 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4403
4404 switch (opc) {
4405 case OPC_SLL_CP2:
4406 case OPC_DSLL_CP2:
4407 tcg_gen_shl_i64(t0, t0, t1);
4408 break;
4409 case OPC_SRA_CP2:
4410 case OPC_DSRA_CP2:
7480515f
AM
4411 /*
4412 * Since SRA is UndefinedResult without sign-extended inputs,
4413 * we can treat SRA and DSRA the same.
4414 */
bd277fa1
RH
4415 tcg_gen_sar_i64(t0, t0, t1);
4416 break;
4417 case OPC_SRL_CP2:
4418 /* We want to shift in zeros for SRL; zero-extend first. */
4419 tcg_gen_ext32u_i64(t0, t0);
4420 /* FALLTHRU */
4421 case OPC_DSRL_CP2:
4422 tcg_gen_shr_i64(t0, t0, t1);
4423 break;
4424 }
4425
4426 if (shift_max == 32) {
4427 tcg_gen_ext32s_i64(t0, t0);
4428 }
4429
4430 /* Shifts larger than MAX produce zero. */
4431 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4432 tcg_gen_neg_i64(t1, t1);
4433 tcg_gen_and_i64(t0, t0, t1);
4434 break;
4435
4436 case OPC_ADD_CP2:
4437 case OPC_DADD_CP2:
4438 {
4439 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4440 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4441
4442 tcg_gen_mov_i64(t2, t0);
4443 tcg_gen_add_i64(t0, t1, t2);
4444 if (opc == OPC_ADD_CP2) {
4445 tcg_gen_ext32s_i64(t0, t0);
4446 }
4447 tcg_gen_xor_i64(t1, t1, t2);
4448 tcg_gen_xor_i64(t2, t2, t0);
4449 tcg_gen_andc_i64(t1, t2, t1);
4450 tcg_temp_free_i64(t2);
4451 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4452 generate_exception(ctx, EXCP_OVERFLOW);
4453 gen_set_label(lab);
bd277fa1
RH
4454 break;
4455 }
4456
4457 case OPC_SUB_CP2:
4458 case OPC_DSUB_CP2:
4459 {
4460 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4461 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4462
4463 tcg_gen_mov_i64(t2, t0);
4464 tcg_gen_sub_i64(t0, t1, t2);
4465 if (opc == OPC_SUB_CP2) {
4466 tcg_gen_ext32s_i64(t0, t0);
4467 }
4468 tcg_gen_xor_i64(t1, t1, t2);
4469 tcg_gen_xor_i64(t2, t2, t0);
4470 tcg_gen_and_i64(t1, t1, t2);
4471 tcg_temp_free_i64(t2);
4472 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4473 generate_exception(ctx, EXCP_OVERFLOW);
4474 gen_set_label(lab);
bd277fa1
RH
4475 break;
4476 }
4477
4478 case OPC_PMULUW:
4479 tcg_gen_ext32u_i64(t0, t0);
4480 tcg_gen_ext32u_i64(t1, t1);
4481 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
4482 break;
4483
4484 case OPC_SEQU_CP2:
4485 case OPC_SEQ_CP2:
84878f4c
JY
4486 cond = TCG_COND_EQ;
4487 goto do_cc_cond;
4488 break;
bd277fa1 4489 case OPC_SLTU_CP2:
84878f4c
JY
4490 cond = TCG_COND_LTU;
4491 goto do_cc_cond;
4492 break;
bd277fa1 4493 case OPC_SLT_CP2:
84878f4c
JY
4494 cond = TCG_COND_LT;
4495 goto do_cc_cond;
4496 break;
bd277fa1 4497 case OPC_SLEU_CP2:
84878f4c
JY
4498 cond = TCG_COND_LEU;
4499 goto do_cc_cond;
4500 break;
bd277fa1 4501 case OPC_SLE_CP2:
84878f4c
JY
4502 cond = TCG_COND_LE;
4503 do_cc_cond:
4504 {
4505 int cc = (ctx->opcode >> 8) & 0x7;
4506 TCGv_i64 t64 = tcg_temp_new_i64();
4507 TCGv_i32 t32 = tcg_temp_new_i32();
4508
4509 tcg_gen_setcond_i64(cond, t64, t0, t1);
4510 tcg_gen_extrl_i64_i32(t32, t64);
4511 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4512 get_fp_bit(cc), 1);
4513
4514 tcg_temp_free_i32(t32);
4515 tcg_temp_free_i64(t64);
4516 }
4517 goto no_rd;
4518 break;
bd277fa1 4519 default:
9d68ac14 4520 MIPS_INVAL("loongson_cp2");
3a4ef3b7 4521 gen_reserved_instruction(ctx);
bd277fa1
RH
4522 return;
4523 }
4524
bd277fa1
RH
4525 gen_store_fpr64(ctx, t0, rd);
4526
84878f4c 4527no_rd:
bd277fa1
RH
4528 tcg_temp_free_i64(t0);
4529 tcg_temp_free_i64(t1);
4530}
4531
e10a0ca1
JY
4532static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4533 int rs, int rd)
4534{
fd723105
JY
4535 TCGv t0, t1, t2;
4536 TCGv_i32 fp0;
e10a0ca1 4537#if defined(TARGET_MIPS64)
e10a0ca1
JY
4538 int lsq_rt1 = ctx->opcode & 0x1f;
4539 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4540#endif
fd723105 4541 int shf_offset = sextract32(ctx->opcode, 6, 8);
e10a0ca1
JY
4542
4543 t0 = tcg_temp_new();
4544
4545 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4546#if defined(TARGET_MIPS64)
4547 case OPC_GSLQ:
4548 t1 = tcg_temp_new();
4549 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4550 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4551 ctx->default_tcg_memop_mask);
4552 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4553 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4554 ctx->default_tcg_memop_mask);
4555 gen_store_gpr(t1, rt);
4556 gen_store_gpr(t0, lsq_rt1);
4557 tcg_temp_free(t1);
4558 break;
4559 case OPC_GSLQC1:
4560 check_cp1_enabled(ctx);
4561 t1 = tcg_temp_new();
4562 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4563 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4564 ctx->default_tcg_memop_mask);
4565 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4566 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4567 ctx->default_tcg_memop_mask);
4568 gen_store_fpr64(ctx, t1, rt);
4569 gen_store_fpr64(ctx, t0, lsq_rt1);
4570 tcg_temp_free(t1);
4571 break;
4572 case OPC_GSSQ:
4573 t1 = tcg_temp_new();
4574 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4575 gen_load_gpr(t1, rt);
4576 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4577 ctx->default_tcg_memop_mask);
4578 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4579 gen_load_gpr(t1, lsq_rt1);
4580 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4581 ctx->default_tcg_memop_mask);
4582 tcg_temp_free(t1);
4583 break;
4584 case OPC_GSSQC1:
4585 check_cp1_enabled(ctx);
4586 t1 = tcg_temp_new();
4587 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4588 gen_load_fpr64(ctx, t1, rt);
4589 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4590 ctx->default_tcg_memop_mask);
4591 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4592 gen_load_fpr64(ctx, t1, lsq_rt1);
4593 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4594 ctx->default_tcg_memop_mask);
4595 tcg_temp_free(t1);
4596 break;
4597#endif
fd723105
JY
4598 case OPC_GSSHFL:
4599 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4600 case OPC_GSLWLC1:
4601 check_cp1_enabled(ctx);
4602 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4603 t1 = tcg_temp_new();
4604 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4605 tcg_gen_andi_tl(t1, t0, 3);
4606#ifndef TARGET_WORDS_BIGENDIAN
4607 tcg_gen_xori_tl(t1, t1, 3);
4608#endif
4609 tcg_gen_shli_tl(t1, t1, 3);
4610 tcg_gen_andi_tl(t0, t0, ~3);
4611 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4612 tcg_gen_shl_tl(t0, t0, t1);
4613 t2 = tcg_const_tl(-1);
4614 tcg_gen_shl_tl(t2, t2, t1);
4615 fp0 = tcg_temp_new_i32();
4616 gen_load_fpr32(ctx, fp0, rt);
4617 tcg_gen_ext_i32_tl(t1, fp0);
4618 tcg_gen_andc_tl(t1, t1, t2);
4619 tcg_temp_free(t2);
4620 tcg_gen_or_tl(t0, t0, t1);
4621 tcg_temp_free(t1);
4622#if defined(TARGET_MIPS64)
4623 tcg_gen_extrl_i64_i32(fp0, t0);
4624#else
4625 tcg_gen_ext32s_tl(fp0, t0);
4626#endif
4627 gen_store_fpr32(ctx, fp0, rt);
4628 tcg_temp_free_i32(fp0);
4629 break;
4630 case OPC_GSLWRC1:
4631 check_cp1_enabled(ctx);
4632 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4633 t1 = tcg_temp_new();
4634 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4635 tcg_gen_andi_tl(t1, t0, 3);
4636#ifdef TARGET_WORDS_BIGENDIAN
4637 tcg_gen_xori_tl(t1, t1, 3);
4638#endif
4639 tcg_gen_shli_tl(t1, t1, 3);
4640 tcg_gen_andi_tl(t0, t0, ~3);
4641 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4642 tcg_gen_shr_tl(t0, t0, t1);
4643 tcg_gen_xori_tl(t1, t1, 31);
4644 t2 = tcg_const_tl(0xfffffffeull);
4645 tcg_gen_shl_tl(t2, t2, t1);
4646 fp0 = tcg_temp_new_i32();
4647 gen_load_fpr32(ctx, fp0, rt);
4648 tcg_gen_ext_i32_tl(t1, fp0);
4649 tcg_gen_and_tl(t1, t1, t2);
4650 tcg_temp_free(t2);
4651 tcg_gen_or_tl(t0, t0, t1);
4652 tcg_temp_free(t1);
4653#if defined(TARGET_MIPS64)
4654 tcg_gen_extrl_i64_i32(fp0, t0);
4655#else
4656 tcg_gen_ext32s_tl(fp0, t0);
4657#endif
4658 gen_store_fpr32(ctx, fp0, rt);
4659 tcg_temp_free_i32(fp0);
4660 break;
4661#if defined(TARGET_MIPS64)
4662 case OPC_GSLDLC1:
4663 check_cp1_enabled(ctx);
4664 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4665 t1 = tcg_temp_new();
4666 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4667 tcg_gen_andi_tl(t1, t0, 7);
4668#ifndef TARGET_WORDS_BIGENDIAN
4669 tcg_gen_xori_tl(t1, t1, 7);
4670#endif
4671 tcg_gen_shli_tl(t1, t1, 3);
4672 tcg_gen_andi_tl(t0, t0, ~7);
4673 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4674 tcg_gen_shl_tl(t0, t0, t1);
4675 t2 = tcg_const_tl(-1);
4676 tcg_gen_shl_tl(t2, t2, t1);
4677 gen_load_fpr64(ctx, t1, rt);
4678 tcg_gen_andc_tl(t1, t1, t2);
4679 tcg_temp_free(t2);
4680 tcg_gen_or_tl(t0, t0, t1);
4681 tcg_temp_free(t1);
4682 gen_store_fpr64(ctx, t0, rt);
4683 break;
4684 case OPC_GSLDRC1:
4685 check_cp1_enabled(ctx);
4686 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4687 t1 = tcg_temp_new();
4688 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4689 tcg_gen_andi_tl(t1, t0, 7);
4690#ifdef TARGET_WORDS_BIGENDIAN
4691 tcg_gen_xori_tl(t1, t1, 7);
4692#endif
4693 tcg_gen_shli_tl(t1, t1, 3);
4694 tcg_gen_andi_tl(t0, t0, ~7);
4695 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4696 tcg_gen_shr_tl(t0, t0, t1);
4697 tcg_gen_xori_tl(t1, t1, 63);
4698 t2 = tcg_const_tl(0xfffffffffffffffeull);
4699 tcg_gen_shl_tl(t2, t2, t1);
4700 gen_load_fpr64(ctx, t1, rt);
4701 tcg_gen_and_tl(t1, t1, t2);
4702 tcg_temp_free(t2);
4703 tcg_gen_or_tl(t0, t0, t1);
4704 tcg_temp_free(t1);
4705 gen_store_fpr64(ctx, t0, rt);
4706 break;
4707#endif
4708 default:
4709 MIPS_INVAL("loongson_gsshfl");
3a4ef3b7 4710 gen_reserved_instruction(ctx);
fd723105
JY
4711 break;
4712 }
4713 break;
4714 case OPC_GSSHFS:
4715 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4716 case OPC_GSSWLC1:
4717 check_cp1_enabled(ctx);
4718 t1 = tcg_temp_new();
4719 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4720 fp0 = tcg_temp_new_i32();
4721 gen_load_fpr32(ctx, fp0, rt);
4722 tcg_gen_ext_i32_tl(t1, fp0);
4723 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4724 tcg_temp_free_i32(fp0);
4725 tcg_temp_free(t1);
4726 break;
4727 case OPC_GSSWRC1:
4728 check_cp1_enabled(ctx);
4729 t1 = tcg_temp_new();
4730 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4731 fp0 = tcg_temp_new_i32();
4732 gen_load_fpr32(ctx, fp0, rt);
4733 tcg_gen_ext_i32_tl(t1, fp0);
4734 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4735 tcg_temp_free_i32(fp0);
4736 tcg_temp_free(t1);
4737 break;
4738#if defined(TARGET_MIPS64)
4739 case OPC_GSSDLC1:
4740 check_cp1_enabled(ctx);
4741 t1 = tcg_temp_new();
4742 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4743 gen_load_fpr64(ctx, t1, rt);
4744 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4745 tcg_temp_free(t1);
4746 break;
4747 case OPC_GSSDRC1:
4748 check_cp1_enabled(ctx);
4749 t1 = tcg_temp_new();
4750 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4751 gen_load_fpr64(ctx, t1, rt);
4752 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4753 tcg_temp_free(t1);
4754 break;
4755#endif
4756 default:
4757 MIPS_INVAL("loongson_gsshfs");
3a4ef3b7 4758 gen_reserved_instruction(ctx);
fd723105
JY
4759 break;
4760 }
4761 break;
e10a0ca1
JY
4762 default:
4763 MIPS_INVAL("loongson_gslsq");
3a4ef3b7 4764 gen_reserved_instruction(ctx);
e10a0ca1
JY
4765 break;
4766 }
4767 tcg_temp_free(t0);
4768}
4769
90e22a57
JY
4770/* Loongson EXT LDC2/SDC2 */
4771static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4772 int rs, int rd)
4773{
4774 int offset = sextract32(ctx->opcode, 3, 8);
4775 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4776 TCGv t0, t1;
4777 TCGv_i32 fp0;
4778
4779 /* Pre-conditions */
4780 switch (opc) {
4781 case OPC_GSLBX:
4782 case OPC_GSLHX:
4783 case OPC_GSLWX:
4784 case OPC_GSLDX:
4785 /* prefetch, implement as NOP */
4786 if (rt == 0) {
4787 return;
4788 }
4789 break;
4790 case OPC_GSSBX:
4791 case OPC_GSSHX:
4792 case OPC_GSSWX:
4793 case OPC_GSSDX:
4794 break;
4795 case OPC_GSLWXC1:
4796#if defined(TARGET_MIPS64)
4797 case OPC_GSLDXC1:
4798#endif
4799 check_cp1_enabled(ctx);
4800 /* prefetch, implement as NOP */
4801 if (rt == 0) {
4802 return;
4803 }
4804 break;
4805 case OPC_GSSWXC1:
4806#if defined(TARGET_MIPS64)
4807 case OPC_GSSDXC1:
4808#endif
4809 check_cp1_enabled(ctx);
4810 break;
4811 default:
4812 MIPS_INVAL("loongson_lsdc2");
3a4ef3b7 4813 gen_reserved_instruction(ctx);
90e22a57
JY
4814 return;
4815 break;
4816 }
4817
4818 t0 = tcg_temp_new();
4819
4820 gen_base_offset_addr(ctx, t0, rs, offset);
4821 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4822
4823 switch (opc) {
4824 case OPC_GSLBX:
4825 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4826 gen_store_gpr(t0, rt);
4827 break;
4828 case OPC_GSLHX:
4829 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4830 ctx->default_tcg_memop_mask);
4831 gen_store_gpr(t0, rt);
4832 break;
4833 case OPC_GSLWX:
4834 gen_base_offset_addr(ctx, t0, rs, offset);
4835 if (rd) {
4836 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4837 }
4838 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4839 ctx->default_tcg_memop_mask);
4840 gen_store_gpr(t0, rt);
4841 break;
4842#if defined(TARGET_MIPS64)
4843 case OPC_GSLDX:
4844 gen_base_offset_addr(ctx, t0, rs, offset);
4845 if (rd) {
4846 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4847 }
4848 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4849 ctx->default_tcg_memop_mask);
4850 gen_store_gpr(t0, rt);
4851 break;
4852#endif
4853 case OPC_GSLWXC1:
4854 check_cp1_enabled(ctx);
4855 gen_base_offset_addr(ctx, t0, rs, offset);
4856 if (rd) {
4857 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4858 }
4859 fp0 = tcg_temp_new_i32();
4860 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4861 ctx->default_tcg_memop_mask);
4862 gen_store_fpr32(ctx, fp0, rt);
4863 tcg_temp_free_i32(fp0);
4864 break;
4865#if defined(TARGET_MIPS64)
4866 case OPC_GSLDXC1:
4867 check_cp1_enabled(ctx);
4868 gen_base_offset_addr(ctx, t0, rs, offset);
4869 if (rd) {
4870 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4871 }
4872 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4873 ctx->default_tcg_memop_mask);
4874 gen_store_fpr64(ctx, t0, rt);
4875 break;
4876#endif
4877 case OPC_GSSBX:
4878 t1 = tcg_temp_new();
4879 gen_load_gpr(t1, rt);
4880 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4881 tcg_temp_free(t1);
4882 break;
4883 case OPC_GSSHX:
4884 t1 = tcg_temp_new();
4885 gen_load_gpr(t1, rt);
4886 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4887 ctx->default_tcg_memop_mask);
4888 tcg_temp_free(t1);
4889 break;
4890 case OPC_GSSWX:
4891 t1 = tcg_temp_new();
4892 gen_load_gpr(t1, rt);
4893 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4894 ctx->default_tcg_memop_mask);
4895 tcg_temp_free(t1);
4896 break;
4897#if defined(TARGET_MIPS64)
4898 case OPC_GSSDX:
4899 t1 = tcg_temp_new();
4900 gen_load_gpr(t1, rt);
4901 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4902 ctx->default_tcg_memop_mask);
4903 tcg_temp_free(t1);
4904 break;
4905#endif
4906 case OPC_GSSWXC1:
4907 fp0 = tcg_temp_new_i32();
4908 gen_load_fpr32(ctx, fp0, rt);
4909 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4910 ctx->default_tcg_memop_mask);
4911 tcg_temp_free_i32(fp0);
4912 break;
4913#if defined(TARGET_MIPS64)
4914 case OPC_GSSDXC1:
4915 t1 = tcg_temp_new();
4916 gen_load_fpr64(ctx, t1, rt);
4917 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4918 ctx->default_tcg_memop_mask);
4919 tcg_temp_free(t1);
4920 break;
4921#endif
4922 default:
4923 break;
4924 }
4925
4926 tcg_temp_free(t0);
4927}
4928
6af0bf9c 4929/* Traps */
71375b59
AM
4930static void gen_trap(DisasContext *ctx, uint32_t opc,
4931 int rs, int rt, int16_t imm)
6af0bf9c
FB
4932{
4933 int cond;
cdc0faa6 4934 TCGv t0 = tcg_temp_new();
1ba74fb8 4935 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4936
4937 cond = 0;
4938 /* Load needed operands */
4939 switch (opc) {
4940 case OPC_TEQ:
4941 case OPC_TGE:
4942 case OPC_TGEU:
4943 case OPC_TLT:
4944 case OPC_TLTU:
4945 case OPC_TNE:
4946 /* Compare two registers */
4947 if (rs != rt) {
be24bb4f
TS
4948 gen_load_gpr(t0, rs);
4949 gen_load_gpr(t1, rt);
6af0bf9c
FB
4950 cond = 1;
4951 }
179e32bb 4952 break;
6af0bf9c
FB
4953 case OPC_TEQI:
4954 case OPC_TGEI:
4955 case OPC_TGEIU:
4956 case OPC_TLTI:
4957 case OPC_TLTIU:
4958 case OPC_TNEI:
4959 /* Compare register to immediate */
4960 if (rs != 0 || imm != 0) {
be24bb4f
TS
4961 gen_load_gpr(t0, rs);
4962 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4963 cond = 1;
4964 }
4965 break;
4966 }
4967 if (cond == 0) {
4968 switch (opc) {
4969 case OPC_TEQ: /* rs == rs */
4970 case OPC_TEQI: /* r0 == 0 */
4971 case OPC_TGE: /* rs >= rs */
4972 case OPC_TGEI: /* r0 >= 0 */
4973 case OPC_TGEU: /* rs >= rs unsigned */
4974 case OPC_TGEIU: /* r0 >= 0 unsigned */
4975 /* Always trap */
9c708c7f 4976 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
4977 break;
4978 case OPC_TLT: /* rs < rs */
4979 case OPC_TLTI: /* r0 < 0 */
4980 case OPC_TLTU: /* rs < rs unsigned */
4981 case OPC_TLTIU: /* r0 < 0 unsigned */
4982 case OPC_TNE: /* rs != rs */
4983 case OPC_TNEI: /* r0 != 0 */
ead9360e 4984 /* Never trap: treat as NOP. */
cdc0faa6 4985 break;
6af0bf9c
FB
4986 }
4987 } else {
42a268c2 4988 TCGLabel *l1 = gen_new_label();
cdc0faa6 4989
6af0bf9c
FB
4990 switch (opc) {
4991 case OPC_TEQ:
4992 case OPC_TEQI:
cdc0faa6 4993 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4994 break;
4995 case OPC_TGE:
4996 case OPC_TGEI:
cdc0faa6 4997 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4998 break;
4999 case OPC_TGEU:
5000 case OPC_TGEIU:
cdc0faa6 5001 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5002 break;
5003 case OPC_TLT:
5004 case OPC_TLTI:
cdc0faa6 5005 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5006 break;
5007 case OPC_TLTU:
5008 case OPC_TLTIU:
cdc0faa6 5009 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5010 break;
5011 case OPC_TNE:
5012 case OPC_TNEI:
cdc0faa6 5013 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5014 break;
6af0bf9c 5015 }
cdc0faa6 5016 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5017 gen_set_label(l1);
5018 }
be24bb4f
TS
5019 tcg_temp_free(t0);
5020 tcg_temp_free(t1);
6af0bf9c
FB
5021}
5022
90aa39a1
SF
5023static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5024{
eeb3bba8 5025 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5026 return false;
5027 }
5028
5029#ifndef CONFIG_USER_ONLY
eeb3bba8 5030 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5031#else
5032 return true;
5033#endif
5034}
5035
356265ae 5036static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5037{
90aa39a1 5038 if (use_goto_tb(ctx, dest)) {
57fec1fe 5039 tcg_gen_goto_tb(n);
9b9e4393 5040 gen_save_pc(dest);
07ea28b4 5041 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5042 } else {
9b9e4393 5043 gen_save_pc(dest);
eeb3bba8 5044 if (ctx->base.singlestep_enabled) {
7b270ef2 5045 save_cpu_state(ctx, 0);
9c708c7f 5046 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5047 }
7f11636d 5048 tcg_gen_lookup_and_goto_ptr();
6e256c93 5049 }
c53be334
FB
5050}
5051
6af0bf9c 5052/* Branches (before delay slot) */
71375b59
AM
5053static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5054 int insn_bytes,
5055 int rs, int rt, int32_t offset,
5056 int delayslot_size)
6af0bf9c 5057{
d077b6f7 5058 target_ulong btgt = -1;
3ad4bb2d 5059 int blink = 0;
2fdbad25 5060 int bcond_compute = 0;
1ba74fb8
AJ
5061 TCGv t0 = tcg_temp_new();
5062 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5063
5064 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5065#ifdef MIPS_DEBUG_DISAS
339cd2a8 5066 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5067 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5068#endif
3a4ef3b7 5069 gen_reserved_instruction(ctx);
6c5c1e20 5070 goto out;
3ad4bb2d 5071 }
6af0bf9c 5072
6af0bf9c
FB
5073 /* Load needed operands */
5074 switch (opc) {
5075 case OPC_BEQ:
5076 case OPC_BEQL:
5077 case OPC_BNE:
5078 case OPC_BNEL:
5079 /* Compare two registers */
5080 if (rs != rt) {
6c5c1e20
TS
5081 gen_load_gpr(t0, rs);
5082 gen_load_gpr(t1, rt);
2fdbad25 5083 bcond_compute = 1;
6af0bf9c 5084 }
eeb3bba8 5085 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5086 break;
5087 case OPC_BGEZ:
5088 case OPC_BGEZAL:
5089 case OPC_BGEZALL:
5090 case OPC_BGEZL:
5091 case OPC_BGTZ:
5092 case OPC_BGTZL:
5093 case OPC_BLEZ:
5094 case OPC_BLEZL:
5095 case OPC_BLTZ:
5096 case OPC_BLTZAL:
5097 case OPC_BLTZALL:
5098 case OPC_BLTZL:
5099 /* Compare to zero */
5100 if (rs != 0) {
6c5c1e20 5101 gen_load_gpr(t0, rs);
2fdbad25 5102 bcond_compute = 1;
6af0bf9c 5103 }
eeb3bba8 5104 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5105 break;
e45a93e2
JL
5106 case OPC_BPOSGE32:
5107#if defined(TARGET_MIPS64)
5108 case OPC_BPOSGE64:
5109 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5110#else
5111 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5112#endif
5113 bcond_compute = 1;
eeb3bba8 5114 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5115 break;
6af0bf9c
FB
5116 case OPC_J:
5117 case OPC_JAL:
364d4831 5118 case OPC_JALX:
6af0bf9c 5119 /* Jump to immediate */
eeb3bba8
EC
5120 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5121 (uint32_t)offset;
6af0bf9c
FB
5122 break;
5123 case OPC_JR:
5124 case OPC_JALR:
5125 /* Jump to register */
7a387fff 5126 if (offset != 0 && offset != 16) {
7480515f
AM
5127 /*
5128 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5129 * others are reserved.
5130 */
923617a3 5131 MIPS_INVAL("jump hint");
3a4ef3b7 5132 gen_reserved_instruction(ctx);
6c5c1e20 5133 goto out;
6af0bf9c 5134 }
d077b6f7 5135 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5136 break;
5137 default:
5138 MIPS_INVAL("branch/jump");
3a4ef3b7 5139 gen_reserved_instruction(ctx);
6c5c1e20 5140 goto out;
6af0bf9c 5141 }
2fdbad25 5142 if (bcond_compute == 0) {
6af0bf9c
FB
5143 /* No condition to be computed */
5144 switch (opc) {
5145 case OPC_BEQ: /* rx == rx */
5146 case OPC_BEQL: /* rx == rx likely */
5147 case OPC_BGEZ: /* 0 >= 0 */
5148 case OPC_BGEZL: /* 0 >= 0 likely */
5149 case OPC_BLEZ: /* 0 <= 0 */
5150 case OPC_BLEZL: /* 0 <= 0 likely */
5151 /* Always take */
4ad40f36 5152 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5153 break;
5154 case OPC_BGEZAL: /* 0 >= 0 */
5155 case OPC_BGEZALL: /* 0 >= 0 likely */
5156 /* Always take and link */
5157 blink = 31;
4ad40f36 5158 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5159 break;
5160 case OPC_BNE: /* rx != rx */
5161 case OPC_BGTZ: /* 0 > 0 */
5162 case OPC_BLTZ: /* 0 < 0 */
ead9360e 5163 /* Treat as NOP. */
6c5c1e20 5164 goto out;
eeef26cd 5165 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
5166 /*
5167 * Handle as an unconditional branch to get correct delay
5168 * slot checking.
5169 */
3c824109 5170 blink = 31;
eeb3bba8 5171 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 5172 ctx->hflags |= MIPS_HFLAG_B;
3c824109 5173 break;
eeef26cd 5174 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 5175 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 5176 /* Skip the instruction in the delay slot */
eeb3bba8 5177 ctx->base.pc_next += 4;
6c5c1e20 5178 goto out;
6af0bf9c
FB
5179 case OPC_BNEL: /* rx != rx likely */
5180 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
5181 case OPC_BLTZL: /* 0 < 0 likely */
5182 /* Skip the instruction in the delay slot */
eeb3bba8 5183 ctx->base.pc_next += 4;
6c5c1e20 5184 goto out;
6af0bf9c 5185 case OPC_J:
4ad40f36 5186 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 5187 break;
364d4831
NF
5188 case OPC_JALX:
5189 ctx->hflags |= MIPS_HFLAG_BX;
5190 /* Fallthrough */
6af0bf9c
FB
5191 case OPC_JAL:
5192 blink = 31;
4ad40f36 5193 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5194 break;
5195 case OPC_JR:
4ad40f36 5196 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5197 break;
5198 case OPC_JALR:
5199 blink = rt;
4ad40f36 5200 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5201 break;
5202 default:
5203 MIPS_INVAL("branch/jump");
3a4ef3b7 5204 gen_reserved_instruction(ctx);
6c5c1e20 5205 goto out;
6af0bf9c
FB
5206 }
5207 } else {
5208 switch (opc) {
5209 case OPC_BEQ:
e68dd28f 5210 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5211 goto not_likely;
5212 case OPC_BEQL:
e68dd28f 5213 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5214 goto likely;
5215 case OPC_BNE:
e68dd28f 5216 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5217 goto not_likely;
5218 case OPC_BNEL:
e68dd28f 5219 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5220 goto likely;
5221 case OPC_BGEZ:
e68dd28f 5222 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5223 goto not_likely;
5224 case OPC_BGEZL:
e68dd28f 5225 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5226 goto likely;
5227 case OPC_BGEZAL:
e68dd28f 5228 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5229 blink = 31;
5230 goto not_likely;
5231 case OPC_BGEZALL:
e68dd28f 5232 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 5233 blink = 31;
6af0bf9c
FB
5234 goto likely;
5235 case OPC_BGTZ:
e68dd28f 5236 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5237 goto not_likely;
5238 case OPC_BGTZL:
e68dd28f 5239 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5240 goto likely;
5241 case OPC_BLEZ:
e68dd28f 5242 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5243 goto not_likely;
5244 case OPC_BLEZL:
e68dd28f 5245 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5246 goto likely;
5247 case OPC_BLTZ:
e68dd28f 5248 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
5249 goto not_likely;
5250 case OPC_BLTZL:
e68dd28f 5251 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5252 goto likely;
e45a93e2
JL
5253 case OPC_BPOSGE32:
5254 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
5255 goto not_likely;
5256#if defined(TARGET_MIPS64)
5257 case OPC_BPOSGE64:
5258 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
5259 goto not_likely;
5260#endif
6af0bf9c 5261 case OPC_BLTZAL:
e68dd28f 5262 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5263 blink = 31;
6af0bf9c 5264 not_likely:
4ad40f36 5265 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
5266 break;
5267 case OPC_BLTZALL:
e68dd28f 5268 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5269 blink = 31;
6af0bf9c 5270 likely:
4ad40f36 5271 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 5272 break;
c53f4a62
TS
5273 default:
5274 MIPS_INVAL("conditional branch/jump");
3a4ef3b7 5275 gen_reserved_instruction(ctx);
6c5c1e20 5276 goto out;
6af0bf9c 5277 }
6af0bf9c 5278 }
9b9e4393 5279
d077b6f7 5280 ctx->btarget = btgt;
b231c103
YK
5281
5282 switch (delayslot_size) {
5283 case 2:
5284 ctx->hflags |= MIPS_HFLAG_BDS16;
5285 break;
5286 case 4:
5287 ctx->hflags |= MIPS_HFLAG_BDS32;
5288 break;
5289 }
5290
6af0bf9c 5291 if (blink > 0) {
b231c103 5292 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
5293 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5294
eeb3bba8
EC
5295 tcg_gen_movi_tl(cpu_gpr[blink],
5296 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 5297 }
6c5c1e20
TS
5298
5299 out:
1f8929d2 5300 if (insn_bytes == 2) {
364d4831 5301 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 5302 }
6c5c1e20
TS
5303 tcg_temp_free(t0);
5304 tcg_temp_free(t1);
6af0bf9c
FB
5305}
5306
764371d2
SM
5307
5308/* nanoMIPS Branches */
5309static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5310 int insn_bytes,
5311 int rs, int rt, int32_t offset)
5312{
5313 target_ulong btgt = -1;
5314 int bcond_compute = 0;
5315 TCGv t0 = tcg_temp_new();
5316 TCGv t1 = tcg_temp_new();
5317
5318 /* Load needed operands */
5319 switch (opc) {
5320 case OPC_BEQ:
5321 case OPC_BNE:
5322 /* Compare two registers */
5323 if (rs != rt) {
5324 gen_load_gpr(t0, rs);
5325 gen_load_gpr(t1, rt);
5326 bcond_compute = 1;
5327 }
5328 btgt = ctx->base.pc_next + insn_bytes + offset;
5329 break;
5330 case OPC_BGEZAL:
5331 /* Compare to zero */
5332 if (rs != 0) {
5333 gen_load_gpr(t0, rs);
5334 bcond_compute = 1;
5335 }
5336 btgt = ctx->base.pc_next + insn_bytes + offset;
5337 break;
5338 case OPC_BPOSGE32:
5339 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5340 bcond_compute = 1;
5341 btgt = ctx->base.pc_next + insn_bytes + offset;
5342 break;
5343 case OPC_JR:
5344 case OPC_JALR:
5345 /* Jump to register */
5346 if (offset != 0 && offset != 16) {
7480515f
AM
5347 /*
5348 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5349 * others are reserved.
5350 */
764371d2 5351 MIPS_INVAL("jump hint");
3a4ef3b7 5352 gen_reserved_instruction(ctx);
764371d2
SM
5353 goto out;
5354 }
5355 gen_load_gpr(btarget, rs);
5356 break;
5357 default:
5358 MIPS_INVAL("branch/jump");
3a4ef3b7 5359 gen_reserved_instruction(ctx);
764371d2
SM
5360 goto out;
5361 }
5362 if (bcond_compute == 0) {
5363 /* No condition to be computed */
5364 switch (opc) {
5365 case OPC_BEQ: /* rx == rx */
5366 /* Always take */
5367 ctx->hflags |= MIPS_HFLAG_B;
5368 break;
5369 case OPC_BGEZAL: /* 0 >= 0 */
5370 /* Always take and link */
5371 tcg_gen_movi_tl(cpu_gpr[31],
5372 ctx->base.pc_next + insn_bytes);
5373 ctx->hflags |= MIPS_HFLAG_B;
5374 break;
5375 case OPC_BNE: /* rx != rx */
5376 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5377 /* Skip the instruction in the delay slot */
5378 ctx->base.pc_next += 4;
5379 goto out;
5380 case OPC_JR:
5381 ctx->hflags |= MIPS_HFLAG_BR;
5382 break;
5383 case OPC_JALR:
5384 if (rt > 0) {
5385 tcg_gen_movi_tl(cpu_gpr[rt],
5386 ctx->base.pc_next + insn_bytes);
5387 }
5388 ctx->hflags |= MIPS_HFLAG_BR;
5389 break;
5390 default:
5391 MIPS_INVAL("branch/jump");
3a4ef3b7 5392 gen_reserved_instruction(ctx);
764371d2
SM
5393 goto out;
5394 }
5395 } else {
5396 switch (opc) {
5397 case OPC_BEQ:
5398 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5399 goto not_likely;
5400 case OPC_BNE:
5401 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5402 goto not_likely;
5403 case OPC_BGEZAL:
5404 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5405 tcg_gen_movi_tl(cpu_gpr[31],
5406 ctx->base.pc_next + insn_bytes);
5407 goto not_likely;
5408 case OPC_BPOSGE32:
5409 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5410 not_likely:
5411 ctx->hflags |= MIPS_HFLAG_BC;
5412 break;
5413 default:
5414 MIPS_INVAL("conditional branch/jump");
3a4ef3b7 5415 gen_reserved_instruction(ctx);
764371d2
SM
5416 goto out;
5417 }
5418 }
5419
5420 ctx->btarget = btgt;
5421
5422 out:
5423 if (insn_bytes == 2) {
5424 ctx->hflags |= MIPS_HFLAG_B16;
5425 }
5426 tcg_temp_free(t0);
5427 tcg_temp_free(t1);
5428}
5429
5430
7a387fff 5431/* special3 bitfield operations */
235785e8
AM
5432static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5433 int rs, int lsb, int msb)
7a387fff 5434{
a7812ae4
PB
5435 TCGv t0 = tcg_temp_new();
5436 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
5437
5438 gen_load_gpr(t1, rs);
7a387fff
TS
5439 switch (opc) {
5440 case OPC_EXT:
b7f26e52 5441 if (lsb + msb > 31) {
7a387fff 5442 goto fail;
b7f26e52 5443 }
505ad7c2 5444 if (msb != 31) {
6eebb7a4 5445 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 5446 } else {
7480515f
AM
5447 /*
5448 * The two checks together imply that lsb == 0,
5449 * so this is a simple sign-extension.
5450 */
6eebb7a4 5451 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 5452 }
7a387fff 5453 break;
c6d6dd7c 5454#if defined(TARGET_MIPS64)
7a387fff 5455 case OPC_DEXTU:
b7f26e52
RH
5456 lsb += 32;
5457 goto do_dext;
5458 case OPC_DEXTM:
5459 msb += 32;
5460 goto do_dext;
7a387fff 5461 case OPC_DEXT:
b7f26e52
RH
5462 do_dext:
5463 if (lsb + msb > 63) {
5464 goto fail;
5465 }
6eebb7a4 5466 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 5467 break;
c6d6dd7c 5468#endif
7a387fff 5469 case OPC_INS:
b7f26e52 5470 if (lsb > msb) {
7a387fff 5471 goto fail;
b7f26e52 5472 }
6c5c1e20 5473 gen_load_gpr(t0, rt);
e0d002f1 5474 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 5475 tcg_gen_ext32s_tl(t0, t0);
7a387fff 5476 break;
c6d6dd7c 5477#if defined(TARGET_MIPS64)
7a387fff 5478 case OPC_DINSU:
b7f26e52
RH
5479 lsb += 32;
5480 /* FALLTHRU */
5481 case OPC_DINSM:
5482 msb += 32;
5483 /* FALLTHRU */
7a387fff 5484 case OPC_DINS:
b7f26e52
RH
5485 if (lsb > msb) {
5486 goto fail;
5487 }
6c5c1e20 5488 gen_load_gpr(t0, rt);
e0d002f1 5489 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 5490 break;
c6d6dd7c 5491#endif
7a387fff
TS
5492 default:
5493fail:
5494 MIPS_INVAL("bitops");
3a4ef3b7 5495 gen_reserved_instruction(ctx);
6c5c1e20
TS
5496 tcg_temp_free(t0);
5497 tcg_temp_free(t1);
7a387fff
TS
5498 return;
5499 }
6c5c1e20
TS
5500 gen_store_gpr(t0, rt);
5501 tcg_temp_free(t0);
5502 tcg_temp_free(t1);
7a387fff
TS
5503}
5504
235785e8 5505static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 5506{
3a55fa47 5507 TCGv t0;
49bcf33c 5508
3a55fa47
AJ
5509 if (rd == 0) {
5510 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
5511 return;
5512 }
5513
5514 t0 = tcg_temp_new();
5515 gen_load_gpr(t0, rt);
49bcf33c
AJ
5516 switch (op2) {
5517 case OPC_WSBH:
3a55fa47
AJ
5518 {
5519 TCGv t1 = tcg_temp_new();
06a57e5c 5520 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
5521
5522 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5523 tcg_gen_and_tl(t1, t1, t2);
5524 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5525 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5526 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 5527 tcg_temp_free(t2);
3a55fa47
AJ
5528 tcg_temp_free(t1);
5529 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5530 }
49bcf33c
AJ
5531 break;
5532 case OPC_SEB:
3a55fa47 5533 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5534 break;
5535 case OPC_SEH:
3a55fa47 5536 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5537 break;
5538#if defined(TARGET_MIPS64)
5539 case OPC_DSBH:
3a55fa47
AJ
5540 {
5541 TCGv t1 = tcg_temp_new();
06a57e5c 5542 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
5543
5544 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5545 tcg_gen_and_tl(t1, t1, t2);
5546 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5547 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5548 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5549 tcg_temp_free(t2);
3a55fa47
AJ
5550 tcg_temp_free(t1);
5551 }
49bcf33c
AJ
5552 break;
5553 case OPC_DSHD:
3a55fa47
AJ
5554 {
5555 TCGv t1 = tcg_temp_new();
06a57e5c 5556 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
5557
5558 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
5559 tcg_gen_and_tl(t1, t1, t2);
5560 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5561 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
5562 tcg_gen_or_tl(t0, t0, t1);
5563 tcg_gen_shri_tl(t1, t0, 32);
5564 tcg_gen_shli_tl(t0, t0, 32);
5565 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5566 tcg_temp_free(t2);
3a55fa47
AJ
5567 tcg_temp_free(t1);
5568 }
49bcf33c
AJ
5569 break;
5570#endif
5571 default:
5572 MIPS_INVAL("bsfhl");
3a4ef3b7 5573 gen_reserved_instruction(ctx);
49bcf33c 5574 tcg_temp_free(t0);
49bcf33c
AJ
5575 return;
5576 }
49bcf33c 5577 tcg_temp_free(t0);
49bcf33c
AJ
5578}
5579
821f2008
JH
5580static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5581 int rt, int bits)
284b731a 5582{
1f1b4c00
YK
5583 TCGv t0;
5584 if (rd == 0) {
5585 /* Treat as NOP. */
5586 return;
5587 }
5588 t0 = tcg_temp_new();
821f2008
JH
5589 if (bits == 0 || bits == wordsz) {
5590 if (bits == 0) {
5591 gen_load_gpr(t0, rt);
5592 } else {
5593 gen_load_gpr(t0, rs);
5594 }
5595 switch (wordsz) {
5596 case 32:
51243852
MD
5597 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5598 break;
5599#if defined(TARGET_MIPS64)
821f2008 5600 case 64:
51243852
MD
5601 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5602 break;
5603#endif
5604 }
1f1b4c00
YK
5605 } else {
5606 TCGv t1 = tcg_temp_new();
821f2008 5607 gen_load_gpr(t0, rt);
1f1b4c00 5608 gen_load_gpr(t1, rs);
821f2008
JH
5609 switch (wordsz) {
5610 case 32:
1f1b4c00
YK
5611 {
5612 TCGv_i64 t2 = tcg_temp_new_i64();
5613 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 5614 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
5615 gen_move_low32(cpu_gpr[rd], t2);
5616 tcg_temp_free_i64(t2);
5617 }
5618 break;
284b731a 5619#if defined(TARGET_MIPS64)
821f2008
JH
5620 case 64:
5621 tcg_gen_shli_tl(t0, t0, bits);
5622 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
5623 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5624 break;
284b731a 5625#endif
1f1b4c00
YK
5626 }
5627 tcg_temp_free(t1);
5628 }
5629
5630 tcg_temp_free(t0);
5631}
5632
821f2008
JH
5633static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5634 int bp)
5635{
5636 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5637}
5638
5639static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5640 int shift)
5641{
5642 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5643}
5644
1f1b4c00
YK
5645static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5646{
5647 TCGv t0;
5648 if (rd == 0) {
5649 /* Treat as NOP. */
5650 return;
5651 }
5652 t0 = tcg_temp_new();
5653 gen_load_gpr(t0, rt);
5654 switch (opc) {
5655 case OPC_BITSWAP:
5656 gen_helper_bitswap(cpu_gpr[rd], t0);
5657 break;
5658#if defined(TARGET_MIPS64)
5659 case OPC_DBITSWAP:
5660 gen_helper_dbitswap(cpu_gpr[rd], t0);
5661 break;
5662#endif
5663 }
5664 tcg_temp_free(t0);
284b731a
LA
5665}
5666
1f1b4c00
YK
5667#ifndef CONFIG_USER_ONLY
5668/* CP0 (MMU and control) */
5204ea79
LA
5669static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5670{
5671 TCGv_i64 t0 = tcg_temp_new_i64();
5672 TCGv_i64 t1 = tcg_temp_new_i64();
5673
5674 tcg_gen_ext_tl_i64(t0, arg);
5675 tcg_gen_ld_i64(t1, cpu_env, off);
5676#if defined(TARGET_MIPS64)
5677 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5678#else
5679 tcg_gen_concat32_i64(t1, t1, t0);
5680#endif
5681 tcg_gen_st_i64(t1, cpu_env, off);
5682 tcg_temp_free_i64(t1);
5683 tcg_temp_free_i64(t0);
5684}
5685
5686static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5687{
5688 TCGv_i64 t0 = tcg_temp_new_i64();
5689 TCGv_i64 t1 = tcg_temp_new_i64();
5690
5691 tcg_gen_ext_tl_i64(t0, arg);
5692 tcg_gen_ld_i64(t1, cpu_env, off);
5693 tcg_gen_concat32_i64(t1, t1, t0);
5694 tcg_gen_st_i64(t1, cpu_env, off);
5695 tcg_temp_free_i64(t1);
5696 tcg_temp_free_i64(t0);
5697}
5698
5699static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5700{
5701 TCGv_i64 t0 = tcg_temp_new_i64();
5702
5703 tcg_gen_ld_i64(t0, cpu_env, off);
5704#if defined(TARGET_MIPS64)
5705 tcg_gen_shri_i64(t0, t0, 30);
5706#else
5707 tcg_gen_shri_i64(t0, t0, 32);
5708#endif
5709 gen_move_low32(arg, t0);
5710 tcg_temp_free_i64(t0);
5711}
5712
5713static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5714{
5715 TCGv_i64 t0 = tcg_temp_new_i64();
5716
5717 tcg_gen_ld_i64(t0, cpu_env, off);
5718 tcg_gen_shri_i64(t0, t0, 32 + shift);
5719 gen_move_low32(arg, t0);
5720 tcg_temp_free_i64(t0);
5721}
5722
235785e8 5723static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 5724{
d9bea114 5725 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 5726
d9bea114
AJ
5727 tcg_gen_ld_i32(t0, cpu_env, off);
5728 tcg_gen_ext_i32_tl(arg, t0);
5729 tcg_temp_free_i32(t0);
4f57689a
TS
5730}
5731
235785e8 5732static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 5733{
d9bea114
AJ
5734 tcg_gen_ld_tl(arg, cpu_env, off);
5735 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
5736}
5737
235785e8 5738static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 5739{
d9bea114 5740 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 5741
d9bea114
AJ
5742 tcg_gen_trunc_tl_i32(t0, arg);
5743 tcg_gen_st_i32(t0, cpu_env, off);
5744 tcg_temp_free_i32(t0);
f1aa6320
TS
5745}
5746
c98d3d79
YK
5747#define CP0_CHECK(c) \
5748 do { \
5749 if (!(c)) { \
5750 goto cp0_unimplemented; \
5751 } \
5752 } while (0)
5753
5204ea79
LA
5754static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5755{
294fc2ea 5756 const char *register_name = "invalid";
5204ea79 5757
5204ea79 5758 switch (reg) {
04992c8c 5759 case CP0_REGISTER_02:
5204ea79
LA
5760 switch (sel) {
5761 case 0:
59488dda 5762 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5763 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5764 register_name = "EntryLo0";
5204ea79
LA
5765 break;
5766 default:
c98d3d79 5767 goto cp0_unimplemented;
5204ea79
LA
5768 }
5769 break;
04992c8c 5770 case CP0_REGISTER_03:
5204ea79 5771 switch (sel) {
acd37316 5772 case CP0_REG03__ENTRYLO1:
59488dda 5773 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5774 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5775 register_name = "EntryLo1";
5204ea79
LA
5776 break;
5777 default:
c98d3d79 5778 goto cp0_unimplemented;
5204ea79
LA
5779 }
5780 break;
04992c8c 5781 case CP0_REGISTER_09:
5fb2dcd1 5782 switch (sel) {
e5a98a72 5783 case CP0_REG09__SAAR:
5fb2dcd1
YK
5784 CP0_CHECK(ctx->saar);
5785 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 5786 register_name = "SAAR";
5fb2dcd1
YK
5787 break;
5788 default:
5789 goto cp0_unimplemented;
5790 }
5791 break;
04992c8c 5792 case CP0_REGISTER_17:
5204ea79 5793 switch (sel) {
706ce142 5794 case CP0_REG17__LLADDR:
c7c7e1e9 5795 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 5796 ctx->CP0_LLAddr_shift);
294fc2ea 5797 register_name = "LLAddr";
5204ea79 5798 break;
706ce142 5799 case CP0_REG17__MAAR:
f6d4dd81
YK
5800 CP0_CHECK(ctx->mrp);
5801 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 5802 register_name = "MAAR";
f6d4dd81 5803 break;
5204ea79 5804 default:
c98d3d79 5805 goto cp0_unimplemented;
5204ea79
LA
5806 }
5807 break;
feafe82c
YK
5808 case CP0_REGISTER_19:
5809 switch (sel) {
5810 case CP0_REG19__WATCHHI0:
5811 case CP0_REG19__WATCHHI1:
5812 case CP0_REG19__WATCHHI2:
5813 case CP0_REG19__WATCHHI3:
5814 case CP0_REG19__WATCHHI4:
5815 case CP0_REG19__WATCHHI5:
5816 case CP0_REG19__WATCHHI6:
5817 case CP0_REG19__WATCHHI7:
5818 /* upper 32 bits are only available when Config5MI != 0 */
5819 CP0_CHECK(ctx->mi);
5820 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5821 register_name = "WatchHi";
5822 break;
5823 default:
5824 goto cp0_unimplemented;
5825 }
5826 break;
04992c8c 5827 case CP0_REGISTER_28:
5204ea79
LA
5828 switch (sel) {
5829 case 0:
5830 case 2:
5831 case 4:
5832 case 6:
5833 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 5834 register_name = "TagLo";
5204ea79
LA
5835 break;
5836 default:
c98d3d79 5837 goto cp0_unimplemented;
5204ea79
LA
5838 }
5839 break;
5840 default:
c98d3d79 5841 goto cp0_unimplemented;
5204ea79 5842 }
294fc2ea 5843 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
5844 return;
5845
c98d3d79 5846cp0_unimplemented:
294fc2ea
AM
5847 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5848 register_name, reg, sel);
5204ea79
LA
5849 tcg_gen_movi_tl(arg, 0);
5850}
5851
5852static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5853{
294fc2ea 5854 const char *register_name = "invalid";
5204ea79
LA
5855 uint64_t mask = ctx->PAMask >> 36;
5856
5204ea79 5857 switch (reg) {
04992c8c 5858 case CP0_REGISTER_02:
5204ea79
LA
5859 switch (sel) {
5860 case 0:
59488dda 5861 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5862 tcg_gen_andi_tl(arg, arg, mask);
5863 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5864 register_name = "EntryLo0";
5204ea79
LA
5865 break;
5866 default:
c98d3d79 5867 goto cp0_unimplemented;
5204ea79
LA
5868 }
5869 break;
04992c8c 5870 case CP0_REGISTER_03:
5204ea79 5871 switch (sel) {
acd37316 5872 case CP0_REG03__ENTRYLO1:
59488dda 5873 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5874 tcg_gen_andi_tl(arg, arg, mask);
5875 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5876 register_name = "EntryLo1";
5204ea79
LA
5877 break;
5878 default:
c98d3d79 5879 goto cp0_unimplemented;
5204ea79
LA
5880 }
5881 break;
04992c8c 5882 case CP0_REGISTER_09:
5fb2dcd1 5883 switch (sel) {
e5a98a72 5884 case CP0_REG09__SAAR:
5fb2dcd1
YK
5885 CP0_CHECK(ctx->saar);
5886 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 5887 register_name = "SAAR";
5fb2dcd1
YK
5888 break;
5889 default:
5890 goto cp0_unimplemented;
5891 }
ab8c3410 5892 break;
04992c8c 5893 case CP0_REGISTER_17:
5204ea79 5894 switch (sel) {
706ce142 5895 case CP0_REG17__LLADDR:
7480515f
AM
5896 /*
5897 * LLAddr is read-only (the only exception is bit 0 if LLB is
5898 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5899 * relevant for modern MIPS cores supporting MTHC0, therefore
5900 * treating MTHC0 to LLAddr as NOP.
5901 */
294fc2ea 5902 register_name = "LLAddr";
5204ea79 5903 break;
706ce142 5904 case CP0_REG17__MAAR:
f6d4dd81
YK
5905 CP0_CHECK(ctx->mrp);
5906 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 5907 register_name = "MAAR";
f6d4dd81 5908 break;
5204ea79 5909 default:
c98d3d79 5910 goto cp0_unimplemented;
5204ea79
LA
5911 }
5912 break;
feafe82c
YK
5913 case CP0_REGISTER_19:
5914 switch (sel) {
5915 case CP0_REG19__WATCHHI0:
5916 case CP0_REG19__WATCHHI1:
5917 case CP0_REG19__WATCHHI2:
5918 case CP0_REG19__WATCHHI3:
5919 case CP0_REG19__WATCHHI4:
5920 case CP0_REG19__WATCHHI5:
5921 case CP0_REG19__WATCHHI6:
5922 case CP0_REG19__WATCHHI7:
5923 /* upper 32 bits are only available when Config5MI != 0 */
5924 CP0_CHECK(ctx->mi);
5925 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5926 register_name = "WatchHi";
5927 break;
5928 default:
5929 goto cp0_unimplemented;
5930 }
5931 break;
04992c8c 5932 case CP0_REGISTER_28:
5204ea79
LA
5933 switch (sel) {
5934 case 0:
5935 case 2:
5936 case 4:
5937 case 6:
5938 tcg_gen_andi_tl(arg, arg, mask);
5939 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 5940 register_name = "TagLo";
5204ea79
LA
5941 break;
5942 default:
c98d3d79 5943 goto cp0_unimplemented;
5204ea79
LA
5944 }
5945 break;
5946 default:
c98d3d79 5947 goto cp0_unimplemented;
5204ea79 5948 }
294fc2ea 5949 trace_mips_translate_c0("mthc0", register_name, reg, sel);
bc2eb5ea 5950 return;
5204ea79 5951
c98d3d79 5952cp0_unimplemented:
294fc2ea
AM
5953 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5954 register_name, reg, sel);
5204ea79
LA
5955}
5956
e98c0d17
LA
5957static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5958{
2e211e0a 5959 if (ctx->insn_flags & ISA_MIPS_R6) {
e98c0d17
LA
5960 tcg_gen_movi_tl(arg, 0);
5961 } else {
5962 tcg_gen_movi_tl(arg, ~0);
5963 }
5964}
5965
d75c135e 5966static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 5967{
294fc2ea 5968 const char *register_name = "invalid";
873eb012 5969
1f8929d2 5970 if (sel != 0) {
bbd5e4a2 5971 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 5972 }
e189e748 5973
873eb012 5974 switch (reg) {
04992c8c 5975 case CP0_REGISTER_00:
7a387fff 5976 switch (sel) {
1b142da5 5977 case CP0_REG00__INDEX:
7db13fae 5978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 5979 register_name = "Index";
7a387fff 5980 break;
1b142da5 5981 case CP0_REG00__MVPCONTROL:
f31b035a 5982 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5983 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 5984 register_name = "MVPControl";
ead9360e 5985 break;
1b142da5 5986 case CP0_REG00__MVPCONF0:
f31b035a 5987 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5988 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 5989 register_name = "MVPConf0";
ead9360e 5990 break;
1b142da5 5991 case CP0_REG00__MVPCONF1:
f31b035a 5992 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5993 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 5994 register_name = "MVPConf1";
ead9360e 5995 break;
1b142da5 5996 case CP0_REG00__VPCONTROL:
01bc435b
YK
5997 CP0_CHECK(ctx->vp);
5998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 5999 register_name = "VPControl";
01bc435b 6000 break;
7a387fff 6001 default:
f31b035a 6002 goto cp0_unimplemented;
7a387fff 6003 }
873eb012 6004 break;
04992c8c 6005 case CP0_REGISTER_01:
7a387fff 6006 switch (sel) {
30deb460 6007 case CP0_REG01__RANDOM:
2e211e0a 6008 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 6009 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6010 register_name = "Random";
2423f660 6011 break;
30deb460 6012 case CP0_REG01__VPECONTROL:
f31b035a 6013 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6015 register_name = "VPEControl";
ead9360e 6016 break;
30deb460 6017 case CP0_REG01__VPECONF0:
f31b035a 6018 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6019 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6020 register_name = "VPEConf0";
ead9360e 6021 break;
30deb460 6022 case CP0_REG01__VPECONF1:
f31b035a 6023 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6025 register_name = "VPEConf1";
ead9360e 6026 break;
30deb460 6027 case CP0_REG01__YQMASK:
f31b035a 6028 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6029 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6030 register_name = "YQMask";
ead9360e 6031 break;
30deb460 6032 case CP0_REG01__VPESCHEDULE:
f31b035a 6033 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6034 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6035 register_name = "VPESchedule";
ead9360e 6036 break;
30deb460 6037 case CP0_REG01__VPESCHEFBACK:
f31b035a 6038 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6039 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6040 register_name = "VPEScheFBack";
ead9360e 6041 break;
30deb460 6042 case CP0_REG01__VPEOPT:
f31b035a 6043 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6045 register_name = "VPEOpt";
ead9360e 6046 break;
7a387fff 6047 default:
f31b035a 6048 goto cp0_unimplemented;
7a387fff 6049 }
873eb012 6050 break;
04992c8c 6051 case CP0_REGISTER_02:
7a387fff 6052 switch (sel) {
6d27d5bd 6053 case CP0_REG02__ENTRYLO0:
284b731a
LA
6054 {
6055 TCGv_i64 tmp = tcg_temp_new_i64();
6056 tcg_gen_ld_i64(tmp, cpu_env,
6057 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6058#if defined(TARGET_MIPS64)
284b731a
LA
6059 if (ctx->rxi) {
6060 /* Move RI/XI fields to bits 31:30 */
6061 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6062 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6063 }
7207c7f9 6064#endif
284b731a
LA
6065 gen_move_low32(arg, tmp);
6066 tcg_temp_free_i64(tmp);
6067 }
294fc2ea 6068 register_name = "EntryLo0";
2423f660 6069 break;
6d27d5bd 6070 case CP0_REG02__TCSTATUS:
f31b035a 6071 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6072 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 6073 register_name = "TCStatus";
ead9360e 6074 break;
6d27d5bd 6075 case CP0_REG02__TCBIND:
f31b035a 6076 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6077 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 6078 register_name = "TCBind";
ead9360e 6079 break;
6d27d5bd 6080 case CP0_REG02__TCRESTART:
f31b035a 6081 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6082 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 6083 register_name = "TCRestart";
ead9360e 6084 break;
6d27d5bd 6085 case CP0_REG02__TCHALT:
f31b035a 6086 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6087 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 6088 register_name = "TCHalt";
ead9360e 6089 break;
6d27d5bd 6090 case CP0_REG02__TCCONTEXT:
f31b035a 6091 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6092 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 6093 register_name = "TCContext";
ead9360e 6094 break;
6d27d5bd 6095 case CP0_REG02__TCSCHEDULE:
f31b035a 6096 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6097 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 6098 register_name = "TCSchedule";
ead9360e 6099 break;
6d27d5bd 6100 case CP0_REG02__TCSCHEFBACK:
f31b035a 6101 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6102 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 6103 register_name = "TCScheFBack";
ead9360e 6104 break;
7a387fff 6105 default:
f31b035a 6106 goto cp0_unimplemented;
7a387fff 6107 }
873eb012 6108 break;
04992c8c 6109 case CP0_REGISTER_03:
7a387fff 6110 switch (sel) {
acd37316 6111 case CP0_REG03__ENTRYLO1:
284b731a
LA
6112 {
6113 TCGv_i64 tmp = tcg_temp_new_i64();
6114 tcg_gen_ld_i64(tmp, cpu_env,
6115 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6116#if defined(TARGET_MIPS64)
284b731a
LA
6117 if (ctx->rxi) {
6118 /* Move RI/XI fields to bits 31:30 */
6119 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6120 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6121 }
7207c7f9 6122#endif
284b731a
LA
6123 gen_move_low32(arg, tmp);
6124 tcg_temp_free_i64(tmp);
6125 }
294fc2ea 6126 register_name = "EntryLo1";
2423f660 6127 break;
acd37316 6128 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6129 CP0_CHECK(ctx->vp);
6130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 6131 register_name = "GlobalNumber";
01bc435b 6132 break;
7a387fff 6133 default:
f31b035a 6134 goto cp0_unimplemented;
1579a72e 6135 }
873eb012 6136 break;
04992c8c 6137 case CP0_REGISTER_04:
7a387fff 6138 switch (sel) {
020fe379 6139 case CP0_REG04__CONTEXT:
7db13fae 6140 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6141 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6142 register_name = "Context";
2423f660 6143 break;
020fe379
AM
6144 case CP0_REG04__CONTEXTCONFIG:
6145 /* SmartMIPS ASE */
6146 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 6147 register_name = "ContextConfig";
f31b035a 6148 goto cp0_unimplemented;
020fe379 6149 case CP0_REG04__USERLOCAL:
f31b035a 6150 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6151 tcg_gen_ld_tl(arg, cpu_env,
6152 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6153 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6154 register_name = "UserLocal";
d279279e 6155 break;
99029be1
YK
6156 case CP0_REG04__MMID:
6157 CP0_CHECK(ctx->mi);
6158 gen_helper_mtc0_memorymapid(cpu_env, arg);
6159 register_name = "MMID";
6160 break;
7a387fff 6161 default:
f31b035a 6162 goto cp0_unimplemented;
1579a72e 6163 }
873eb012 6164 break;
04992c8c 6165 case CP0_REGISTER_05:
7a387fff 6166 switch (sel) {
a1e76353 6167 case CP0_REG05__PAGEMASK:
7db13fae 6168 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 6169 register_name = "PageMask";
2423f660 6170 break;
a1e76353 6171 case CP0_REG05__PAGEGRAIN:
7a47bae5 6172 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 6174 register_name = "PageGrain";
2423f660 6175 break;
a1e76353 6176 case CP0_REG05__SEGCTL0:
cec56a73
JH
6177 CP0_CHECK(ctx->sc);
6178 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6179 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6180 register_name = "SegCtl0";
cec56a73 6181 break;
a1e76353 6182 case CP0_REG05__SEGCTL1:
cec56a73
JH
6183 CP0_CHECK(ctx->sc);
6184 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6185 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6186 register_name = "SegCtl1";
cec56a73 6187 break;
a1e76353 6188 case CP0_REG05__SEGCTL2:
cec56a73
JH
6189 CP0_CHECK(ctx->sc);
6190 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6191 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6192 register_name = "SegCtl2";
cec56a73 6193 break;
a1e76353 6194 case CP0_REG05__PWBASE:
5e31fdd5
YK
6195 check_pw(ctx);
6196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6197 register_name = "PWBase";
5e31fdd5 6198 break;
a1e76353 6199 case CP0_REG05__PWFIELD:
fa75ad14
YK
6200 check_pw(ctx);
6201 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 6202 register_name = "PWField";
fa75ad14 6203 break;
a1e76353 6204 case CP0_REG05__PWSIZE:
20b28ebc
YK
6205 check_pw(ctx);
6206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 6207 register_name = "PWSize";
20b28ebc 6208 break;
7a387fff 6209 default:
f31b035a 6210 goto cp0_unimplemented;
1579a72e 6211 }
873eb012 6212 break;
04992c8c 6213 case CP0_REGISTER_06:
7a387fff 6214 switch (sel) {
9023594b 6215 case CP0_REG06__WIRED:
7db13fae 6216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 6217 register_name = "Wired";
2423f660 6218 break;
9023594b 6219 case CP0_REG06__SRSCONF0:
7a47bae5 6220 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 6222 register_name = "SRSConf0";
ead9360e 6223 break;
9023594b 6224 case CP0_REG06__SRSCONF1:
7a47bae5 6225 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 6227 register_name = "SRSConf1";
ead9360e 6228 break;
9023594b 6229 case CP0_REG06__SRSCONF2:
7a47bae5 6230 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 6232 register_name = "SRSConf2";
ead9360e 6233 break;
9023594b 6234 case CP0_REG06__SRSCONF3:
7a47bae5 6235 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 6237 register_name = "SRSConf3";
ead9360e 6238 break;
9023594b 6239 case CP0_REG06__SRSCONF4:
7a47bae5 6240 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 6242 register_name = "SRSConf4";
ead9360e 6243 break;
9023594b 6244 case CP0_REG06__PWCTL:
103be64c
YK
6245 check_pw(ctx);
6246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 6247 register_name = "PWCtl";
103be64c 6248 break;
7a387fff 6249 default:
f31b035a 6250 goto cp0_unimplemented;
1579a72e 6251 }
873eb012 6252 break;
04992c8c 6253 case CP0_REGISTER_07:
7a387fff 6254 switch (sel) {
143a9875 6255 case CP0_REG07__HWRENA:
7a47bae5 6256 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 6258 register_name = "HWREna";
2423f660 6259 break;
7a387fff 6260 default:
f31b035a 6261 goto cp0_unimplemented;
1579a72e 6262 }
8c0fdd85 6263 break;
04992c8c 6264 case CP0_REGISTER_08:
7a387fff 6265 switch (sel) {
67d167d2 6266 case CP0_REG08__BADVADDR:
7db13fae 6267 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 6268 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6269 register_name = "BadVAddr";
2423f660 6270 break;
67d167d2 6271 case CP0_REG08__BADINSTR:
f31b035a
LA
6272 CP0_CHECK(ctx->bi);
6273 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 6274 register_name = "BadInstr";
aea14095 6275 break;
67d167d2 6276 case CP0_REG08__BADINSTRP:
f31b035a
LA
6277 CP0_CHECK(ctx->bp);
6278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 6279 register_name = "BadInstrP";
aea14095 6280 break;
67d167d2 6281 case CP0_REG08__BADINSTRX:
25beba9b
SM
6282 CP0_CHECK(ctx->bi);
6283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6284 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 6285 register_name = "BadInstrX";
25beba9b 6286 break;
05aa7e93 6287 default:
f31b035a 6288 goto cp0_unimplemented;
aea14095 6289 }
873eb012 6290 break;
04992c8c 6291 case CP0_REGISTER_09:
7a387fff 6292 switch (sel) {
e5a98a72 6293 case CP0_REG09__COUNT:
2e70f6ef 6294 /* Mark as an IO operation because we read the time. */
eeb3bba8 6295 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6296 gen_io_start();
7d37435b 6297 }
895c2d04 6298 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
6299 /*
6300 * Break the TB to be able to take timer interrupts immediately
6301 * after reading count. DISAS_STOP isn't sufficient, we need to
6302 * ensure we break completely out of translated code.
6303 */
eeb3bba8
EC
6304 gen_save_pc(ctx->base.pc_next + 4);
6305 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 6306 register_name = "Count";
2423f660 6307 break;
e5a98a72 6308 case CP0_REG09__SAARI:
5fb2dcd1
YK
6309 CP0_CHECK(ctx->saar);
6310 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 6311 register_name = "SAARI";
5fb2dcd1 6312 break;
e5a98a72 6313 case CP0_REG09__SAAR:
5fb2dcd1
YK
6314 CP0_CHECK(ctx->saar);
6315 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 6316 register_name = "SAAR";
5fb2dcd1 6317 break;
7a387fff 6318 default:
f31b035a 6319 goto cp0_unimplemented;
2423f660 6320 }
873eb012 6321 break;
04992c8c 6322 case CP0_REGISTER_10:
7a387fff 6323 switch (sel) {
860ffef0 6324 case CP0_REG10__ENTRYHI:
7db13fae 6325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 6326 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6327 register_name = "EntryHi";
2423f660 6328 break;
7a387fff 6329 default:
f31b035a 6330 goto cp0_unimplemented;
1579a72e 6331 }
873eb012 6332 break;
04992c8c 6333 case CP0_REGISTER_11:
7a387fff 6334 switch (sel) {
f5f3834f 6335 case CP0_REG11__COMPARE:
7db13fae 6336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 6337 register_name = "Compare";
2423f660
TS
6338 break;
6339 /* 6,7 are implementation dependent */
7a387fff 6340 default:
f31b035a 6341 goto cp0_unimplemented;
2423f660 6342 }
873eb012 6343 break;
04992c8c 6344 case CP0_REGISTER_12:
7a387fff 6345 switch (sel) {
2b084867 6346 case CP0_REG12__STATUS:
7db13fae 6347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 6348 register_name = "Status";
2423f660 6349 break;
2b084867 6350 case CP0_REG12__INTCTL:
7a47bae5 6351 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 6353 register_name = "IntCtl";
2423f660 6354 break;
2b084867 6355 case CP0_REG12__SRSCTL:
7a47bae5 6356 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 6358 register_name = "SRSCtl";
2423f660 6359 break;
2b084867 6360 case CP0_REG12__SRSMAP:
7a47bae5 6361 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 6363 register_name = "SRSMap";
fd88b6ab 6364 break;
7a387fff 6365 default:
f31b035a 6366 goto cp0_unimplemented;
7a387fff 6367 }
873eb012 6368 break;
04992c8c 6369 case CP0_REGISTER_13:
7a387fff 6370 switch (sel) {
e3c7559d 6371 case CP0_REG13__CAUSE:
7db13fae 6372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 6373 register_name = "Cause";
2423f660 6374 break;
7a387fff 6375 default:
f31b035a 6376 goto cp0_unimplemented;
7a387fff 6377 }
873eb012 6378 break;
04992c8c 6379 case CP0_REGISTER_14:
7a387fff 6380 switch (sel) {
35e4b54d 6381 case CP0_REG14__EPC:
7db13fae 6382 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 6383 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6384 register_name = "EPC";
2423f660 6385 break;
7a387fff 6386 default:
f31b035a 6387 goto cp0_unimplemented;
1579a72e 6388 }
873eb012 6389 break;
04992c8c 6390 case CP0_REGISTER_15:
7a387fff 6391 switch (sel) {
4466cd49 6392 case CP0_REG15__PRID:
7db13fae 6393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 6394 register_name = "PRid";
2423f660 6395 break;
4466cd49 6396 case CP0_REG15__EBASE:
7a47bae5 6397 check_insn(ctx, ISA_MIPS_R2);
74dbf824
JH
6398 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6399 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6400 register_name = "EBase";
2423f660 6401 break;
4466cd49 6402 case CP0_REG15__CMGCRBASE:
7a47bae5 6403 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
6404 CP0_CHECK(ctx->cmgcr);
6405 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6406 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6407 register_name = "CMGCRBase";
c870e3f5 6408 break;
7a387fff 6409 default:
f31b035a 6410 goto cp0_unimplemented;
7a387fff 6411 }
873eb012 6412 break;
04992c8c 6413 case CP0_REGISTER_16:
873eb012 6414 switch (sel) {
433efb4c 6415 case CP0_REG16__CONFIG:
7db13fae 6416 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 6417 register_name = "Config";
873eb012 6418 break;
433efb4c 6419 case CP0_REG16__CONFIG1:
7db13fae 6420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 6421 register_name = "Config1";
873eb012 6422 break;
433efb4c 6423 case CP0_REG16__CONFIG2:
7db13fae 6424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 6425 register_name = "Config2";
7a387fff 6426 break;
433efb4c 6427 case CP0_REG16__CONFIG3:
7db13fae 6428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 6429 register_name = "Config3";
7a387fff 6430 break;
433efb4c 6431 case CP0_REG16__CONFIG4:
b4160af1 6432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 6433 register_name = "Config4";
b4160af1 6434 break;
433efb4c 6435 case CP0_REG16__CONFIG5:
b4dd99a3 6436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 6437 register_name = "Config5";
b4dd99a3 6438 break;
e397ee33 6439 /* 6,7 are implementation dependent */
433efb4c 6440 case CP0_REG16__CONFIG6:
7db13fae 6441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 6442 register_name = "Config6";
e397ee33 6443 break;
433efb4c 6444 case CP0_REG16__CONFIG7:
7db13fae 6445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 6446 register_name = "Config7";
e397ee33 6447 break;
873eb012 6448 default:
f31b035a 6449 goto cp0_unimplemented;
873eb012
TS
6450 }
6451 break;
04992c8c 6452 case CP0_REGISTER_17:
7a387fff 6453 switch (sel) {
706ce142 6454 case CP0_REG17__LLADDR:
895c2d04 6455 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 6456 register_name = "LLAddr";
2423f660 6457 break;
706ce142 6458 case CP0_REG17__MAAR:
f6d4dd81
YK
6459 CP0_CHECK(ctx->mrp);
6460 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 6461 register_name = "MAAR";
f6d4dd81 6462 break;
706ce142 6463 case CP0_REG17__MAARI:
f6d4dd81
YK
6464 CP0_CHECK(ctx->mrp);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 6466 register_name = "MAARI";
f6d4dd81 6467 break;
7a387fff 6468 default:
f31b035a 6469 goto cp0_unimplemented;
7a387fff 6470 }
873eb012 6471 break;
04992c8c 6472 case CP0_REGISTER_18:
7a387fff 6473 switch (sel) {
e8dcfe82
AM
6474 case CP0_REG18__WATCHLO0:
6475 case CP0_REG18__WATCHLO1:
6476 case CP0_REG18__WATCHLO2:
6477 case CP0_REG18__WATCHLO3:
6478 case CP0_REG18__WATCHLO4:
6479 case CP0_REG18__WATCHLO5:
6480 case CP0_REG18__WATCHLO6:
6481 case CP0_REG18__WATCHLO7:
fa192d49 6482 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6483 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 6484 register_name = "WatchLo";
2423f660 6485 break;
7a387fff 6486 default:
f31b035a 6487 goto cp0_unimplemented;
7a387fff 6488 }
873eb012 6489 break;
04992c8c 6490 case CP0_REGISTER_19:
7a387fff 6491 switch (sel) {
be274dc1
AM
6492 case CP0_REG19__WATCHHI0:
6493 case CP0_REG19__WATCHHI1:
6494 case CP0_REG19__WATCHHI2:
6495 case CP0_REG19__WATCHHI3:
6496 case CP0_REG19__WATCHHI4:
6497 case CP0_REG19__WATCHHI5:
6498 case CP0_REG19__WATCHHI6:
6499 case CP0_REG19__WATCHHI7:
fa192d49 6500 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6501 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 6502 register_name = "WatchHi";
2423f660 6503 break;
7a387fff 6504 default:
f31b035a 6505 goto cp0_unimplemented;
7a387fff 6506 }
873eb012 6507 break;
04992c8c 6508 case CP0_REGISTER_20:
7a387fff 6509 switch (sel) {
14f92b0b 6510 case CP0_REG20__XCONTEXT:
d26bc211 6511#if defined(TARGET_MIPS64)
d75c135e 6512 check_insn(ctx, ISA_MIPS3);
7db13fae 6513 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 6514 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6515 register_name = "XContext";
2423f660 6516 break;
703eaf37 6517#endif
7a387fff 6518 default:
f31b035a 6519 goto cp0_unimplemented;
7a387fff 6520 }
8c0fdd85 6521 break;
04992c8c 6522 case CP0_REGISTER_21:
7a387fff 6523 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 6524 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
6525 switch (sel) {
6526 case 0:
7db13fae 6527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 6528 register_name = "Framemask";
2423f660 6529 break;
7a387fff 6530 default:
f31b035a 6531 goto cp0_unimplemented;
7a387fff 6532 }
8c0fdd85 6533 break;
04992c8c 6534 case CP0_REGISTER_22:
d9bea114 6535 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 6536 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 6537 break;
04992c8c 6538 case CP0_REGISTER_23:
7a387fff 6539 switch (sel) {
4cbf4b6d 6540 case CP0_REG23__DEBUG:
895c2d04 6541 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 6542 register_name = "Debug";
2423f660 6543 break;
4cbf4b6d
AM
6544 case CP0_REG23__TRACECONTROL:
6545 /* PDtrace support */
6546 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 6547 register_name = "TraceControl";
3570d7f6 6548 goto cp0_unimplemented;
4cbf4b6d
AM
6549 case CP0_REG23__TRACECONTROL2:
6550 /* PDtrace support */
6551 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 6552 register_name = "TraceControl2";
3570d7f6 6553 goto cp0_unimplemented;
4cbf4b6d
AM
6554 case CP0_REG23__USERTRACEDATA1:
6555 /* PDtrace support */
6556 /* gen_helper_mfc0_usertracedata1(arg);*/
6557 register_name = "UserTraceData1";
3570d7f6 6558 goto cp0_unimplemented;
4cbf4b6d
AM
6559 case CP0_REG23__TRACEIBPC:
6560 /* PDtrace support */
6561 /* gen_helper_mfc0_traceibpc(arg); */
6562 register_name = "TraceIBPC";
6563 goto cp0_unimplemented;
6564 case CP0_REG23__TRACEDBPC:
6565 /* PDtrace support */
6566 /* gen_helper_mfc0_tracedbpc(arg); */
6567 register_name = "TraceDBPC";
3570d7f6 6568 goto cp0_unimplemented;
7a387fff 6569 default:
f31b035a 6570 goto cp0_unimplemented;
7a387fff 6571 }
873eb012 6572 break;
04992c8c 6573 case CP0_REGISTER_24:
7a387fff 6574 switch (sel) {
8d7b4b6e 6575 case CP0_REG24__DEPC:
f0b3f3ae 6576 /* EJTAG support */
7db13fae 6577 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 6578 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6579 register_name = "DEPC";
2423f660 6580 break;
7a387fff 6581 default:
f31b035a 6582 goto cp0_unimplemented;
7a387fff 6583 }
873eb012 6584 break;
04992c8c 6585 case CP0_REGISTER_25:
7a387fff 6586 switch (sel) {
1176b328 6587 case CP0_REG25__PERFCTL0:
7db13fae 6588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 6589 register_name = "Performance0";
7a387fff 6590 break;
1176b328 6591 case CP0_REG25__PERFCNT0:
7480515f 6592 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 6593 register_name = "Performance1";
3570d7f6 6594 goto cp0_unimplemented;
1176b328 6595 case CP0_REG25__PERFCTL1:
7480515f 6596 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 6597 register_name = "Performance2";
3570d7f6 6598 goto cp0_unimplemented;
1176b328 6599 case CP0_REG25__PERFCNT1:
7480515f 6600 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 6601 register_name = "Performance3";
3570d7f6 6602 goto cp0_unimplemented;
1176b328 6603 case CP0_REG25__PERFCTL2:
7480515f 6604 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 6605 register_name = "Performance4";
3570d7f6 6606 goto cp0_unimplemented;
1176b328 6607 case CP0_REG25__PERFCNT2:
7480515f 6608 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 6609 register_name = "Performance5";
3570d7f6 6610 goto cp0_unimplemented;
1176b328 6611 case CP0_REG25__PERFCTL3:
7480515f 6612 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 6613 register_name = "Performance6";
3570d7f6 6614 goto cp0_unimplemented;
1176b328 6615 case CP0_REG25__PERFCNT3:
7480515f 6616 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 6617 register_name = "Performance7";
3570d7f6 6618 goto cp0_unimplemented;
7a387fff 6619 default:
f31b035a 6620 goto cp0_unimplemented;
7a387fff 6621 }
8c0fdd85 6622 break;
04992c8c 6623 case CP0_REGISTER_26:
0d74a222 6624 switch (sel) {
dbbf08b2 6625 case CP0_REG26__ERRCTL:
0d74a222 6626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 6627 register_name = "ErrCtl";
0d74a222
LA
6628 break;
6629 default:
6630 goto cp0_unimplemented;
6631 }
da80682b 6632 break;
04992c8c 6633 case CP0_REGISTER_27:
7a387fff 6634 switch (sel) {
5a10873d 6635 case CP0_REG27__CACHERR:
d9bea114 6636 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 6637 register_name = "CacheErr";
2423f660 6638 break;
7a387fff 6639 default:
f31b035a 6640 goto cp0_unimplemented;
7a387fff 6641 }
8c0fdd85 6642 break;
04992c8c 6643 case CP0_REGISTER_28:
873eb012 6644 switch (sel) {
a30e2f21
AM
6645 case CP0_REG28__TAGLO:
6646 case CP0_REG28__TAGLO1:
6647 case CP0_REG28__TAGLO2:
6648 case CP0_REG28__TAGLO3:
284b731a
LA
6649 {
6650 TCGv_i64 tmp = tcg_temp_new_i64();
6651 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6652 gen_move_low32(arg, tmp);
6653 tcg_temp_free_i64(tmp);
6654 }
294fc2ea 6655 register_name = "TagLo";
873eb012 6656 break;
a30e2f21
AM
6657 case CP0_REG28__DATALO:
6658 case CP0_REG28__DATALO1:
6659 case CP0_REG28__DATALO2:
6660 case CP0_REG28__DATALO3:
7db13fae 6661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 6662 register_name = "DataLo";
873eb012
TS
6663 break;
6664 default:
f31b035a 6665 goto cp0_unimplemented;
873eb012
TS
6666 }
6667 break;
04992c8c 6668 case CP0_REGISTER_29:
7a387fff 6669 switch (sel) {
af4bb6da
AM
6670 case CP0_REG29__TAGHI:
6671 case CP0_REG29__TAGHI1:
6672 case CP0_REG29__TAGHI2:
6673 case CP0_REG29__TAGHI3:
7db13fae 6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 6675 register_name = "TagHi";
7a387fff 6676 break;
af4bb6da
AM
6677 case CP0_REG29__DATAHI:
6678 case CP0_REG29__DATAHI1:
6679 case CP0_REG29__DATAHI2:
6680 case CP0_REG29__DATAHI3:
7db13fae 6681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 6682 register_name = "DataHi";
7a387fff
TS
6683 break;
6684 default:
f31b035a 6685 goto cp0_unimplemented;
7a387fff 6686 }
8c0fdd85 6687 break;
04992c8c 6688 case CP0_REGISTER_30:
7a387fff 6689 switch (sel) {
4bcf121e 6690 case CP0_REG30__ERROREPC:
7db13fae 6691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 6692 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6693 register_name = "ErrorEPC";
2423f660 6694 break;
7a387fff 6695 default:
f31b035a 6696 goto cp0_unimplemented;
7a387fff 6697 }
873eb012 6698 break;
04992c8c 6699 case CP0_REGISTER_31:
7a387fff 6700 switch (sel) {
14d92efd 6701 case CP0_REG31__DESAVE:
f0b3f3ae 6702 /* EJTAG support */
7db13fae 6703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 6704 register_name = "DESAVE";
2423f660 6705 break;
14d92efd
AM
6706 case CP0_REG31__KSCRATCH1:
6707 case CP0_REG31__KSCRATCH2:
6708 case CP0_REG31__KSCRATCH3:
6709 case CP0_REG31__KSCRATCH4:
6710 case CP0_REG31__KSCRATCH5:
6711 case CP0_REG31__KSCRATCH6:
f31b035a
LA
6712 CP0_CHECK(ctx->kscrexist & (1 << sel));
6713 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 6714 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 6715 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6716 register_name = "KScratch";
e98c0d17 6717 break;
7a387fff 6718 default:
f31b035a 6719 goto cp0_unimplemented;
7a387fff 6720 }
873eb012
TS
6721 break;
6722 default:
f31b035a 6723 goto cp0_unimplemented;
873eb012 6724 }
294fc2ea 6725 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
6726 return;
6727
f31b035a 6728cp0_unimplemented:
294fc2ea
AM
6729 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6730 register_name, reg, sel);
f31b035a 6731 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
6732}
6733
d75c135e 6734static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 6735{
294fc2ea 6736 const char *register_name = "invalid";
7a387fff 6737
1f8929d2 6738 if (sel != 0) {
bbd5e4a2 6739 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 6740 }
e189e748 6741
eeb3bba8 6742 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6743 gen_io_start();
bd79255d 6744 }
2e70f6ef 6745
8c0fdd85 6746 switch (reg) {
04992c8c 6747 case CP0_REGISTER_00:
7a387fff 6748 switch (sel) {
1b142da5 6749 case CP0_REG00__INDEX:
895c2d04 6750 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 6751 register_name = "Index";
7a387fff 6752 break;
1b142da5 6753 case CP0_REG00__MVPCONTROL:
f31b035a 6754 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6755 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 6756 register_name = "MVPControl";
ead9360e 6757 break;
1b142da5 6758 case CP0_REG00__MVPCONF0:
f31b035a 6759 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6760 /* ignored */
294fc2ea 6761 register_name = "MVPConf0";
ead9360e 6762 break;
1b142da5 6763 case CP0_REG00__MVPCONF1:
f31b035a 6764 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6765 /* ignored */
294fc2ea 6766 register_name = "MVPConf1";
ead9360e 6767 break;
1b142da5 6768 case CP0_REG00__VPCONTROL:
01bc435b
YK
6769 CP0_CHECK(ctx->vp);
6770 /* ignored */
294fc2ea 6771 register_name = "VPControl";
01bc435b 6772 break;
7a387fff 6773 default:
f31b035a 6774 goto cp0_unimplemented;
7a387fff 6775 }
8c0fdd85 6776 break;
04992c8c 6777 case CP0_REGISTER_01:
7a387fff 6778 switch (sel) {
30deb460 6779 case CP0_REG01__RANDOM:
2423f660 6780 /* ignored */
294fc2ea 6781 register_name = "Random";
2423f660 6782 break;
30deb460 6783 case CP0_REG01__VPECONTROL:
f31b035a 6784 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6785 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 6786 register_name = "VPEControl";
ead9360e 6787 break;
30deb460 6788 case CP0_REG01__VPECONF0:
f31b035a 6789 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6790 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 6791 register_name = "VPEConf0";
ead9360e 6792 break;
30deb460 6793 case CP0_REG01__VPECONF1:
f31b035a 6794 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6795 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 6796 register_name = "VPEConf1";
ead9360e 6797 break;
30deb460 6798 case CP0_REG01__YQMASK:
f31b035a 6799 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6800 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 6801 register_name = "YQMask";
ead9360e 6802 break;
30deb460 6803 case CP0_REG01__VPESCHEDULE:
f31b035a 6804 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6805 tcg_gen_st_tl(arg, cpu_env,
6806 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6807 register_name = "VPESchedule";
ead9360e 6808 break;
30deb460 6809 case CP0_REG01__VPESCHEFBACK:
f31b035a 6810 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6811 tcg_gen_st_tl(arg, cpu_env,
6812 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6813 register_name = "VPEScheFBack";
ead9360e 6814 break;
30deb460 6815 case CP0_REG01__VPEOPT:
f31b035a 6816 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6817 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 6818 register_name = "VPEOpt";
ead9360e 6819 break;
7a387fff 6820 default:
f31b035a 6821 goto cp0_unimplemented;
7a387fff 6822 }
8c0fdd85 6823 break;
04992c8c 6824 case CP0_REGISTER_02:
7a387fff 6825 switch (sel) {
6d27d5bd 6826 case CP0_REG02__ENTRYLO0:
895c2d04 6827 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 6828 register_name = "EntryLo0";
2423f660 6829 break;
6d27d5bd 6830 case CP0_REG02__TCSTATUS:
f31b035a 6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6832 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 6833 register_name = "TCStatus";
ead9360e 6834 break;
6d27d5bd 6835 case CP0_REG02__TCBIND:
f31b035a 6836 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6837 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 6838 register_name = "TCBind";
ead9360e 6839 break;
6d27d5bd 6840 case CP0_REG02__TCRESTART:
f31b035a 6841 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6842 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 6843 register_name = "TCRestart";
ead9360e 6844 break;
6d27d5bd 6845 case CP0_REG02__TCHALT:
f31b035a 6846 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6847 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 6848 register_name = "TCHalt";
ead9360e 6849 break;
6d27d5bd 6850 case CP0_REG02__TCCONTEXT:
f31b035a 6851 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6852 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 6853 register_name = "TCContext";
ead9360e 6854 break;
6d27d5bd 6855 case CP0_REG02__TCSCHEDULE:
f31b035a 6856 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6857 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 6858 register_name = "TCSchedule";
ead9360e 6859 break;
6d27d5bd 6860 case CP0_REG02__TCSCHEFBACK:
f31b035a 6861 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6862 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 6863 register_name = "TCScheFBack";
ead9360e 6864 break;
7a387fff 6865 default:
f31b035a 6866 goto cp0_unimplemented;
7a387fff 6867 }
8c0fdd85 6868 break;
04992c8c 6869 case CP0_REGISTER_03:
7a387fff 6870 switch (sel) {
acd37316 6871 case CP0_REG03__ENTRYLO1:
895c2d04 6872 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 6873 register_name = "EntryLo1";
2423f660 6874 break;
acd37316 6875 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6876 CP0_CHECK(ctx->vp);
6877 /* ignored */
294fc2ea 6878 register_name = "GlobalNumber";
01bc435b 6879 break;
7a387fff 6880 default:
f31b035a 6881 goto cp0_unimplemented;
876d4b07 6882 }
8c0fdd85 6883 break;
04992c8c 6884 case CP0_REGISTER_04:
7a387fff 6885 switch (sel) {
020fe379 6886 case CP0_REG04__CONTEXT:
895c2d04 6887 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 6888 register_name = "Context";
2423f660 6889 break;
020fe379
AM
6890 case CP0_REG04__CONTEXTCONFIG:
6891 /* SmartMIPS ASE */
6892 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 6893 register_name = "ContextConfig";
f31b035a 6894 goto cp0_unimplemented;
020fe379 6895 case CP0_REG04__USERLOCAL:
f31b035a
LA
6896 CP0_CHECK(ctx->ulri);
6897 tcg_gen_st_tl(arg, cpu_env,
6898 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 6899 register_name = "UserLocal";
d279279e 6900 break;
99029be1
YK
6901 case CP0_REG04__MMID:
6902 CP0_CHECK(ctx->mi);
6903 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6904 register_name = "MMID";
6905 break;
7a387fff 6906 default:
f31b035a 6907 goto cp0_unimplemented;
876d4b07 6908 }
8c0fdd85 6909 break;
04992c8c 6910 case CP0_REGISTER_05:
7a387fff 6911 switch (sel) {
a1e76353 6912 case CP0_REG05__PAGEMASK:
895c2d04 6913 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 6914 register_name = "PageMask";
2423f660 6915 break;
a1e76353 6916 case CP0_REG05__PAGEGRAIN:
7a47bae5 6917 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6918 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 6919 register_name = "PageGrain";
eeb3bba8 6920 ctx->base.is_jmp = DISAS_STOP;
2423f660 6921 break;
a1e76353 6922 case CP0_REG05__SEGCTL0:
cec56a73
JH
6923 CP0_CHECK(ctx->sc);
6924 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 6925 register_name = "SegCtl0";
cec56a73 6926 break;
a1e76353 6927 case CP0_REG05__SEGCTL1:
cec56a73
JH
6928 CP0_CHECK(ctx->sc);
6929 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 6930 register_name = "SegCtl1";
cec56a73 6931 break;
a1e76353 6932 case CP0_REG05__SEGCTL2:
cec56a73
JH
6933 CP0_CHECK(ctx->sc);
6934 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 6935 register_name = "SegCtl2";
cec56a73 6936 break;
a1e76353 6937 case CP0_REG05__PWBASE:
5e31fdd5
YK
6938 check_pw(ctx);
6939 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6940 register_name = "PWBase";
5e31fdd5 6941 break;
a1e76353 6942 case CP0_REG05__PWFIELD:
fa75ad14
YK
6943 check_pw(ctx);
6944 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 6945 register_name = "PWField";
fa75ad14 6946 break;
a1e76353 6947 case CP0_REG05__PWSIZE:
20b28ebc
YK
6948 check_pw(ctx);
6949 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 6950 register_name = "PWSize";
20b28ebc 6951 break;
7a387fff 6952 default:
f31b035a 6953 goto cp0_unimplemented;
876d4b07 6954 }
8c0fdd85 6955 break;
04992c8c 6956 case CP0_REGISTER_06:
7a387fff 6957 switch (sel) {
9023594b 6958 case CP0_REG06__WIRED:
895c2d04 6959 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 6960 register_name = "Wired";
2423f660 6961 break;
9023594b 6962 case CP0_REG06__SRSCONF0:
7a47bae5 6963 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6964 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 6965 register_name = "SRSConf0";
ead9360e 6966 break;
9023594b 6967 case CP0_REG06__SRSCONF1:
7a47bae5 6968 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6969 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 6970 register_name = "SRSConf1";
ead9360e 6971 break;
9023594b 6972 case CP0_REG06__SRSCONF2:
7a47bae5 6973 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6974 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 6975 register_name = "SRSConf2";
ead9360e 6976 break;
9023594b 6977 case CP0_REG06__SRSCONF3:
7a47bae5 6978 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6979 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 6980 register_name = "SRSConf3";
ead9360e 6981 break;
9023594b 6982 case CP0_REG06__SRSCONF4:
7a47bae5 6983 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6984 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 6985 register_name = "SRSConf4";
ead9360e 6986 break;
9023594b 6987 case CP0_REG06__PWCTL:
103be64c
YK
6988 check_pw(ctx);
6989 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 6990 register_name = "PWCtl";
103be64c 6991 break;
7a387fff 6992 default:
f31b035a 6993 goto cp0_unimplemented;
876d4b07 6994 }
8c0fdd85 6995 break;
04992c8c 6996 case CP0_REGISTER_07:
7a387fff 6997 switch (sel) {
143a9875 6998 case CP0_REG07__HWRENA:
7a47bae5 6999 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7000 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7001 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7002 register_name = "HWREna";
2423f660 7003 break;
7a387fff 7004 default:
f31b035a 7005 goto cp0_unimplemented;
876d4b07 7006 }
8c0fdd85 7007 break;
04992c8c 7008 case CP0_REGISTER_08:
aea14095 7009 switch (sel) {
67d167d2 7010 case CP0_REG08__BADVADDR:
aea14095 7011 /* ignored */
294fc2ea 7012 register_name = "BadVAddr";
aea14095 7013 break;
67d167d2 7014 case CP0_REG08__BADINSTR:
aea14095 7015 /* ignored */
294fc2ea 7016 register_name = "BadInstr";
aea14095 7017 break;
67d167d2 7018 case CP0_REG08__BADINSTRP:
aea14095 7019 /* ignored */
294fc2ea 7020 register_name = "BadInstrP";
aea14095 7021 break;
67d167d2 7022 case CP0_REG08__BADINSTRX:
25beba9b 7023 /* ignored */
294fc2ea 7024 register_name = "BadInstrX";
25beba9b 7025 break;
aea14095 7026 default:
f31b035a 7027 goto cp0_unimplemented;
aea14095 7028 }
8c0fdd85 7029 break;
04992c8c 7030 case CP0_REGISTER_09:
7a387fff 7031 switch (sel) {
e5a98a72 7032 case CP0_REG09__COUNT:
895c2d04 7033 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 7034 register_name = "Count";
2423f660 7035 break;
e5a98a72 7036 case CP0_REG09__SAARI:
5fb2dcd1
YK
7037 CP0_CHECK(ctx->saar);
7038 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 7039 register_name = "SAARI";
5fb2dcd1 7040 break;
e5a98a72 7041 case CP0_REG09__SAAR:
5fb2dcd1
YK
7042 CP0_CHECK(ctx->saar);
7043 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 7044 register_name = "SAAR";
5fb2dcd1 7045 break;
7a387fff 7046 default:
f31b035a 7047 goto cp0_unimplemented;
876d4b07 7048 }
8c0fdd85 7049 break;
04992c8c 7050 case CP0_REGISTER_10:
7a387fff 7051 switch (sel) {
860ffef0 7052 case CP0_REG10__ENTRYHI:
895c2d04 7053 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 7054 register_name = "EntryHi";
2423f660 7055 break;
7a387fff 7056 default:
f31b035a 7057 goto cp0_unimplemented;
876d4b07 7058 }
8c0fdd85 7059 break;
04992c8c 7060 case CP0_REGISTER_11:
7a387fff 7061 switch (sel) {
f5f3834f 7062 case CP0_REG11__COMPARE:
895c2d04 7063 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 7064 register_name = "Compare";
2423f660
TS
7065 break;
7066 /* 6,7 are implementation dependent */
7a387fff 7067 default:
f31b035a 7068 goto cp0_unimplemented;
876d4b07 7069 }
8c0fdd85 7070 break;
04992c8c 7071 case CP0_REGISTER_12:
7a387fff 7072 switch (sel) {
2b084867 7073 case CP0_REG12__STATUS:
867abc7e 7074 save_cpu_state(ctx, 1);
895c2d04 7075 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7076 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7077 gen_save_pc(ctx->base.pc_next + 4);
7078 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7079 register_name = "Status";
2423f660 7080 break;
2b084867 7081 case CP0_REG12__INTCTL:
7a47bae5 7082 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7083 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7084 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7085 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7086 register_name = "IntCtl";
2423f660 7087 break;
2b084867 7088 case CP0_REG12__SRSCTL:
7a47bae5 7089 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7090 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7091 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7092 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7093 register_name = "SRSCtl";
2423f660 7094 break;
2b084867 7095 case CP0_REG12__SRSMAP:
7a47bae5 7096 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7097 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7098 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7099 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7100 register_name = "SRSMap";
fd88b6ab 7101 break;
7a387fff 7102 default:
f31b035a 7103 goto cp0_unimplemented;
876d4b07 7104 }
8c0fdd85 7105 break;
04992c8c 7106 case CP0_REGISTER_13:
7a387fff 7107 switch (sel) {
e3c7559d 7108 case CP0_REG13__CAUSE:
867abc7e 7109 save_cpu_state(ctx, 1);
895c2d04 7110 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
7111 /*
7112 * Stop translation as we may have triggered an interrupt.
b28425ba 7113 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
7114 * translated code to check for pending interrupts.
7115 */
eeb3bba8
EC
7116 gen_save_pc(ctx->base.pc_next + 4);
7117 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7118 register_name = "Cause";
2423f660 7119 break;
7a387fff 7120 default:
f31b035a 7121 goto cp0_unimplemented;
876d4b07 7122 }
8c0fdd85 7123 break;
04992c8c 7124 case CP0_REGISTER_14:
7a387fff 7125 switch (sel) {
35e4b54d 7126 case CP0_REG14__EPC:
d54a299b 7127 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7128 register_name = "EPC";
2423f660 7129 break;
7a387fff 7130 default:
f31b035a 7131 goto cp0_unimplemented;
876d4b07 7132 }
8c0fdd85 7133 break;
04992c8c 7134 case CP0_REGISTER_15:
7a387fff 7135 switch (sel) {
4466cd49 7136 case CP0_REG15__PRID:
2423f660 7137 /* ignored */
294fc2ea 7138 register_name = "PRid";
2423f660 7139 break;
4466cd49 7140 case CP0_REG15__EBASE:
7a47bae5 7141 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7142 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 7143 register_name = "EBase";
2423f660 7144 break;
7a387fff 7145 default:
f31b035a 7146 goto cp0_unimplemented;
1579a72e 7147 }
8c0fdd85 7148 break;
04992c8c 7149 case CP0_REGISTER_16:
8c0fdd85 7150 switch (sel) {
433efb4c 7151 case CP0_REG16__CONFIG:
895c2d04 7152 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 7153 register_name = "Config";
2423f660 7154 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7155 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7156 break;
433efb4c 7157 case CP0_REG16__CONFIG1:
e397ee33 7158 /* ignored, read only */
294fc2ea 7159 register_name = "Config1";
7a387fff 7160 break;
433efb4c 7161 case CP0_REG16__CONFIG2:
895c2d04 7162 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 7163 register_name = "Config2";
2423f660 7164 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7165 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7166 break;
433efb4c 7167 case CP0_REG16__CONFIG3:
90f12d73 7168 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 7169 register_name = "Config3";
90f12d73 7170 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7171 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7172 break;
433efb4c 7173 case CP0_REG16__CONFIG4:
b4160af1 7174 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 7175 register_name = "Config4";
eeb3bba8 7176 ctx->base.is_jmp = DISAS_STOP;
b4160af1 7177 break;
433efb4c 7178 case CP0_REG16__CONFIG5:
b4dd99a3 7179 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 7180 register_name = "Config5";
b4dd99a3 7181 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7182 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 7183 break;
e397ee33 7184 /* 6,7 are implementation dependent */
433efb4c 7185 case CP0_REG16__CONFIG6:
e397ee33 7186 /* ignored */
294fc2ea 7187 register_name = "Config6";
e397ee33 7188 break;
433efb4c 7189 case CP0_REG16__CONFIG7:
e397ee33 7190 /* ignored */
294fc2ea 7191 register_name = "Config7";
e397ee33 7192 break;
8c0fdd85 7193 default:
294fc2ea 7194 register_name = "Invalid config selector";
f31b035a 7195 goto cp0_unimplemented;
8c0fdd85
TS
7196 }
7197 break;
04992c8c 7198 case CP0_REGISTER_17:
7a387fff 7199 switch (sel) {
706ce142 7200 case CP0_REG17__LLADDR:
895c2d04 7201 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 7202 register_name = "LLAddr";
2423f660 7203 break;
706ce142 7204 case CP0_REG17__MAAR:
f6d4dd81
YK
7205 CP0_CHECK(ctx->mrp);
7206 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 7207 register_name = "MAAR";
f6d4dd81 7208 break;
706ce142 7209 case CP0_REG17__MAARI:
f6d4dd81
YK
7210 CP0_CHECK(ctx->mrp);
7211 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 7212 register_name = "MAARI";
f6d4dd81 7213 break;
7a387fff 7214 default:
f31b035a 7215 goto cp0_unimplemented;
7a387fff 7216 }
8c0fdd85 7217 break;
04992c8c 7218 case CP0_REGISTER_18:
7a387fff 7219 switch (sel) {
e8dcfe82
AM
7220 case CP0_REG18__WATCHLO0:
7221 case CP0_REG18__WATCHLO1:
7222 case CP0_REG18__WATCHLO2:
7223 case CP0_REG18__WATCHLO3:
7224 case CP0_REG18__WATCHLO4:
7225 case CP0_REG18__WATCHLO5:
7226 case CP0_REG18__WATCHLO6:
7227 case CP0_REG18__WATCHLO7:
fa192d49 7228 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7229 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 7230 register_name = "WatchLo";
2423f660 7231 break;
7a387fff 7232 default:
f31b035a 7233 goto cp0_unimplemented;
7a387fff 7234 }
8c0fdd85 7235 break;
04992c8c 7236 case CP0_REGISTER_19:
7a387fff 7237 switch (sel) {
be274dc1
AM
7238 case CP0_REG19__WATCHHI0:
7239 case CP0_REG19__WATCHHI1:
7240 case CP0_REG19__WATCHHI2:
7241 case CP0_REG19__WATCHHI3:
7242 case CP0_REG19__WATCHHI4:
7243 case CP0_REG19__WATCHHI5:
7244 case CP0_REG19__WATCHHI6:
7245 case CP0_REG19__WATCHHI7:
fa192d49 7246 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7247 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 7248 register_name = "WatchHi";
2423f660 7249 break;
7a387fff 7250 default:
f31b035a 7251 goto cp0_unimplemented;
7a387fff 7252 }
8c0fdd85 7253 break;
04992c8c 7254 case CP0_REGISTER_20:
7a387fff 7255 switch (sel) {
14f92b0b 7256 case CP0_REG20__XCONTEXT:
d26bc211 7257#if defined(TARGET_MIPS64)
d75c135e 7258 check_insn(ctx, ISA_MIPS3);
895c2d04 7259 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 7260 register_name = "XContext";
2423f660 7261 break;
703eaf37 7262#endif
7a387fff 7263 default:
f31b035a 7264 goto cp0_unimplemented;
7a387fff 7265 }
8c0fdd85 7266 break;
04992c8c 7267 case CP0_REGISTER_21:
7a387fff 7268 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 7269 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
7270 switch (sel) {
7271 case 0:
895c2d04 7272 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 7273 register_name = "Framemask";
2423f660 7274 break;
7a387fff 7275 default:
f31b035a 7276 goto cp0_unimplemented;
7a387fff
TS
7277 }
7278 break;
04992c8c 7279 case CP0_REGISTER_22:
7a387fff 7280 /* ignored */
294fc2ea 7281 register_name = "Diagnostic"; /* implementation dependent */
2423f660 7282 break;
04992c8c 7283 case CP0_REGISTER_23:
7a387fff 7284 switch (sel) {
4cbf4b6d 7285 case CP0_REG23__DEBUG:
895c2d04 7286 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 7287 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7288 gen_save_pc(ctx->base.pc_next + 4);
7289 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7290 register_name = "Debug";
2423f660 7291 break;
4cbf4b6d
AM
7292 case CP0_REG23__TRACECONTROL:
7293 /* PDtrace support */
7294 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 7295 register_name = "TraceControl";
8487327a 7296 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7297 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7298 goto cp0_unimplemented;
4cbf4b6d
AM
7299 case CP0_REG23__TRACECONTROL2:
7300 /* PDtrace support */
7301 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 7302 register_name = "TraceControl2";
8487327a 7303 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7304 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7305 goto cp0_unimplemented;
4cbf4b6d 7306 case CP0_REG23__USERTRACEDATA1:
8487327a 7307 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7308 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
7309 /* PDtrace support */
7310 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 7311 register_name = "UserTraceData";
8487327a 7312 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7313 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7314 goto cp0_unimplemented;
4cbf4b6d
AM
7315 case CP0_REG23__TRACEIBPC:
7316 /* PDtrace support */
7317 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 7318 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7319 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
7320 register_name = "TraceIBPC";
7321 goto cp0_unimplemented;
7322 case CP0_REG23__TRACEDBPC:
7323 /* PDtrace support */
7324 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7325 /* Stop translation as we may have switched the execution mode */
7326 ctx->base.is_jmp = DISAS_STOP;
7327 register_name = "TraceDBPC";
3570d7f6 7328 goto cp0_unimplemented;
7a387fff 7329 default:
f31b035a 7330 goto cp0_unimplemented;
7a387fff 7331 }
8c0fdd85 7332 break;
04992c8c 7333 case CP0_REGISTER_24:
7a387fff 7334 switch (sel) {
8d7b4b6e 7335 case CP0_REG24__DEPC:
f1aa6320 7336 /* EJTAG support */
d54a299b 7337 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 7338 register_name = "DEPC";
2423f660 7339 break;
7a387fff 7340 default:
f31b035a 7341 goto cp0_unimplemented;
7a387fff 7342 }
8c0fdd85 7343 break;
04992c8c 7344 case CP0_REGISTER_25:
7a387fff 7345 switch (sel) {
1176b328 7346 case CP0_REG25__PERFCTL0:
895c2d04 7347 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 7348 register_name = "Performance0";
2423f660 7349 break;
1176b328 7350 case CP0_REG25__PERFCNT0:
7480515f 7351 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 7352 register_name = "Performance1";
3570d7f6 7353 goto cp0_unimplemented;
1176b328 7354 case CP0_REG25__PERFCTL1:
7480515f 7355 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 7356 register_name = "Performance2";
3570d7f6 7357 goto cp0_unimplemented;
1176b328 7358 case CP0_REG25__PERFCNT1:
7480515f 7359 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 7360 register_name = "Performance3";
3570d7f6 7361 goto cp0_unimplemented;
1176b328 7362 case CP0_REG25__PERFCTL2:
7480515f 7363 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 7364 register_name = "Performance4";
3570d7f6 7365 goto cp0_unimplemented;
1176b328 7366 case CP0_REG25__PERFCNT2:
7480515f 7367 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 7368 register_name = "Performance5";
3570d7f6 7369 goto cp0_unimplemented;
1176b328 7370 case CP0_REG25__PERFCTL3:
7480515f 7371 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 7372 register_name = "Performance6";
3570d7f6 7373 goto cp0_unimplemented;
1176b328 7374 case CP0_REG25__PERFCNT3:
7480515f 7375 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 7376 register_name = "Performance7";
3570d7f6 7377 goto cp0_unimplemented;
7a387fff 7378 default:
f31b035a 7379 goto cp0_unimplemented;
7a387fff 7380 }
8c0fdd85 7381 break;
04992c8c 7382 case CP0_REGISTER_26:
0d74a222 7383 switch (sel) {
dbbf08b2 7384 case CP0_REG26__ERRCTL:
0d74a222 7385 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 7386 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7387 register_name = "ErrCtl";
0d74a222
LA
7388 break;
7389 default:
7390 goto cp0_unimplemented;
7391 }
2423f660 7392 break;
04992c8c 7393 case CP0_REGISTER_27:
7a387fff 7394 switch (sel) {
5a10873d 7395 case CP0_REG27__CACHERR:
2423f660 7396 /* ignored */
294fc2ea 7397 register_name = "CacheErr";
2423f660 7398 break;
7a387fff 7399 default:
f31b035a 7400 goto cp0_unimplemented;
7a387fff 7401 }
8c0fdd85 7402 break;
04992c8c 7403 case CP0_REGISTER_28:
8c0fdd85 7404 switch (sel) {
a30e2f21
AM
7405 case CP0_REG28__TAGLO:
7406 case CP0_REG28__TAGLO1:
7407 case CP0_REG28__TAGLO2:
7408 case CP0_REG28__TAGLO3:
895c2d04 7409 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 7410 register_name = "TagLo";
8c0fdd85 7411 break;
a30e2f21
AM
7412 case CP0_REG28__DATALO:
7413 case CP0_REG28__DATALO1:
7414 case CP0_REG28__DATALO2:
7415 case CP0_REG28__DATALO3:
895c2d04 7416 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 7417 register_name = "DataLo";
7a387fff 7418 break;
8c0fdd85 7419 default:
f31b035a 7420 goto cp0_unimplemented;
8c0fdd85
TS
7421 }
7422 break;
04992c8c 7423 case CP0_REGISTER_29:
7a387fff 7424 switch (sel) {
af4bb6da
AM
7425 case CP0_REG29__TAGHI:
7426 case CP0_REG29__TAGHI1:
7427 case CP0_REG29__TAGHI2:
7428 case CP0_REG29__TAGHI3:
895c2d04 7429 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 7430 register_name = "TagHi";
7a387fff 7431 break;
af4bb6da
AM
7432 case CP0_REG29__DATAHI:
7433 case CP0_REG29__DATAHI1:
7434 case CP0_REG29__DATAHI2:
7435 case CP0_REG29__DATAHI3:
895c2d04 7436 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 7437 register_name = "DataHi";
7a387fff
TS
7438 break;
7439 default:
294fc2ea 7440 register_name = "invalid sel";
f31b035a 7441 goto cp0_unimplemented;
7a387fff 7442 }
8c0fdd85 7443 break;
04992c8c 7444 case CP0_REGISTER_30:
7a387fff 7445 switch (sel) {
4bcf121e 7446 case CP0_REG30__ERROREPC:
d54a299b 7447 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 7448 register_name = "ErrorEPC";
2423f660 7449 break;
7a387fff 7450 default:
f31b035a 7451 goto cp0_unimplemented;
7a387fff 7452 }
8c0fdd85 7453 break;
04992c8c 7454 case CP0_REGISTER_31:
7a387fff 7455 switch (sel) {
14d92efd 7456 case CP0_REG31__DESAVE:
f1aa6320 7457 /* EJTAG support */
7db13fae 7458 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7459 register_name = "DESAVE";
2423f660 7460 break;
14d92efd
AM
7461 case CP0_REG31__KSCRATCH1:
7462 case CP0_REG31__KSCRATCH2:
7463 case CP0_REG31__KSCRATCH3:
7464 case CP0_REG31__KSCRATCH4:
7465 case CP0_REG31__KSCRATCH5:
7466 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7467 CP0_CHECK(ctx->kscrexist & (1 << sel));
7468 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 7469 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 7470 register_name = "KScratch";
e98c0d17 7471 break;
7a387fff 7472 default:
f31b035a 7473 goto cp0_unimplemented;
7a387fff 7474 }
8c0fdd85
TS
7475 break;
7476 default:
f31b035a 7477 goto cp0_unimplemented;
8c0fdd85 7478 }
294fc2ea 7479 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 7480
bf20dc07 7481 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 7482 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
7483 /*
7484 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7485 * translated code to check for pending interrupts.
7486 */
eeb3bba8
EC
7487 gen_save_pc(ctx->base.pc_next + 4);
7488 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 7489 }
8c0fdd85
TS
7490 return;
7491
f31b035a 7492cp0_unimplemented:
294fc2ea
AM
7493 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7494 register_name, reg, sel);
8c0fdd85
TS
7495}
7496
d26bc211 7497#if defined(TARGET_MIPS64)
d75c135e 7498static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 7499{
294fc2ea 7500 const char *register_name = "invalid";
9c2149c8 7501
1f8929d2 7502 if (sel != 0) {
bbd5e4a2 7503 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 7504 }
e189e748 7505
9c2149c8 7506 switch (reg) {
04992c8c 7507 case CP0_REGISTER_00:
9c2149c8 7508 switch (sel) {
1b142da5 7509 case CP0_REG00__INDEX:
7db13fae 7510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 7511 register_name = "Index";
9c2149c8 7512 break;
1b142da5 7513 case CP0_REG00__MVPCONTROL:
f31b035a 7514 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7515 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 7516 register_name = "MVPControl";
ead9360e 7517 break;
1b142da5 7518 case CP0_REG00__MVPCONF0:
f31b035a 7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7520 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 7521 register_name = "MVPConf0";
ead9360e 7522 break;
1b142da5 7523 case CP0_REG00__MVPCONF1:
f31b035a 7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7525 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 7526 register_name = "MVPConf1";
ead9360e 7527 break;
1b142da5 7528 case CP0_REG00__VPCONTROL:
01bc435b
YK
7529 CP0_CHECK(ctx->vp);
7530 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 7531 register_name = "VPControl";
01bc435b 7532 break;
9c2149c8 7533 default:
f31b035a 7534 goto cp0_unimplemented;
9c2149c8
TS
7535 }
7536 break;
04992c8c 7537 case CP0_REGISTER_01:
9c2149c8 7538 switch (sel) {
30deb460 7539 case CP0_REG01__RANDOM:
2e211e0a 7540 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 7541 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 7542 register_name = "Random";
2423f660 7543 break;
30deb460 7544 case CP0_REG01__VPECONTROL:
f31b035a 7545 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 7547 register_name = "VPEControl";
ead9360e 7548 break;
30deb460 7549 case CP0_REG01__VPECONF0:
f31b035a 7550 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 7552 register_name = "VPEConf0";
ead9360e 7553 break;
30deb460 7554 case CP0_REG01__VPECONF1:
f31b035a 7555 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 7557 register_name = "VPEConf1";
ead9360e 7558 break;
30deb460 7559 case CP0_REG01__YQMASK:
f31b035a 7560 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7561 tcg_gen_ld_tl(arg, cpu_env,
7562 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 7563 register_name = "YQMask";
ead9360e 7564 break;
30deb460 7565 case CP0_REG01__VPESCHEDULE:
f31b035a 7566 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7567 tcg_gen_ld_tl(arg, cpu_env,
7568 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7569 register_name = "VPESchedule";
ead9360e 7570 break;
30deb460 7571 case CP0_REG01__VPESCHEFBACK:
f31b035a 7572 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7573 tcg_gen_ld_tl(arg, cpu_env,
7574 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7575 register_name = "VPEScheFBack";
ead9360e 7576 break;
30deb460 7577 case CP0_REG01__VPEOPT:
f31b035a 7578 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 7580 register_name = "VPEOpt";
ead9360e 7581 break;
9c2149c8 7582 default:
f31b035a 7583 goto cp0_unimplemented;
9c2149c8
TS
7584 }
7585 break;
04992c8c 7586 case CP0_REGISTER_02:
9c2149c8 7587 switch (sel) {
6d27d5bd 7588 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
7589 tcg_gen_ld_tl(arg, cpu_env,
7590 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 7591 register_name = "EntryLo0";
2423f660 7592 break;
6d27d5bd 7593 case CP0_REG02__TCSTATUS:
f31b035a 7594 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7595 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 7596 register_name = "TCStatus";
ead9360e 7597 break;
6d27d5bd 7598 case CP0_REG02__TCBIND:
f31b035a 7599 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7600 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 7601 register_name = "TCBind";
ead9360e 7602 break;
6d27d5bd 7603 case CP0_REG02__TCRESTART:
f31b035a 7604 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7605 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 7606 register_name = "TCRestart";
ead9360e 7607 break;
6d27d5bd 7608 case CP0_REG02__TCHALT:
f31b035a 7609 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7610 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 7611 register_name = "TCHalt";
ead9360e 7612 break;
6d27d5bd 7613 case CP0_REG02__TCCONTEXT:
f31b035a 7614 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7615 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 7616 register_name = "TCContext";
ead9360e 7617 break;
6d27d5bd 7618 case CP0_REG02__TCSCHEDULE:
f31b035a 7619 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7620 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 7621 register_name = "TCSchedule";
ead9360e 7622 break;
6d27d5bd 7623 case CP0_REG02__TCSCHEFBACK:
f31b035a 7624 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7625 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 7626 register_name = "TCScheFBack";
ead9360e 7627 break;
9c2149c8 7628 default:
f31b035a 7629 goto cp0_unimplemented;
9c2149c8
TS
7630 }
7631 break;
04992c8c 7632 case CP0_REGISTER_03:
9c2149c8 7633 switch (sel) {
acd37316 7634 case CP0_REG03__ENTRYLO1:
7db13fae 7635 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 7636 register_name = "EntryLo1";
2423f660 7637 break;
acd37316 7638 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7639 CP0_CHECK(ctx->vp);
7640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7641 register_name = "GlobalNumber";
01bc435b 7642 break;
9c2149c8 7643 default:
f31b035a 7644 goto cp0_unimplemented;
1579a72e 7645 }
9c2149c8 7646 break;
04992c8c 7647 case CP0_REGISTER_04:
9c2149c8 7648 switch (sel) {
020fe379 7649 case CP0_REG04__CONTEXT:
7db13fae 7650 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 7651 register_name = "Context";
2423f660 7652 break;
020fe379
AM
7653 case CP0_REG04__CONTEXTCONFIG:
7654 /* SmartMIPS ASE */
7655 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 7656 register_name = "ContextConfig";
f31b035a 7657 goto cp0_unimplemented;
020fe379 7658 case CP0_REG04__USERLOCAL:
f31b035a
LA
7659 CP0_CHECK(ctx->ulri);
7660 tcg_gen_ld_tl(arg, cpu_env,
7661 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7662 register_name = "UserLocal";
d279279e 7663 break;
99029be1
YK
7664 case CP0_REG04__MMID:
7665 CP0_CHECK(ctx->mi);
7666 gen_helper_mtc0_memorymapid(cpu_env, arg);
7667 register_name = "MMID";
7668 break;
9c2149c8 7669 default:
f31b035a 7670 goto cp0_unimplemented;
876d4b07 7671 }
9c2149c8 7672 break;
04992c8c 7673 case CP0_REGISTER_05:
9c2149c8 7674 switch (sel) {
a1e76353 7675 case CP0_REG05__PAGEMASK:
7db13fae 7676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7677 register_name = "PageMask";
2423f660 7678 break;
a1e76353 7679 case CP0_REG05__PAGEGRAIN:
7a47bae5 7680 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7682 register_name = "PageGrain";
2423f660 7683 break;
a1e76353 7684 case CP0_REG05__SEGCTL0:
cec56a73
JH
7685 CP0_CHECK(ctx->sc);
7686 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 7687 register_name = "SegCtl0";
cec56a73 7688 break;
a1e76353 7689 case CP0_REG05__SEGCTL1:
cec56a73
JH
7690 CP0_CHECK(ctx->sc);
7691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 7692 register_name = "SegCtl1";
cec56a73 7693 break;
a1e76353 7694 case CP0_REG05__SEGCTL2:
cec56a73
JH
7695 CP0_CHECK(ctx->sc);
7696 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 7697 register_name = "SegCtl2";
cec56a73 7698 break;
a1e76353 7699 case CP0_REG05__PWBASE:
5e31fdd5
YK
7700 check_pw(ctx);
7701 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7702 register_name = "PWBase";
5e31fdd5 7703 break;
a1e76353 7704 case CP0_REG05__PWFIELD:
fa75ad14
YK
7705 check_pw(ctx);
7706 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7707 register_name = "PWField";
fa75ad14 7708 break;
a1e76353 7709 case CP0_REG05__PWSIZE:
20b28ebc
YK
7710 check_pw(ctx);
7711 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7712 register_name = "PWSize";
20b28ebc 7713 break;
9c2149c8 7714 default:
f31b035a 7715 goto cp0_unimplemented;
876d4b07 7716 }
9c2149c8 7717 break;
04992c8c 7718 case CP0_REGISTER_06:
9c2149c8 7719 switch (sel) {
9023594b 7720 case CP0_REG06__WIRED:
7db13fae 7721 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7722 register_name = "Wired";
2423f660 7723 break;
9023594b 7724 case CP0_REG06__SRSCONF0:
7a47bae5 7725 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7727 register_name = "SRSConf0";
ead9360e 7728 break;
9023594b 7729 case CP0_REG06__SRSCONF1:
7a47bae5 7730 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7732 register_name = "SRSConf1";
ead9360e 7733 break;
9023594b 7734 case CP0_REG06__SRSCONF2:
7a47bae5 7735 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7737 register_name = "SRSConf2";
ead9360e 7738 break;
9023594b 7739 case CP0_REG06__SRSCONF3:
7a47bae5 7740 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7742 register_name = "SRSConf3";
ead9360e 7743 break;
9023594b 7744 case CP0_REG06__SRSCONF4:
7a47bae5 7745 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7747 register_name = "SRSConf4";
ead9360e 7748 break;
9023594b 7749 case CP0_REG06__PWCTL:
103be64c
YK
7750 check_pw(ctx);
7751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7752 register_name = "PWCtl";
103be64c 7753 break;
9c2149c8 7754 default:
f31b035a 7755 goto cp0_unimplemented;
876d4b07 7756 }
9c2149c8 7757 break;
04992c8c 7758 case CP0_REGISTER_07:
9c2149c8 7759 switch (sel) {
143a9875 7760 case CP0_REG07__HWRENA:
7a47bae5 7761 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7763 register_name = "HWREna";
2423f660 7764 break;
9c2149c8 7765 default:
f31b035a 7766 goto cp0_unimplemented;
876d4b07 7767 }
9c2149c8 7768 break;
04992c8c 7769 case CP0_REGISTER_08:
9c2149c8 7770 switch (sel) {
67d167d2 7771 case CP0_REG08__BADVADDR:
7db13fae 7772 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 7773 register_name = "BadVAddr";
2423f660 7774 break;
67d167d2 7775 case CP0_REG08__BADINSTR:
f31b035a
LA
7776 CP0_CHECK(ctx->bi);
7777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7778 register_name = "BadInstr";
aea14095 7779 break;
67d167d2 7780 case CP0_REG08__BADINSTRP:
f31b035a
LA
7781 CP0_CHECK(ctx->bp);
7782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7783 register_name = "BadInstrP";
aea14095 7784 break;
67d167d2 7785 case CP0_REG08__BADINSTRX:
25beba9b
SM
7786 CP0_CHECK(ctx->bi);
7787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7788 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7789 register_name = "BadInstrX";
25beba9b 7790 break;
9c2149c8 7791 default:
f31b035a 7792 goto cp0_unimplemented;
876d4b07 7793 }
9c2149c8 7794 break;
04992c8c 7795 case CP0_REGISTER_09:
9c2149c8 7796 switch (sel) {
e5a98a72 7797 case CP0_REG09__COUNT:
2e70f6ef 7798 /* Mark as an IO operation because we read the time. */
eeb3bba8 7799 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7800 gen_io_start();
bd79255d 7801 }
895c2d04 7802 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7803 /*
7804 * Break the TB to be able to take timer interrupts immediately
7805 * after reading count. DISAS_STOP isn't sufficient, we need to
7806 * ensure we break completely out of translated code.
7807 */
eeb3bba8
EC
7808 gen_save_pc(ctx->base.pc_next + 4);
7809 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7810 register_name = "Count";
2423f660 7811 break;
e5a98a72 7812 case CP0_REG09__SAARI:
5fb2dcd1
YK
7813 CP0_CHECK(ctx->saar);
7814 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7815 register_name = "SAARI";
5fb2dcd1 7816 break;
e5a98a72 7817 case CP0_REG09__SAAR:
5fb2dcd1
YK
7818 CP0_CHECK(ctx->saar);
7819 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 7820 register_name = "SAAR";
5fb2dcd1 7821 break;
9c2149c8 7822 default:
f31b035a 7823 goto cp0_unimplemented;
876d4b07 7824 }
9c2149c8 7825 break;
04992c8c 7826 case CP0_REGISTER_10:
9c2149c8 7827 switch (sel) {
860ffef0 7828 case CP0_REG10__ENTRYHI:
7db13fae 7829 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 7830 register_name = "EntryHi";
2423f660 7831 break;
9c2149c8 7832 default:
f31b035a 7833 goto cp0_unimplemented;
876d4b07 7834 }
9c2149c8 7835 break;
04992c8c 7836 case CP0_REGISTER_11:
9c2149c8 7837 switch (sel) {
f5f3834f 7838 case CP0_REG11__COMPARE:
7db13fae 7839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7840 register_name = "Compare";
2423f660 7841 break;
876d4b07 7842 /* 6,7 are implementation dependent */
9c2149c8 7843 default:
f31b035a 7844 goto cp0_unimplemented;
876d4b07 7845 }
9c2149c8 7846 break;
04992c8c 7847 case CP0_REGISTER_12:
9c2149c8 7848 switch (sel) {
2b084867 7849 case CP0_REG12__STATUS:
7db13fae 7850 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7851 register_name = "Status";
2423f660 7852 break;
2b084867 7853 case CP0_REG12__INTCTL:
7a47bae5 7854 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7855 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7856 register_name = "IntCtl";
2423f660 7857 break;
2b084867 7858 case CP0_REG12__SRSCTL:
7a47bae5 7859 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7861 register_name = "SRSCtl";
2423f660 7862 break;
2b084867 7863 case CP0_REG12__SRSMAP:
7a47bae5 7864 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7865 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7866 register_name = "SRSMap";
2423f660 7867 break;
9c2149c8 7868 default:
f31b035a 7869 goto cp0_unimplemented;
876d4b07 7870 }
9c2149c8 7871 break;
04992c8c 7872 case CP0_REGISTER_13:
9c2149c8 7873 switch (sel) {
e3c7559d 7874 case CP0_REG13__CAUSE:
7db13fae 7875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7876 register_name = "Cause";
2423f660 7877 break;
9c2149c8 7878 default:
f31b035a 7879 goto cp0_unimplemented;
876d4b07 7880 }
9c2149c8 7881 break;
04992c8c 7882 case CP0_REGISTER_14:
9c2149c8 7883 switch (sel) {
35e4b54d 7884 case CP0_REG14__EPC:
7db13fae 7885 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7886 register_name = "EPC";
2423f660 7887 break;
9c2149c8 7888 default:
f31b035a 7889 goto cp0_unimplemented;
876d4b07 7890 }
9c2149c8 7891 break;
04992c8c 7892 case CP0_REGISTER_15:
9c2149c8 7893 switch (sel) {
4466cd49 7894 case CP0_REG15__PRID:
7db13fae 7895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7896 register_name = "PRid";
2423f660 7897 break;
4466cd49 7898 case CP0_REG15__EBASE:
7a47bae5 7899 check_insn(ctx, ISA_MIPS_R2);
74dbf824 7900 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 7901 register_name = "EBase";
2423f660 7902 break;
4466cd49 7903 case CP0_REG15__CMGCRBASE:
7a47bae5 7904 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
7905 CP0_CHECK(ctx->cmgcr);
7906 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 7907 register_name = "CMGCRBase";
c870e3f5 7908 break;
9c2149c8 7909 default:
f31b035a 7910 goto cp0_unimplemented;
876d4b07 7911 }
9c2149c8 7912 break;
04992c8c 7913 case CP0_REGISTER_16:
9c2149c8 7914 switch (sel) {
433efb4c 7915 case CP0_REG16__CONFIG:
7db13fae 7916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7917 register_name = "Config";
9c2149c8 7918 break;
433efb4c 7919 case CP0_REG16__CONFIG1:
7db13fae 7920 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7921 register_name = "Config1";
9c2149c8 7922 break;
433efb4c 7923 case CP0_REG16__CONFIG2:
7db13fae 7924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7925 register_name = "Config2";
9c2149c8 7926 break;
433efb4c 7927 case CP0_REG16__CONFIG3:
7db13fae 7928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7929 register_name = "Config3";
9c2149c8 7930 break;
433efb4c 7931 case CP0_REG16__CONFIG4:
faf1f68b 7932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7933 register_name = "Config4";
faf1f68b 7934 break;
433efb4c 7935 case CP0_REG16__CONFIG5:
faf1f68b 7936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7937 register_name = "Config5";
faf1f68b 7938 break;
05aa7e93 7939 /* 6,7 are implementation dependent */
433efb4c 7940 case CP0_REG16__CONFIG6:
7db13fae 7941 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7942 register_name = "Config6";
f0b3f3ae 7943 break;
433efb4c 7944 case CP0_REG16__CONFIG7:
7db13fae 7945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7946 register_name = "Config7";
f0b3f3ae 7947 break;
9c2149c8 7948 default:
f31b035a 7949 goto cp0_unimplemented;
9c2149c8
TS
7950 }
7951 break;
04992c8c 7952 case CP0_REGISTER_17:
9c2149c8 7953 switch (sel) {
706ce142 7954 case CP0_REG17__LLADDR:
895c2d04 7955 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 7956 register_name = "LLAddr";
2423f660 7957 break;
706ce142 7958 case CP0_REG17__MAAR:
f6d4dd81
YK
7959 CP0_CHECK(ctx->mrp);
7960 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 7961 register_name = "MAAR";
f6d4dd81 7962 break;
706ce142 7963 case CP0_REG17__MAARI:
f6d4dd81
YK
7964 CP0_CHECK(ctx->mrp);
7965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7966 register_name = "MAARI";
f6d4dd81 7967 break;
9c2149c8 7968 default:
f31b035a 7969 goto cp0_unimplemented;
9c2149c8
TS
7970 }
7971 break;
04992c8c 7972 case CP0_REGISTER_18:
9c2149c8 7973 switch (sel) {
e8dcfe82
AM
7974 case CP0_REG18__WATCHLO0:
7975 case CP0_REG18__WATCHLO1:
7976 case CP0_REG18__WATCHLO2:
7977 case CP0_REG18__WATCHLO3:
7978 case CP0_REG18__WATCHLO4:
7979 case CP0_REG18__WATCHLO5:
7980 case CP0_REG18__WATCHLO6:
7981 case CP0_REG18__WATCHLO7:
fa192d49 7982 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7983 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 7984 register_name = "WatchLo";
2423f660 7985 break;
9c2149c8 7986 default:
f31b035a 7987 goto cp0_unimplemented;
9c2149c8
TS
7988 }
7989 break;
04992c8c 7990 case CP0_REGISTER_19:
9c2149c8 7991 switch (sel) {
be274dc1
AM
7992 case CP0_REG19__WATCHHI0:
7993 case CP0_REG19__WATCHHI1:
7994 case CP0_REG19__WATCHHI2:
7995 case CP0_REG19__WATCHHI3:
7996 case CP0_REG19__WATCHHI4:
7997 case CP0_REG19__WATCHHI5:
7998 case CP0_REG19__WATCHHI6:
7999 case CP0_REG19__WATCHHI7:
fa192d49 8000 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 8001 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 8002 register_name = "WatchHi";
2423f660 8003 break;
9c2149c8 8004 default:
f31b035a 8005 goto cp0_unimplemented;
9c2149c8
TS
8006 }
8007 break;
04992c8c 8008 case CP0_REGISTER_20:
9c2149c8 8009 switch (sel) {
14f92b0b 8010 case CP0_REG20__XCONTEXT:
d75c135e 8011 check_insn(ctx, ISA_MIPS3);
7db13fae 8012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8013 register_name = "XContext";
2423f660 8014 break;
9c2149c8 8015 default:
f31b035a 8016 goto cp0_unimplemented;
9c2149c8
TS
8017 }
8018 break;
04992c8c 8019 case CP0_REGISTER_21:
05aa7e93 8020 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8021 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
8022 switch (sel) {
8023 case 0:
7db13fae 8024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8025 register_name = "Framemask";
2423f660 8026 break;
9c2149c8 8027 default:
f31b035a 8028 goto cp0_unimplemented;
9c2149c8
TS
8029 }
8030 break;
04992c8c 8031 case CP0_REGISTER_22:
d9bea114 8032 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8033 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8034 break;
04992c8c 8035 case CP0_REGISTER_23:
9c2149c8 8036 switch (sel) {
4cbf4b6d 8037 case CP0_REG23__DEBUG:
895c2d04 8038 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 8039 register_name = "Debug";
2423f660 8040 break;
4cbf4b6d
AM
8041 case CP0_REG23__TRACECONTROL:
8042 /* PDtrace support */
8043 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 8044 register_name = "TraceControl";
3570d7f6 8045 goto cp0_unimplemented;
4cbf4b6d
AM
8046 case CP0_REG23__TRACECONTROL2:
8047 /* PDtrace support */
8048 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 8049 register_name = "TraceControl2";
3570d7f6 8050 goto cp0_unimplemented;
4cbf4b6d
AM
8051 case CP0_REG23__USERTRACEDATA1:
8052 /* PDtrace support */
8053 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8054 register_name = "UserTraceData1";
3570d7f6 8055 goto cp0_unimplemented;
4cbf4b6d
AM
8056 case CP0_REG23__TRACEIBPC:
8057 /* PDtrace support */
8058 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8059 register_name = "TraceIBPC";
8060 goto cp0_unimplemented;
8061 case CP0_REG23__TRACEDBPC:
8062 /* PDtrace support */
8063 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8064 register_name = "TraceDBPC";
3570d7f6 8065 goto cp0_unimplemented;
9c2149c8 8066 default:
f31b035a 8067 goto cp0_unimplemented;
9c2149c8
TS
8068 }
8069 break;
04992c8c 8070 case CP0_REGISTER_24:
9c2149c8 8071 switch (sel) {
8d7b4b6e 8072 case CP0_REG24__DEPC:
f0b3f3ae 8073 /* EJTAG support */
7db13fae 8074 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8075 register_name = "DEPC";
2423f660 8076 break;
9c2149c8 8077 default:
f31b035a 8078 goto cp0_unimplemented;
9c2149c8
TS
8079 }
8080 break;
04992c8c 8081 case CP0_REGISTER_25:
9c2149c8 8082 switch (sel) {
1176b328 8083 case CP0_REG25__PERFCTL0:
7db13fae 8084 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8085 register_name = "Performance0";
9c2149c8 8086 break;
1176b328 8087 case CP0_REG25__PERFCNT0:
7480515f 8088 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 8089 register_name = "Performance1";
3570d7f6 8090 goto cp0_unimplemented;
1176b328 8091 case CP0_REG25__PERFCTL1:
7480515f 8092 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 8093 register_name = "Performance2";
3570d7f6 8094 goto cp0_unimplemented;
1176b328 8095 case CP0_REG25__PERFCNT1:
7480515f 8096 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 8097 register_name = "Performance3";
3570d7f6 8098 goto cp0_unimplemented;
1176b328 8099 case CP0_REG25__PERFCTL2:
7480515f 8100 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 8101 register_name = "Performance4";
3570d7f6 8102 goto cp0_unimplemented;
1176b328 8103 case CP0_REG25__PERFCNT2:
7480515f 8104 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 8105 register_name = "Performance5";
3570d7f6 8106 goto cp0_unimplemented;
1176b328 8107 case CP0_REG25__PERFCTL3:
7480515f 8108 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 8109 register_name = "Performance6";
3570d7f6 8110 goto cp0_unimplemented;
1176b328 8111 case CP0_REG25__PERFCNT3:
7480515f 8112 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 8113 register_name = "Performance7";
3570d7f6 8114 goto cp0_unimplemented;
9c2149c8 8115 default:
f31b035a 8116 goto cp0_unimplemented;
9c2149c8
TS
8117 }
8118 break;
04992c8c 8119 case CP0_REGISTER_26:
0d74a222 8120 switch (sel) {
dbbf08b2 8121 case CP0_REG26__ERRCTL:
0d74a222 8122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8123 register_name = "ErrCtl";
0d74a222
LA
8124 break;
8125 default:
8126 goto cp0_unimplemented;
8127 }
da80682b 8128 break;
04992c8c 8129 case CP0_REGISTER_27:
9c2149c8
TS
8130 switch (sel) {
8131 /* ignored */
5a10873d 8132 case CP0_REG27__CACHERR:
d9bea114 8133 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8134 register_name = "CacheErr";
2423f660 8135 break;
9c2149c8 8136 default:
f31b035a 8137 goto cp0_unimplemented;
9c2149c8
TS
8138 }
8139 break;
04992c8c 8140 case CP0_REGISTER_28:
9c2149c8 8141 switch (sel) {
a30e2f21
AM
8142 case CP0_REG28__TAGLO:
8143 case CP0_REG28__TAGLO1:
8144 case CP0_REG28__TAGLO2:
8145 case CP0_REG28__TAGLO3:
7db13fae 8146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 8147 register_name = "TagLo";
9c2149c8 8148 break;
a30e2f21
AM
8149 case CP0_REG28__DATALO:
8150 case CP0_REG28__DATALO1:
8151 case CP0_REG28__DATALO2:
8152 case CP0_REG28__DATALO3:
7db13fae 8153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8154 register_name = "DataLo";
9c2149c8
TS
8155 break;
8156 default:
f31b035a 8157 goto cp0_unimplemented;
9c2149c8
TS
8158 }
8159 break;
04992c8c 8160 case CP0_REGISTER_29:
9c2149c8 8161 switch (sel) {
af4bb6da
AM
8162 case CP0_REG29__TAGHI:
8163 case CP0_REG29__TAGHI1:
8164 case CP0_REG29__TAGHI2:
8165 case CP0_REG29__TAGHI3:
7db13fae 8166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8167 register_name = "TagHi";
9c2149c8 8168 break;
af4bb6da
AM
8169 case CP0_REG29__DATAHI:
8170 case CP0_REG29__DATAHI1:
8171 case CP0_REG29__DATAHI2:
8172 case CP0_REG29__DATAHI3:
7db13fae 8173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8174 register_name = "DataHi";
9c2149c8
TS
8175 break;
8176 default:
f31b035a 8177 goto cp0_unimplemented;
9c2149c8
TS
8178 }
8179 break;
04992c8c 8180 case CP0_REGISTER_30:
9c2149c8 8181 switch (sel) {
4bcf121e 8182 case CP0_REG30__ERROREPC:
7db13fae 8183 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8184 register_name = "ErrorEPC";
2423f660 8185 break;
9c2149c8 8186 default:
f31b035a 8187 goto cp0_unimplemented;
9c2149c8
TS
8188 }
8189 break;
04992c8c 8190 case CP0_REGISTER_31:
9c2149c8 8191 switch (sel) {
14d92efd 8192 case CP0_REG31__DESAVE:
f0b3f3ae 8193 /* EJTAG support */
7db13fae 8194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8195 register_name = "DESAVE";
2423f660 8196 break;
14d92efd
AM
8197 case CP0_REG31__KSCRATCH1:
8198 case CP0_REG31__KSCRATCH2:
8199 case CP0_REG31__KSCRATCH3:
8200 case CP0_REG31__KSCRATCH4:
8201 case CP0_REG31__KSCRATCH5:
8202 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8203 CP0_CHECK(ctx->kscrexist & (1 << sel));
8204 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 8205 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8206 register_name = "KScratch";
e98c0d17 8207 break;
9c2149c8 8208 default:
f31b035a 8209 goto cp0_unimplemented;
9c2149c8
TS
8210 }
8211 break;
8212 default:
f31b035a 8213 goto cp0_unimplemented;
9c2149c8 8214 }
294fc2ea 8215 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
8216 return;
8217
f31b035a 8218cp0_unimplemented:
294fc2ea
AM
8219 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8220 register_name, reg, sel);
f31b035a 8221 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
8222}
8223
d75c135e 8224static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8225{
294fc2ea 8226 const char *register_name = "invalid";
9c2149c8 8227
1f8929d2 8228 if (sel != 0) {
bbd5e4a2 8229 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 8230 }
e189e748 8231
eeb3bba8 8232 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8233 gen_io_start();
bd79255d 8234 }
2e70f6ef 8235
9c2149c8 8236 switch (reg) {
04992c8c 8237 case CP0_REGISTER_00:
9c2149c8 8238 switch (sel) {
1b142da5 8239 case CP0_REG00__INDEX:
895c2d04 8240 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 8241 register_name = "Index";
9c2149c8 8242 break;
1b142da5 8243 case CP0_REG00__MVPCONTROL:
f31b035a 8244 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8245 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 8246 register_name = "MVPControl";
ead9360e 8247 break;
1b142da5 8248 case CP0_REG00__MVPCONF0:
f31b035a 8249 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8250 /* ignored */
294fc2ea 8251 register_name = "MVPConf0";
ead9360e 8252 break;
1b142da5 8253 case CP0_REG00__MVPCONF1:
f31b035a 8254 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8255 /* ignored */
294fc2ea 8256 register_name = "MVPConf1";
ead9360e 8257 break;
1b142da5 8258 case CP0_REG00__VPCONTROL:
01bc435b
YK
8259 CP0_CHECK(ctx->vp);
8260 /* ignored */
294fc2ea 8261 register_name = "VPControl";
01bc435b 8262 break;
9c2149c8 8263 default:
f31b035a 8264 goto cp0_unimplemented;
9c2149c8
TS
8265 }
8266 break;
04992c8c 8267 case CP0_REGISTER_01:
9c2149c8 8268 switch (sel) {
30deb460 8269 case CP0_REG01__RANDOM:
2423f660 8270 /* ignored */
294fc2ea 8271 register_name = "Random";
2423f660 8272 break;
30deb460 8273 case CP0_REG01__VPECONTROL:
f31b035a 8274 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8275 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 8276 register_name = "VPEControl";
ead9360e 8277 break;
30deb460 8278 case CP0_REG01__VPECONF0:
f31b035a 8279 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8280 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 8281 register_name = "VPEConf0";
ead9360e 8282 break;
30deb460 8283 case CP0_REG01__VPECONF1:
f31b035a 8284 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8285 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 8286 register_name = "VPEConf1";
ead9360e 8287 break;
30deb460 8288 case CP0_REG01__YQMASK:
f31b035a 8289 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8290 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 8291 register_name = "YQMask";
ead9360e 8292 break;
30deb460 8293 case CP0_REG01__VPESCHEDULE:
f31b035a 8294 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8295 tcg_gen_st_tl(arg, cpu_env,
8296 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8297 register_name = "VPESchedule";
ead9360e 8298 break;
30deb460 8299 case CP0_REG01__VPESCHEFBACK:
f31b035a 8300 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8301 tcg_gen_st_tl(arg, cpu_env,
8302 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8303 register_name = "VPEScheFBack";
ead9360e 8304 break;
30deb460 8305 case CP0_REG01__VPEOPT:
f31b035a 8306 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8307 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 8308 register_name = "VPEOpt";
ead9360e 8309 break;
9c2149c8 8310 default:
f31b035a 8311 goto cp0_unimplemented;
9c2149c8
TS
8312 }
8313 break;
04992c8c 8314 case CP0_REGISTER_02:
9c2149c8 8315 switch (sel) {
6d27d5bd 8316 case CP0_REG02__ENTRYLO0:
7207c7f9 8317 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 8318 register_name = "EntryLo0";
2423f660 8319 break;
6d27d5bd 8320 case CP0_REG02__TCSTATUS:
f31b035a 8321 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8322 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 8323 register_name = "TCStatus";
ead9360e 8324 break;
6d27d5bd 8325 case CP0_REG02__TCBIND:
f31b035a 8326 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8327 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 8328 register_name = "TCBind";
ead9360e 8329 break;
6d27d5bd 8330 case CP0_REG02__TCRESTART:
f31b035a 8331 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8332 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 8333 register_name = "TCRestart";
ead9360e 8334 break;
6d27d5bd 8335 case CP0_REG02__TCHALT:
f31b035a 8336 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8337 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 8338 register_name = "TCHalt";
ead9360e 8339 break;
6d27d5bd 8340 case CP0_REG02__TCCONTEXT:
f31b035a 8341 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8342 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 8343 register_name = "TCContext";
ead9360e 8344 break;
6d27d5bd 8345 case CP0_REG02__TCSCHEDULE:
f31b035a 8346 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8347 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 8348 register_name = "TCSchedule";
ead9360e 8349 break;
6d27d5bd 8350 case CP0_REG02__TCSCHEFBACK:
f31b035a 8351 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8352 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 8353 register_name = "TCScheFBack";
ead9360e 8354 break;
9c2149c8 8355 default:
f31b035a 8356 goto cp0_unimplemented;
9c2149c8
TS
8357 }
8358 break;
04992c8c 8359 case CP0_REGISTER_03:
9c2149c8 8360 switch (sel) {
acd37316 8361 case CP0_REG03__ENTRYLO1:
7207c7f9 8362 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 8363 register_name = "EntryLo1";
2423f660 8364 break;
acd37316 8365 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8366 CP0_CHECK(ctx->vp);
8367 /* ignored */
294fc2ea 8368 register_name = "GlobalNumber";
01bc435b 8369 break;
9c2149c8 8370 default:
f31b035a 8371 goto cp0_unimplemented;
876d4b07 8372 }
9c2149c8 8373 break;
04992c8c 8374 case CP0_REGISTER_04:
9c2149c8 8375 switch (sel) {
020fe379 8376 case CP0_REG04__CONTEXT:
895c2d04 8377 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 8378 register_name = "Context";
2423f660 8379 break;
020fe379
AM
8380 case CP0_REG04__CONTEXTCONFIG:
8381 /* SmartMIPS ASE */
8382 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 8383 register_name = "ContextConfig";
f31b035a 8384 goto cp0_unimplemented;
020fe379 8385 case CP0_REG04__USERLOCAL:
f31b035a
LA
8386 CP0_CHECK(ctx->ulri);
8387 tcg_gen_st_tl(arg, cpu_env,
8388 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8389 register_name = "UserLocal";
d279279e 8390 break;
99029be1
YK
8391 case CP0_REG04__MMID:
8392 CP0_CHECK(ctx->mi);
8393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8394 register_name = "MMID";
8395 break;
9c2149c8 8396 default:
f31b035a 8397 goto cp0_unimplemented;
876d4b07 8398 }
9c2149c8 8399 break;
04992c8c 8400 case CP0_REGISTER_05:
9c2149c8 8401 switch (sel) {
a1e76353 8402 case CP0_REG05__PAGEMASK:
895c2d04 8403 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 8404 register_name = "PageMask";
2423f660 8405 break;
a1e76353 8406 case CP0_REG05__PAGEGRAIN:
7a47bae5 8407 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8408 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 8409 register_name = "PageGrain";
2423f660 8410 break;
a1e76353 8411 case CP0_REG05__SEGCTL0:
cec56a73
JH
8412 CP0_CHECK(ctx->sc);
8413 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 8414 register_name = "SegCtl0";
cec56a73 8415 break;
a1e76353 8416 case CP0_REG05__SEGCTL1:
cec56a73
JH
8417 CP0_CHECK(ctx->sc);
8418 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 8419 register_name = "SegCtl1";
cec56a73 8420 break;
a1e76353 8421 case CP0_REG05__SEGCTL2:
cec56a73
JH
8422 CP0_CHECK(ctx->sc);
8423 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 8424 register_name = "SegCtl2";
cec56a73 8425 break;
a1e76353 8426 case CP0_REG05__PWBASE:
5e31fdd5
YK
8427 check_pw(ctx);
8428 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8429 register_name = "PWBase";
5e31fdd5 8430 break;
a1e76353 8431 case CP0_REG05__PWFIELD:
fa75ad14
YK
8432 check_pw(ctx);
8433 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 8434 register_name = "PWField";
fa75ad14 8435 break;
a1e76353 8436 case CP0_REG05__PWSIZE:
20b28ebc
YK
8437 check_pw(ctx);
8438 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 8439 register_name = "PWSize";
20b28ebc 8440 break;
9c2149c8 8441 default:
f31b035a 8442 goto cp0_unimplemented;
876d4b07 8443 }
9c2149c8 8444 break;
04992c8c 8445 case CP0_REGISTER_06:
9c2149c8 8446 switch (sel) {
9023594b 8447 case CP0_REG06__WIRED:
895c2d04 8448 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 8449 register_name = "Wired";
2423f660 8450 break;
9023594b 8451 case CP0_REG06__SRSCONF0:
7a47bae5 8452 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8453 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 8454 register_name = "SRSConf0";
ead9360e 8455 break;
9023594b 8456 case CP0_REG06__SRSCONF1:
7a47bae5 8457 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8458 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 8459 register_name = "SRSConf1";
ead9360e 8460 break;
9023594b 8461 case CP0_REG06__SRSCONF2:
7a47bae5 8462 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8463 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 8464 register_name = "SRSConf2";
ead9360e 8465 break;
9023594b 8466 case CP0_REG06__SRSCONF3:
7a47bae5 8467 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8468 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 8469 register_name = "SRSConf3";
ead9360e 8470 break;
9023594b 8471 case CP0_REG06__SRSCONF4:
7a47bae5 8472 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8473 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 8474 register_name = "SRSConf4";
ead9360e 8475 break;
9023594b 8476 case CP0_REG06__PWCTL:
103be64c
YK
8477 check_pw(ctx);
8478 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 8479 register_name = "PWCtl";
103be64c 8480 break;
9c2149c8 8481 default:
f31b035a 8482 goto cp0_unimplemented;
876d4b07 8483 }
9c2149c8 8484 break;
04992c8c 8485 case CP0_REGISTER_07:
9c2149c8 8486 switch (sel) {
143a9875 8487 case CP0_REG07__HWRENA:
7a47bae5 8488 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8489 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 8490 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8491 register_name = "HWREna";
2423f660 8492 break;
9c2149c8 8493 default:
f31b035a 8494 goto cp0_unimplemented;
876d4b07 8495 }
9c2149c8 8496 break;
04992c8c 8497 case CP0_REGISTER_08:
aea14095 8498 switch (sel) {
67d167d2 8499 case CP0_REG08__BADVADDR:
aea14095 8500 /* ignored */
294fc2ea 8501 register_name = "BadVAddr";
aea14095 8502 break;
67d167d2 8503 case CP0_REG08__BADINSTR:
aea14095 8504 /* ignored */
294fc2ea 8505 register_name = "BadInstr";
aea14095 8506 break;
67d167d2 8507 case CP0_REG08__BADINSTRP:
aea14095 8508 /* ignored */
294fc2ea 8509 register_name = "BadInstrP";
aea14095 8510 break;
67d167d2 8511 case CP0_REG08__BADINSTRX:
25beba9b 8512 /* ignored */
294fc2ea 8513 register_name = "BadInstrX";
25beba9b 8514 break;
aea14095 8515 default:
f31b035a 8516 goto cp0_unimplemented;
aea14095 8517 }
9c2149c8 8518 break;
04992c8c 8519 case CP0_REGISTER_09:
9c2149c8 8520 switch (sel) {
e5a98a72 8521 case CP0_REG09__COUNT:
895c2d04 8522 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 8523 register_name = "Count";
2423f660 8524 break;
e5a98a72 8525 case CP0_REG09__SAARI:
5fb2dcd1
YK
8526 CP0_CHECK(ctx->saar);
8527 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 8528 register_name = "SAARI";
5fb2dcd1 8529 break;
e5a98a72 8530 case CP0_REG09__SAAR:
5fb2dcd1
YK
8531 CP0_CHECK(ctx->saar);
8532 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 8533 register_name = "SAAR";
5fb2dcd1 8534 break;
9c2149c8 8535 default:
f31b035a 8536 goto cp0_unimplemented;
876d4b07
TS
8537 }
8538 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8539 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8540 break;
04992c8c 8541 case CP0_REGISTER_10:
9c2149c8 8542 switch (sel) {
860ffef0 8543 case CP0_REG10__ENTRYHI:
895c2d04 8544 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 8545 register_name = "EntryHi";
2423f660 8546 break;
9c2149c8 8547 default:
f31b035a 8548 goto cp0_unimplemented;
876d4b07 8549 }
9c2149c8 8550 break;
04992c8c 8551 case CP0_REGISTER_11:
9c2149c8 8552 switch (sel) {
f5f3834f 8553 case CP0_REG11__COMPARE:
895c2d04 8554 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 8555 register_name = "Compare";
2423f660 8556 break;
876d4b07 8557 /* 6,7 are implementation dependent */
9c2149c8 8558 default:
f31b035a 8559 goto cp0_unimplemented;
876d4b07 8560 }
de9a95f0 8561 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8562 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8563 break;
04992c8c 8564 case CP0_REGISTER_12:
9c2149c8 8565 switch (sel) {
2b084867 8566 case CP0_REG12__STATUS:
867abc7e 8567 save_cpu_state(ctx, 1);
895c2d04 8568 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8569 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8570 gen_save_pc(ctx->base.pc_next + 4);
8571 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8572 register_name = "Status";
2423f660 8573 break;
2b084867 8574 case CP0_REG12__INTCTL:
7a47bae5 8575 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8576 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8577 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8578 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8579 register_name = "IntCtl";
2423f660 8580 break;
2b084867 8581 case CP0_REG12__SRSCTL:
7a47bae5 8582 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8583 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8584 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8585 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8586 register_name = "SRSCtl";
2423f660 8587 break;
2b084867 8588 case CP0_REG12__SRSMAP:
7a47bae5 8589 check_insn(ctx, ISA_MIPS_R2);
7db13fae 8590 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8591 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8592 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8593 register_name = "SRSMap";
2423f660
TS
8594 break;
8595 default:
f31b035a 8596 goto cp0_unimplemented;
876d4b07 8597 }
9c2149c8 8598 break;
04992c8c 8599 case CP0_REGISTER_13:
9c2149c8 8600 switch (sel) {
e3c7559d 8601 case CP0_REG13__CAUSE:
867abc7e 8602 save_cpu_state(ctx, 1);
895c2d04 8603 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
8604 /*
8605 * Stop translation as we may have triggered an interrupt.
b28425ba 8606 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
8607 * translated code to check for pending interrupts.
8608 */
eeb3bba8
EC
8609 gen_save_pc(ctx->base.pc_next + 4);
8610 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8611 register_name = "Cause";
2423f660 8612 break;
9c2149c8 8613 default:
f31b035a 8614 goto cp0_unimplemented;
876d4b07 8615 }
9c2149c8 8616 break;
04992c8c 8617 case CP0_REGISTER_14:
9c2149c8 8618 switch (sel) {
35e4b54d 8619 case CP0_REG14__EPC:
7db13fae 8620 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8621 register_name = "EPC";
2423f660 8622 break;
9c2149c8 8623 default:
f31b035a 8624 goto cp0_unimplemented;
876d4b07 8625 }
9c2149c8 8626 break;
04992c8c 8627 case CP0_REGISTER_15:
9c2149c8 8628 switch (sel) {
4466cd49 8629 case CP0_REG15__PRID:
2423f660 8630 /* ignored */
294fc2ea 8631 register_name = "PRid";
2423f660 8632 break;
4466cd49 8633 case CP0_REG15__EBASE:
7a47bae5 8634 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8635 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 8636 register_name = "EBase";
2423f660 8637 break;
9c2149c8 8638 default:
f31b035a 8639 goto cp0_unimplemented;
876d4b07 8640 }
9c2149c8 8641 break;
04992c8c 8642 case CP0_REGISTER_16:
9c2149c8 8643 switch (sel) {
433efb4c 8644 case CP0_REG16__CONFIG:
895c2d04 8645 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 8646 register_name = "Config";
2423f660 8647 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8648 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8649 break;
433efb4c 8650 case CP0_REG16__CONFIG1:
1fc7bf6e 8651 /* ignored, read only */
294fc2ea 8652 register_name = "Config1";
9c2149c8 8653 break;
433efb4c 8654 case CP0_REG16__CONFIG2:
895c2d04 8655 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 8656 register_name = "Config2";
2423f660 8657 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8658 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8659 break;
433efb4c 8660 case CP0_REG16__CONFIG3:
90f12d73 8661 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 8662 register_name = "Config3";
90f12d73 8663 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8664 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8665 break;
433efb4c 8666 case CP0_REG16__CONFIG4:
faf1f68b 8667 /* currently ignored */
294fc2ea 8668 register_name = "Config4";
faf1f68b 8669 break;
433efb4c 8670 case CP0_REG16__CONFIG5:
faf1f68b 8671 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8672 register_name = "Config5";
faf1f68b 8673 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8674 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 8675 break;
9c2149c8
TS
8676 /* 6,7 are implementation dependent */
8677 default:
294fc2ea 8678 register_name = "Invalid config selector";
f31b035a 8679 goto cp0_unimplemented;
9c2149c8 8680 }
9c2149c8 8681 break;
04992c8c 8682 case CP0_REGISTER_17:
9c2149c8 8683 switch (sel) {
706ce142 8684 case CP0_REG17__LLADDR:
895c2d04 8685 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8686 register_name = "LLAddr";
2423f660 8687 break;
706ce142 8688 case CP0_REG17__MAAR:
f6d4dd81
YK
8689 CP0_CHECK(ctx->mrp);
8690 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8691 register_name = "MAAR";
f6d4dd81 8692 break;
706ce142 8693 case CP0_REG17__MAARI:
f6d4dd81
YK
8694 CP0_CHECK(ctx->mrp);
8695 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8696 register_name = "MAARI";
f6d4dd81 8697 break;
9c2149c8 8698 default:
f31b035a 8699 goto cp0_unimplemented;
9c2149c8
TS
8700 }
8701 break;
04992c8c 8702 case CP0_REGISTER_18:
9c2149c8 8703 switch (sel) {
e8dcfe82
AM
8704 case CP0_REG18__WATCHLO0:
8705 case CP0_REG18__WATCHLO1:
8706 case CP0_REG18__WATCHLO2:
8707 case CP0_REG18__WATCHLO3:
8708 case CP0_REG18__WATCHLO4:
8709 case CP0_REG18__WATCHLO5:
8710 case CP0_REG18__WATCHLO6:
8711 case CP0_REG18__WATCHLO7:
fa192d49 8712 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8713 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8714 register_name = "WatchLo";
2423f660 8715 break;
9c2149c8 8716 default:
f31b035a 8717 goto cp0_unimplemented;
9c2149c8
TS
8718 }
8719 break;
04992c8c 8720 case CP0_REGISTER_19:
9c2149c8 8721 switch (sel) {
be274dc1
AM
8722 case CP0_REG19__WATCHHI0:
8723 case CP0_REG19__WATCHHI1:
8724 case CP0_REG19__WATCHHI2:
8725 case CP0_REG19__WATCHHI3:
8726 case CP0_REG19__WATCHHI4:
8727 case CP0_REG19__WATCHHI5:
8728 case CP0_REG19__WATCHHI6:
8729 case CP0_REG19__WATCHHI7:
fa192d49 8730 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8731 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8732 register_name = "WatchHi";
2423f660 8733 break;
9c2149c8 8734 default:
f31b035a 8735 goto cp0_unimplemented;
9c2149c8
TS
8736 }
8737 break;
04992c8c 8738 case CP0_REGISTER_20:
9c2149c8 8739 switch (sel) {
14f92b0b 8740 case CP0_REG20__XCONTEXT:
d75c135e 8741 check_insn(ctx, ISA_MIPS3);
895c2d04 8742 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8743 register_name = "XContext";
2423f660 8744 break;
9c2149c8 8745 default:
f31b035a 8746 goto cp0_unimplemented;
9c2149c8
TS
8747 }
8748 break;
04992c8c 8749 case CP0_REGISTER_21:
9c2149c8 8750 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8751 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
8752 switch (sel) {
8753 case 0:
895c2d04 8754 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8755 register_name = "Framemask";
2423f660 8756 break;
9c2149c8 8757 default:
f31b035a 8758 goto cp0_unimplemented;
9c2149c8
TS
8759 }
8760 break;
04992c8c 8761 case CP0_REGISTER_22:
9c2149c8 8762 /* ignored */
294fc2ea 8763 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 8764 break;
04992c8c 8765 case CP0_REGISTER_23:
9c2149c8 8766 switch (sel) {
4cbf4b6d 8767 case CP0_REG23__DEBUG:
895c2d04 8768 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8769 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8770 gen_save_pc(ctx->base.pc_next + 4);
8771 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8772 register_name = "Debug";
2423f660 8773 break;
4cbf4b6d
AM
8774 case CP0_REG23__TRACECONTROL:
8775 /* PDtrace support */
8776 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 8777 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8778 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8779 register_name = "TraceControl";
3570d7f6 8780 goto cp0_unimplemented;
4cbf4b6d
AM
8781 case CP0_REG23__TRACECONTROL2:
8782 /* PDtrace support */
8783 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 8784 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8785 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8786 register_name = "TraceControl2";
3570d7f6 8787 goto cp0_unimplemented;
4cbf4b6d
AM
8788 case CP0_REG23__USERTRACEDATA1:
8789 /* PDtrace support */
8790 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 8791 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8792 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8793 register_name = "UserTraceData1";
3570d7f6 8794 goto cp0_unimplemented;
4cbf4b6d
AM
8795 case CP0_REG23__TRACEIBPC:
8796 /* PDtrace support */
8797 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8798 /* Stop translation as we may have switched the execution mode */
8799 ctx->base.is_jmp = DISAS_STOP;
8800 register_name = "TraceIBPC";
8801 goto cp0_unimplemented;
8802 case CP0_REG23__TRACEDBPC:
8803 /* PDtrace support */
8804 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 8805 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8806 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8807 register_name = "TraceDBPC";
3570d7f6 8808 goto cp0_unimplemented;
9c2149c8 8809 default:
f31b035a 8810 goto cp0_unimplemented;
9c2149c8 8811 }
9c2149c8 8812 break;
04992c8c 8813 case CP0_REGISTER_24:
9c2149c8 8814 switch (sel) {
8d7b4b6e 8815 case CP0_REG24__DEPC:
f1aa6320 8816 /* EJTAG support */
7db13fae 8817 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8818 register_name = "DEPC";
2423f660 8819 break;
9c2149c8 8820 default:
f31b035a 8821 goto cp0_unimplemented;
9c2149c8
TS
8822 }
8823 break;
04992c8c 8824 case CP0_REGISTER_25:
9c2149c8 8825 switch (sel) {
1176b328 8826 case CP0_REG25__PERFCTL0:
895c2d04 8827 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8828 register_name = "Performance0";
2423f660 8829 break;
1176b328 8830 case CP0_REG25__PERFCNT0:
7480515f 8831 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 8832 register_name = "Performance1";
3570d7f6 8833 goto cp0_unimplemented;
1176b328 8834 case CP0_REG25__PERFCTL1:
7480515f 8835 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 8836 register_name = "Performance2";
3570d7f6 8837 goto cp0_unimplemented;
1176b328 8838 case CP0_REG25__PERFCNT1:
7480515f 8839 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 8840 register_name = "Performance3";
3570d7f6 8841 goto cp0_unimplemented;
1176b328 8842 case CP0_REG25__PERFCTL2:
7480515f 8843 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 8844 register_name = "Performance4";
3570d7f6 8845 goto cp0_unimplemented;
1176b328 8846 case CP0_REG25__PERFCNT2:
7480515f 8847 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 8848 register_name = "Performance5";
3570d7f6 8849 goto cp0_unimplemented;
1176b328 8850 case CP0_REG25__PERFCTL3:
7480515f 8851 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 8852 register_name = "Performance6";
3570d7f6 8853 goto cp0_unimplemented;
1176b328 8854 case CP0_REG25__PERFCNT3:
7480515f 8855 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 8856 register_name = "Performance7";
3570d7f6 8857 goto cp0_unimplemented;
9c2149c8 8858 default:
f31b035a 8859 goto cp0_unimplemented;
9c2149c8 8860 }
876d4b07 8861 break;
04992c8c 8862 case CP0_REGISTER_26:
0d74a222 8863 switch (sel) {
dbbf08b2 8864 case CP0_REG26__ERRCTL:
0d74a222 8865 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8866 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8867 register_name = "ErrCtl";
0d74a222
LA
8868 break;
8869 default:
8870 goto cp0_unimplemented;
8871 }
876d4b07 8872 break;
04992c8c 8873 case CP0_REGISTER_27:
9c2149c8 8874 switch (sel) {
5a10873d 8875 case CP0_REG27__CACHERR:
2423f660 8876 /* ignored */
294fc2ea 8877 register_name = "CacheErr";
2423f660 8878 break;
9c2149c8 8879 default:
f31b035a 8880 goto cp0_unimplemented;
9c2149c8 8881 }
876d4b07 8882 break;
04992c8c 8883 case CP0_REGISTER_28:
9c2149c8 8884 switch (sel) {
a30e2f21
AM
8885 case CP0_REG28__TAGLO:
8886 case CP0_REG28__TAGLO1:
8887 case CP0_REG28__TAGLO2:
8888 case CP0_REG28__TAGLO3:
895c2d04 8889 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8890 register_name = "TagLo";
9c2149c8 8891 break;
a30e2f21
AM
8892 case CP0_REG28__DATALO:
8893 case CP0_REG28__DATALO1:
8894 case CP0_REG28__DATALO2:
8895 case CP0_REG28__DATALO3:
895c2d04 8896 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8897 register_name = "DataLo";
9c2149c8
TS
8898 break;
8899 default:
f31b035a 8900 goto cp0_unimplemented;
9c2149c8
TS
8901 }
8902 break;
04992c8c 8903 case CP0_REGISTER_29:
9c2149c8 8904 switch (sel) {
af4bb6da
AM
8905 case CP0_REG29__TAGHI:
8906 case CP0_REG29__TAGHI1:
8907 case CP0_REG29__TAGHI2:
8908 case CP0_REG29__TAGHI3:
895c2d04 8909 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8910 register_name = "TagHi";
9c2149c8 8911 break;
af4bb6da
AM
8912 case CP0_REG29__DATAHI:
8913 case CP0_REG29__DATAHI1:
8914 case CP0_REG29__DATAHI2:
8915 case CP0_REG29__DATAHI3:
895c2d04 8916 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8917 register_name = "DataHi";
9c2149c8
TS
8918 break;
8919 default:
294fc2ea 8920 register_name = "invalid sel";
f31b035a 8921 goto cp0_unimplemented;
9c2149c8 8922 }
876d4b07 8923 break;
04992c8c 8924 case CP0_REGISTER_30:
9c2149c8 8925 switch (sel) {
4bcf121e 8926 case CP0_REG30__ERROREPC:
7db13fae 8927 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8928 register_name = "ErrorEPC";
2423f660 8929 break;
9c2149c8 8930 default:
f31b035a 8931 goto cp0_unimplemented;
9c2149c8
TS
8932 }
8933 break;
04992c8c 8934 case CP0_REGISTER_31:
9c2149c8 8935 switch (sel) {
14d92efd 8936 case CP0_REG31__DESAVE:
f1aa6320 8937 /* EJTAG support */
7db13fae 8938 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8939 register_name = "DESAVE";
2423f660 8940 break;
14d92efd
AM
8941 case CP0_REG31__KSCRATCH1:
8942 case CP0_REG31__KSCRATCH2:
8943 case CP0_REG31__KSCRATCH3:
8944 case CP0_REG31__KSCRATCH4:
8945 case CP0_REG31__KSCRATCH5:
8946 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8947 CP0_CHECK(ctx->kscrexist & (1 << sel));
8948 tcg_gen_st_tl(arg, cpu_env,
71375b59 8949 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8950 register_name = "KScratch";
e98c0d17 8951 break;
9c2149c8 8952 default:
f31b035a 8953 goto cp0_unimplemented;
9c2149c8 8954 }
9c2149c8
TS
8955 break;
8956 default:
f31b035a 8957 goto cp0_unimplemented;
9c2149c8 8958 }
294fc2ea 8959 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 8960
bf20dc07 8961 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8962 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8963 /*
8964 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8965 * translated code to check for pending interrupts.
8966 */
eeb3bba8
EC
8967 gen_save_pc(ctx->base.pc_next + 4);
8968 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8969 }
9c2149c8
TS
8970 return;
8971
f31b035a 8972cp0_unimplemented:
294fc2ea
AM
8973 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8974 register_name, reg, sel);
9c2149c8 8975}
d26bc211 8976#endif /* TARGET_MIPS64 */
9c2149c8 8977
7db13fae 8978static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
8979 int u, int sel, int h)
8980{
8981 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8982 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
8983
8984 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 8985 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 8986 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 8987 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
8988 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8989 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 8990 tcg_gen_movi_tl(t0, -1);
1f8929d2 8991 } else if (u == 0) {
ead9360e 8992 switch (rt) {
5a25ce94
EI
8993 case 1:
8994 switch (sel) {
8995 case 1:
895c2d04 8996 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
8997 break;
8998 case 2:
895c2d04 8999 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9000 break;
9001 default:
9002 goto die;
9003 break;
9004 }
9005 break;
ead9360e
TS
9006 case 2:
9007 switch (sel) {
9008 case 1:
895c2d04 9009 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9010 break;
9011 case 2:
895c2d04 9012 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9013 break;
9014 case 3:
895c2d04 9015 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9016 break;
9017 case 4:
895c2d04 9018 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9019 break;
9020 case 5:
895c2d04 9021 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9022 break;
9023 case 6:
895c2d04 9024 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9025 break;
9026 case 7:
895c2d04 9027 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9028 break;
9029 default:
d75c135e 9030 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9031 break;
9032 }
9033 break;
9034 case 10:
9035 switch (sel) {
9036 case 0:
895c2d04 9037 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9038 break;
9039 default:
d75c135e 9040 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9041 break;
9042 }
f1fadbb2 9043 break;
ead9360e
TS
9044 case 12:
9045 switch (sel) {
9046 case 0:
895c2d04 9047 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9048 break;
9049 default:
d75c135e 9050 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9051 break;
9052 }
f1fadbb2 9053 break;
5a25ce94
EI
9054 case 13:
9055 switch (sel) {
9056 case 0:
895c2d04 9057 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9058 break;
9059 default:
9060 goto die;
9061 break;
9062 }
9063 break;
9064 case 14:
9065 switch (sel) {
9066 case 0:
895c2d04 9067 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9068 break;
9069 default:
9070 goto die;
9071 break;
9072 }
9073 break;
9074 case 15:
9075 switch (sel) {
9076 case 1:
895c2d04 9077 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9078 break;
9079 default:
9080 goto die;
9081 break;
9082 }
9083 break;
9084 case 16:
9085 switch (sel) {
c2e19f3c
AM
9086 case 0:
9087 case 1:
9088 case 2:
9089 case 3:
9090 case 4:
9091 case 5:
9092 case 6:
9093 case 7:
895c2d04 9094 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9095 break;
9096 default:
9097 goto die;
9098 break;
9099 }
9100 break;
ead9360e
TS
9101 case 23:
9102 switch (sel) {
9103 case 0:
895c2d04 9104 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9105 break;
9106 default:
d75c135e 9107 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9108 break;
9109 }
9110 break;
9111 default:
d75c135e 9112 gen_mfc0(ctx, t0, rt, sel);
ead9360e 9113 }
71375b59
AM
9114 } else {
9115 switch (sel) {
9116 /* GPR registers. */
ead9360e 9117 case 0:
71375b59 9118 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 9119 break;
71375b59 9120 /* Auxiliary CPU registers */
ead9360e 9121 case 1:
71375b59
AM
9122 switch (rt) {
9123 case 0:
9124 gen_helper_1e0i(mftlo, t0, 0);
9125 break;
9126 case 1:
9127 gen_helper_1e0i(mfthi, t0, 0);
9128 break;
9129 case 2:
9130 gen_helper_1e0i(mftacx, t0, 0);
9131 break;
9132 case 4:
9133 gen_helper_1e0i(mftlo, t0, 1);
9134 break;
9135 case 5:
9136 gen_helper_1e0i(mfthi, t0, 1);
9137 break;
9138 case 6:
9139 gen_helper_1e0i(mftacx, t0, 1);
9140 break;
9141 case 8:
9142 gen_helper_1e0i(mftlo, t0, 2);
9143 break;
9144 case 9:
9145 gen_helper_1e0i(mfthi, t0, 2);
9146 break;
9147 case 10:
9148 gen_helper_1e0i(mftacx, t0, 2);
9149 break;
9150 case 12:
9151 gen_helper_1e0i(mftlo, t0, 3);
9152 break;
9153 case 13:
9154 gen_helper_1e0i(mfthi, t0, 3);
9155 break;
9156 case 14:
9157 gen_helper_1e0i(mftacx, t0, 3);
9158 break;
9159 case 16:
9160 gen_helper_mftdsp(t0, cpu_env);
9161 break;
9162 default:
9163 goto die;
9164 }
ead9360e 9165 break;
71375b59 9166 /* Floating point (COP1). */
ead9360e 9167 case 2:
71375b59
AM
9168 /* XXX: For now we support only a single FPU context. */
9169 if (h == 0) {
9170 TCGv_i32 fp0 = tcg_temp_new_i32();
9171
9172 gen_load_fpr32(ctx, fp0, rt);
9173 tcg_gen_ext_i32_tl(t0, fp0);
9174 tcg_temp_free_i32(fp0);
9175 } else {
9176 TCGv_i32 fp0 = tcg_temp_new_i32();
9177
9178 gen_load_fpr32h(ctx, fp0, rt);
9179 tcg_gen_ext_i32_tl(t0, fp0);
9180 tcg_temp_free_i32(fp0);
9181 }
ead9360e 9182 break;
71375b59
AM
9183 case 3:
9184 /* XXX: For now we support only a single FPU context. */
9185 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 9186 break;
71375b59
AM
9187 /* COP2: Not implemented. */
9188 case 4:
ead9360e 9189 case 5:
71375b59 9190 /* fall through */
ead9360e
TS
9191 default:
9192 goto die;
9193 }
ead9360e 9194 }
b44a7fb1 9195 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
9196 gen_store_gpr(t0, rd);
9197 tcg_temp_free(t0);
ead9360e
TS
9198 return;
9199
9200die:
1a3fd9c3 9201 tcg_temp_free(t0);
d12d51d5 9202 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
3a4ef3b7 9203 gen_reserved_instruction(ctx);
ead9360e
TS
9204}
9205
7db13fae 9206static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
9207 int u, int sel, int h)
9208{
9209 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9210 TCGv t0 = tcg_temp_local_new();
ead9360e 9211
1a3fd9c3 9212 gen_load_gpr(t0, rt);
ead9360e 9213 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9214 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9215 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
9216 /* NOP */
9217 ;
1f8929d2
AM
9218 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9219 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
9220 /* NOP */
9221 ;
1f8929d2 9222 } else if (u == 0) {
ead9360e 9223 switch (rd) {
5a25ce94
EI
9224 case 1:
9225 switch (sel) {
9226 case 1:
895c2d04 9227 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
9228 break;
9229 case 2:
895c2d04 9230 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
9231 break;
9232 default:
9233 goto die;
9234 break;
9235 }
9236 break;
ead9360e
TS
9237 case 2:
9238 switch (sel) {
9239 case 1:
895c2d04 9240 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
9241 break;
9242 case 2:
895c2d04 9243 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
9244 break;
9245 case 3:
895c2d04 9246 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
9247 break;
9248 case 4:
895c2d04 9249 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
9250 break;
9251 case 5:
895c2d04 9252 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
9253 break;
9254 case 6:
895c2d04 9255 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
9256 break;
9257 case 7:
895c2d04 9258 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
9259 break;
9260 default:
d75c135e 9261 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9262 break;
9263 }
9264 break;
9265 case 10:
9266 switch (sel) {
9267 case 0:
895c2d04 9268 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
9269 break;
9270 default:
d75c135e 9271 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9272 break;
9273 }
0d0304f2 9274 break;
ead9360e
TS
9275 case 12:
9276 switch (sel) {
9277 case 0:
895c2d04 9278 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
9279 break;
9280 default:
d75c135e 9281 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9282 break;
9283 }
0d0304f2 9284 break;
5a25ce94
EI
9285 case 13:
9286 switch (sel) {
9287 case 0:
895c2d04 9288 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
9289 break;
9290 default:
9291 goto die;
9292 break;
9293 }
9294 break;
9295 case 15:
9296 switch (sel) {
9297 case 1:
895c2d04 9298 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
9299 break;
9300 default:
9301 goto die;
9302 break;
9303 }
9304 break;
ead9360e
TS
9305 case 23:
9306 switch (sel) {
9307 case 0:
895c2d04 9308 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
9309 break;
9310 default:
d75c135e 9311 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9312 break;
9313 }
9314 break;
9315 default:
d75c135e 9316 gen_mtc0(ctx, t0, rd, sel);
ead9360e 9317 }
71375b59
AM
9318 } else {
9319 switch (sel) {
9320 /* GPR registers. */
ead9360e 9321 case 0:
71375b59 9322 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 9323 break;
71375b59 9324 /* Auxiliary CPU registers */
ead9360e 9325 case 1:
71375b59
AM
9326 switch (rd) {
9327 case 0:
9328 gen_helper_0e1i(mttlo, t0, 0);
9329 break;
9330 case 1:
9331 gen_helper_0e1i(mtthi, t0, 0);
9332 break;
9333 case 2:
9334 gen_helper_0e1i(mttacx, t0, 0);
9335 break;
9336 case 4:
9337 gen_helper_0e1i(mttlo, t0, 1);
9338 break;
9339 case 5:
9340 gen_helper_0e1i(mtthi, t0, 1);
9341 break;
9342 case 6:
9343 gen_helper_0e1i(mttacx, t0, 1);
9344 break;
9345 case 8:
9346 gen_helper_0e1i(mttlo, t0, 2);
9347 break;
9348 case 9:
9349 gen_helper_0e1i(mtthi, t0, 2);
9350 break;
9351 case 10:
9352 gen_helper_0e1i(mttacx, t0, 2);
9353 break;
9354 case 12:
9355 gen_helper_0e1i(mttlo, t0, 3);
9356 break;
9357 case 13:
9358 gen_helper_0e1i(mtthi, t0, 3);
9359 break;
9360 case 14:
9361 gen_helper_0e1i(mttacx, t0, 3);
9362 break;
9363 case 16:
9364 gen_helper_mttdsp(cpu_env, t0);
9365 break;
9366 default:
9367 goto die;
9368 }
ead9360e 9369 break;
71375b59 9370 /* Floating point (COP1). */
ead9360e 9371 case 2:
71375b59
AM
9372 /* XXX: For now we support only a single FPU context. */
9373 if (h == 0) {
9374 TCGv_i32 fp0 = tcg_temp_new_i32();
9375
9376 tcg_gen_trunc_tl_i32(fp0, t0);
9377 gen_store_fpr32(ctx, fp0, rd);
9378 tcg_temp_free_i32(fp0);
9379 } else {
9380 TCGv_i32 fp0 = tcg_temp_new_i32();
9381
9382 tcg_gen_trunc_tl_i32(fp0, t0);
9383 gen_store_fpr32h(ctx, fp0, rd);
9384 tcg_temp_free_i32(fp0);
9385 }
ead9360e 9386 break;
71375b59
AM
9387 case 3:
9388 /* XXX: For now we support only a single FPU context. */
9389 {
9390 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9391
9392 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9393 tcg_temp_free_i32(fs_tmp);
9394 }
9395 /* Stop translation as we may have changed hflags */
9396 ctx->base.is_jmp = DISAS_STOP;
ead9360e 9397 break;
71375b59
AM
9398 /* COP2: Not implemented. */
9399 case 4:
ead9360e 9400 case 5:
71375b59 9401 /* fall through */
ead9360e
TS
9402 default:
9403 goto die;
9404 }
ead9360e 9405 }
b44a7fb1 9406 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 9407 tcg_temp_free(t0);
ead9360e
TS
9408 return;
9409
9410die:
1a3fd9c3 9411 tcg_temp_free(t0);
d12d51d5 9412 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
3a4ef3b7 9413 gen_reserved_instruction(ctx);
ead9360e
TS
9414}
9415
235785e8
AM
9416static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9417 int rt, int rd)
6af0bf9c 9418{
287c4b84 9419 const char *opn = "ldst";
6af0bf9c 9420
2e15497c 9421 check_cp0_enabled(ctx);
6af0bf9c
FB
9422 switch (opc) {
9423 case OPC_MFC0:
9424 if (rt == 0) {
ead9360e 9425 /* Treat as NOP. */
6af0bf9c
FB
9426 return;
9427 }
d75c135e 9428 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
9429 opn = "mfc0";
9430 break;
9431 case OPC_MTC0:
1a3fd9c3 9432 {
1fc7bf6e 9433 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9434
9435 gen_load_gpr(t0, rt);
d75c135e 9436 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9437 tcg_temp_free(t0);
9438 }
6af0bf9c
FB
9439 opn = "mtc0";
9440 break;
d26bc211 9441#if defined(TARGET_MIPS64)
9c2149c8 9442 case OPC_DMFC0:
d75c135e 9443 check_insn(ctx, ISA_MIPS3);
9c2149c8 9444 if (rt == 0) {
ead9360e 9445 /* Treat as NOP. */
9c2149c8
TS
9446 return;
9447 }
d75c135e 9448 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
9449 opn = "dmfc0";
9450 break;
9451 case OPC_DMTC0:
d75c135e 9452 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 9453 {
1fc7bf6e 9454 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9455
9456 gen_load_gpr(t0, rt);
d75c135e 9457 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9458 tcg_temp_free(t0);
9459 }
9c2149c8
TS
9460 opn = "dmtc0";
9461 break;
534ce69f 9462#endif
5204ea79
LA
9463 case OPC_MFHC0:
9464 check_mvh(ctx);
9465 if (rt == 0) {
9466 /* Treat as NOP. */
9467 return;
9468 }
9469 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9470 opn = "mfhc0";
9471 break;
9472 case OPC_MTHC0:
9473 check_mvh(ctx);
9474 {
9475 TCGv t0 = tcg_temp_new();
9476 gen_load_gpr(t0, rt);
9477 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9478 tcg_temp_free(t0);
9479 }
9480 opn = "mthc0";
9481 break;
ead9360e 9482 case OPC_MFTR:
9affc1c5 9483 check_cp0_enabled(ctx);
ead9360e
TS
9484 if (rd == 0) {
9485 /* Treat as NOP. */
9486 return;
9487 }
6c5c1e20 9488 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 9489 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
9490 opn = "mftr";
9491 break;
9492 case OPC_MTTR:
9affc1c5 9493 check_cp0_enabled(ctx);
6c5c1e20 9494 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
9495 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9496 opn = "mttr";
9497 break;
6af0bf9c 9498 case OPC_TLBWI:
6af0bf9c 9499 opn = "tlbwi";
1f8929d2 9500 if (!env->tlb->helper_tlbwi) {
29929e34 9501 goto die;
1f8929d2 9502 }
895c2d04 9503 gen_helper_tlbwi(cpu_env);
6af0bf9c 9504 break;
9456c2fb
LA
9505 case OPC_TLBINV:
9506 opn = "tlbinv";
9507 if (ctx->ie >= 2) {
9508 if (!env->tlb->helper_tlbinv) {
9509 goto die;
9510 }
9511 gen_helper_tlbinv(cpu_env);
9512 } /* treat as nop if TLBINV not supported */
9513 break;
9514 case OPC_TLBINVF:
9515 opn = "tlbinvf";
9516 if (ctx->ie >= 2) {
9517 if (!env->tlb->helper_tlbinvf) {
9518 goto die;
9519 }
9520 gen_helper_tlbinvf(cpu_env);
9521 } /* treat as nop if TLBINV not supported */
9522 break;
6af0bf9c 9523 case OPC_TLBWR:
6af0bf9c 9524 opn = "tlbwr";
1f8929d2 9525 if (!env->tlb->helper_tlbwr) {
29929e34 9526 goto die;
1f8929d2 9527 }
895c2d04 9528 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
9529 break;
9530 case OPC_TLBP:
6af0bf9c 9531 opn = "tlbp";
1f8929d2 9532 if (!env->tlb->helper_tlbp) {
29929e34 9533 goto die;
1f8929d2 9534 }
895c2d04 9535 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
9536 break;
9537 case OPC_TLBR:
6af0bf9c 9538 opn = "tlbr";
1f8929d2 9539 if (!env->tlb->helper_tlbr) {
29929e34 9540 goto die;
1f8929d2 9541 }
895c2d04 9542 gen_helper_tlbr(cpu_env);
6af0bf9c 9543 break;
ce9782f4 9544 case OPC_ERET: /* OPC_ERETNC */
2e211e0a 9545 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9546 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 9547 goto die;
ce9782f4
LA
9548 } else {
9549 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9550 if (ctx->opcode & (1 << bit_shift)) {
9551 /* OPC_ERETNC */
9552 opn = "eretnc";
5f89ce4f 9553 check_insn(ctx, ISA_MIPS_R5);
ce9782f4
LA
9554 gen_helper_eretnc(cpu_env);
9555 } else {
9556 /* OPC_ERET */
9557 opn = "eret";
9558 check_insn(ctx, ISA_MIPS2);
9559 gen_helper_eret(cpu_env);
9560 }
eeb3bba8 9561 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 9562 }
6af0bf9c
FB
9563 break;
9564 case OPC_DERET:
9565 opn = "deret";
bbd5e4a2 9566 check_insn(ctx, ISA_MIPS_R1);
2e211e0a 9567 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9568 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9569 goto die;
9570 }
6af0bf9c 9571 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 9572 MIPS_INVAL(opn);
3a4ef3b7 9573 gen_reserved_instruction(ctx);
6af0bf9c 9574 } else {
895c2d04 9575 gen_helper_deret(cpu_env);
eeb3bba8 9576 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
9577 }
9578 break;
4ad40f36
FB
9579 case OPC_WAIT:
9580 opn = "wait";
bbd5e4a2 9581 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
2e211e0a 9582 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9583 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9584 goto die;
9585 }
4ad40f36 9586 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 9587 ctx->base.pc_next += 4;
4ad40f36 9588 save_cpu_state(ctx, 1);
eeb3bba8 9589 ctx->base.pc_next -= 4;
895c2d04 9590 gen_helper_wait(cpu_env);
eeb3bba8 9591 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 9592 break;
6af0bf9c 9593 default:
29929e34 9594 die:
923617a3 9595 MIPS_INVAL(opn);
3a4ef3b7 9596 gen_reserved_instruction(ctx);
6af0bf9c
FB
9597 return;
9598 }
2abf314d 9599 (void)opn; /* avoid a compiler warning */
6af0bf9c 9600}
f1aa6320 9601#endif /* !CONFIG_USER_ONLY */
6af0bf9c 9602
6ea83fed 9603/* CP1 Branches (before delay slot) */
d75c135e
AJ
9604static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9605 int32_t cc, int32_t offset)
6ea83fed
FB
9606{
9607 target_ulong btarget;
a7812ae4 9608 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 9609
2e211e0a 9610 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 9611 gen_reserved_instruction(ctx);
339cd2a8
LA
9612 goto out;
9613 }
9614
1f8929d2 9615 if (cc != 0) {
bbd5e4a2 9616 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
1f8929d2 9617 }
e189e748 9618
eeb3bba8 9619 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 9620
7a387fff
TS
9621 switch (op) {
9622 case OPC_BC1F:
d94536f4
AJ
9623 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9624 tcg_gen_not_i32(t0, t0);
9625 tcg_gen_andi_i32(t0, t0, 1);
9626 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9627 goto not_likely;
7a387fff 9628 case OPC_BC1FL:
d94536f4
AJ
9629 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9630 tcg_gen_not_i32(t0, t0);
9631 tcg_gen_andi_i32(t0, t0, 1);
9632 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9633 goto likely;
7a387fff 9634 case OPC_BC1T:
d94536f4
AJ
9635 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9636 tcg_gen_andi_i32(t0, t0, 1);
9637 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 9638 goto not_likely;
7a387fff 9639 case OPC_BC1TL:
d94536f4
AJ
9640 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9641 tcg_gen_andi_i32(t0, t0, 1);
9642 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
9643 likely:
9644 ctx->hflags |= MIPS_HFLAG_BL;
9645 break;
5a5012ec 9646 case OPC_BC1FANY2:
a16336e4 9647 {
d94536f4
AJ
9648 TCGv_i32 t1 = tcg_temp_new_i32();
9649 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9650 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9651 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9652 tcg_temp_free_i32(t1);
d94536f4
AJ
9653 tcg_gen_andi_i32(t0, t0, 1);
9654 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9655 }
5a5012ec
TS
9656 goto not_likely;
9657 case OPC_BC1TANY2:
a16336e4 9658 {
d94536f4
AJ
9659 TCGv_i32 t1 = tcg_temp_new_i32();
9660 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9661 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
9662 tcg_gen_or_i32(t0, t0, t1);
9663 tcg_temp_free_i32(t1);
9664 tcg_gen_andi_i32(t0, t0, 1);
9665 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9666 }
5a5012ec
TS
9667 goto not_likely;
9668 case OPC_BC1FANY4:
a16336e4 9669 {
d94536f4
AJ
9670 TCGv_i32 t1 = tcg_temp_new_i32();
9671 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9672 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9673 tcg_gen_and_i32(t0, t0, t1);
71375b59 9674 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 9675 tcg_gen_and_i32(t0, t0, t1);
71375b59 9676 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 9677 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9678 tcg_temp_free_i32(t1);
d94536f4
AJ
9679 tcg_gen_andi_i32(t0, t0, 1);
9680 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9681 }
5a5012ec
TS
9682 goto not_likely;
9683 case OPC_BC1TANY4:
a16336e4 9684 {
d94536f4
AJ
9685 TCGv_i32 t1 = tcg_temp_new_i32();
9686 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9687 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 9688 tcg_gen_or_i32(t0, t0, t1);
71375b59 9689 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 9690 tcg_gen_or_i32(t0, t0, t1);
71375b59 9691 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
9692 tcg_gen_or_i32(t0, t0, t1);
9693 tcg_temp_free_i32(t1);
9694 tcg_gen_andi_i32(t0, t0, 1);
9695 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9696 }
5a5012ec
TS
9697 not_likely:
9698 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
9699 break;
9700 default:
9d68ac14 9701 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9702 gen_reserved_instruction(ctx);
6c5c1e20 9703 goto out;
6ea83fed 9704 }
6ea83fed 9705 ctx->btarget = btarget;
b231c103 9706 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 9707 out:
a7812ae4 9708 tcg_temp_free_i32(t0);
6ea83fed
FB
9709}
9710
31837be3
YK
9711/* R6 CP1 Branches */
9712static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
9713 int32_t ft, int32_t offset,
9714 int delayslot_size)
31837be3
YK
9715{
9716 target_ulong btarget;
31837be3
YK
9717 TCGv_i64 t0 = tcg_temp_new_i64();
9718
9719 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9720#ifdef MIPS_DEBUG_DISAS
339cd2a8 9721 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 9722 "\n", ctx->base.pc_next);
31837be3 9723#endif
3a4ef3b7 9724 gen_reserved_instruction(ctx);
31837be3
YK
9725 goto out;
9726 }
9727
9728 gen_load_fpr64(ctx, t0, ft);
9729 tcg_gen_andi_i64(t0, t0, 1);
9730
eeb3bba8 9731 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
9732
9733 switch (op) {
9734 case OPC_BC1EQZ:
9735 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
9736 ctx->hflags |= MIPS_HFLAG_BC;
9737 break;
9738 case OPC_BC1NEZ:
9739 /* t0 already set */
31837be3
YK
9740 ctx->hflags |= MIPS_HFLAG_BC;
9741 break;
9742 default:
9d68ac14 9743 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9744 gen_reserved_instruction(ctx);
31837be3
YK
9745 goto out;
9746 }
9747
9748 tcg_gen_trunc_i64_tl(bcond, t0);
9749
31837be3 9750 ctx->btarget = btarget;
65935f07
YK
9751
9752 switch (delayslot_size) {
9753 case 2:
9754 ctx->hflags |= MIPS_HFLAG_BDS16;
9755 break;
9756 case 4:
9757 ctx->hflags |= MIPS_HFLAG_BDS32;
9758 break;
9759 }
31837be3
YK
9760
9761out:
9762 tcg_temp_free_i64(t0);
9763}
9764
6af0bf9c 9765/* Coprocessor 1 (FPU) */
5a5012ec 9766
5a5012ec
TS
9767#define FOP(func, fmt) (((fmt) << 21) | (func))
9768
bf4120ad
NF
9769enum fopcode {
9770 OPC_ADD_S = FOP(0, FMT_S),
9771 OPC_SUB_S = FOP(1, FMT_S),
9772 OPC_MUL_S = FOP(2, FMT_S),
9773 OPC_DIV_S = FOP(3, FMT_S),
9774 OPC_SQRT_S = FOP(4, FMT_S),
9775 OPC_ABS_S = FOP(5, FMT_S),
9776 OPC_MOV_S = FOP(6, FMT_S),
9777 OPC_NEG_S = FOP(7, FMT_S),
9778 OPC_ROUND_L_S = FOP(8, FMT_S),
9779 OPC_TRUNC_L_S = FOP(9, FMT_S),
9780 OPC_CEIL_L_S = FOP(10, FMT_S),
9781 OPC_FLOOR_L_S = FOP(11, FMT_S),
9782 OPC_ROUND_W_S = FOP(12, FMT_S),
9783 OPC_TRUNC_W_S = FOP(13, FMT_S),
9784 OPC_CEIL_W_S = FOP(14, FMT_S),
9785 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 9786 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
9787 OPC_MOVCF_S = FOP(17, FMT_S),
9788 OPC_MOVZ_S = FOP(18, FMT_S),
9789 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 9790 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
9791 OPC_RECIP_S = FOP(21, FMT_S),
9792 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
9793 OPC_SELNEZ_S = FOP(23, FMT_S),
9794 OPC_MADDF_S = FOP(24, FMT_S),
9795 OPC_MSUBF_S = FOP(25, FMT_S),
9796 OPC_RINT_S = FOP(26, FMT_S),
9797 OPC_CLASS_S = FOP(27, FMT_S),
9798 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 9799 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 9800 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 9801 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 9802 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 9803 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 9804 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
9805 OPC_RSQRT2_S = FOP(31, FMT_S),
9806 OPC_CVT_D_S = FOP(33, FMT_S),
9807 OPC_CVT_W_S = FOP(36, FMT_S),
9808 OPC_CVT_L_S = FOP(37, FMT_S),
9809 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
9810 OPC_CMP_F_S = FOP(48, FMT_S),
9811 OPC_CMP_UN_S = FOP(49, FMT_S),
9812 OPC_CMP_EQ_S = FOP(50, FMT_S),
9813 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9814 OPC_CMP_OLT_S = FOP(52, FMT_S),
9815 OPC_CMP_ULT_S = FOP(53, FMT_S),
9816 OPC_CMP_OLE_S = FOP(54, FMT_S),
9817 OPC_CMP_ULE_S = FOP(55, FMT_S),
9818 OPC_CMP_SF_S = FOP(56, FMT_S),
9819 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9820 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9821 OPC_CMP_NGL_S = FOP(59, FMT_S),
9822 OPC_CMP_LT_S = FOP(60, FMT_S),
9823 OPC_CMP_NGE_S = FOP(61, FMT_S),
9824 OPC_CMP_LE_S = FOP(62, FMT_S),
9825 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
9826
9827 OPC_ADD_D = FOP(0, FMT_D),
9828 OPC_SUB_D = FOP(1, FMT_D),
9829 OPC_MUL_D = FOP(2, FMT_D),
9830 OPC_DIV_D = FOP(3, FMT_D),
9831 OPC_SQRT_D = FOP(4, FMT_D),
9832 OPC_ABS_D = FOP(5, FMT_D),
9833 OPC_MOV_D = FOP(6, FMT_D),
9834 OPC_NEG_D = FOP(7, FMT_D),
9835 OPC_ROUND_L_D = FOP(8, FMT_D),
9836 OPC_TRUNC_L_D = FOP(9, FMT_D),
9837 OPC_CEIL_L_D = FOP(10, FMT_D),
9838 OPC_FLOOR_L_D = FOP(11, FMT_D),
9839 OPC_ROUND_W_D = FOP(12, FMT_D),
9840 OPC_TRUNC_W_D = FOP(13, FMT_D),
9841 OPC_CEIL_W_D = FOP(14, FMT_D),
9842 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 9843 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
9844 OPC_MOVCF_D = FOP(17, FMT_D),
9845 OPC_MOVZ_D = FOP(18, FMT_D),
9846 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 9847 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
9848 OPC_RECIP_D = FOP(21, FMT_D),
9849 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
9850 OPC_SELNEZ_D = FOP(23, FMT_D),
9851 OPC_MADDF_D = FOP(24, FMT_D),
9852 OPC_MSUBF_D = FOP(25, FMT_D),
9853 OPC_RINT_D = FOP(26, FMT_D),
9854 OPC_CLASS_D = FOP(27, FMT_D),
9855 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 9856 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 9857 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 9858 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 9859 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 9860 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 9861 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
9862 OPC_RSQRT2_D = FOP(31, FMT_D),
9863 OPC_CVT_S_D = FOP(32, FMT_D),
9864 OPC_CVT_W_D = FOP(36, FMT_D),
9865 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
9866 OPC_CMP_F_D = FOP(48, FMT_D),
9867 OPC_CMP_UN_D = FOP(49, FMT_D),
9868 OPC_CMP_EQ_D = FOP(50, FMT_D),
9869 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9870 OPC_CMP_OLT_D = FOP(52, FMT_D),
9871 OPC_CMP_ULT_D = FOP(53, FMT_D),
9872 OPC_CMP_OLE_D = FOP(54, FMT_D),
9873 OPC_CMP_ULE_D = FOP(55, FMT_D),
9874 OPC_CMP_SF_D = FOP(56, FMT_D),
9875 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9876 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9877 OPC_CMP_NGL_D = FOP(59, FMT_D),
9878 OPC_CMP_LT_D = FOP(60, FMT_D),
9879 OPC_CMP_NGE_D = FOP(61, FMT_D),
9880 OPC_CMP_LE_D = FOP(62, FMT_D),
9881 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
9882
9883 OPC_CVT_S_W = FOP(32, FMT_W),
9884 OPC_CVT_D_W = FOP(33, FMT_W),
9885 OPC_CVT_S_L = FOP(32, FMT_L),
9886 OPC_CVT_D_L = FOP(33, FMT_L),
9887 OPC_CVT_PS_PW = FOP(38, FMT_W),
9888
9889 OPC_ADD_PS = FOP(0, FMT_PS),
9890 OPC_SUB_PS = FOP(1, FMT_PS),
9891 OPC_MUL_PS = FOP(2, FMT_PS),
9892 OPC_DIV_PS = FOP(3, FMT_PS),
9893 OPC_ABS_PS = FOP(5, FMT_PS),
9894 OPC_MOV_PS = FOP(6, FMT_PS),
9895 OPC_NEG_PS = FOP(7, FMT_PS),
9896 OPC_MOVCF_PS = FOP(17, FMT_PS),
9897 OPC_MOVZ_PS = FOP(18, FMT_PS),
9898 OPC_MOVN_PS = FOP(19, FMT_PS),
9899 OPC_ADDR_PS = FOP(24, FMT_PS),
9900 OPC_MULR_PS = FOP(26, FMT_PS),
9901 OPC_RECIP2_PS = FOP(28, FMT_PS),
9902 OPC_RECIP1_PS = FOP(29, FMT_PS),
9903 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9904 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9905
9906 OPC_CVT_S_PU = FOP(32, FMT_PS),
9907 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9908 OPC_CVT_S_PL = FOP(40, FMT_PS),
9909 OPC_PLL_PS = FOP(44, FMT_PS),
9910 OPC_PLU_PS = FOP(45, FMT_PS),
9911 OPC_PUL_PS = FOP(46, FMT_PS),
9912 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
9913 OPC_CMP_F_PS = FOP(48, FMT_PS),
9914 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9915 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9916 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9917 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9918 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9919 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9920 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9921 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9922 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9923 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9924 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9925 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9926 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9927 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9928 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
9929};
9930
3f493883
YK
9931enum r6_f_cmp_op {
9932 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9933 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9934 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9935 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9936 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9937 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9938 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9939 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9940 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9941 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9942 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9943 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9944 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9945 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9946 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9947 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9948 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9949 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9950 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9951 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9952 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9953 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9954
9955 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9956 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9957 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9958 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9959 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9960 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9961 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9962 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9963 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9964 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9965 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9966 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9967 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9968 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9969 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9970 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9971 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9972 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9973 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9974 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9975 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9976 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9977};
235785e8
AM
9978
9979static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 9980{
72c3a3ee 9981 TCGv t0 = tcg_temp_new();
6ea83fed
FB
9982
9983 switch (opc) {
9984 case OPC_MFC1:
b6d96bed 9985 {
a7812ae4 9986 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9987
7c979afd 9988 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 9989 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9990 tcg_temp_free_i32(fp0);
6958549d 9991 }
6c5c1e20 9992 gen_store_gpr(t0, rt);
6ea83fed
FB
9993 break;
9994 case OPC_MTC1:
6c5c1e20 9995 gen_load_gpr(t0, rt);
b6d96bed 9996 {
a7812ae4 9997 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9998
9999 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10000 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10001 tcg_temp_free_i32(fp0);
6958549d 10002 }
6ea83fed
FB
10003 break;
10004 case OPC_CFC1:
895c2d04 10005 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10006 gen_store_gpr(t0, rt);
6ea83fed
FB
10007 break;
10008 case OPC_CTC1:
6c5c1e20 10009 gen_load_gpr(t0, rt);
9c708c7f 10010 save_cpu_state(ctx, 0);
736d120a
PJ
10011 {
10012 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10013
10014 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10015 tcg_temp_free_i32(fs_tmp);
10016 }
4cf8a45f 10017 /* Stop translation as we may have changed hflags */
eeb3bba8 10018 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10019 break;
72c3a3ee 10020#if defined(TARGET_MIPS64)
9c2149c8 10021 case OPC_DMFC1:
72c3a3ee 10022 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10023 gen_store_gpr(t0, rt);
5a5012ec 10024 break;
9c2149c8 10025 case OPC_DMTC1:
6c5c1e20 10026 gen_load_gpr(t0, rt);
72c3a3ee 10027 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10028 break;
72c3a3ee 10029#endif
5a5012ec 10030 case OPC_MFHC1:
b6d96bed 10031 {
a7812ae4 10032 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10033
7f6613ce 10034 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10035 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10036 tcg_temp_free_i32(fp0);
6958549d 10037 }
6c5c1e20 10038 gen_store_gpr(t0, rt);
5a5012ec
TS
10039 break;
10040 case OPC_MTHC1:
6c5c1e20 10041 gen_load_gpr(t0, rt);
b6d96bed 10042 {
a7812ae4 10043 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10044
10045 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10046 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10047 tcg_temp_free_i32(fp0);
6958549d 10048 }
5a5012ec 10049 break;
6ea83fed 10050 default:
9d68ac14 10051 MIPS_INVAL("cp1 move");
3a4ef3b7 10052 gen_reserved_instruction(ctx);
6c5c1e20 10053 goto out;
6ea83fed 10054 }
6c5c1e20
TS
10055
10056 out:
10057 tcg_temp_free(t0);
6ea83fed
FB
10058}
10059
235785e8 10060static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 10061{
42a268c2 10062 TCGLabel *l1;
e214b9bb 10063 TCGCond cond;
af58f9ca
AJ
10064 TCGv_i32 t0;
10065
10066 if (rd == 0) {
10067 /* Treat as NOP. */
10068 return;
10069 }
6ea83fed 10070
1f8929d2 10071 if (tf) {
e214b9bb 10072 cond = TCG_COND_EQ;
1f8929d2 10073 } else {
27848470 10074 cond = TCG_COND_NE;
1f8929d2 10075 }
27848470 10076
af58f9ca
AJ
10077 l1 = gen_new_label();
10078 t0 = tcg_temp_new_i32();
fa31af0e 10079 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10080 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10081 tcg_temp_free_i32(t0);
c27b4579 10082 gen_load_gpr(cpu_gpr[rd], rs);
e214b9bb 10083 gen_set_label(l1);
5a5012ec
TS
10084}
10085
7c979afd
LA
10086static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10087 int tf)
a16336e4 10088{
a16336e4 10089 int cond;
cbc37b28 10090 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10091 TCGLabel *l1 = gen_new_label();
a16336e4 10092
1f8929d2 10093 if (tf) {
a16336e4 10094 cond = TCG_COND_EQ;
1f8929d2 10095 } else {
a16336e4 10096 cond = TCG_COND_NE;
1f8929d2 10097 }
a16336e4 10098
fa31af0e 10099 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10100 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10101 gen_load_fpr32(ctx, t0, fs);
10102 gen_store_fpr32(ctx, t0, fd);
a16336e4 10103 gen_set_label(l1);
cbc37b28 10104 tcg_temp_free_i32(t0);
5a5012ec 10105}
a16336e4 10106
235785e8
AM
10107static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10108 int tf)
a16336e4 10109{
a16336e4 10110 int cond;
cbc37b28
AJ
10111 TCGv_i32 t0 = tcg_temp_new_i32();
10112 TCGv_i64 fp0;
42a268c2 10113 TCGLabel *l1 = gen_new_label();
a16336e4 10114
1f8929d2 10115 if (tf) {
a16336e4 10116 cond = TCG_COND_EQ;
1f8929d2 10117 } else {
a16336e4 10118 cond = TCG_COND_NE;
1f8929d2 10119 }
a16336e4 10120
fa31af0e 10121 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10122 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10123 tcg_temp_free_i32(t0);
11f94258 10124 fp0 = tcg_temp_new_i64();
9bf3eb2c 10125 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10126 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10127 tcg_temp_free_i64(fp0);
cbc37b28 10128 gen_set_label(l1);
a16336e4
TS
10129}
10130
7f6613ce
PJ
10131static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10132 int cc, int tf)
a16336e4
TS
10133{
10134 int cond;
cbc37b28 10135 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10136 TCGLabel *l1 = gen_new_label();
10137 TCGLabel *l2 = gen_new_label();
a16336e4 10138
1f8929d2 10139 if (tf) {
a16336e4 10140 cond = TCG_COND_EQ;
1f8929d2 10141 } else {
a16336e4 10142 cond = TCG_COND_NE;
1f8929d2 10143 }
a16336e4 10144
fa31af0e 10145 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10146 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10147 gen_load_fpr32(ctx, t0, fs);
10148 gen_store_fpr32(ctx, t0, fd);
a16336e4 10149 gen_set_label(l1);
9bf3eb2c 10150
71375b59 10151 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 10152 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10153 gen_load_fpr32h(ctx, t0, fs);
10154 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10155 tcg_temp_free_i32(t0);
a16336e4 10156 gen_set_label(l2);
a16336e4
TS
10157}
10158
e7f16abb
LA
10159static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10160 int fs)
10161{
10162 TCGv_i32 t1 = tcg_const_i32(0);
10163 TCGv_i32 fp0 = tcg_temp_new_i32();
10164 TCGv_i32 fp1 = tcg_temp_new_i32();
10165 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10166 gen_load_fpr32(ctx, fp0, fd);
10167 gen_load_fpr32(ctx, fp1, ft);
10168 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10169
10170 switch (op1) {
10171 case OPC_SEL_S:
10172 tcg_gen_andi_i32(fp0, fp0, 1);
10173 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10174 break;
10175 case OPC_SELEQZ_S:
10176 tcg_gen_andi_i32(fp1, fp1, 1);
10177 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10178 break;
10179 case OPC_SELNEZ_S:
10180 tcg_gen_andi_i32(fp1, fp1, 1);
10181 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10182 break;
10183 default:
10184 MIPS_INVAL("gen_sel_s");
3a4ef3b7 10185 gen_reserved_instruction(ctx);
e7f16abb
LA
10186 break;
10187 }
10188
7c979afd 10189 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10190 tcg_temp_free_i32(fp2);
10191 tcg_temp_free_i32(fp1);
10192 tcg_temp_free_i32(fp0);
10193 tcg_temp_free_i32(t1);
10194}
10195
10196static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10197 int fs)
10198{
10199 TCGv_i64 t1 = tcg_const_i64(0);
10200 TCGv_i64 fp0 = tcg_temp_new_i64();
10201 TCGv_i64 fp1 = tcg_temp_new_i64();
10202 TCGv_i64 fp2 = tcg_temp_new_i64();
10203 gen_load_fpr64(ctx, fp0, fd);
10204 gen_load_fpr64(ctx, fp1, ft);
10205 gen_load_fpr64(ctx, fp2, fs);
10206
10207 switch (op1) {
10208 case OPC_SEL_D:
10209 tcg_gen_andi_i64(fp0, fp0, 1);
10210 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10211 break;
10212 case OPC_SELEQZ_D:
10213 tcg_gen_andi_i64(fp1, fp1, 1);
10214 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10215 break;
10216 case OPC_SELNEZ_D:
10217 tcg_gen_andi_i64(fp1, fp1, 1);
10218 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10219 break;
10220 default:
10221 MIPS_INVAL("gen_sel_d");
3a4ef3b7 10222 gen_reserved_instruction(ctx);
e7f16abb
LA
10223 break;
10224 }
10225
10226 gen_store_fpr64(ctx, fp0, fd);
10227 tcg_temp_free_i64(fp2);
10228 tcg_temp_free_i64(fp1);
10229 tcg_temp_free_i64(fp0);
10230 tcg_temp_free_i64(t1);
10231}
6ea83fed 10232
235785e8
AM
10233static void gen_farith(DisasContext *ctx, enum fopcode op1,
10234 int ft, int fs, int fd, int cc)
6ea83fed 10235{
7a387fff 10236 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
10237 switch (op1) {
10238 case OPC_ADD_S:
b6d96bed 10239 {
a7812ae4
PB
10240 TCGv_i32 fp0 = tcg_temp_new_i32();
10241 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10242
7c979afd
LA
10243 gen_load_fpr32(ctx, fp0, fs);
10244 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10245 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10246 tcg_temp_free_i32(fp1);
7c979afd 10247 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10248 tcg_temp_free_i32(fp0);
b6d96bed 10249 }
5a5012ec 10250 break;
bf4120ad 10251 case OPC_SUB_S:
b6d96bed 10252 {
a7812ae4
PB
10253 TCGv_i32 fp0 = tcg_temp_new_i32();
10254 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10255
7c979afd
LA
10256 gen_load_fpr32(ctx, fp0, fs);
10257 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10258 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10259 tcg_temp_free_i32(fp1);
7c979afd 10260 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10261 tcg_temp_free_i32(fp0);
b6d96bed 10262 }
5a5012ec 10263 break;
bf4120ad 10264 case OPC_MUL_S:
b6d96bed 10265 {
a7812ae4
PB
10266 TCGv_i32 fp0 = tcg_temp_new_i32();
10267 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10268
7c979afd
LA
10269 gen_load_fpr32(ctx, fp0, fs);
10270 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10271 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10272 tcg_temp_free_i32(fp1);
7c979afd 10273 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10274 tcg_temp_free_i32(fp0);
b6d96bed 10275 }
5a5012ec 10276 break;
bf4120ad 10277 case OPC_DIV_S:
b6d96bed 10278 {
a7812ae4
PB
10279 TCGv_i32 fp0 = tcg_temp_new_i32();
10280 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10281
7c979afd
LA
10282 gen_load_fpr32(ctx, fp0, fs);
10283 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10284 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10285 tcg_temp_free_i32(fp1);
7c979afd 10286 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10287 tcg_temp_free_i32(fp0);
b6d96bed 10288 }
5a5012ec 10289 break;
bf4120ad 10290 case OPC_SQRT_S:
b6d96bed 10291 {
a7812ae4 10292 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10293
7c979afd 10294 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10295 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 10296 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10297 tcg_temp_free_i32(fp0);
b6d96bed 10298 }
5a5012ec 10299 break;
bf4120ad 10300 case OPC_ABS_S:
b6d96bed 10301 {
a7812ae4 10302 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10303
7c979afd 10304 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10305 if (ctx->abs2008) {
10306 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10307 } else {
10308 gen_helper_float_abs_s(fp0, fp0);
10309 }
7c979afd 10310 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10311 tcg_temp_free_i32(fp0);
b6d96bed 10312 }
5a5012ec 10313 break;
bf4120ad 10314 case OPC_MOV_S:
b6d96bed 10315 {
a7812ae4 10316 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10317
7c979afd
LA
10318 gen_load_fpr32(ctx, fp0, fs);
10319 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10320 tcg_temp_free_i32(fp0);
b6d96bed 10321 }
5a5012ec 10322 break;
bf4120ad 10323 case OPC_NEG_S:
b6d96bed 10324 {
a7812ae4 10325 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10326
7c979afd 10327 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10328 if (ctx->abs2008) {
10329 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10330 } else {
10331 gen_helper_float_chs_s(fp0, fp0);
10332 }
7c979afd 10333 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10334 tcg_temp_free_i32(fp0);
b6d96bed 10335 }
5a5012ec 10336 break;
bf4120ad 10337 case OPC_ROUND_L_S:
5e755519 10338 check_cp1_64bitmode(ctx);
b6d96bed 10339 {
a7812ae4
PB
10340 TCGv_i32 fp32 = tcg_temp_new_i32();
10341 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10342
7c979afd 10343 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10344 if (ctx->nan2008) {
10345 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10346 } else {
10347 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10348 }
a7812ae4 10349 tcg_temp_free_i32(fp32);
b6d96bed 10350 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10351 tcg_temp_free_i64(fp64);
b6d96bed 10352 }
5a5012ec 10353 break;
bf4120ad 10354 case OPC_TRUNC_L_S:
5e755519 10355 check_cp1_64bitmode(ctx);
b6d96bed 10356 {
a7812ae4
PB
10357 TCGv_i32 fp32 = tcg_temp_new_i32();
10358 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10359
7c979afd 10360 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10361 if (ctx->nan2008) {
10362 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10363 } else {
10364 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10365 }
a7812ae4 10366 tcg_temp_free_i32(fp32);
b6d96bed 10367 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10368 tcg_temp_free_i64(fp64);
b6d96bed 10369 }
5a5012ec 10370 break;
bf4120ad 10371 case OPC_CEIL_L_S:
5e755519 10372 check_cp1_64bitmode(ctx);
b6d96bed 10373 {
a7812ae4
PB
10374 TCGv_i32 fp32 = tcg_temp_new_i32();
10375 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10376
7c979afd 10377 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10378 if (ctx->nan2008) {
10379 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10380 } else {
10381 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10382 }
a7812ae4 10383 tcg_temp_free_i32(fp32);
b6d96bed 10384 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10385 tcg_temp_free_i64(fp64);
b6d96bed 10386 }
5a5012ec 10387 break;
bf4120ad 10388 case OPC_FLOOR_L_S:
5e755519 10389 check_cp1_64bitmode(ctx);
b6d96bed 10390 {
a7812ae4
PB
10391 TCGv_i32 fp32 = tcg_temp_new_i32();
10392 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10393
7c979afd 10394 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10395 if (ctx->nan2008) {
10396 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10397 } else {
10398 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10399 }
a7812ae4 10400 tcg_temp_free_i32(fp32);
b6d96bed 10401 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10402 tcg_temp_free_i64(fp64);
b6d96bed 10403 }
5a5012ec 10404 break;
bf4120ad 10405 case OPC_ROUND_W_S:
b6d96bed 10406 {
a7812ae4 10407 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10408
7c979afd 10409 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10410 if (ctx->nan2008) {
10411 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10412 } else {
10413 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10414 }
7c979afd 10415 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10416 tcg_temp_free_i32(fp0);
b6d96bed 10417 }
5a5012ec 10418 break;
bf4120ad 10419 case OPC_TRUNC_W_S:
b6d96bed 10420 {
a7812ae4 10421 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10422
7c979afd 10423 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10424 if (ctx->nan2008) {
10425 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10426 } else {
10427 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10428 }
7c979afd 10429 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10430 tcg_temp_free_i32(fp0);
b6d96bed 10431 }
5a5012ec 10432 break;
bf4120ad 10433 case OPC_CEIL_W_S:
b6d96bed 10434 {
a7812ae4 10435 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10436
7c979afd 10437 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10438 if (ctx->nan2008) {
10439 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10440 } else {
10441 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10442 }
7c979afd 10443 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10444 tcg_temp_free_i32(fp0);
b6d96bed 10445 }
5a5012ec 10446 break;
bf4120ad 10447 case OPC_FLOOR_W_S:
b6d96bed 10448 {
a7812ae4 10449 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10450
7c979afd 10451 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10452 if (ctx->nan2008) {
10453 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10454 } else {
10455 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10456 }
7c979afd 10457 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10458 tcg_temp_free_i32(fp0);
b6d96bed 10459 }
5a5012ec 10460 break;
e7f16abb 10461 case OPC_SEL_S:
2e211e0a 10462 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10463 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10464 break;
10465 case OPC_SELEQZ_S:
2e211e0a 10466 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10467 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10468 break;
10469 case OPC_SELNEZ_S:
2e211e0a 10470 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10471 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 10472 break;
bf4120ad 10473 case OPC_MOVCF_S:
2e211e0a 10474 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7c979afd 10475 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 10476 break;
bf4120ad 10477 case OPC_MOVZ_S:
2e211e0a 10478 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10479 {
42a268c2 10480 TCGLabel *l1 = gen_new_label();
c9297f4d 10481 TCGv_i32 fp0;
a16336e4 10482
c9297f4d
AJ
10483 if (ft != 0) {
10484 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10485 }
10486 fp0 = tcg_temp_new_i32();
7c979afd
LA
10487 gen_load_fpr32(ctx, fp0, fs);
10488 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10489 tcg_temp_free_i32(fp0);
a16336e4
TS
10490 gen_set_label(l1);
10491 }
5a5012ec 10492 break;
bf4120ad 10493 case OPC_MOVN_S:
2e211e0a 10494 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10495 {
42a268c2 10496 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10497 TCGv_i32 fp0;
10498
10499 if (ft != 0) {
10500 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10501 fp0 = tcg_temp_new_i32();
7c979afd
LA
10502 gen_load_fpr32(ctx, fp0, fs);
10503 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
10504 tcg_temp_free_i32(fp0);
10505 gen_set_label(l1);
10506 }
a16336e4 10507 }
5a5012ec 10508 break;
bf4120ad 10509 case OPC_RECIP_S:
b6d96bed 10510 {
a7812ae4 10511 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10512
7c979afd 10513 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10514 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 10515 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10516 tcg_temp_free_i32(fp0);
b6d96bed 10517 }
57fa1fb3 10518 break;
bf4120ad 10519 case OPC_RSQRT_S:
b6d96bed 10520 {
a7812ae4 10521 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10522
7c979afd 10523 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10524 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 10525 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10526 tcg_temp_free_i32(fp0);
b6d96bed 10527 }
57fa1fb3 10528 break;
e7f16abb 10529 case OPC_MADDF_S:
2e211e0a 10530 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10531 {
a7812ae4
PB
10532 TCGv_i32 fp0 = tcg_temp_new_i32();
10533 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10534 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10535 gen_load_fpr32(ctx, fp0, fs);
10536 gen_load_fpr32(ctx, fp1, ft);
10537 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10538 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10539 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 10540 tcg_temp_free_i32(fp2);
a7812ae4 10541 tcg_temp_free_i32(fp1);
a7812ae4 10542 tcg_temp_free_i32(fp0);
b6d96bed 10543 }
57fa1fb3 10544 break;
e7f16abb 10545 case OPC_MSUBF_S:
2e211e0a 10546 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10547 {
a7812ae4 10548 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
10549 TCGv_i32 fp1 = tcg_temp_new_i32();
10550 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10551 gen_load_fpr32(ctx, fp0, fs);
10552 gen_load_fpr32(ctx, fp1, ft);
10553 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10554 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10555 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10556 tcg_temp_free_i32(fp2);
10557 tcg_temp_free_i32(fp1);
a7812ae4 10558 tcg_temp_free_i32(fp0);
b6d96bed 10559 }
57fa1fb3 10560 break;
e7f16abb 10561 case OPC_RINT_S:
2e211e0a 10562 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10563 {
a7812ae4 10564 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10565 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10566 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 10567 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10568 tcg_temp_free_i32(fp0);
b6d96bed 10569 }
57fa1fb3 10570 break;
e7f16abb 10571 case OPC_CLASS_S:
2e211e0a 10572 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10573 {
e7f16abb 10574 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10575 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 10576 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 10577 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 10578 tcg_temp_free_i32(fp0);
e7f16abb
LA
10579 }
10580 break;
10581 case OPC_MIN_S: /* OPC_RECIP2_S */
2e211e0a 10582 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 10583 /* OPC_MIN_S */
a7812ae4
PB
10584 TCGv_i32 fp0 = tcg_temp_new_i32();
10585 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10586 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10587 gen_load_fpr32(ctx, fp0, fs);
10588 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10589 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 10590 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10591 tcg_temp_free_i32(fp2);
10592 tcg_temp_free_i32(fp1);
10593 tcg_temp_free_i32(fp0);
e7f16abb
LA
10594 } else {
10595 /* OPC_RECIP2_S */
10596 check_cp1_64bitmode(ctx);
10597 {
10598 TCGv_i32 fp0 = tcg_temp_new_i32();
10599 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10600
7c979afd
LA
10601 gen_load_fpr32(ctx, fp0, fs);
10602 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10603 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10604 tcg_temp_free_i32(fp1);
7c979afd 10605 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10606 tcg_temp_free_i32(fp0);
10607 }
e7f16abb
LA
10608 }
10609 break;
10610 case OPC_MINA_S: /* OPC_RECIP1_S */
2e211e0a 10611 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10612 /* OPC_MINA_S */
10613 TCGv_i32 fp0 = tcg_temp_new_i32();
10614 TCGv_i32 fp1 = tcg_temp_new_i32();
10615 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10616 gen_load_fpr32(ctx, fp0, fs);
10617 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10618 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 10619 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10620 tcg_temp_free_i32(fp2);
10621 tcg_temp_free_i32(fp1);
10622 tcg_temp_free_i32(fp0);
e7f16abb
LA
10623 } else {
10624 /* OPC_RECIP1_S */
10625 check_cp1_64bitmode(ctx);
10626 {
10627 TCGv_i32 fp0 = tcg_temp_new_i32();
10628
7c979afd 10629 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10630 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 10631 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10632 tcg_temp_free_i32(fp0);
10633 }
e7f16abb
LA
10634 }
10635 break;
10636 case OPC_MAX_S: /* OPC_RSQRT1_S */
2e211e0a 10637 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10638 /* OPC_MAX_S */
10639 TCGv_i32 fp0 = tcg_temp_new_i32();
10640 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10641 gen_load_fpr32(ctx, fp0, fs);
10642 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10643 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 10644 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
10645 tcg_temp_free_i32(fp1);
10646 tcg_temp_free_i32(fp0);
e7f16abb
LA
10647 } else {
10648 /* OPC_RSQRT1_S */
10649 check_cp1_64bitmode(ctx);
10650 {
10651 TCGv_i32 fp0 = tcg_temp_new_i32();
10652
7c979afd 10653 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10654 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 10655 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10656 tcg_temp_free_i32(fp0);
10657 }
e7f16abb
LA
10658 }
10659 break;
10660 case OPC_MAXA_S: /* OPC_RSQRT2_S */
2e211e0a 10661 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10662 /* OPC_MAXA_S */
10663 TCGv_i32 fp0 = tcg_temp_new_i32();
10664 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10665 gen_load_fpr32(ctx, fp0, fs);
10666 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10667 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 10668 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 10669 tcg_temp_free_i32(fp1);
a7812ae4 10670 tcg_temp_free_i32(fp0);
e7f16abb
LA
10671 } else {
10672 /* OPC_RSQRT2_S */
10673 check_cp1_64bitmode(ctx);
10674 {
10675 TCGv_i32 fp0 = tcg_temp_new_i32();
10676 TCGv_i32 fp1 = tcg_temp_new_i32();
10677
7c979afd
LA
10678 gen_load_fpr32(ctx, fp0, fs);
10679 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10680 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10681 tcg_temp_free_i32(fp1);
7c979afd 10682 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10683 tcg_temp_free_i32(fp0);
10684 }
b6d96bed 10685 }
57fa1fb3 10686 break;
bf4120ad 10687 case OPC_CVT_D_S:
5e755519 10688 check_cp1_registers(ctx, fd);
b6d96bed 10689 {
a7812ae4
PB
10690 TCGv_i32 fp32 = tcg_temp_new_i32();
10691 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10692
7c979afd 10693 gen_load_fpr32(ctx, fp32, fs);
895c2d04 10694 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 10695 tcg_temp_free_i32(fp32);
b6d96bed 10696 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10697 tcg_temp_free_i64(fp64);
b6d96bed 10698 }
5a5012ec 10699 break;
bf4120ad 10700 case OPC_CVT_W_S:
b6d96bed 10701 {
a7812ae4 10702 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10703
7c979afd 10704 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10705 if (ctx->nan2008) {
10706 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10707 } else {
10708 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10709 }
7c979afd 10710 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10711 tcg_temp_free_i32(fp0);
b6d96bed 10712 }
5a5012ec 10713 break;
bf4120ad 10714 case OPC_CVT_L_S:
5e755519 10715 check_cp1_64bitmode(ctx);
b6d96bed 10716 {
a7812ae4
PB
10717 TCGv_i32 fp32 = tcg_temp_new_i32();
10718 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10719
7c979afd 10720 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10721 if (ctx->nan2008) {
10722 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10723 } else {
10724 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10725 }
a7812ae4 10726 tcg_temp_free_i32(fp32);
b6d96bed 10727 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10728 tcg_temp_free_i64(fp64);
b6d96bed 10729 }
5a5012ec 10730 break;
bf4120ad 10731 case OPC_CVT_PS_S:
e29c9628 10732 check_ps(ctx);
b6d96bed 10733 {
a7812ae4
PB
10734 TCGv_i64 fp64 = tcg_temp_new_i64();
10735 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10736 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 10737
7c979afd
LA
10738 gen_load_fpr32(ctx, fp32_0, fs);
10739 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 10740 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
10741 tcg_temp_free_i32(fp32_1);
10742 tcg_temp_free_i32(fp32_0);
36aa55dc 10743 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10744 tcg_temp_free_i64(fp64);
b6d96bed 10745 }
5a5012ec 10746 break;
bf4120ad
NF
10747 case OPC_CMP_F_S:
10748 case OPC_CMP_UN_S:
10749 case OPC_CMP_EQ_S:
10750 case OPC_CMP_UEQ_S:
10751 case OPC_CMP_OLT_S:
10752 case OPC_CMP_ULT_S:
10753 case OPC_CMP_OLE_S:
10754 case OPC_CMP_ULE_S:
10755 case OPC_CMP_SF_S:
10756 case OPC_CMP_NGLE_S:
10757 case OPC_CMP_SEQ_S:
10758 case OPC_CMP_NGL_S:
10759 case OPC_CMP_LT_S:
10760 case OPC_CMP_NGE_S:
10761 case OPC_CMP_LE_S:
10762 case OPC_CMP_NGT_S:
2e211e0a 10763 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 10764 if (ctx->opcode & (1 << 6)) {
71375b59 10765 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 10766 } else {
71375b59 10767 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 10768 }
5a5012ec 10769 break;
bf4120ad 10770 case OPC_ADD_D:
5e755519 10771 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10772 {
a7812ae4
PB
10773 TCGv_i64 fp0 = tcg_temp_new_i64();
10774 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10775
10776 gen_load_fpr64(ctx, fp0, fs);
10777 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10778 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10779 tcg_temp_free_i64(fp1);
b6d96bed 10780 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10781 tcg_temp_free_i64(fp0);
b6d96bed 10782 }
6ea83fed 10783 break;
bf4120ad 10784 case OPC_SUB_D:
5e755519 10785 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10786 {
a7812ae4
PB
10787 TCGv_i64 fp0 = tcg_temp_new_i64();
10788 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10789
10790 gen_load_fpr64(ctx, fp0, fs);
10791 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10792 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10793 tcg_temp_free_i64(fp1);
b6d96bed 10794 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10795 tcg_temp_free_i64(fp0);
b6d96bed 10796 }
6ea83fed 10797 break;
bf4120ad 10798 case OPC_MUL_D:
5e755519 10799 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10800 {
a7812ae4
PB
10801 TCGv_i64 fp0 = tcg_temp_new_i64();
10802 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10803
10804 gen_load_fpr64(ctx, fp0, fs);
10805 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10806 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10807 tcg_temp_free_i64(fp1);
b6d96bed 10808 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10809 tcg_temp_free_i64(fp0);
b6d96bed 10810 }
6ea83fed 10811 break;
bf4120ad 10812 case OPC_DIV_D:
5e755519 10813 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10814 {
a7812ae4
PB
10815 TCGv_i64 fp0 = tcg_temp_new_i64();
10816 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10817
10818 gen_load_fpr64(ctx, fp0, fs);
10819 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10820 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10821 tcg_temp_free_i64(fp1);
b6d96bed 10822 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10823 tcg_temp_free_i64(fp0);
b6d96bed 10824 }
6ea83fed 10825 break;
bf4120ad 10826 case OPC_SQRT_D:
5e755519 10827 check_cp1_registers(ctx, fs | fd);
b6d96bed 10828 {
a7812ae4 10829 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10830
10831 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10832 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 10833 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10834 tcg_temp_free_i64(fp0);
b6d96bed 10835 }
6ea83fed 10836 break;
bf4120ad 10837 case OPC_ABS_D:
5e755519 10838 check_cp1_registers(ctx, fs | fd);
b6d96bed 10839 {
a7812ae4 10840 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10841
10842 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10843 if (ctx->abs2008) {
10844 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10845 } else {
10846 gen_helper_float_abs_d(fp0, fp0);
10847 }
b6d96bed 10848 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10849 tcg_temp_free_i64(fp0);
b6d96bed 10850 }
6ea83fed 10851 break;
bf4120ad 10852 case OPC_MOV_D:
5e755519 10853 check_cp1_registers(ctx, fs | fd);
b6d96bed 10854 {
a7812ae4 10855 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10856
10857 gen_load_fpr64(ctx, fp0, fs);
10858 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10859 tcg_temp_free_i64(fp0);
b6d96bed 10860 }
6ea83fed 10861 break;
bf4120ad 10862 case OPC_NEG_D:
5e755519 10863 check_cp1_registers(ctx, fs | fd);
b6d96bed 10864 {
a7812ae4 10865 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10866
10867 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10868 if (ctx->abs2008) {
10869 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10870 } else {
10871 gen_helper_float_chs_d(fp0, fp0);
10872 }
b6d96bed 10873 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10874 tcg_temp_free_i64(fp0);
b6d96bed 10875 }
6ea83fed 10876 break;
bf4120ad 10877 case OPC_ROUND_L_D:
5e755519 10878 check_cp1_64bitmode(ctx);
b6d96bed 10879 {
a7812ae4 10880 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10881
10882 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10883 if (ctx->nan2008) {
10884 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10885 } else {
10886 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10887 }
b6d96bed 10888 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10889 tcg_temp_free_i64(fp0);
b6d96bed 10890 }
5a5012ec 10891 break;
bf4120ad 10892 case OPC_TRUNC_L_D:
5e755519 10893 check_cp1_64bitmode(ctx);
b6d96bed 10894 {
a7812ae4 10895 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10896
10897 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10898 if (ctx->nan2008) {
10899 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10900 } else {
10901 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10902 }
b6d96bed 10903 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10904 tcg_temp_free_i64(fp0);
b6d96bed 10905 }
5a5012ec 10906 break;
bf4120ad 10907 case OPC_CEIL_L_D:
5e755519 10908 check_cp1_64bitmode(ctx);
b6d96bed 10909 {
a7812ae4 10910 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10911
10912 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10913 if (ctx->nan2008) {
10914 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10915 } else {
10916 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10917 }
b6d96bed 10918 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10919 tcg_temp_free_i64(fp0);
b6d96bed 10920 }
5a5012ec 10921 break;
bf4120ad 10922 case OPC_FLOOR_L_D:
5e755519 10923 check_cp1_64bitmode(ctx);
b6d96bed 10924 {
a7812ae4 10925 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10926
10927 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10928 if (ctx->nan2008) {
10929 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10930 } else {
10931 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10932 }
b6d96bed 10933 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10934 tcg_temp_free_i64(fp0);
b6d96bed 10935 }
5a5012ec 10936 break;
bf4120ad 10937 case OPC_ROUND_W_D:
5e755519 10938 check_cp1_registers(ctx, fs);
b6d96bed 10939 {
a7812ae4
PB
10940 TCGv_i32 fp32 = tcg_temp_new_i32();
10941 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10942
10943 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10944 if (ctx->nan2008) {
10945 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10946 } else {
10947 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10948 }
a7812ae4 10949 tcg_temp_free_i64(fp64);
7c979afd 10950 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10951 tcg_temp_free_i32(fp32);
b6d96bed 10952 }
6ea83fed 10953 break;
bf4120ad 10954 case OPC_TRUNC_W_D:
5e755519 10955 check_cp1_registers(ctx, fs);
b6d96bed 10956 {
a7812ae4
PB
10957 TCGv_i32 fp32 = tcg_temp_new_i32();
10958 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10959
10960 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10961 if (ctx->nan2008) {
10962 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10963 } else {
10964 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10965 }
a7812ae4 10966 tcg_temp_free_i64(fp64);
7c979afd 10967 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10968 tcg_temp_free_i32(fp32);
b6d96bed 10969 }
6ea83fed 10970 break;
bf4120ad 10971 case OPC_CEIL_W_D:
5e755519 10972 check_cp1_registers(ctx, fs);
b6d96bed 10973 {
a7812ae4
PB
10974 TCGv_i32 fp32 = tcg_temp_new_i32();
10975 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10976
10977 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10978 if (ctx->nan2008) {
10979 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10980 } else {
10981 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10982 }
a7812ae4 10983 tcg_temp_free_i64(fp64);
7c979afd 10984 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10985 tcg_temp_free_i32(fp32);
b6d96bed 10986 }
6ea83fed 10987 break;
bf4120ad 10988 case OPC_FLOOR_W_D:
5e755519 10989 check_cp1_registers(ctx, fs);
b6d96bed 10990 {
a7812ae4
PB
10991 TCGv_i32 fp32 = tcg_temp_new_i32();
10992 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10993
10994 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10995 if (ctx->nan2008) {
10996 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10997 } else {
10998 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10999 }
a7812ae4 11000 tcg_temp_free_i64(fp64);
7c979afd 11001 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11002 tcg_temp_free_i32(fp32);
b6d96bed 11003 }
6ea83fed 11004 break;
e7f16abb 11005 case OPC_SEL_D:
2e211e0a 11006 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11007 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11008 break;
11009 case OPC_SELEQZ_D:
2e211e0a 11010 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11011 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11012 break;
11013 case OPC_SELNEZ_D:
2e211e0a 11014 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11015 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11016 break;
bf4120ad 11017 case OPC_MOVCF_D:
2e211e0a 11018 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6d96bed 11019 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11020 break;
bf4120ad 11021 case OPC_MOVZ_D:
2e211e0a 11022 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11023 {
42a268c2 11024 TCGLabel *l1 = gen_new_label();
c9297f4d 11025 TCGv_i64 fp0;
a16336e4 11026
c9297f4d
AJ
11027 if (ft != 0) {
11028 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11029 }
11030 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11031 gen_load_fpr64(ctx, fp0, fs);
11032 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11033 tcg_temp_free_i64(fp0);
a16336e4
TS
11034 gen_set_label(l1);
11035 }
5a5012ec 11036 break;
bf4120ad 11037 case OPC_MOVN_D:
2e211e0a 11038 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11039 {
42a268c2 11040 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11041 TCGv_i64 fp0;
11042
11043 if (ft != 0) {
11044 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11045 fp0 = tcg_temp_new_i64();
11046 gen_load_fpr64(ctx, fp0, fs);
11047 gen_store_fpr64(ctx, fp0, fd);
11048 tcg_temp_free_i64(fp0);
11049 gen_set_label(l1);
11050 }
a16336e4 11051 }
6ea83fed 11052 break;
bf4120ad 11053 case OPC_RECIP_D:
ca6c7803 11054 check_cp1_registers(ctx, fs | fd);
b6d96bed 11055 {
a7812ae4 11056 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11057
11058 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11059 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11060 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11061 tcg_temp_free_i64(fp0);
b6d96bed 11062 }
57fa1fb3 11063 break;
bf4120ad 11064 case OPC_RSQRT_D:
ca6c7803 11065 check_cp1_registers(ctx, fs | fd);
b6d96bed 11066 {
a7812ae4 11067 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11068
11069 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11070 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11071 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11072 tcg_temp_free_i64(fp0);
b6d96bed 11073 }
57fa1fb3 11074 break;
e7f16abb 11075 case OPC_MADDF_D:
2e211e0a 11076 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11077 {
a7812ae4
PB
11078 TCGv_i64 fp0 = tcg_temp_new_i64();
11079 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11080 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11081 gen_load_fpr64(ctx, fp0, fs);
11082 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11083 gen_load_fpr64(ctx, fp2, fd);
11084 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11085 gen_store_fpr64(ctx, fp2, fd);
11086 tcg_temp_free_i64(fp2);
a7812ae4 11087 tcg_temp_free_i64(fp1);
a7812ae4 11088 tcg_temp_free_i64(fp0);
b6d96bed 11089 }
57fa1fb3 11090 break;
e7f16abb 11091 case OPC_MSUBF_D:
2e211e0a 11092 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11093 {
a7812ae4 11094 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11095 TCGv_i64 fp1 = tcg_temp_new_i64();
11096 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11097 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11098 gen_load_fpr64(ctx, fp1, ft);
11099 gen_load_fpr64(ctx, fp2, fd);
11100 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11101 gen_store_fpr64(ctx, fp2, fd);
11102 tcg_temp_free_i64(fp2);
11103 tcg_temp_free_i64(fp1);
a7812ae4 11104 tcg_temp_free_i64(fp0);
b6d96bed 11105 }
57fa1fb3 11106 break;
e7f16abb 11107 case OPC_RINT_D:
2e211e0a 11108 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11109 {
a7812ae4 11110 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11111 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11112 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11113 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11114 tcg_temp_free_i64(fp0);
b6d96bed 11115 }
57fa1fb3 11116 break;
e7f16abb 11117 case OPC_CLASS_D:
2e211e0a 11118 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11119 {
e7f16abb
LA
11120 TCGv_i64 fp0 = tcg_temp_new_i64();
11121 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11122 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11123 gen_store_fpr64(ctx, fp0, fd);
11124 tcg_temp_free_i64(fp0);
e7f16abb
LA
11125 }
11126 break;
11127 case OPC_MIN_D: /* OPC_RECIP2_D */
2e211e0a 11128 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 11129 /* OPC_MIN_D */
a7812ae4
PB
11130 TCGv_i64 fp0 = tcg_temp_new_i64();
11131 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11132 gen_load_fpr64(ctx, fp0, fs);
11133 gen_load_fpr64(ctx, fp1, ft);
11134 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11135 gen_store_fpr64(ctx, fp1, fd);
11136 tcg_temp_free_i64(fp1);
11137 tcg_temp_free_i64(fp0);
e7f16abb
LA
11138 } else {
11139 /* OPC_RECIP2_D */
11140 check_cp1_64bitmode(ctx);
11141 {
11142 TCGv_i64 fp0 = tcg_temp_new_i64();
11143 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11144
e7f16abb
LA
11145 gen_load_fpr64(ctx, fp0, fs);
11146 gen_load_fpr64(ctx, fp1, ft);
11147 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11148 tcg_temp_free_i64(fp1);
11149 gen_store_fpr64(ctx, fp0, fd);
11150 tcg_temp_free_i64(fp0);
11151 }
e7f16abb
LA
11152 }
11153 break;
11154 case OPC_MINA_D: /* OPC_RECIP1_D */
2e211e0a 11155 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11156 /* OPC_MINA_D */
11157 TCGv_i64 fp0 = tcg_temp_new_i64();
11158 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11159 gen_load_fpr64(ctx, fp0, fs);
11160 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11161 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11162 gen_store_fpr64(ctx, fp1, fd);
11163 tcg_temp_free_i64(fp1);
11164 tcg_temp_free_i64(fp0);
e7f16abb
LA
11165 } else {
11166 /* OPC_RECIP1_D */
11167 check_cp1_64bitmode(ctx);
11168 {
11169 TCGv_i64 fp0 = tcg_temp_new_i64();
11170
11171 gen_load_fpr64(ctx, fp0, fs);
11172 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11173 gen_store_fpr64(ctx, fp0, fd);
11174 tcg_temp_free_i64(fp0);
11175 }
e7f16abb
LA
11176 }
11177 break;
11178 case OPC_MAX_D: /* OPC_RSQRT1_D */
2e211e0a 11179 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11180 /* OPC_MAX_D */
11181 TCGv_i64 fp0 = tcg_temp_new_i64();
11182 TCGv_i64 fp1 = tcg_temp_new_i64();
11183 gen_load_fpr64(ctx, fp0, fs);
11184 gen_load_fpr64(ctx, fp1, ft);
11185 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11186 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 11187 tcg_temp_free_i64(fp1);
a7812ae4 11188 tcg_temp_free_i64(fp0);
e7f16abb
LA
11189 } else {
11190 /* OPC_RSQRT1_D */
11191 check_cp1_64bitmode(ctx);
11192 {
11193 TCGv_i64 fp0 = tcg_temp_new_i64();
11194
11195 gen_load_fpr64(ctx, fp0, fs);
11196 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11197 gen_store_fpr64(ctx, fp0, fd);
11198 tcg_temp_free_i64(fp0);
11199 }
e7f16abb
LA
11200 }
11201 break;
11202 case OPC_MAXA_D: /* OPC_RSQRT2_D */
2e211e0a 11203 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11204 /* OPC_MAXA_D */
11205 TCGv_i64 fp0 = tcg_temp_new_i64();
11206 TCGv_i64 fp1 = tcg_temp_new_i64();
11207 gen_load_fpr64(ctx, fp0, fs);
11208 gen_load_fpr64(ctx, fp1, ft);
11209 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11210 gen_store_fpr64(ctx, fp1, fd);
11211 tcg_temp_free_i64(fp1);
11212 tcg_temp_free_i64(fp0);
e7f16abb
LA
11213 } else {
11214 /* OPC_RSQRT2_D */
11215 check_cp1_64bitmode(ctx);
11216 {
11217 TCGv_i64 fp0 = tcg_temp_new_i64();
11218 TCGv_i64 fp1 = tcg_temp_new_i64();
11219
11220 gen_load_fpr64(ctx, fp0, fs);
11221 gen_load_fpr64(ctx, fp1, ft);
11222 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11223 tcg_temp_free_i64(fp1);
11224 gen_store_fpr64(ctx, fp0, fd);
11225 tcg_temp_free_i64(fp0);
11226 }
b6d96bed 11227 }
57fa1fb3 11228 break;
bf4120ad
NF
11229 case OPC_CMP_F_D:
11230 case OPC_CMP_UN_D:
11231 case OPC_CMP_EQ_D:
11232 case OPC_CMP_UEQ_D:
11233 case OPC_CMP_OLT_D:
11234 case OPC_CMP_ULT_D:
11235 case OPC_CMP_OLE_D:
11236 case OPC_CMP_ULE_D:
11237 case OPC_CMP_SF_D:
11238 case OPC_CMP_NGLE_D:
11239 case OPC_CMP_SEQ_D:
11240 case OPC_CMP_NGL_D:
11241 case OPC_CMP_LT_D:
11242 case OPC_CMP_NGE_D:
11243 case OPC_CMP_LE_D:
11244 case OPC_CMP_NGT_D:
2e211e0a 11245 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 11246 if (ctx->opcode & (1 << 6)) {
71375b59 11247 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 11248 } else {
71375b59 11249 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11250 }
6ea83fed 11251 break;
bf4120ad 11252 case OPC_CVT_S_D:
5e755519 11253 check_cp1_registers(ctx, fs);
b6d96bed 11254 {
a7812ae4
PB
11255 TCGv_i32 fp32 = tcg_temp_new_i32();
11256 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11257
11258 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11259 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 11260 tcg_temp_free_i64(fp64);
7c979afd 11261 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11262 tcg_temp_free_i32(fp32);
b6d96bed 11263 }
5a5012ec 11264 break;
bf4120ad 11265 case OPC_CVT_W_D:
5e755519 11266 check_cp1_registers(ctx, fs);
b6d96bed 11267 {
a7812ae4
PB
11268 TCGv_i32 fp32 = tcg_temp_new_i32();
11269 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11270
11271 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11272 if (ctx->nan2008) {
11273 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11274 } else {
11275 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11276 }
a7812ae4 11277 tcg_temp_free_i64(fp64);
7c979afd 11278 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11279 tcg_temp_free_i32(fp32);
b6d96bed 11280 }
5a5012ec 11281 break;
bf4120ad 11282 case OPC_CVT_L_D:
5e755519 11283 check_cp1_64bitmode(ctx);
b6d96bed 11284 {
a7812ae4 11285 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11286
11287 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11288 if (ctx->nan2008) {
11289 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11290 } else {
11291 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11292 }
b6d96bed 11293 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11294 tcg_temp_free_i64(fp0);
b6d96bed 11295 }
5a5012ec 11296 break;
bf4120ad 11297 case OPC_CVT_S_W:
b6d96bed 11298 {
a7812ae4 11299 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11300
7c979afd 11301 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11302 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 11303 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11304 tcg_temp_free_i32(fp0);
b6d96bed 11305 }
6ea83fed 11306 break;
bf4120ad 11307 case OPC_CVT_D_W:
5e755519 11308 check_cp1_registers(ctx, fd);
b6d96bed 11309 {
a7812ae4
PB
11310 TCGv_i32 fp32 = tcg_temp_new_i32();
11311 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11312
7c979afd 11313 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11314 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 11315 tcg_temp_free_i32(fp32);
b6d96bed 11316 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11317 tcg_temp_free_i64(fp64);
b6d96bed 11318 }
5a5012ec 11319 break;
bf4120ad 11320 case OPC_CVT_S_L:
5e755519 11321 check_cp1_64bitmode(ctx);
b6d96bed 11322 {
a7812ae4
PB
11323 TCGv_i32 fp32 = tcg_temp_new_i32();
11324 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11325
11326 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11327 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 11328 tcg_temp_free_i64(fp64);
7c979afd 11329 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11330 tcg_temp_free_i32(fp32);
b6d96bed 11331 }
5a5012ec 11332 break;
bf4120ad 11333 case OPC_CVT_D_L:
5e755519 11334 check_cp1_64bitmode(ctx);
b6d96bed 11335 {
a7812ae4 11336 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11337
11338 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11339 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 11340 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11341 tcg_temp_free_i64(fp0);
b6d96bed 11342 }
5a5012ec 11343 break;
bf4120ad 11344 case OPC_CVT_PS_PW:
e29c9628 11345 check_ps(ctx);
b6d96bed 11346 {
a7812ae4 11347 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11348
11349 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11350 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 11351 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11352 tcg_temp_free_i64(fp0);
b6d96bed 11353 }
5a5012ec 11354 break;
bf4120ad 11355 case OPC_ADD_PS:
e29c9628 11356 check_ps(ctx);
b6d96bed 11357 {
a7812ae4
PB
11358 TCGv_i64 fp0 = tcg_temp_new_i64();
11359 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11360
11361 gen_load_fpr64(ctx, fp0, fs);
11362 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11363 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11364 tcg_temp_free_i64(fp1);
b6d96bed 11365 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11366 tcg_temp_free_i64(fp0);
b6d96bed 11367 }
6ea83fed 11368 break;
bf4120ad 11369 case OPC_SUB_PS:
e29c9628 11370 check_ps(ctx);
b6d96bed 11371 {
a7812ae4
PB
11372 TCGv_i64 fp0 = tcg_temp_new_i64();
11373 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11374
11375 gen_load_fpr64(ctx, fp0, fs);
11376 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11377 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11378 tcg_temp_free_i64(fp1);
b6d96bed 11379 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11380 tcg_temp_free_i64(fp0);
b6d96bed 11381 }
6ea83fed 11382 break;
bf4120ad 11383 case OPC_MUL_PS:
e29c9628 11384 check_ps(ctx);
b6d96bed 11385 {
a7812ae4
PB
11386 TCGv_i64 fp0 = tcg_temp_new_i64();
11387 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11388
11389 gen_load_fpr64(ctx, fp0, fs);
11390 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11391 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11392 tcg_temp_free_i64(fp1);
b6d96bed 11393 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11394 tcg_temp_free_i64(fp0);
b6d96bed 11395 }
6ea83fed 11396 break;
bf4120ad 11397 case OPC_ABS_PS:
e29c9628 11398 check_ps(ctx);
b6d96bed 11399 {
a7812ae4 11400 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11401
11402 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11403 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 11404 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11405 tcg_temp_free_i64(fp0);
b6d96bed 11406 }
6ea83fed 11407 break;
bf4120ad 11408 case OPC_MOV_PS:
e29c9628 11409 check_ps(ctx);
b6d96bed 11410 {
a7812ae4 11411 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11412
11413 gen_load_fpr64(ctx, fp0, fs);
11414 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11415 tcg_temp_free_i64(fp0);
b6d96bed 11416 }
6ea83fed 11417 break;
bf4120ad 11418 case OPC_NEG_PS:
e29c9628 11419 check_ps(ctx);
b6d96bed 11420 {
a7812ae4 11421 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11422
11423 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11424 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 11425 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11426 tcg_temp_free_i64(fp0);
b6d96bed 11427 }
6ea83fed 11428 break;
bf4120ad 11429 case OPC_MOVCF_PS:
e29c9628 11430 check_ps(ctx);
7f6613ce 11431 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 11432 break;
bf4120ad 11433 case OPC_MOVZ_PS:
e29c9628 11434 check_ps(ctx);
a16336e4 11435 {
42a268c2 11436 TCGLabel *l1 = gen_new_label();
30a3848b 11437 TCGv_i64 fp0;
a16336e4 11438
1f8929d2 11439 if (ft != 0) {
c9297f4d 11440 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 11441 }
c9297f4d
AJ
11442 fp0 = tcg_temp_new_i64();
11443 gen_load_fpr64(ctx, fp0, fs);
11444 gen_store_fpr64(ctx, fp0, fd);
11445 tcg_temp_free_i64(fp0);
a16336e4
TS
11446 gen_set_label(l1);
11447 }
6ea83fed 11448 break;
bf4120ad 11449 case OPC_MOVN_PS:
e29c9628 11450 check_ps(ctx);
a16336e4 11451 {
42a268c2 11452 TCGLabel *l1 = gen_new_label();
30a3848b 11453 TCGv_i64 fp0;
c9297f4d
AJ
11454
11455 if (ft != 0) {
11456 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11457 fp0 = tcg_temp_new_i64();
11458 gen_load_fpr64(ctx, fp0, fs);
11459 gen_store_fpr64(ctx, fp0, fd);
11460 tcg_temp_free_i64(fp0);
11461 gen_set_label(l1);
11462 }
a16336e4 11463 }
6ea83fed 11464 break;
bf4120ad 11465 case OPC_ADDR_PS:
e29c9628 11466 check_ps(ctx);
b6d96bed 11467 {
a7812ae4
PB
11468 TCGv_i64 fp0 = tcg_temp_new_i64();
11469 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11470
11471 gen_load_fpr64(ctx, fp0, ft);
11472 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11473 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11474 tcg_temp_free_i64(fp1);
b6d96bed 11475 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11476 tcg_temp_free_i64(fp0);
b6d96bed 11477 }
fbcc6828 11478 break;
bf4120ad 11479 case OPC_MULR_PS:
e29c9628 11480 check_ps(ctx);
b6d96bed 11481 {
a7812ae4
PB
11482 TCGv_i64 fp0 = tcg_temp_new_i64();
11483 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11484
11485 gen_load_fpr64(ctx, fp0, ft);
11486 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11487 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11488 tcg_temp_free_i64(fp1);
b6d96bed 11489 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11490 tcg_temp_free_i64(fp0);
b6d96bed 11491 }
57fa1fb3 11492 break;
bf4120ad 11493 case OPC_RECIP2_PS:
e29c9628 11494 check_ps(ctx);
b6d96bed 11495 {
a7812ae4
PB
11496 TCGv_i64 fp0 = tcg_temp_new_i64();
11497 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11498
11499 gen_load_fpr64(ctx, fp0, fs);
d22d7289 11500 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11501 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11502 tcg_temp_free_i64(fp1);
b6d96bed 11503 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11504 tcg_temp_free_i64(fp0);
b6d96bed 11505 }
57fa1fb3 11506 break;
bf4120ad 11507 case OPC_RECIP1_PS:
e29c9628 11508 check_ps(ctx);
b6d96bed 11509 {
a7812ae4 11510 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11511
11512 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11513 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 11514 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11515 tcg_temp_free_i64(fp0);
b6d96bed 11516 }
57fa1fb3 11517 break;
bf4120ad 11518 case OPC_RSQRT1_PS:
e29c9628 11519 check_ps(ctx);
b6d96bed 11520 {
a7812ae4 11521 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11522
11523 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11524 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 11525 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11526 tcg_temp_free_i64(fp0);
b6d96bed 11527 }
57fa1fb3 11528 break;
bf4120ad 11529 case OPC_RSQRT2_PS:
e29c9628 11530 check_ps(ctx);
b6d96bed 11531 {
a7812ae4
PB
11532 TCGv_i64 fp0 = tcg_temp_new_i64();
11533 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11534
11535 gen_load_fpr64(ctx, fp0, fs);
11536 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11537 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11538 tcg_temp_free_i64(fp1);
b6d96bed 11539 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11540 tcg_temp_free_i64(fp0);
b6d96bed 11541 }
57fa1fb3 11542 break;
bf4120ad 11543 case OPC_CVT_S_PU:
5e755519 11544 check_cp1_64bitmode(ctx);
b6d96bed 11545 {
a7812ae4 11546 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11547
7f6613ce 11548 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 11549 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 11550 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11551 tcg_temp_free_i32(fp0);
b6d96bed 11552 }
dd016883 11553 break;
bf4120ad 11554 case OPC_CVT_PW_PS:
e29c9628 11555 check_ps(ctx);
b6d96bed 11556 {
a7812ae4 11557 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11558
11559 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11560 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 11561 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11562 tcg_temp_free_i64(fp0);
b6d96bed 11563 }
6ea83fed 11564 break;
bf4120ad 11565 case OPC_CVT_S_PL:
5e755519 11566 check_cp1_64bitmode(ctx);
b6d96bed 11567 {
a7812ae4 11568 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11569
7c979afd 11570 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11571 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 11572 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11573 tcg_temp_free_i32(fp0);
b6d96bed 11574 }
6ea83fed 11575 break;
bf4120ad 11576 case OPC_PLL_PS:
e29c9628 11577 check_ps(ctx);
b6d96bed 11578 {
a7812ae4
PB
11579 TCGv_i32 fp0 = tcg_temp_new_i32();
11580 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11581
7c979afd
LA
11582 gen_load_fpr32(ctx, fp0, fs);
11583 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 11584 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 11585 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
11586 tcg_temp_free_i32(fp0);
11587 tcg_temp_free_i32(fp1);
b6d96bed 11588 }
6ea83fed 11589 break;
bf4120ad 11590 case OPC_PLU_PS:
e29c9628 11591 check_ps(ctx);
b6d96bed 11592 {
a7812ae4
PB
11593 TCGv_i32 fp0 = tcg_temp_new_i32();
11594 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11595
7c979afd 11596 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 11597 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11598 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11599 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11600 tcg_temp_free_i32(fp0);
11601 tcg_temp_free_i32(fp1);
b6d96bed 11602 }
5a5012ec 11603 break;
bf4120ad 11604 case OPC_PUL_PS:
e29c9628 11605 check_ps(ctx);
b6d96bed 11606 {
a7812ae4
PB
11607 TCGv_i32 fp0 = tcg_temp_new_i32();
11608 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11609
7f6613ce 11610 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
11611 gen_load_fpr32(ctx, fp1, ft);
11612 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11613 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11614 tcg_temp_free_i32(fp0);
11615 tcg_temp_free_i32(fp1);
b6d96bed 11616 }
5a5012ec 11617 break;
bf4120ad 11618 case OPC_PUU_PS:
e29c9628 11619 check_ps(ctx);
b6d96bed 11620 {
a7812ae4
PB
11621 TCGv_i32 fp0 = tcg_temp_new_i32();
11622 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11623
7f6613ce
PJ
11624 gen_load_fpr32h(ctx, fp0, fs);
11625 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11626 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11627 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11628 tcg_temp_free_i32(fp0);
11629 tcg_temp_free_i32(fp1);
b6d96bed 11630 }
5a5012ec 11631 break;
bf4120ad
NF
11632 case OPC_CMP_F_PS:
11633 case OPC_CMP_UN_PS:
11634 case OPC_CMP_EQ_PS:
11635 case OPC_CMP_UEQ_PS:
11636 case OPC_CMP_OLT_PS:
11637 case OPC_CMP_ULT_PS:
11638 case OPC_CMP_OLE_PS:
11639 case OPC_CMP_ULE_PS:
11640 case OPC_CMP_SF_PS:
11641 case OPC_CMP_NGLE_PS:
11642 case OPC_CMP_SEQ_PS:
11643 case OPC_CMP_NGL_PS:
11644 case OPC_CMP_LT_PS:
11645 case OPC_CMP_NGE_PS:
11646 case OPC_CMP_LE_PS:
11647 case OPC_CMP_NGT_PS:
8153667c 11648 if (ctx->opcode & (1 << 6)) {
71375b59 11649 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 11650 } else {
71375b59 11651 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11652 }
6ea83fed 11653 break;
5a5012ec 11654 default:
9d68ac14 11655 MIPS_INVAL("farith");
3a4ef3b7 11656 gen_reserved_instruction(ctx);
6ea83fed
FB
11657 return;
11658 }
6ea83fed 11659}
6af0bf9c 11660
5a5012ec 11661/* Coprocessor 3 (FPU) */
235785e8
AM
11662static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11663 int fd, int fs, int base, int index)
7a387fff 11664{
4e2474d6 11665 TCGv t0 = tcg_temp_new();
7a387fff 11666
93b12ccc 11667 if (base == 0) {
6c5c1e20 11668 gen_load_gpr(t0, index);
93b12ccc 11669 } else if (index == 0) {
6c5c1e20 11670 gen_load_gpr(t0, base);
93b12ccc 11671 } else {
05168674 11672 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 11673 }
7480515f
AM
11674 /*
11675 * Don't do NOP if destination is zero: we must perform the actual
11676 * memory access.
11677 */
5a5012ec
TS
11678 switch (opc) {
11679 case OPC_LWXC1:
8c0ab41f 11680 check_cop1x(ctx);
b6d96bed 11681 {
a7812ae4 11682 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11683
5f68f5ae 11684 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 11685 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 11686 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11687 tcg_temp_free_i32(fp0);
b6d96bed 11688 }
5a5012ec
TS
11689 break;
11690 case OPC_LDXC1:
8c0ab41f
AJ
11691 check_cop1x(ctx);
11692 check_cp1_registers(ctx, fd);
b6d96bed 11693 {
a7812ae4 11694 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 11695 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11696 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11697 tcg_temp_free_i64(fp0);
b6d96bed 11698 }
5a5012ec
TS
11699 break;
11700 case OPC_LUXC1:
8c0ab41f 11701 check_cp1_64bitmode(ctx);
6c5c1e20 11702 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11703 {
a7812ae4 11704 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11705
5f68f5ae 11706 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11707 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11708 tcg_temp_free_i64(fp0);
b6d96bed 11709 }
5a5012ec
TS
11710 break;
11711 case OPC_SWXC1:
8c0ab41f 11712 check_cop1x(ctx);
b6d96bed 11713 {
a7812ae4 11714 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11715 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 11716 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 11717 tcg_temp_free_i32(fp0);
b6d96bed 11718 }
5a5012ec
TS
11719 break;
11720 case OPC_SDXC1:
8c0ab41f
AJ
11721 check_cop1x(ctx);
11722 check_cp1_registers(ctx, fs);
b6d96bed 11723 {
a7812ae4 11724 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11725 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11726 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11727 tcg_temp_free_i64(fp0);
b6d96bed 11728 }
5a5012ec
TS
11729 break;
11730 case OPC_SUXC1:
8c0ab41f 11731 check_cp1_64bitmode(ctx);
6c5c1e20 11732 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11733 {
a7812ae4 11734 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11735 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11736 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11737 tcg_temp_free_i64(fp0);
b6d96bed 11738 }
5a5012ec 11739 break;
5a5012ec 11740 }
6c5c1e20 11741 tcg_temp_free(t0);
5a5012ec
TS
11742}
11743
235785e8
AM
11744static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11745 int fd, int fr, int fs, int ft)
5a5012ec 11746{
5a5012ec
TS
11747 switch (opc) {
11748 case OPC_ALNV_PS:
e29c9628 11749 check_ps(ctx);
a16336e4 11750 {
a7812ae4 11751 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
11752 TCGv_i32 fp = tcg_temp_new_i32();
11753 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
11754 TCGLabel *l1 = gen_new_label();
11755 TCGLabel *l2 = gen_new_label();
a16336e4 11756
6c5c1e20
TS
11757 gen_load_gpr(t0, fr);
11758 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
11759
11760 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 11761 gen_load_fpr32(ctx, fp, fs);
7f6613ce 11762 gen_load_fpr32h(ctx, fph, fs);
7c979afd 11763 gen_store_fpr32(ctx, fp, fd);
7f6613ce 11764 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
11765 tcg_gen_br(l2);
11766 gen_set_label(l1);
6c5c1e20
TS
11767 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11768 tcg_temp_free(t0);
a16336e4 11769#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 11770 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
11771 gen_load_fpr32h(ctx, fph, ft);
11772 gen_store_fpr32h(ctx, fp, fd);
7c979afd 11773 gen_store_fpr32(ctx, fph, fd);
a16336e4 11774#else
7f6613ce 11775 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
11776 gen_load_fpr32(ctx, fp, ft);
11777 gen_store_fpr32(ctx, fph, fd);
7f6613ce 11778 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
11779#endif
11780 gen_set_label(l2);
c905fdac
AJ
11781 tcg_temp_free_i32(fp);
11782 tcg_temp_free_i32(fph);
a16336e4 11783 }
5a5012ec
TS
11784 break;
11785 case OPC_MADD_S:
b8aa4598 11786 check_cop1x(ctx);
b6d96bed 11787 {
a7812ae4
PB
11788 TCGv_i32 fp0 = tcg_temp_new_i32();
11789 TCGv_i32 fp1 = tcg_temp_new_i32();
11790 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11791
7c979afd
LA
11792 gen_load_fpr32(ctx, fp0, fs);
11793 gen_load_fpr32(ctx, fp1, ft);
11794 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11795 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11796 tcg_temp_free_i32(fp0);
11797 tcg_temp_free_i32(fp1);
7c979afd 11798 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11799 tcg_temp_free_i32(fp2);
b6d96bed 11800 }
5a5012ec
TS
11801 break;
11802 case OPC_MADD_D:
b8aa4598
TS
11803 check_cop1x(ctx);
11804 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11805 {
a7812ae4
PB
11806 TCGv_i64 fp0 = tcg_temp_new_i64();
11807 TCGv_i64 fp1 = tcg_temp_new_i64();
11808 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11809
11810 gen_load_fpr64(ctx, fp0, fs);
11811 gen_load_fpr64(ctx, fp1, ft);
11812 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11813 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11814 tcg_temp_free_i64(fp0);
11815 tcg_temp_free_i64(fp1);
b6d96bed 11816 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11817 tcg_temp_free_i64(fp2);
b6d96bed 11818 }
5a5012ec
TS
11819 break;
11820 case OPC_MADD_PS:
e29c9628 11821 check_ps(ctx);
b6d96bed 11822 {
a7812ae4
PB
11823 TCGv_i64 fp0 = tcg_temp_new_i64();
11824 TCGv_i64 fp1 = tcg_temp_new_i64();
11825 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11826
11827 gen_load_fpr64(ctx, fp0, fs);
11828 gen_load_fpr64(ctx, fp1, ft);
11829 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11830 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11831 tcg_temp_free_i64(fp0);
11832 tcg_temp_free_i64(fp1);
b6d96bed 11833 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11834 tcg_temp_free_i64(fp2);
b6d96bed 11835 }
5a5012ec
TS
11836 break;
11837 case OPC_MSUB_S:
b8aa4598 11838 check_cop1x(ctx);
b6d96bed 11839 {
a7812ae4
PB
11840 TCGv_i32 fp0 = tcg_temp_new_i32();
11841 TCGv_i32 fp1 = tcg_temp_new_i32();
11842 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11843
7c979afd
LA
11844 gen_load_fpr32(ctx, fp0, fs);
11845 gen_load_fpr32(ctx, fp1, ft);
11846 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11847 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11848 tcg_temp_free_i32(fp0);
11849 tcg_temp_free_i32(fp1);
7c979afd 11850 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11851 tcg_temp_free_i32(fp2);
b6d96bed 11852 }
5a5012ec
TS
11853 break;
11854 case OPC_MSUB_D:
b8aa4598
TS
11855 check_cop1x(ctx);
11856 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11857 {
a7812ae4
PB
11858 TCGv_i64 fp0 = tcg_temp_new_i64();
11859 TCGv_i64 fp1 = tcg_temp_new_i64();
11860 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11861
11862 gen_load_fpr64(ctx, fp0, fs);
11863 gen_load_fpr64(ctx, fp1, ft);
11864 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11865 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11866 tcg_temp_free_i64(fp0);
11867 tcg_temp_free_i64(fp1);
b6d96bed 11868 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11869 tcg_temp_free_i64(fp2);
b6d96bed 11870 }
5a5012ec
TS
11871 break;
11872 case OPC_MSUB_PS:
e29c9628 11873 check_ps(ctx);
b6d96bed 11874 {
a7812ae4
PB
11875 TCGv_i64 fp0 = tcg_temp_new_i64();
11876 TCGv_i64 fp1 = tcg_temp_new_i64();
11877 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11878
11879 gen_load_fpr64(ctx, fp0, fs);
11880 gen_load_fpr64(ctx, fp1, ft);
11881 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11882 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11883 tcg_temp_free_i64(fp0);
11884 tcg_temp_free_i64(fp1);
b6d96bed 11885 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11886 tcg_temp_free_i64(fp2);
b6d96bed 11887 }
5a5012ec
TS
11888 break;
11889 case OPC_NMADD_S:
b8aa4598 11890 check_cop1x(ctx);
b6d96bed 11891 {
a7812ae4
PB
11892 TCGv_i32 fp0 = tcg_temp_new_i32();
11893 TCGv_i32 fp1 = tcg_temp_new_i32();
11894 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11895
7c979afd
LA
11896 gen_load_fpr32(ctx, fp0, fs);
11897 gen_load_fpr32(ctx, fp1, ft);
11898 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11899 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11900 tcg_temp_free_i32(fp0);
11901 tcg_temp_free_i32(fp1);
7c979afd 11902 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11903 tcg_temp_free_i32(fp2);
b6d96bed 11904 }
5a5012ec
TS
11905 break;
11906 case OPC_NMADD_D:
b8aa4598
TS
11907 check_cop1x(ctx);
11908 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11909 {
a7812ae4
PB
11910 TCGv_i64 fp0 = tcg_temp_new_i64();
11911 TCGv_i64 fp1 = tcg_temp_new_i64();
11912 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11913
11914 gen_load_fpr64(ctx, fp0, fs);
11915 gen_load_fpr64(ctx, fp1, ft);
11916 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11917 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11918 tcg_temp_free_i64(fp0);
11919 tcg_temp_free_i64(fp1);
b6d96bed 11920 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11921 tcg_temp_free_i64(fp2);
b6d96bed 11922 }
5a5012ec
TS
11923 break;
11924 case OPC_NMADD_PS:
e29c9628 11925 check_ps(ctx);
b6d96bed 11926 {
a7812ae4
PB
11927 TCGv_i64 fp0 = tcg_temp_new_i64();
11928 TCGv_i64 fp1 = tcg_temp_new_i64();
11929 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11930
11931 gen_load_fpr64(ctx, fp0, fs);
11932 gen_load_fpr64(ctx, fp1, ft);
11933 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11934 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11935 tcg_temp_free_i64(fp0);
11936 tcg_temp_free_i64(fp1);
b6d96bed 11937 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11938 tcg_temp_free_i64(fp2);
b6d96bed 11939 }
5a5012ec
TS
11940 break;
11941 case OPC_NMSUB_S:
b8aa4598 11942 check_cop1x(ctx);
b6d96bed 11943 {
a7812ae4
PB
11944 TCGv_i32 fp0 = tcg_temp_new_i32();
11945 TCGv_i32 fp1 = tcg_temp_new_i32();
11946 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11947
7c979afd
LA
11948 gen_load_fpr32(ctx, fp0, fs);
11949 gen_load_fpr32(ctx, fp1, ft);
11950 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11951 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11952 tcg_temp_free_i32(fp0);
11953 tcg_temp_free_i32(fp1);
7c979afd 11954 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11955 tcg_temp_free_i32(fp2);
b6d96bed 11956 }
5a5012ec
TS
11957 break;
11958 case OPC_NMSUB_D:
b8aa4598
TS
11959 check_cop1x(ctx);
11960 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11961 {
a7812ae4
PB
11962 TCGv_i64 fp0 = tcg_temp_new_i64();
11963 TCGv_i64 fp1 = tcg_temp_new_i64();
11964 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11965
11966 gen_load_fpr64(ctx, fp0, fs);
11967 gen_load_fpr64(ctx, fp1, ft);
11968 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11969 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11970 tcg_temp_free_i64(fp0);
11971 tcg_temp_free_i64(fp1);
b6d96bed 11972 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11973 tcg_temp_free_i64(fp2);
b6d96bed 11974 }
5a5012ec
TS
11975 break;
11976 case OPC_NMSUB_PS:
e29c9628 11977 check_ps(ctx);
b6d96bed 11978 {
a7812ae4
PB
11979 TCGv_i64 fp0 = tcg_temp_new_i64();
11980 TCGv_i64 fp1 = tcg_temp_new_i64();
11981 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11982
11983 gen_load_fpr64(ctx, fp0, fs);
11984 gen_load_fpr64(ctx, fp1, ft);
11985 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11986 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11987 tcg_temp_free_i64(fp0);
11988 tcg_temp_free_i64(fp1);
b6d96bed 11989 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11990 tcg_temp_free_i64(fp2);
b6d96bed 11991 }
5a5012ec 11992 break;
923617a3 11993 default:
9d68ac14 11994 MIPS_INVAL("flt3_arith");
3a4ef3b7 11995 gen_reserved_instruction(ctx);
5a5012ec
TS
11996 return;
11997 }
7a387fff
TS
11998}
11999
f9fa53f1 12000void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12001{
12002 TCGv t0;
12003
b3167288 12004#if !defined(CONFIG_USER_ONLY)
7480515f
AM
12005 /*
12006 * The Linux kernel will emulate rdhwr if it's not supported natively.
12007 * Therefore only check the ISA in system mode.
12008 */
7a47bae5 12009 check_insn(ctx, ISA_MIPS_R2);
b3167288 12010#endif
26ebe468
NF
12011 t0 = tcg_temp_new();
12012
12013 switch (rd) {
12014 case 0:
895c2d04 12015 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12016 gen_store_gpr(t0, rt);
12017 break;
12018 case 1:
895c2d04 12019 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12020 gen_store_gpr(t0, rt);
12021 break;
12022 case 2:
eeb3bba8 12023 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12024 gen_io_start();
12025 }
895c2d04 12026 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 12027 gen_store_gpr(t0, rt);
7480515f
AM
12028 /*
12029 * Break the TB to be able to take timer interrupts immediately
12030 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12031 * we break completely out of translated code.
12032 */
eeb3bba8
EC
12033 gen_save_pc(ctx->base.pc_next + 4);
12034 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12035 break;
12036 case 3:
895c2d04 12037 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12038 gen_store_gpr(t0, rt);
12039 break;
b00c7218 12040 case 4:
2e211e0a 12041 check_insn(ctx, ISA_MIPS_R6);
b00c7218 12042 if (sel != 0) {
7480515f
AM
12043 /*
12044 * Performance counter registers are not implemented other than
b00c7218
YK
12045 * control register 0.
12046 */
12047 generate_exception(ctx, EXCP_RI);
12048 }
12049 gen_helper_rdhwr_performance(t0, cpu_env);
12050 gen_store_gpr(t0, rt);
12051 break;
12052 case 5:
2e211e0a 12053 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
12054 gen_helper_rdhwr_xnp(t0, cpu_env);
12055 gen_store_gpr(t0, rt);
12056 break;
26ebe468
NF
12057 case 29:
12058#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12059 tcg_gen_ld_tl(t0, cpu_env,
12060 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12061 gen_store_gpr(t0, rt);
12062 break;
12063#else
d279279e
PJ
12064 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12065 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12066 tcg_gen_ld_tl(t0, cpu_env,
12067 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12068 gen_store_gpr(t0, rt);
12069 } else {
3a4ef3b7 12070 gen_reserved_instruction(ctx);
d279279e
PJ
12071 }
12072 break;
26ebe468
NF
12073#endif
12074 default: /* Invalid */
12075 MIPS_INVAL("rdhwr");
3a4ef3b7 12076 gen_reserved_instruction(ctx);
26ebe468
NF
12077 break;
12078 }
12079 tcg_temp_free(t0);
12080}
12081
a5f53390
LA
12082static inline void clear_branch_hflags(DisasContext *ctx)
12083{
12084 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12085 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12086 save_cpu_state(ctx, 0);
12087 } else {
7480515f
AM
12088 /*
12089 * It is not safe to save ctx->hflags as hflags may be changed
12090 * in execution time by the instruction in delay / forbidden slot.
12091 */
a5f53390
LA
12092 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12093 }
12094}
12095
31837be3 12096static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12097{
12098 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12099 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12100 /* Branches completion */
a5f53390 12101 clear_branch_hflags(ctx);
eeb3bba8 12102 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12103 /* FIXME: Need to clear can_do_io. */
364d4831 12104 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12105 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12106 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12107 break;
c9602061
NF
12108 case MIPS_HFLAG_B:
12109 /* unconditional branch */
364d4831
NF
12110 if (proc_hflags & MIPS_HFLAG_BX) {
12111 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12112 }
c9602061
NF
12113 gen_goto_tb(ctx, 0, ctx->btarget);
12114 break;
12115 case MIPS_HFLAG_BL:
12116 /* blikely taken case */
c9602061
NF
12117 gen_goto_tb(ctx, 0, ctx->btarget);
12118 break;
12119 case MIPS_HFLAG_BC:
12120 /* Conditional branch */
c9602061 12121 {
42a268c2 12122 TCGLabel *l1 = gen_new_label();
c9602061
NF
12123
12124 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12125 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12126 gen_set_label(l1);
12127 gen_goto_tb(ctx, 0, ctx->btarget);
12128 }
12129 break;
12130 case MIPS_HFLAG_BR:
12131 /* unconditional branch to register */
d75c135e 12132 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12133 TCGv t0 = tcg_temp_new();
12134 TCGv_i32 t1 = tcg_temp_new_i32();
12135
12136 tcg_gen_andi_tl(t0, btarget, 0x1);
12137 tcg_gen_trunc_tl_i32(t1, t0);
12138 tcg_temp_free(t0);
12139 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12140 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12141 tcg_gen_or_i32(hflags, hflags, t1);
12142 tcg_temp_free_i32(t1);
12143
12144 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12145 } else {
12146 tcg_gen_mov_tl(cpu_PC, btarget);
12147 }
eeb3bba8 12148 if (ctx->base.singlestep_enabled) {
c9602061 12149 save_cpu_state(ctx, 0);
9c708c7f 12150 gen_helper_raise_exception_debug(cpu_env);
c9602061 12151 }
7f11636d 12152 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12153 break;
12154 default:
a5f53390
LA
12155 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12156 abort();
c9602061
NF
12157 }
12158 }
12159}
12160
6893f074
YK
12161/* Compact Branches */
12162static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12163 int rs, int rt, int32_t offset)
12164{
12165 int bcond_compute = 0;
12166 TCGv t0 = tcg_temp_new();
12167 TCGv t1 = tcg_temp_new();
65935f07 12168 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12169
12170 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12171#ifdef MIPS_DEBUG_DISAS
12172 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12173 "\n", ctx->base.pc_next);
6893f074 12174#endif
3a4ef3b7 12175 gen_reserved_instruction(ctx);
6893f074
YK
12176 goto out;
12177 }
12178
12179 /* Load needed operands and calculate btarget */
12180 switch (opc) {
12181 /* compact branch */
12182 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12183 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12184 gen_load_gpr(t0, rs);
12185 gen_load_gpr(t1, rt);
12186 bcond_compute = 1;
eeb3bba8 12187 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12188 if (rs <= rt && rs == 0) {
12189 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 12190 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12191 }
12192 break;
12193 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12194 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12195 gen_load_gpr(t0, rs);
12196 gen_load_gpr(t1, rt);
12197 bcond_compute = 1;
eeb3bba8 12198 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12199 break;
12200 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12201 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12202 if (rs == 0 || rs == rt) {
12203 /* OPC_BLEZALC, OPC_BGEZALC */
12204 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 12205 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12206 }
12207 gen_load_gpr(t0, rs);
12208 gen_load_gpr(t1, rt);
12209 bcond_compute = 1;
eeb3bba8 12210 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12211 break;
12212 case OPC_BC:
12213 case OPC_BALC:
eeb3bba8 12214 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12215 break;
12216 case OPC_BEQZC:
12217 case OPC_BNEZC:
12218 if (rs != 0) {
12219 /* OPC_BEQZC, OPC_BNEZC */
12220 gen_load_gpr(t0, rs);
12221 bcond_compute = 1;
eeb3bba8 12222 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12223 } else {
12224 /* OPC_JIC, OPC_JIALC */
12225 TCGv tbase = tcg_temp_new();
12226 TCGv toffset = tcg_temp_new();
12227
12228 gen_load_gpr(tbase, rt);
12229 tcg_gen_movi_tl(toffset, offset);
12230 gen_op_addr_add(ctx, btarget, tbase, toffset);
12231 tcg_temp_free(tbase);
12232 tcg_temp_free(toffset);
12233 }
12234 break;
12235 default:
12236 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 12237 gen_reserved_instruction(ctx);
6893f074
YK
12238 goto out;
12239 }
12240
12241 if (bcond_compute == 0) {
12242 /* Uncoditional compact branch */
12243 switch (opc) {
12244 case OPC_JIALC:
eeb3bba8 12245 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12246 /* Fallthrough */
12247 case OPC_JIC:
12248 ctx->hflags |= MIPS_HFLAG_BR;
12249 break;
12250 case OPC_BALC:
eeb3bba8 12251 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12252 /* Fallthrough */
12253 case OPC_BC:
12254 ctx->hflags |= MIPS_HFLAG_B;
12255 break;
12256 default:
12257 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 12258 gen_reserved_instruction(ctx);
6893f074
YK
12259 goto out;
12260 }
12261
12262 /* Generating branch here as compact branches don't have delay slot */
12263 gen_branch(ctx, 4);
12264 } else {
12265 /* Conditional compact branch */
12266 TCGLabel *fs = gen_new_label();
12267 save_cpu_state(ctx, 0);
12268
12269 switch (opc) {
12270 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12271 if (rs == 0 && rt != 0) {
12272 /* OPC_BLEZALC */
12273 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12274 } else if (rs != 0 && rt != 0 && rs == rt) {
12275 /* OPC_BGEZALC */
12276 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12277 } else {
12278 /* OPC_BGEUC */
12279 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12280 }
12281 break;
12282 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12283 if (rs == 0 && rt != 0) {
12284 /* OPC_BGTZALC */
12285 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12286 } else if (rs != 0 && rt != 0 && rs == rt) {
12287 /* OPC_BLTZALC */
12288 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12289 } else {
12290 /* OPC_BLTUC */
12291 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12292 }
12293 break;
12294 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12295 if (rs == 0 && rt != 0) {
12296 /* OPC_BLEZC */
12297 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12298 } else if (rs != 0 && rt != 0 && rs == rt) {
12299 /* OPC_BGEZC */
12300 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12301 } else {
12302 /* OPC_BGEC */
12303 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12304 }
12305 break;
12306 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12307 if (rs == 0 && rt != 0) {
12308 /* OPC_BGTZC */
12309 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12310 } else if (rs != 0 && rt != 0 && rs == rt) {
12311 /* OPC_BLTZC */
12312 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12313 } else {
12314 /* OPC_BLTC */
12315 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12316 }
12317 break;
12318 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12319 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12320 if (rs >= rt) {
12321 /* OPC_BOVC, OPC_BNVC */
12322 TCGv t2 = tcg_temp_new();
12323 TCGv t3 = tcg_temp_new();
12324 TCGv t4 = tcg_temp_new();
12325 TCGv input_overflow = tcg_temp_new();
12326
12327 gen_load_gpr(t0, rs);
12328 gen_load_gpr(t1, rt);
12329 tcg_gen_ext32s_tl(t2, t0);
12330 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12331 tcg_gen_ext32s_tl(t3, t1);
12332 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12333 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12334
12335 tcg_gen_add_tl(t4, t2, t3);
12336 tcg_gen_ext32s_tl(t4, t4);
12337 tcg_gen_xor_tl(t2, t2, t3);
12338 tcg_gen_xor_tl(t3, t4, t3);
12339 tcg_gen_andc_tl(t2, t3, t2);
12340 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12341 tcg_gen_or_tl(t4, t4, input_overflow);
12342 if (opc == OPC_BOVC) {
12343 /* OPC_BOVC */
12344 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12345 } else {
12346 /* OPC_BNVC */
12347 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12348 }
12349 tcg_temp_free(input_overflow);
12350 tcg_temp_free(t4);
12351 tcg_temp_free(t3);
12352 tcg_temp_free(t2);
12353 } else if (rs < rt && rs == 0) {
12354 /* OPC_BEQZALC, OPC_BNEZALC */
12355 if (opc == OPC_BEQZALC) {
12356 /* OPC_BEQZALC */
12357 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12358 } else {
12359 /* OPC_BNEZALC */
12360 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12361 }
12362 } else {
12363 /* OPC_BEQC, OPC_BNEC */
12364 if (opc == OPC_BEQC) {
12365 /* OPC_BEQC */
12366 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12367 } else {
12368 /* OPC_BNEC */
12369 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12370 }
12371 }
12372 break;
12373 case OPC_BEQZC:
12374 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12375 break;
12376 case OPC_BNEZC:
12377 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12378 break;
12379 default:
12380 MIPS_INVAL("Compact conditional branch/jump");
3a4ef3b7 12381 gen_reserved_instruction(ctx);
6893f074
YK
12382 goto out;
12383 }
12384
12385 /* Generating branch here as compact branches don't have delay slot */
12386 gen_goto_tb(ctx, 1, ctx->btarget);
12387 gen_set_label(fs);
12388
12389 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
12390 }
12391
12392out:
12393 tcg_temp_free(t0);
12394 tcg_temp_free(t1);
12395}
12396
7a387fff 12397/* ISA extensions (ASEs) */
6af0bf9c 12398/* MIPS16 extension to MIPS32 */
6ea219d0
NF
12399
12400/* MIPS16 major opcodes */
12401enum {
12402 M16_OPC_ADDIUSP = 0x00,
12403 M16_OPC_ADDIUPC = 0x01,
12404 M16_OPC_B = 0x02,
12405 M16_OPC_JAL = 0x03,
12406 M16_OPC_BEQZ = 0x04,
12407 M16_OPC_BNEQZ = 0x05,
12408 M16_OPC_SHIFT = 0x06,
12409 M16_OPC_LD = 0x07,
12410 M16_OPC_RRIA = 0x08,
12411 M16_OPC_ADDIU8 = 0x09,
12412 M16_OPC_SLTI = 0x0a,
12413 M16_OPC_SLTIU = 0x0b,
12414 M16_OPC_I8 = 0x0c,
12415 M16_OPC_LI = 0x0d,
12416 M16_OPC_CMPI = 0x0e,
12417 M16_OPC_SD = 0x0f,
12418 M16_OPC_LB = 0x10,
12419 M16_OPC_LH = 0x11,
12420 M16_OPC_LWSP = 0x12,
12421 M16_OPC_LW = 0x13,
12422 M16_OPC_LBU = 0x14,
12423 M16_OPC_LHU = 0x15,
12424 M16_OPC_LWPC = 0x16,
12425 M16_OPC_LWU = 0x17,
12426 M16_OPC_SB = 0x18,
12427 M16_OPC_SH = 0x19,
12428 M16_OPC_SWSP = 0x1a,
12429 M16_OPC_SW = 0x1b,
12430 M16_OPC_RRR = 0x1c,
12431 M16_OPC_RR = 0x1d,
12432 M16_OPC_EXTEND = 0x1e,
12433 M16_OPC_I64 = 0x1f
12434};
12435
12436/* I8 funct field */
12437enum {
12438 I8_BTEQZ = 0x0,
12439 I8_BTNEZ = 0x1,
12440 I8_SWRASP = 0x2,
12441 I8_ADJSP = 0x3,
12442 I8_SVRS = 0x4,
12443 I8_MOV32R = 0x5,
12444 I8_MOVR32 = 0x7
12445};
12446
12447/* RRR f field */
12448enum {
12449 RRR_DADDU = 0x0,
12450 RRR_ADDU = 0x1,
12451 RRR_DSUBU = 0x2,
12452 RRR_SUBU = 0x3
12453};
12454
12455/* RR funct field */
12456enum {
12457 RR_JR = 0x00,
12458 RR_SDBBP = 0x01,
12459 RR_SLT = 0x02,
12460 RR_SLTU = 0x03,
12461 RR_SLLV = 0x04,
12462 RR_BREAK = 0x05,
12463 RR_SRLV = 0x06,
12464 RR_SRAV = 0x07,
12465 RR_DSRL = 0x08,
12466 RR_CMP = 0x0a,
12467 RR_NEG = 0x0b,
12468 RR_AND = 0x0c,
12469 RR_OR = 0x0d,
12470 RR_XOR = 0x0e,
12471 RR_NOT = 0x0f,
12472 RR_MFHI = 0x10,
12473 RR_CNVT = 0x11,
12474 RR_MFLO = 0x12,
12475 RR_DSRA = 0x13,
12476 RR_DSLLV = 0x14,
12477 RR_DSRLV = 0x16,
12478 RR_DSRAV = 0x17,
12479 RR_MULT = 0x18,
12480 RR_MULTU = 0x19,
12481 RR_DIV = 0x1a,
12482 RR_DIVU = 0x1b,
12483 RR_DMULT = 0x1c,
12484 RR_DMULTU = 0x1d,
12485 RR_DDIV = 0x1e,
12486 RR_DDIVU = 0x1f
12487};
12488
12489/* I64 funct field */
12490enum {
12491 I64_LDSP = 0x0,
12492 I64_SDSP = 0x1,
12493 I64_SDRASP = 0x2,
12494 I64_DADJSP = 0x3,
12495 I64_LDPC = 0x4,
364d4831 12496 I64_DADDIU5 = 0x5,
6ea219d0
NF
12497 I64_DADDIUPC = 0x6,
12498 I64_DADDIUSP = 0x7
12499};
12500
12501/* RR ry field for CNVT */
12502enum {
12503 RR_RY_CNVT_ZEB = 0x0,
12504 RR_RY_CNVT_ZEH = 0x1,
12505 RR_RY_CNVT_ZEW = 0x2,
12506 RR_RY_CNVT_SEB = 0x4,
12507 RR_RY_CNVT_SEH = 0x5,
12508 RR_RY_CNVT_SEW = 0x6,
12509};
12510
235785e8 12511static int xlat(int r)
364d4831
NF
12512{
12513 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12514
12515 return map[r];
12516}
12517
235785e8
AM
12518static void gen_mips16_save(DisasContext *ctx,
12519 int xsregs, int aregs,
12520 int do_ra, int do_s0, int do_s1,
12521 int framesize)
364d4831
NF
12522{
12523 TCGv t0 = tcg_temp_new();
12524 TCGv t1 = tcg_temp_new();
c48245f0 12525 TCGv t2 = tcg_temp_new();
364d4831
NF
12526 int args, astatic;
12527
12528 switch (aregs) {
12529 case 0:
12530 case 1:
12531 case 2:
12532 case 3:
12533 case 11:
12534 args = 0;
12535 break;
12536 case 4:
12537 case 5:
12538 case 6:
12539 case 7:
12540 args = 1;
12541 break;
12542 case 8:
12543 case 9:
12544 case 10:
12545 args = 2;
12546 break;
12547 case 12:
12548 case 13:
12549 args = 3;
12550 break;
12551 case 14:
12552 args = 4;
12553 break;
12554 default:
3a4ef3b7 12555 gen_reserved_instruction(ctx);
364d4831
NF
12556 return;
12557 }
12558
12559 switch (args) {
12560 case 4:
12561 gen_base_offset_addr(ctx, t0, 29, 12);
12562 gen_load_gpr(t1, 7);
5f68f5ae 12563 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12564 /* Fall through */
12565 case 3:
12566 gen_base_offset_addr(ctx, t0, 29, 8);
12567 gen_load_gpr(t1, 6);
5f68f5ae 12568 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12569 /* Fall through */
12570 case 2:
12571 gen_base_offset_addr(ctx, t0, 29, 4);
12572 gen_load_gpr(t1, 5);
5f68f5ae 12573 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12574 /* Fall through */
12575 case 1:
12576 gen_base_offset_addr(ctx, t0, 29, 0);
12577 gen_load_gpr(t1, 4);
5f68f5ae 12578 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12579 }
12580
12581 gen_load_gpr(t0, 29);
12582
5f68f5ae 12583#define DECR_AND_STORE(reg) do { \
c48245f0
MR
12584 tcg_gen_movi_tl(t2, -4); \
12585 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12586 gen_load_gpr(t1, reg); \
12587 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
12588 } while (0)
12589
12590 if (do_ra) {
12591 DECR_AND_STORE(31);
12592 }
12593
12594 switch (xsregs) {
12595 case 7:
12596 DECR_AND_STORE(30);
12597 /* Fall through */
12598 case 6:
12599 DECR_AND_STORE(23);
12600 /* Fall through */
12601 case 5:
12602 DECR_AND_STORE(22);
12603 /* Fall through */
12604 case 4:
12605 DECR_AND_STORE(21);
12606 /* Fall through */
12607 case 3:
12608 DECR_AND_STORE(20);
12609 /* Fall through */
12610 case 2:
12611 DECR_AND_STORE(19);
12612 /* Fall through */
12613 case 1:
12614 DECR_AND_STORE(18);
12615 }
12616
12617 if (do_s1) {
12618 DECR_AND_STORE(17);
12619 }
12620 if (do_s0) {
12621 DECR_AND_STORE(16);
12622 }
12623
12624 switch (aregs) {
12625 case 0:
12626 case 4:
12627 case 8:
12628 case 12:
12629 case 14:
12630 astatic = 0;
12631 break;
12632 case 1:
12633 case 5:
12634 case 9:
12635 case 13:
12636 astatic = 1;
12637 break;
12638 case 2:
12639 case 6:
12640 case 10:
12641 astatic = 2;
12642 break;
12643 case 3:
12644 case 7:
12645 astatic = 3;
12646 break;
12647 case 11:
12648 astatic = 4;
12649 break;
12650 default:
3a4ef3b7 12651 gen_reserved_instruction(ctx);
364d4831
NF
12652 return;
12653 }
12654
12655 if (astatic > 0) {
12656 DECR_AND_STORE(7);
12657 if (astatic > 1) {
12658 DECR_AND_STORE(6);
12659 if (astatic > 2) {
12660 DECR_AND_STORE(5);
12661 if (astatic > 3) {
12662 DECR_AND_STORE(4);
12663 }
12664 }
12665 }
12666 }
12667#undef DECR_AND_STORE
12668
c48245f0
MR
12669 tcg_gen_movi_tl(t2, -framesize);
12670 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12671 tcg_temp_free(t0);
12672 tcg_temp_free(t1);
c48245f0 12673 tcg_temp_free(t2);
364d4831
NF
12674}
12675
235785e8
AM
12676static void gen_mips16_restore(DisasContext *ctx,
12677 int xsregs, int aregs,
12678 int do_ra, int do_s0, int do_s1,
12679 int framesize)
364d4831
NF
12680{
12681 int astatic;
12682 TCGv t0 = tcg_temp_new();
12683 TCGv t1 = tcg_temp_new();
c48245f0 12684 TCGv t2 = tcg_temp_new();
364d4831 12685
c48245f0
MR
12686 tcg_gen_movi_tl(t2, framesize);
12687 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 12688
5f68f5ae 12689#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
12690 tcg_gen_movi_tl(t2, -4); \
12691 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12692 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12693 gen_store_gpr(t1, reg); \
364d4831
NF
12694 } while (0)
12695
12696 if (do_ra) {
12697 DECR_AND_LOAD(31);
12698 }
12699
12700 switch (xsregs) {
12701 case 7:
12702 DECR_AND_LOAD(30);
12703 /* Fall through */
12704 case 6:
12705 DECR_AND_LOAD(23);
12706 /* Fall through */
12707 case 5:
12708 DECR_AND_LOAD(22);
12709 /* Fall through */
12710 case 4:
12711 DECR_AND_LOAD(21);
12712 /* Fall through */
12713 case 3:
12714 DECR_AND_LOAD(20);
12715 /* Fall through */
12716 case 2:
12717 DECR_AND_LOAD(19);
12718 /* Fall through */
12719 case 1:
12720 DECR_AND_LOAD(18);
12721 }
12722
12723 if (do_s1) {
12724 DECR_AND_LOAD(17);
12725 }
12726 if (do_s0) {
12727 DECR_AND_LOAD(16);
12728 }
12729
12730 switch (aregs) {
12731 case 0:
12732 case 4:
12733 case 8:
12734 case 12:
12735 case 14:
12736 astatic = 0;
12737 break;
12738 case 1:
12739 case 5:
12740 case 9:
12741 case 13:
12742 astatic = 1;
12743 break;
12744 case 2:
12745 case 6:
12746 case 10:
12747 astatic = 2;
12748 break;
12749 case 3:
12750 case 7:
12751 astatic = 3;
12752 break;
12753 case 11:
12754 astatic = 4;
12755 break;
12756 default:
3a4ef3b7 12757 gen_reserved_instruction(ctx);
364d4831
NF
12758 return;
12759 }
12760
12761 if (astatic > 0) {
12762 DECR_AND_LOAD(7);
12763 if (astatic > 1) {
12764 DECR_AND_LOAD(6);
12765 if (astatic > 2) {
12766 DECR_AND_LOAD(5);
12767 if (astatic > 3) {
12768 DECR_AND_LOAD(4);
12769 }
12770 }
12771 }
12772 }
12773#undef DECR_AND_LOAD
12774
c48245f0
MR
12775 tcg_gen_movi_tl(t2, framesize);
12776 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12777 tcg_temp_free(t0);
12778 tcg_temp_free(t1);
c48245f0 12779 tcg_temp_free(t2);
364d4831
NF
12780}
12781
235785e8
AM
12782static void gen_addiupc(DisasContext *ctx, int rx, int imm,
12783 int is_64_bit, int extended)
364d4831
NF
12784{
12785 TCGv t0;
12786
12787 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 12788 gen_reserved_instruction(ctx);
364d4831
NF
12789 return;
12790 }
12791
12792 t0 = tcg_temp_new();
12793
12794 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12795 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12796 if (!is_64_bit) {
12797 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12798 }
12799
12800 tcg_temp_free(t0);
12801}
12802
0d74a222
LA
12803static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12804 int16_t offset)
12805{
12806 TCGv_i32 t0 = tcg_const_i32(op);
12807 TCGv t1 = tcg_temp_new();
12808 gen_base_offset_addr(ctx, t1, base, offset);
12809 gen_helper_cache(cpu_env, t1, t0);
f4349ba9
PMD
12810 tcg_temp_free(t1);
12811 tcg_temp_free_i32(t0);
0d74a222
LA
12812}
12813
364d4831 12814#if defined(TARGET_MIPS64)
235785e8
AM
12815static void decode_i64_mips16(DisasContext *ctx,
12816 int ry, int funct, int16_t offset,
12817 int extended)
364d4831
NF
12818{
12819 switch (funct) {
12820 case I64_LDSP:
d9224450 12821 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12822 check_mips_64(ctx);
12823 offset = extended ? offset : offset << 3;
d75c135e 12824 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
12825 break;
12826 case I64_SDSP:
d9224450 12827 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12828 check_mips_64(ctx);
12829 offset = extended ? offset : offset << 3;
5c13fdfd 12830 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
12831 break;
12832 case I64_SDRASP:
d9224450 12833 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12834 check_mips_64(ctx);
12835 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 12836 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
12837 break;
12838 case I64_DADJSP:
d9224450 12839 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12840 check_mips_64(ctx);
12841 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 12842 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
12843 break;
12844 case I64_LDPC:
d9224450
MR
12845 check_insn(ctx, ISA_MIPS3);
12846 check_mips_64(ctx);
364d4831 12847 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 12848 gen_reserved_instruction(ctx);
364d4831
NF
12849 } else {
12850 offset = extended ? offset : offset << 3;
d75c135e 12851 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
12852 }
12853 break;
12854 case I64_DADDIU5:
d9224450 12855 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12856 check_mips_64(ctx);
12857 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 12858 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
12859 break;
12860 case I64_DADDIUPC:
d9224450 12861 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12862 check_mips_64(ctx);
12863 offset = extended ? offset : offset << 2;
12864 gen_addiupc(ctx, ry, offset, 1, extended);
12865 break;
12866 case I64_DADDIUSP:
d9224450 12867 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12868 check_mips_64(ctx);
12869 offset = extended ? offset : offset << 2;
d75c135e 12870 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
12871 break;
12872 }
12873}
12874#endif
12875
235785e8 12876static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 12877{
0ab8e33a 12878 int extend = translator_lduw(env, ctx->base.pc_next + 2);
364d4831
NF
12879 int op, rx, ry, funct, sa;
12880 int16_t imm, offset;
12881
12882 ctx->opcode = (ctx->opcode << 16) | extend;
12883 op = (ctx->opcode >> 11) & 0x1f;
12884 sa = (ctx->opcode >> 22) & 0x1f;
12885 funct = (ctx->opcode >> 8) & 0x7;
12886 rx = xlat((ctx->opcode >> 8) & 0x7);
12887 ry = xlat((ctx->opcode >> 5) & 0x7);
12888 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12889 | ((ctx->opcode >> 21) & 0x3f) << 5
12890 | (ctx->opcode & 0x1f));
12891
7480515f
AM
12892 /*
12893 * The extended opcodes cleverly reuse the opcodes from their 16-bit
12894 * counterparts.
12895 */
364d4831
NF
12896 switch (op) {
12897 case M16_OPC_ADDIUSP:
d75c135e 12898 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
12899 break;
12900 case M16_OPC_ADDIUPC:
12901 gen_addiupc(ctx, rx, imm, 0, 1);
12902 break;
12903 case M16_OPC_B:
b231c103 12904 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
12905 /* No delay slot, so just process as a normal instruction */
12906 break;
12907 case M16_OPC_BEQZ:
b231c103 12908 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
12909 /* No delay slot, so just process as a normal instruction */
12910 break;
12911 case M16_OPC_BNEQZ:
b231c103 12912 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
12913 /* No delay slot, so just process as a normal instruction */
12914 break;
12915 case M16_OPC_SHIFT:
12916 switch (ctx->opcode & 0x3) {
12917 case 0x0:
d75c135e 12918 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12919 break;
12920 case 0x1:
12921#if defined(TARGET_MIPS64)
12922 check_mips_64(ctx);
d75c135e 12923 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12924#else
3a4ef3b7 12925 gen_reserved_instruction(ctx);
364d4831
NF
12926#endif
12927 break;
12928 case 0x2:
d75c135e 12929 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12930 break;
12931 case 0x3:
d75c135e 12932 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12933 break;
12934 }
12935 break;
12936#if defined(TARGET_MIPS64)
12937 case M16_OPC_LD:
d9224450 12938 check_insn(ctx, ISA_MIPS3);
d75de749 12939 check_mips_64(ctx);
d75c135e 12940 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
12941 break;
12942#endif
12943 case M16_OPC_RRIA:
12944 imm = ctx->opcode & 0xf;
12945 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12946 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12947 imm = (int16_t) (imm << 1) >> 1;
12948 if ((ctx->opcode >> 4) & 0x1) {
12949#if defined(TARGET_MIPS64)
12950 check_mips_64(ctx);
d75c135e 12951 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12952#else
3a4ef3b7 12953 gen_reserved_instruction(ctx);
364d4831
NF
12954#endif
12955 } else {
d75c135e 12956 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12957 }
12958 break;
12959 case M16_OPC_ADDIU8:
d75c135e 12960 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12961 break;
12962 case M16_OPC_SLTI:
d75c135e 12963 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12964 break;
12965 case M16_OPC_SLTIU:
d75c135e 12966 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12967 break;
12968 case M16_OPC_I8:
12969 switch (funct) {
12970 case I8_BTEQZ:
b231c103 12971 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
12972 break;
12973 case I8_BTNEZ:
b231c103 12974 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
12975 break;
12976 case I8_SWRASP:
5c13fdfd 12977 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
12978 break;
12979 case I8_ADJSP:
d75c135e 12980 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
12981 break;
12982 case I8_SVRS:
bbd5e4a2 12983 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
12984 {
12985 int xsregs = (ctx->opcode >> 24) & 0x7;
12986 int aregs = (ctx->opcode >> 16) & 0xf;
12987 int do_ra = (ctx->opcode >> 6) & 0x1;
12988 int do_s0 = (ctx->opcode >> 5) & 0x1;
12989 int do_s1 = (ctx->opcode >> 4) & 0x1;
12990 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12991 | (ctx->opcode & 0xf)) << 3;
12992
12993 if (ctx->opcode & (1 << 7)) {
12994 gen_mips16_save(ctx, xsregs, aregs,
12995 do_ra, do_s0, do_s1,
12996 framesize);
12997 } else {
12998 gen_mips16_restore(ctx, xsregs, aregs,
12999 do_ra, do_s0, do_s1,
13000 framesize);
13001 }
13002 }
13003 break;
13004 default:
3a4ef3b7 13005 gen_reserved_instruction(ctx);
364d4831
NF
13006 break;
13007 }
13008 break;
13009 case M16_OPC_LI:
13010 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13011 break;
13012 case M16_OPC_CMPI:
13013 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13014 break;
13015#if defined(TARGET_MIPS64)
13016 case M16_OPC_SD:
d9224450
MR
13017 check_insn(ctx, ISA_MIPS3);
13018 check_mips_64(ctx);
5c13fdfd 13019 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13020 break;
13021#endif
13022 case M16_OPC_LB:
d75c135e 13023 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13024 break;
13025 case M16_OPC_LH:
d75c135e 13026 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13027 break;
13028 case M16_OPC_LWSP:
d75c135e 13029 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13030 break;
13031 case M16_OPC_LW:
d75c135e 13032 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13033 break;
13034 case M16_OPC_LBU:
d75c135e 13035 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13036 break;
13037 case M16_OPC_LHU:
d75c135e 13038 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13039 break;
13040 case M16_OPC_LWPC:
d75c135e 13041 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13042 break;
13043#if defined(TARGET_MIPS64)
13044 case M16_OPC_LWU:
d9224450
MR
13045 check_insn(ctx, ISA_MIPS3);
13046 check_mips_64(ctx);
d75c135e 13047 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13048 break;
13049#endif
13050 case M16_OPC_SB:
5c13fdfd 13051 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13052 break;
13053 case M16_OPC_SH:
5c13fdfd 13054 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13055 break;
13056 case M16_OPC_SWSP:
5c13fdfd 13057 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13058 break;
13059 case M16_OPC_SW:
5c13fdfd 13060 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13061 break;
13062#if defined(TARGET_MIPS64)
13063 case M16_OPC_I64:
d75c135e 13064 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13065 break;
13066#endif
13067 default:
3a4ef3b7 13068 gen_reserved_instruction(ctx);
364d4831
NF
13069 break;
13070 }
13071
13072 return 4;
13073}
13074
3b3c1694
LA
13075static inline bool is_uhi(int sdbbp_code)
13076{
13077#ifdef CONFIG_USER_ONLY
13078 return false;
13079#else
13080 return semihosting_enabled() && sdbbp_code == 1;
13081#endif
13082}
13083
82ba4266
AB
13084#ifdef CONFIG_USER_ONLY
13085/* The above should dead-code away any calls to this..*/
13086static inline void gen_helper_do_semihosting(void *env)
13087{
13088 g_assert_not_reached();
13089}
13090#endif
13091
235785e8 13092static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13093{
13094 int rx, ry;
13095 int sa;
13096 int op, cnvt_op, op1, offset;
13097 int funct;
13098 int n_bytes;
13099
13100 op = (ctx->opcode >> 11) & 0x1f;
13101 sa = (ctx->opcode >> 2) & 0x7;
13102 sa = sa == 0 ? 8 : sa;
13103 rx = xlat((ctx->opcode >> 8) & 0x7);
13104 cnvt_op = (ctx->opcode >> 5) & 0x7;
13105 ry = xlat((ctx->opcode >> 5) & 0x7);
13106 op1 = offset = ctx->opcode & 0x1f;
13107
13108 n_bytes = 2;
13109
13110 switch (op) {
13111 case M16_OPC_ADDIUSP:
13112 {
13113 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13114
d75c135e 13115 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13116 }
13117 break;
13118 case M16_OPC_ADDIUPC:
13119 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13120 break;
13121 case M16_OPC_B:
13122 offset = (ctx->opcode & 0x7ff) << 1;
13123 offset = (int16_t)(offset << 4) >> 4;
b231c103 13124 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13125 /* No delay slot, so just process as a normal instruction */
13126 break;
13127 case M16_OPC_JAL:
0ab8e33a 13128 offset = translator_lduw(env, ctx->base.pc_next + 2);
364d4831
NF
13129 offset = (((ctx->opcode & 0x1f) << 21)
13130 | ((ctx->opcode >> 5) & 0x1f) << 16
13131 | offset) << 2;
b231c103
YK
13132 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13133 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13134 n_bytes = 4;
364d4831
NF
13135 break;
13136 case M16_OPC_BEQZ:
b231c103
YK
13137 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13138 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13139 /* No delay slot, so just process as a normal instruction */
13140 break;
13141 case M16_OPC_BNEQZ:
b231c103
YK
13142 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13143 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13144 /* No delay slot, so just process as a normal instruction */
13145 break;
13146 case M16_OPC_SHIFT:
13147 switch (ctx->opcode & 0x3) {
13148 case 0x0:
d75c135e 13149 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13150 break;
13151 case 0x1:
13152#if defined(TARGET_MIPS64)
d9224450 13153 check_insn(ctx, ISA_MIPS3);
364d4831 13154 check_mips_64(ctx);
d75c135e 13155 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13156#else
3a4ef3b7 13157 gen_reserved_instruction(ctx);
364d4831
NF
13158#endif
13159 break;
13160 case 0x2:
d75c135e 13161 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13162 break;
13163 case 0x3:
d75c135e 13164 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13165 break;
13166 }
13167 break;
13168#if defined(TARGET_MIPS64)
13169 case M16_OPC_LD:
d9224450 13170 check_insn(ctx, ISA_MIPS3);
364d4831 13171 check_mips_64(ctx);
d75c135e 13172 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13173 break;
13174#endif
13175 case M16_OPC_RRIA:
13176 {
13177 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13178
13179 if ((ctx->opcode >> 4) & 1) {
13180#if defined(TARGET_MIPS64)
d9224450 13181 check_insn(ctx, ISA_MIPS3);
364d4831 13182 check_mips_64(ctx);
d75c135e 13183 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13184#else
3a4ef3b7 13185 gen_reserved_instruction(ctx);
364d4831
NF
13186#endif
13187 } else {
d75c135e 13188 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13189 }
13190 }
13191 break;
13192 case M16_OPC_ADDIU8:
13193 {
13194 int16_t imm = (int8_t) ctx->opcode;
13195
d75c135e 13196 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13197 }
13198 break;
13199 case M16_OPC_SLTI:
13200 {
13201 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13202 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13203 }
13204 break;
13205 case M16_OPC_SLTIU:
13206 {
13207 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13208 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13209 }
13210 break;
13211 case M16_OPC_I8:
13212 {
13213 int reg32;
13214
13215 funct = (ctx->opcode >> 8) & 0x7;
13216 switch (funct) {
13217 case I8_BTEQZ:
13218 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 13219 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13220 break;
13221 case I8_BTNEZ:
13222 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 13223 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13224 break;
13225 case I8_SWRASP:
5c13fdfd 13226 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
13227 break;
13228 case I8_ADJSP:
d75c135e 13229 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
13230 ((int8_t)ctx->opcode) << 3);
13231 break;
13232 case I8_SVRS:
bbd5e4a2 13233 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13234 {
13235 int do_ra = ctx->opcode & (1 << 6);
13236 int do_s0 = ctx->opcode & (1 << 5);
13237 int do_s1 = ctx->opcode & (1 << 4);
13238 int framesize = ctx->opcode & 0xf;
13239
13240 if (framesize == 0) {
13241 framesize = 128;
13242 } else {
13243 framesize = framesize << 3;
13244 }
13245
13246 if (ctx->opcode & (1 << 7)) {
13247 gen_mips16_save(ctx, 0, 0,
13248 do_ra, do_s0, do_s1, framesize);
13249 } else {
13250 gen_mips16_restore(ctx, 0, 0,
13251 do_ra, do_s0, do_s1, framesize);
13252 }
13253 }
13254 break;
13255 case I8_MOV32R:
13256 {
13257 int rz = xlat(ctx->opcode & 0x7);
13258
13259 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13260 ((ctx->opcode >> 5) & 0x7);
d75c135e 13261 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
13262 }
13263 break;
13264 case I8_MOVR32:
13265 reg32 = ctx->opcode & 0x1f;
d75c135e 13266 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
13267 break;
13268 default:
3a4ef3b7 13269 gen_reserved_instruction(ctx);
364d4831
NF
13270 break;
13271 }
13272 }
13273 break;
13274 case M16_OPC_LI:
13275 {
13276 int16_t imm = (uint8_t) ctx->opcode;
13277
d75c135e 13278 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
13279 }
13280 break;
13281 case M16_OPC_CMPI:
13282 {
13283 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13284 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
13285 }
13286 break;
13287#if defined(TARGET_MIPS64)
13288 case M16_OPC_SD:
d9224450 13289 check_insn(ctx, ISA_MIPS3);
364d4831 13290 check_mips_64(ctx);
5c13fdfd 13291 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
13292 break;
13293#endif
13294 case M16_OPC_LB:
d75c135e 13295 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13296 break;
13297 case M16_OPC_LH:
d75c135e 13298 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
13299 break;
13300 case M16_OPC_LWSP:
d75c135e 13301 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13302 break;
13303 case M16_OPC_LW:
d75c135e 13304 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
13305 break;
13306 case M16_OPC_LBU:
d75c135e 13307 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13308 break;
13309 case M16_OPC_LHU:
d75c135e 13310 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
13311 break;
13312 case M16_OPC_LWPC:
d75c135e 13313 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 13314 break;
235785e8 13315#if defined(TARGET_MIPS64)
364d4831 13316 case M16_OPC_LWU:
d9224450 13317 check_insn(ctx, ISA_MIPS3);
364d4831 13318 check_mips_64(ctx);
d75c135e 13319 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
13320 break;
13321#endif
13322 case M16_OPC_SB:
5c13fdfd 13323 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13324 break;
13325 case M16_OPC_SH:
5c13fdfd 13326 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
13327 break;
13328 case M16_OPC_SWSP:
5c13fdfd 13329 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13330 break;
13331 case M16_OPC_SW:
5c13fdfd 13332 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
13333 break;
13334 case M16_OPC_RRR:
13335 {
13336 int rz = xlat((ctx->opcode >> 2) & 0x7);
13337 int mips32_op;
13338
13339 switch (ctx->opcode & 0x3) {
13340 case RRR_ADDU:
13341 mips32_op = OPC_ADDU;
13342 break;
13343 case RRR_SUBU:
13344 mips32_op = OPC_SUBU;
13345 break;
13346#if defined(TARGET_MIPS64)
13347 case RRR_DADDU:
13348 mips32_op = OPC_DADDU;
d9224450 13349 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13350 check_mips_64(ctx);
13351 break;
13352 case RRR_DSUBU:
13353 mips32_op = OPC_DSUBU;
d9224450 13354 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13355 check_mips_64(ctx);
13356 break;
13357#endif
13358 default:
3a4ef3b7 13359 gen_reserved_instruction(ctx);
364d4831
NF
13360 goto done;
13361 }
13362
d75c135e 13363 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
13364 done:
13365 ;
13366 }
13367 break;
13368 case M16_OPC_RR:
13369 switch (op1) {
13370 case RR_JR:
13371 {
13372 int nd = (ctx->opcode >> 7) & 0x1;
13373 int link = (ctx->opcode >> 6) & 0x1;
13374 int ra = (ctx->opcode >> 5) & 0x1;
13375
d9224450 13376 if (nd) {
bbd5e4a2 13377 check_insn(ctx, ISA_MIPS_R1);
d9224450
MR
13378 }
13379
364d4831 13380 if (link) {
b231c103 13381 op = OPC_JALR;
364d4831
NF
13382 } else {
13383 op = OPC_JR;
13384 }
13385
b231c103
YK
13386 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13387 (nd ? 0 : 2));
364d4831
NF
13388 }
13389 break;
13390 case RR_SDBBP:
3b3c1694
LA
13391 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13392 gen_helper_do_semihosting(cpu_env);
13393 } else {
7480515f
AM
13394 /*
13395 * XXX: not clear which exception should be raised
3b3c1694
LA
13396 * when in debug mode...
13397 */
bbd5e4a2 13398 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 13399 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13400 }
364d4831
NF
13401 break;
13402 case RR_SLT:
d75c135e 13403 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
13404 break;
13405 case RR_SLTU:
d75c135e 13406 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
13407 break;
13408 case RR_BREAK:
9c708c7f 13409 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
13410 break;
13411 case RR_SLLV:
d75c135e 13412 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
13413 break;
13414 case RR_SRLV:
d75c135e 13415 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
13416 break;
13417 case RR_SRAV:
d75c135e 13418 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 13419 break;
235785e8 13420#if defined(TARGET_MIPS64)
364d4831 13421 case RR_DSRL:
d9224450 13422 check_insn(ctx, ISA_MIPS3);
364d4831 13423 check_mips_64(ctx);
d75c135e 13424 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
13425 break;
13426#endif
13427 case RR_CMP:
d75c135e 13428 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
13429 break;
13430 case RR_NEG:
d75c135e 13431 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
13432 break;
13433 case RR_AND:
d75c135e 13434 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
13435 break;
13436 case RR_OR:
d75c135e 13437 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
13438 break;
13439 case RR_XOR:
d75c135e 13440 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
13441 break;
13442 case RR_NOT:
d75c135e 13443 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
13444 break;
13445 case RR_MFHI:
26135ead 13446 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
13447 break;
13448 case RR_CNVT:
bbd5e4a2 13449 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13450 switch (cnvt_op) {
13451 case RR_RY_CNVT_ZEB:
13452 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13453 break;
13454 case RR_RY_CNVT_ZEH:
13455 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13456 break;
13457 case RR_RY_CNVT_SEB:
13458 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13459 break;
13460 case RR_RY_CNVT_SEH:
13461 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13462 break;
71375b59 13463#if defined(TARGET_MIPS64)
364d4831 13464 case RR_RY_CNVT_ZEW:
bbd5e4a2 13465 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13466 check_mips_64(ctx);
13467 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13468 break;
13469 case RR_RY_CNVT_SEW:
bbd5e4a2 13470 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13471 check_mips_64(ctx);
13472 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13473 break;
13474#endif
13475 default:
3a4ef3b7 13476 gen_reserved_instruction(ctx);
364d4831
NF
13477 break;
13478 }
13479 break;
13480 case RR_MFLO:
26135ead 13481 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 13482 break;
235785e8 13483#if defined(TARGET_MIPS64)
364d4831 13484 case RR_DSRA:
d9224450 13485 check_insn(ctx, ISA_MIPS3);
364d4831 13486 check_mips_64(ctx);
d75c135e 13487 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
13488 break;
13489 case RR_DSLLV:
d9224450 13490 check_insn(ctx, ISA_MIPS3);
364d4831 13491 check_mips_64(ctx);
d75c135e 13492 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
13493 break;
13494 case RR_DSRLV:
d9224450 13495 check_insn(ctx, ISA_MIPS3);
364d4831 13496 check_mips_64(ctx);
d75c135e 13497 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
13498 break;
13499 case RR_DSRAV:
d9224450 13500 check_insn(ctx, ISA_MIPS3);
364d4831 13501 check_mips_64(ctx);
d75c135e 13502 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
13503 break;
13504#endif
13505 case RR_MULT:
26135ead 13506 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
13507 break;
13508 case RR_MULTU:
26135ead 13509 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
13510 break;
13511 case RR_DIV:
26135ead 13512 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
13513 break;
13514 case RR_DIVU:
26135ead 13515 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 13516 break;
235785e8 13517#if defined(TARGET_MIPS64)
364d4831 13518 case RR_DMULT:
d9224450 13519 check_insn(ctx, ISA_MIPS3);
364d4831 13520 check_mips_64(ctx);
26135ead 13521 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
13522 break;
13523 case RR_DMULTU:
d9224450 13524 check_insn(ctx, ISA_MIPS3);
364d4831 13525 check_mips_64(ctx);
26135ead 13526 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
13527 break;
13528 case RR_DDIV:
d9224450 13529 check_insn(ctx, ISA_MIPS3);
364d4831 13530 check_mips_64(ctx);
26135ead 13531 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
13532 break;
13533 case RR_DDIVU:
d9224450 13534 check_insn(ctx, ISA_MIPS3);
364d4831 13535 check_mips_64(ctx);
26135ead 13536 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
13537 break;
13538#endif
13539 default:
3a4ef3b7 13540 gen_reserved_instruction(ctx);
364d4831
NF
13541 break;
13542 }
13543 break;
13544 case M16_OPC_EXTEND:
240ce26a 13545 decode_extended_mips16_opc(env, ctx);
364d4831
NF
13546 n_bytes = 4;
13547 break;
13548#if defined(TARGET_MIPS64)
13549 case M16_OPC_I64:
13550 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 13551 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
13552 break;
13553#endif
13554 default:
3a4ef3b7 13555 gen_reserved_instruction(ctx);
364d4831
NF
13556 break;
13557 }
13558
13559 return n_bytes;
13560}
13561
211da992 13562/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 13563
211da992
CWR
13564/*
13565 * microMIPS32/microMIPS64 major opcodes
13566 *
13567 * 1. MIPS Architecture for Programmers Volume II-B:
13568 * The microMIPS32 Instruction Set (Revision 3.05)
13569 *
13570 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13571 *
13572 * 2. MIPS Architecture For Programmers Volume II-A:
13573 * The MIPS64 Instruction Set (Revision 3.51)
13574 */
6af0bf9c 13575
3c824109
NF
13576enum {
13577 POOL32A = 0x00,
13578 POOL16A = 0x01,
13579 LBU16 = 0x02,
13580 MOVE16 = 0x03,
13581 ADDI32 = 0x04,
3a1f4268
YK
13582 R6_LUI = 0x04,
13583 AUI = 0x04,
3c824109
NF
13584 LBU32 = 0x05,
13585 SB32 = 0x06,
13586 LB32 = 0x07,
13587
13588 POOL32B = 0x08,
13589 POOL16B = 0x09,
13590 LHU16 = 0x0a,
13591 ANDI16 = 0x0b,
13592 ADDIU32 = 0x0c,
13593 LHU32 = 0x0d,
13594 SH32 = 0x0e,
13595 LH32 = 0x0f,
13596
13597 POOL32I = 0x10,
13598 POOL16C = 0x11,
13599 LWSP16 = 0x12,
13600 POOL16D = 0x13,
13601 ORI32 = 0x14,
13602 POOL32F = 0x15,
211da992
CWR
13603 POOL32S = 0x16, /* MIPS64 */
13604 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
13605
13606 POOL32C = 0x18,
13607 LWGP16 = 0x19,
13608 LW16 = 0x1a,
13609 POOL16E = 0x1b,
13610 XORI32 = 0x1c,
13611 JALS32 = 0x1d,
3a1f4268
YK
13612 BOVC = 0x1d,
13613 BEQC = 0x1d,
13614 BEQZALC = 0x1d,
3c824109 13615 ADDIUPC = 0x1e,
3a1f4268
YK
13616 PCREL = 0x1e,
13617 BNVC = 0x1f,
13618 BNEC = 0x1f,
13619 BNEZALC = 0x1f,
3c824109 13620
3a1f4268
YK
13621 R6_BEQZC = 0x20,
13622 JIC = 0x20,
3c824109
NF
13623 POOL16F = 0x21,
13624 SB16 = 0x22,
13625 BEQZ16 = 0x23,
3a1f4268 13626 BEQZC16 = 0x23,
3c824109
NF
13627 SLTI32 = 0x24,
13628 BEQ32 = 0x25,
3a1f4268 13629 BC = 0x25,
3c824109
NF
13630 SWC132 = 0x26,
13631 LWC132 = 0x27,
13632
3a1f4268 13633 /* 0x29 is reserved */
3c824109 13634 RES_29 = 0x29,
3a1f4268
YK
13635 R6_BNEZC = 0x28,
13636 JIALC = 0x28,
3c824109
NF
13637 SH16 = 0x2a,
13638 BNEZ16 = 0x2b,
3a1f4268 13639 BNEZC16 = 0x2b,
3c824109
NF
13640 SLTIU32 = 0x2c,
13641 BNE32 = 0x2d,
3a1f4268 13642 BALC = 0x2d,
3c824109
NF
13643 SDC132 = 0x2e,
13644 LDC132 = 0x2f,
13645
3a1f4268 13646 /* 0x31 is reserved */
3c824109 13647 RES_31 = 0x31,
3a1f4268
YK
13648 BLEZALC = 0x30,
13649 BGEZALC = 0x30,
13650 BGEUC = 0x30,
3c824109
NF
13651 SWSP16 = 0x32,
13652 B16 = 0x33,
3a1f4268 13653 BC16 = 0x33,
3c824109
NF
13654 ANDI32 = 0x34,
13655 J32 = 0x35,
3a1f4268
YK
13656 BGTZC = 0x35,
13657 BLTZC = 0x35,
13658 BLTC = 0x35,
211da992
CWR
13659 SD32 = 0x36, /* MIPS64 */
13660 LD32 = 0x37, /* MIPS64 */
3c824109 13661
3a1f4268 13662 /* 0x39 is reserved */
3c824109 13663 RES_39 = 0x39,
3a1f4268
YK
13664 BGTZALC = 0x38,
13665 BLTZALC = 0x38,
13666 BLTUC = 0x38,
3c824109
NF
13667 SW16 = 0x3a,
13668 LI16 = 0x3b,
13669 JALX32 = 0x3c,
13670 JAL32 = 0x3d,
3a1f4268
YK
13671 BLEZC = 0x3d,
13672 BGEZC = 0x3d,
13673 BGEC = 0x3d,
3c824109
NF
13674 SW32 = 0x3e,
13675 LW32 = 0x3f
13676};
13677
3a1f4268
YK
13678/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13679enum {
13680 ADDIUPC_00 = 0x00,
c38a1d52
AR
13681 ADDIUPC_01 = 0x01,
13682 ADDIUPC_02 = 0x02,
13683 ADDIUPC_03 = 0x03,
13684 ADDIUPC_04 = 0x04,
13685 ADDIUPC_05 = 0x05,
13686 ADDIUPC_06 = 0x06,
3a1f4268
YK
13687 ADDIUPC_07 = 0x07,
13688 AUIPC = 0x1e,
13689 ALUIPC = 0x1f,
13690 LWPC_08 = 0x08,
c38a1d52
AR
13691 LWPC_09 = 0x09,
13692 LWPC_0A = 0x0A,
13693 LWPC_0B = 0x0B,
13694 LWPC_0C = 0x0C,
13695 LWPC_0D = 0x0D,
13696 LWPC_0E = 0x0E,
3a1f4268
YK
13697 LWPC_0F = 0x0F,
13698};
13699
3c824109
NF
13700/* POOL32A encoding of minor opcode field */
13701
13702enum {
7480515f
AM
13703 /*
13704 * These opcodes are distinguished only by bits 9..6; those bits are
13705 * what are recorded below.
13706 */
3c824109
NF
13707 SLL32 = 0x0,
13708 SRL32 = 0x1,
13709 SRA = 0x2,
13710 ROTR = 0x3,
3a1f4268
YK
13711 SELEQZ = 0x5,
13712 SELNEZ = 0x6,
b00c7218 13713 R6_RDHWR = 0x7,
3c824109
NF
13714
13715 SLLV = 0x0,
13716 SRLV = 0x1,
13717 SRAV = 0x2,
13718 ROTRV = 0x3,
13719 ADD = 0x4,
13720 ADDU32 = 0x5,
13721 SUB = 0x6,
13722 SUBU32 = 0x7,
13723 MUL = 0x8,
13724 AND = 0x9,
13725 OR32 = 0xa,
13726 NOR = 0xb,
13727 XOR32 = 0xc,
13728 SLT = 0xd,
13729 SLTU = 0xe,
13730
13731 MOVN = 0x0,
3a1f4268 13732 R6_MUL = 0x0,
3c824109 13733 MOVZ = 0x1,
3a1f4268
YK
13734 MUH = 0x1,
13735 MULU = 0x2,
13736 MUHU = 0x3,
3c824109 13737 LWXS = 0x4,
3a1f4268
YK
13738 R6_DIV = 0x4,
13739 MOD = 0x5,
13740 R6_DIVU = 0x6,
13741 MODU = 0x7,
3c824109
NF
13742
13743 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 13744 BREAK32 = 0x07,
3c824109 13745 INS = 0x0c,
3a1f4268
YK
13746 LSA = 0x0f,
13747 ALIGN = 0x1f,
3c824109 13748 EXT = 0x2c,
bb238210
YK
13749 POOL32AXF = 0x3c,
13750 SIGRIE = 0x3f
3c824109
NF
13751};
13752
13753/* POOL32AXF encoding of minor opcode field extension */
13754
d132c79f
CWR
13755/*
13756 * 1. MIPS Architecture for Programmers Volume II-B:
13757 * The microMIPS32 Instruction Set (Revision 3.05)
13758 *
13759 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13760 *
13761 * 2. MIPS Architecture for Programmers VolumeIV-e:
13762 * The MIPS DSP Application-Specific Extension
13763 * to the microMIPS32 Architecture (Revision 2.34)
13764 *
13765 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13766 */
13767
3c824109
NF
13768enum {
13769 /* bits 11..6 */
13770 TEQ = 0x00,
13771 TGE = 0x08,
13772 TGEU = 0x10,
13773 TLT = 0x20,
13774 TLTU = 0x28,
13775 TNE = 0x30,
13776
13777 MFC0 = 0x03,
13778 MTC0 = 0x0b,
13779
d132c79f
CWR
13780 /* begin of microMIPS32 DSP */
13781
3c824109
NF
13782 /* bits 13..12 for 0x01 */
13783 MFHI_ACC = 0x0,
13784 MFLO_ACC = 0x1,
13785 MTHI_ACC = 0x2,
13786 MTLO_ACC = 0x3,
13787
13788 /* bits 13..12 for 0x2a */
13789 MADD_ACC = 0x0,
13790 MADDU_ACC = 0x1,
13791 MSUB_ACC = 0x2,
13792 MSUBU_ACC = 0x3,
13793
13794 /* bits 13..12 for 0x32 */
13795 MULT_ACC = 0x0,
6801038b 13796 MULTU_ACC = 0x1,
3c824109 13797
d132c79f
CWR
13798 /* end of microMIPS32 DSP */
13799
3c824109 13800 /* bits 15..12 for 0x2c */
3a1f4268 13801 BITSWAP = 0x0,
3c824109
NF
13802 SEB = 0x2,
13803 SEH = 0x3,
13804 CLO = 0x4,
13805 CLZ = 0x5,
13806 RDHWR = 0x6,
13807 WSBH = 0x7,
13808 MULT = 0x8,
13809 MULTU = 0x9,
13810 DIV = 0xa,
13811 DIVU = 0xb,
13812 MADD = 0xc,
13813 MADDU = 0xd,
13814 MSUB = 0xe,
13815 MSUBU = 0xf,
13816
13817 /* bits 15..12 for 0x34 */
13818 MFC2 = 0x4,
13819 MTC2 = 0x5,
13820 MFHC2 = 0x8,
13821 MTHC2 = 0x9,
13822 CFC2 = 0xc,
13823 CTC2 = 0xd,
13824
13825 /* bits 15..12 for 0x3c */
13826 JALR = 0x0,
13827 JR = 0x0, /* alias */
3a1f4268
YK
13828 JALRC = 0x0,
13829 JRC = 0x0,
3c824109 13830 JALR_HB = 0x1,
3a1f4268 13831 JALRC_HB = 0x1,
3c824109
NF
13832 JALRS = 0x4,
13833 JALRS_HB = 0x5,
13834
13835 /* bits 15..12 for 0x05 */
13836 RDPGPR = 0xe,
13837 WRPGPR = 0xf,
13838
13839 /* bits 15..12 for 0x0d */
13840 TLBP = 0x0,
13841 TLBR = 0x1,
13842 TLBWI = 0x2,
13843 TLBWR = 0x3,
e60ec063
YK
13844 TLBINV = 0x4,
13845 TLBINVF = 0x5,
3c824109
NF
13846 WAIT = 0x9,
13847 IRET = 0xd,
13848 DERET = 0xe,
13849 ERET = 0xf,
13850
13851 /* bits 15..12 for 0x15 */
13852 DMT = 0x0,
13853 DVPE = 0x1,
13854 EMT = 0x2,
13855 EVPE = 0x3,
13856
13857 /* bits 15..12 for 0x1d */
13858 DI = 0x4,
13859 EI = 0x5,
13860
13861 /* bits 15..12 for 0x2d */
13862 SYNC = 0x6,
13863 SYSCALL = 0x8,
13864 SDBBP = 0xd,
13865
13866 /* bits 15..12 for 0x35 */
13867 MFHI32 = 0x0,
13868 MFLO32 = 0x1,
13869 MTHI32 = 0x2,
13870 MTLO32 = 0x3,
13871};
13872
13873/* POOL32B encoding of minor opcode field (bits 15..12) */
13874
13875enum {
13876 LWC2 = 0x0,
13877 LWP = 0x1,
13878 LDP = 0x4,
13879 LWM32 = 0x5,
13880 CACHE = 0x6,
13881 LDM = 0x7,
13882 SWC2 = 0x8,
13883 SWP = 0x9,
13884 SDP = 0xc,
13885 SWM32 = 0xd,
13886 SDM = 0xf
13887};
13888
13889/* POOL32C encoding of minor opcode field (bits 15..12) */
13890
13891enum {
13892 LWL = 0x0,
13893 SWL = 0x8,
13894 LWR = 0x1,
13895 SWR = 0x9,
13896 PREF = 0x2,
8fffc646 13897 ST_EVA = 0xa,
3c824109
NF
13898 LL = 0x3,
13899 SC = 0xb,
13900 LDL = 0x4,
13901 SDL = 0xc,
13902 LDR = 0x5,
13903 SDR = 0xd,
8fffc646 13904 LD_EVA = 0x6,
3c824109
NF
13905 LWU = 0xe,
13906 LLD = 0x7,
13907 SCD = 0xf
13908};
13909
8fffc646
JH
13910/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13911
13912enum {
13913 LBUE = 0x0,
13914 LHUE = 0x1,
13915 LWLE = 0x2,
13916 LWRE = 0x3,
13917 LBE = 0x4,
13918 LHE = 0x5,
13919 LLE = 0x6,
13920 LWE = 0x7,
13921};
13922
13923/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13924
13925enum {
13926 SWLE = 0x0,
13927 SWRE = 0x1,
13928 PREFE = 0x2,
13929 CACHEE = 0x3,
13930 SBE = 0x4,
13931 SHE = 0x5,
13932 SCE = 0x6,
13933 SWE = 0x7,
13934};
13935
3c824109
NF
13936/* POOL32F encoding of minor opcode field (bits 5..0) */
13937
13938enum {
13939 /* These are the bit 7..6 values */
13940 ADD_FMT = 0x0,
3c824109
NF
13941
13942 SUB_FMT = 0x1,
3c824109
NF
13943
13944 MUL_FMT = 0x2,
13945
13946 DIV_FMT = 0x3,
13947
13948 /* These are the bit 8..6 values */
3a1f4268 13949 MOVN_FMT = 0x0,
3c824109
NF
13950 RSQRT2_FMT = 0x0,
13951 MOVF_FMT = 0x0,
3a1f4268
YK
13952 RINT_FMT = 0x0,
13953 SELNEZ_FMT = 0x0,
3c824109 13954
3a1f4268 13955 MOVZ_FMT = 0x1,
3c824109
NF
13956 LWXC1 = 0x1,
13957 MOVT_FMT = 0x1,
3a1f4268
YK
13958 CLASS_FMT = 0x1,
13959 SELEQZ_FMT = 0x1,
3c824109
NF
13960
13961 PLL_PS = 0x2,
13962 SWXC1 = 0x2,
3a1f4268 13963 SEL_FMT = 0x2,
3c824109
NF
13964
13965 PLU_PS = 0x3,
13966 LDXC1 = 0x3,
13967
3a1f4268 13968 MOVN_FMT_04 = 0x4,
3c824109
NF
13969 PUL_PS = 0x4,
13970 SDXC1 = 0x4,
13971 RECIP2_FMT = 0x4,
13972
3a1f4268 13973 MOVZ_FMT_05 = 0x05,
3c824109
NF
13974 PUU_PS = 0x5,
13975 LUXC1 = 0x5,
13976
13977 CVT_PS_S = 0x6,
13978 SUXC1 = 0x6,
13979 ADDR_PS = 0x6,
13980 PREFX = 0x6,
3a1f4268 13981 MADDF_FMT = 0x6,
3c824109
NF
13982
13983 MULR_PS = 0x7,
3a1f4268 13984 MSUBF_FMT = 0x7,
3c824109
NF
13985
13986 MADD_S = 0x01,
13987 MADD_D = 0x09,
13988 MADD_PS = 0x11,
13989 ALNV_PS = 0x19,
13990 MSUB_S = 0x21,
13991 MSUB_D = 0x29,
13992 MSUB_PS = 0x31,
13993
13994 NMADD_S = 0x02,
13995 NMADD_D = 0x0a,
13996 NMADD_PS = 0x12,
13997 NMSUB_S = 0x22,
13998 NMSUB_D = 0x2a,
13999 NMSUB_PS = 0x32,
14000
3a1f4268
YK
14001 MIN_FMT = 0x3,
14002 MAX_FMT = 0xb,
14003 MINA_FMT = 0x23,
14004 MAXA_FMT = 0x2b,
3c824109
NF
14005 POOL32FXF = 0x3b,
14006
14007 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14008 C_COND_FMT = 0x3c,
14009
14010 CMP_CONDN_S = 0x5,
14011 CMP_CONDN_D = 0x15
3c824109
NF
14012};
14013
14014/* POOL32Fxf encoding of minor opcode extension field */
14015
14016enum {
14017 CVT_L = 0x04,
14018 RSQRT_FMT = 0x08,
14019 FLOOR_L = 0x0c,
14020 CVT_PW_PS = 0x1c,
14021 CVT_W = 0x24,
14022 SQRT_FMT = 0x28,
14023 FLOOR_W = 0x2c,
14024 CVT_PS_PW = 0x3c,
14025 CFC1 = 0x40,
14026 RECIP_FMT = 0x48,
14027 CEIL_L = 0x4c,
14028 CTC1 = 0x60,
14029 CEIL_W = 0x6c,
14030 MFC1 = 0x80,
14031 CVT_S_PL = 0x84,
14032 TRUNC_L = 0x8c,
14033 MTC1 = 0xa0,
14034 CVT_S_PU = 0xa4,
14035 TRUNC_W = 0xac,
14036 MFHC1 = 0xc0,
14037 ROUND_L = 0xcc,
14038 MTHC1 = 0xe0,
14039 ROUND_W = 0xec,
14040
14041 MOV_FMT = 0x01,
14042 MOVF = 0x05,
14043 ABS_FMT = 0x0d,
14044 RSQRT1_FMT = 0x1d,
14045 MOVT = 0x25,
14046 NEG_FMT = 0x2d,
14047 CVT_D = 0x4d,
14048 RECIP1_FMT = 0x5d,
14049 CVT_S = 0x6d
14050};
14051
14052/* POOL32I encoding of minor opcode field (bits 25..21) */
14053
14054enum {
14055 BLTZ = 0x00,
14056 BLTZAL = 0x01,
14057 BGEZ = 0x02,
14058 BGEZAL = 0x03,
14059 BLEZ = 0x04,
14060 BNEZC = 0x05,
14061 BGTZ = 0x06,
14062 BEQZC = 0x07,
14063 TLTI = 0x08,
3a1f4268 14064 BC1EQZC = 0x08,
3c824109 14065 TGEI = 0x09,
3a1f4268 14066 BC1NEZC = 0x09,
3c824109 14067 TLTIU = 0x0a,
3a1f4268 14068 BC2EQZC = 0x0a,
3c824109 14069 TGEIU = 0x0b,
3a1f4268 14070 BC2NEZC = 0x0a,
3c824109 14071 TNEI = 0x0c,
3a1f4268 14072 R6_SYNCI = 0x0c,
3c824109
NF
14073 LUI = 0x0d,
14074 TEQI = 0x0e,
14075 SYNCI = 0x10,
14076 BLTZALS = 0x11,
14077 BGEZALS = 0x13,
14078 BC2F = 0x14,
14079 BC2T = 0x15,
14080 BPOSGE64 = 0x1a,
14081 BPOSGE32 = 0x1b,
14082 /* These overlap and are distinguished by bit16 of the instruction */
14083 BC1F = 0x1c,
14084 BC1T = 0x1d,
14085 BC1ANY2F = 0x1c,
14086 BC1ANY2T = 0x1d,
14087 BC1ANY4F = 0x1e,
14088 BC1ANY4T = 0x1f
14089};
14090
14091/* POOL16A encoding of minor opcode field */
14092
14093enum {
14094 ADDU16 = 0x0,
14095 SUBU16 = 0x1
14096};
14097
14098/* POOL16B encoding of minor opcode field */
14099
14100enum {
14101 SLL16 = 0x0,
14102 SRL16 = 0x1
14103};
14104
14105/* POOL16C encoding of minor opcode field */
14106
14107enum {
14108 NOT16 = 0x00,
14109 XOR16 = 0x04,
14110 AND16 = 0x08,
14111 OR16 = 0x0c,
14112 LWM16 = 0x10,
14113 SWM16 = 0x14,
14114 JR16 = 0x18,
14115 JRC16 = 0x1a,
14116 JALR16 = 0x1c,
14117 JALR16S = 0x1e,
14118 MFHI16 = 0x20,
14119 MFLO16 = 0x24,
14120 BREAK16 = 0x28,
14121 SDBBP16 = 0x2c,
14122 JRADDIUSP = 0x30
14123};
14124
3a1f4268
YK
14125/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14126
14127enum {
14128 R6_NOT16 = 0x00,
14129 R6_AND16 = 0x01,
14130 R6_LWM16 = 0x02,
14131 R6_JRC16 = 0x03,
14132 MOVEP = 0x04,
c38a1d52
AR
14133 MOVEP_05 = 0x05,
14134 MOVEP_06 = 0x06,
3a1f4268
YK
14135 MOVEP_07 = 0x07,
14136 R6_XOR16 = 0x08,
14137 R6_OR16 = 0x09,
14138 R6_SWM16 = 0x0a,
14139 JALRC16 = 0x0b,
14140 MOVEP_0C = 0x0c,
c38a1d52
AR
14141 MOVEP_0D = 0x0d,
14142 MOVEP_0E = 0x0e,
3a1f4268
YK
14143 MOVEP_0F = 0x0f,
14144 JRCADDIUSP = 0x13,
14145 R6_BREAK16 = 0x1b,
14146 R6_SDBBP16 = 0x3b
14147};
14148
3c824109
NF
14149/* POOL16D encoding of minor opcode field */
14150
14151enum {
14152 ADDIUS5 = 0x0,
14153 ADDIUSP = 0x1
14154};
14155
14156/* POOL16E encoding of minor opcode field */
14157
14158enum {
14159 ADDIUR2 = 0x0,
14160 ADDIUR1SP = 0x1
14161};
14162
235785e8 14163static int mmreg(int r)
3c824109
NF
14164{
14165 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14166
14167 return map[r];
14168}
14169
14170/* Used for 16-bit store instructions. */
235785e8 14171static int mmreg2(int r)
3c824109
NF
14172{
14173 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14174
14175 return map[r];
14176}
14177
14178#define uMIPS_RD(op) ((op >> 7) & 0x7)
14179#define uMIPS_RS(op) ((op >> 4) & 0x7)
14180#define uMIPS_RS2(op) uMIPS_RS(op)
14181#define uMIPS_RS1(op) ((op >> 1) & 0x7)
14182#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14183#define uMIPS_RS5(op) (op & 0x1f)
14184
14185/* Signed immediate */
14186#define SIMM(op, start, width) \
71375b59
AM
14187 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14188 << (32 - width)) \
14189 >> (32 - width))
3c824109 14190/* Zero-extended immediate */
71375b59 14191#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 14192
d75c135e 14193static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
14194{
14195 int rd = mmreg(uMIPS_RD(ctx->opcode));
14196
d75c135e 14197 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
14198}
14199
d75c135e 14200static void gen_addiur2(DisasContext *ctx)
3c824109
NF
14201{
14202 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14203 int rd = mmreg(uMIPS_RD(ctx->opcode));
14204 int rs = mmreg(uMIPS_RS(ctx->opcode));
14205
d75c135e 14206 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
14207}
14208
d75c135e 14209static void gen_addiusp(DisasContext *ctx)
3c824109
NF
14210{
14211 int encoded = ZIMM(ctx->opcode, 1, 9);
14212 int decoded;
14213
14214 if (encoded <= 1) {
14215 decoded = 256 + encoded;
14216 } else if (encoded <= 255) {
14217 decoded = encoded;
14218 } else if (encoded <= 509) {
14219 decoded = encoded - 512;
14220 } else {
14221 decoded = encoded - 768;
14222 }
14223
d75c135e 14224 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
14225}
14226
d75c135e 14227static void gen_addius5(DisasContext *ctx)
3c824109
NF
14228{
14229 int imm = SIMM(ctx->opcode, 1, 4);
14230 int rd = (ctx->opcode >> 5) & 0x1f;
14231
d75c135e 14232 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
14233}
14234
d75c135e 14235static void gen_andi16(DisasContext *ctx)
3c824109
NF
14236{
14237 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14238 31, 32, 63, 64, 255, 32768, 65535 };
14239 int rd = mmreg(uMIPS_RD(ctx->opcode));
14240 int rs = mmreg(uMIPS_RS(ctx->opcode));
14241 int encoded = ZIMM(ctx->opcode, 0, 4);
14242
d75c135e 14243 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
14244}
14245
235785e8
AM
14246static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14247 int base, int16_t offset)
3c824109
NF
14248{
14249 TCGv t0, t1;
14250 TCGv_i32 t2;
14251
14252 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3a4ef3b7 14253 gen_reserved_instruction(ctx);
3c824109
NF
14254 return;
14255 }
14256
14257 t0 = tcg_temp_new();
14258
14259 gen_base_offset_addr(ctx, t0, base, offset);
14260
14261 t1 = tcg_const_tl(reglist);
14262 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 14263
3c824109
NF
14264 save_cpu_state(ctx, 1);
14265 switch (opc) {
14266 case LWM32:
895c2d04 14267 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
14268 break;
14269 case SWM32:
895c2d04 14270 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
14271 break;
14272#ifdef TARGET_MIPS64
14273 case LDM:
895c2d04 14274 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
14275 break;
14276 case SDM:
895c2d04 14277 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 14278 break;
6af0bf9c 14279#endif
3c824109 14280 }
3c824109 14281 tcg_temp_free(t0);
33087598 14282 tcg_temp_free(t1);
3c824109
NF
14283 tcg_temp_free_i32(t2);
14284}
6af0bf9c 14285
3c824109 14286
240ce26a 14287static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 14288{
3c824109
NF
14289 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14290 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 14291
3c824109
NF
14292 switch (((ctx->opcode) >> 4) & 0x3f) {
14293 case NOT16 + 0:
14294 case NOT16 + 1:
14295 case NOT16 + 2:
14296 case NOT16 + 3:
d75c135e 14297 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
14298 break;
14299 case XOR16 + 0:
14300 case XOR16 + 1:
14301 case XOR16 + 2:
14302 case XOR16 + 3:
d75c135e 14303 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
14304 break;
14305 case AND16 + 0:
14306 case AND16 + 1:
14307 case AND16 + 2:
14308 case AND16 + 3:
d75c135e 14309 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
14310 break;
14311 case OR16 + 0:
14312 case OR16 + 1:
14313 case OR16 + 2:
14314 case OR16 + 3:
d75c135e 14315 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
14316 break;
14317 case LWM16 + 0:
14318 case LWM16 + 1:
14319 case LWM16 + 2:
14320 case LWM16 + 3:
14321 {
14322 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14323 int offset = ZIMM(ctx->opcode, 0, 4);
14324
14325 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14326 29, offset << 2);
14327 }
14328 break;
14329 case SWM16 + 0:
14330 case SWM16 + 1:
14331 case SWM16 + 2:
14332 case SWM16 + 3:
14333 {
14334 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14335 int offset = ZIMM(ctx->opcode, 0, 4);
14336
14337 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14338 29, offset << 2);
14339 }
14340 break;
14341 case JR16 + 0:
14342 case JR16 + 1:
14343 {
14344 int reg = ctx->opcode & 0x1f;
14345
b231c103 14346 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 14347 }
3c824109
NF
14348 break;
14349 case JRC16 + 0:
14350 case JRC16 + 1:
14351 {
14352 int reg = ctx->opcode & 0x1f;
b231c103 14353 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
14354 /*
14355 * Let normal delay slot handling in our caller take us
14356 * to the branch target.
14357 */
3c824109
NF
14358 }
14359 break;
14360 case JALR16 + 0:
14361 case JALR16 + 1:
b231c103
YK
14362 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14363 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14364 break;
3c824109
NF
14365 case JALR16S + 0:
14366 case JALR16S + 1:
b231c103
YK
14367 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14368 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14369 break;
14370 case MFHI16 + 0:
14371 case MFHI16 + 1:
26135ead 14372 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14373 break;
14374 case MFLO16 + 0:
14375 case MFLO16 + 1:
26135ead 14376 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14377 break;
14378 case BREAK16:
9c708c7f 14379 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
14380 break;
14381 case SDBBP16:
3b3c1694
LA
14382 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14383 gen_helper_do_semihosting(cpu_env);
14384 } else {
7480515f
AM
14385 /*
14386 * XXX: not clear which exception should be raised
3b3c1694
LA
14387 * when in debug mode...
14388 */
bbd5e4a2 14389 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 14390 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14391 }
3c824109
NF
14392 break;
14393 case JRADDIUSP + 0:
14394 case JRADDIUSP + 1:
14395 {
14396 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 14397 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 14398 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
14399 /*
14400 * Let normal delay slot handling in our caller take us
14401 * to the branch target.
14402 */
3c824109
NF
14403 }
14404 break;
14405 default:
3a4ef3b7 14406 gen_reserved_instruction(ctx);
3c824109
NF
14407 break;
14408 }
14409}
14410
ed7ce6c0
YK
14411static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14412 int enc_rs)
14413{
c27b4579 14414 int rd, re;
ed7ce6c0
YK
14415 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14416 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14417 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
c27b4579 14418
ed7ce6c0
YK
14419 rd = rd_enc[enc_dest];
14420 re = re_enc[enc_dest];
c27b4579
PMD
14421 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14422 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
ed7ce6c0
YK
14423}
14424
14425static void gen_pool16c_r6_insn(DisasContext *ctx)
14426{
14427 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14428 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14429
14430 switch (ctx->opcode & 0xf) {
14431 case R6_NOT16:
14432 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14433 break;
14434 case R6_AND16:
14435 gen_logic(ctx, OPC_AND, rt, rt, rs);
14436 break;
14437 case R6_LWM16:
14438 {
14439 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14440 int offset = extract32(ctx->opcode, 4, 4);
14441 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14442 }
14443 break;
14444 case R6_JRC16: /* JRCADDIUSP */
14445 if ((ctx->opcode >> 4) & 1) {
14446 /* JRCADDIUSP */
14447 int imm = extract32(ctx->opcode, 5, 5);
14448 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14449 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14450 } else {
14451 /* JRC16 */
e1555d7d 14452 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
14453 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14454 }
14455 break;
c38a1d52
AR
14456 case MOVEP:
14457 case MOVEP_05:
14458 case MOVEP_06:
14459 case MOVEP_07:
14460 case MOVEP_0C:
14461 case MOVEP_0D:
14462 case MOVEP_0E:
14463 case MOVEP_0F:
ed7ce6c0
YK
14464 {
14465 int enc_dest = uMIPS_RD(ctx->opcode);
14466 int enc_rt = uMIPS_RS2(ctx->opcode);
14467 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14468 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14469 }
14470 break;
14471 case R6_XOR16:
14472 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14473 break;
14474 case R6_OR16:
14475 gen_logic(ctx, OPC_OR, rt, rt, rs);
14476 break;
14477 case R6_SWM16:
14478 {
14479 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14480 int offset = extract32(ctx->opcode, 4, 4);
14481 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14482 }
14483 break;
14484 case JALRC16: /* BREAK16, SDBBP16 */
14485 switch (ctx->opcode & 0x3f) {
14486 case JALRC16:
14487 case JALRC16 + 0x20:
14488 /* JALRC16 */
14489 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14490 31, 0, 0);
14491 break;
14492 case R6_BREAK16:
14493 /* BREAK16 */
14494 generate_exception(ctx, EXCP_BREAK);
14495 break;
14496 case R6_SDBBP16:
14497 /* SDBBP16 */
060ebfef
LA
14498 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14499 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 14500 } else {
060ebfef
LA
14501 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14502 generate_exception(ctx, EXCP_RI);
14503 } else {
14504 generate_exception(ctx, EXCP_DBp);
14505 }
ed7ce6c0
YK
14506 }
14507 break;
14508 }
14509 break;
14510 default:
14511 generate_exception(ctx, EXCP_RI);
14512 break;
14513 }
14514}
14515
235785e8 14516static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
14517{
14518 TCGv t0 = tcg_temp_new();
14519 TCGv t1 = tcg_temp_new();
14520
14521 gen_load_gpr(t0, base);
14522
14523 if (index != 0) {
14524 gen_load_gpr(t1, index);
14525 tcg_gen_shli_tl(t1, t1, 2);
14526 gen_op_addr_add(ctx, t0, t1, t0);
14527 }
14528
5f68f5ae 14529 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14530 gen_store_gpr(t1, rd);
14531
14532 tcg_temp_free(t0);
14533 tcg_temp_free(t1);
14534}
14535
235785e8
AM
14536static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14537 int base, int16_t offset)
3c824109 14538{
3c824109
NF
14539 TCGv t0, t1;
14540
36c6711b 14541 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3a4ef3b7 14542 gen_reserved_instruction(ctx);
d796321b
FB
14543 return;
14544 }
14545
3c824109
NF
14546 t0 = tcg_temp_new();
14547 t1 = tcg_temp_new();
8e9ade68 14548
3c824109
NF
14549 gen_base_offset_addr(ctx, t0, base, offset);
14550
14551 switch (opc) {
14552 case LWP:
36c6711b 14553 if (rd == base) {
3a4ef3b7 14554 gen_reserved_instruction(ctx);
36c6711b
EJ
14555 return;
14556 }
5f68f5ae 14557 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14558 gen_store_gpr(t1, rd);
14559 tcg_gen_movi_tl(t1, 4);
14560 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14561 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 14562 gen_store_gpr(t1, rd + 1);
3c824109
NF
14563 break;
14564 case SWP:
3c824109 14565 gen_load_gpr(t1, rd);
5f68f5ae 14566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14567 tcg_gen_movi_tl(t1, 4);
14568 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 14569 gen_load_gpr(t1, rd + 1);
5f68f5ae 14570 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14571 break;
14572#ifdef TARGET_MIPS64
14573 case LDP:
36c6711b 14574 if (rd == base) {
3a4ef3b7 14575 gen_reserved_instruction(ctx);
36c6711b
EJ
14576 return;
14577 }
5f68f5ae 14578 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14579 gen_store_gpr(t1, rd);
14580 tcg_gen_movi_tl(t1, 8);
14581 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14582 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 14583 gen_store_gpr(t1, rd + 1);
3c824109
NF
14584 break;
14585 case SDP:
3c824109 14586 gen_load_gpr(t1, rd);
5f68f5ae 14587 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14588 tcg_gen_movi_tl(t1, 8);
14589 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 14590 gen_load_gpr(t1, rd + 1);
5f68f5ae 14591 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14592 break;
14593#endif
6af0bf9c 14594 }
3c824109
NF
14595 tcg_temp_free(t0);
14596 tcg_temp_free(t1);
14597}
618b0fe9 14598
d208ac0c
LA
14599static void gen_sync(int stype)
14600{
14601 TCGBar tcg_mo = TCG_BAR_SC;
14602
14603 switch (stype) {
14604 case 0x4: /* SYNC_WMB */
14605 tcg_mo |= TCG_MO_ST_ST;
14606 break;
14607 case 0x10: /* SYNC_MB */
14608 tcg_mo |= TCG_MO_ALL;
14609 break;
14610 case 0x11: /* SYNC_ACQUIRE */
14611 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14612 break;
14613 case 0x12: /* SYNC_RELEASE */
14614 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14615 break;
14616 case 0x13: /* SYNC_RMB */
14617 tcg_mo |= TCG_MO_LD_LD;
14618 break;
14619 default:
14620 tcg_mo |= TCG_MO_ALL;
14621 break;
14622 }
14623
14624 tcg_gen_mb(tcg_mo);
14625}
14626
235785e8 14627static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
14628{
14629 int extension = (ctx->opcode >> 6) & 0x3f;
14630 int minor = (ctx->opcode >> 12) & 0xf;
14631 uint32_t mips32_op;
14632
14633 switch (extension) {
14634 case TEQ:
14635 mips32_op = OPC_TEQ;
14636 goto do_trap;
14637 case TGE:
14638 mips32_op = OPC_TGE;
14639 goto do_trap;
14640 case TGEU:
14641 mips32_op = OPC_TGEU;
14642 goto do_trap;
14643 case TLT:
14644 mips32_op = OPC_TLT;
14645 goto do_trap;
14646 case TLTU:
14647 mips32_op = OPC_TLTU;
14648 goto do_trap;
14649 case TNE:
14650 mips32_op = OPC_TNE;
14651 do_trap:
14652 gen_trap(ctx, mips32_op, rs, rt, -1);
14653 break;
14654#ifndef CONFIG_USER_ONLY
14655 case MFC0:
14656 case MFC0 + 32:
2e15497c 14657 check_cp0_enabled(ctx);
3c824109
NF
14658 if (rt == 0) {
14659 /* Treat as NOP. */
14660 break;
14661 }
d75c135e 14662 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14663 break;
14664 case MTC0:
14665 case MTC0 + 32:
2e15497c 14666 check_cp0_enabled(ctx);
3c824109
NF
14667 {
14668 TCGv t0 = tcg_temp_new();
618b0fe9 14669
3c824109 14670 gen_load_gpr(t0, rt);
d75c135e 14671 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14672 tcg_temp_free(t0);
14673 }
14674 break;
14675#endif
a1fc6246
LA
14676 case 0x2a:
14677 switch (minor & 3) {
14678 case MADD_ACC:
14679 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14680 break;
14681 case MADDU_ACC:
14682 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14683 break;
14684 case MSUB_ACC:
14685 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14686 break;
14687 case MSUBU_ACC:
14688 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14689 break;
14690 default:
14691 goto pool32axf_invalid;
14692 }
14693 break;
14694 case 0x32:
14695 switch (minor & 3) {
14696 case MULT_ACC:
14697 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14698 break;
14699 case MULTU_ACC:
14700 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14701 break;
14702 default:
14703 goto pool32axf_invalid;
14704 }
14705 break;
3c824109
NF
14706 case 0x2c:
14707 switch (minor) {
e0332095 14708 case BITSWAP:
2e211e0a 14709 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
14710 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14711 break;
3c824109
NF
14712 case SEB:
14713 gen_bshfl(ctx, OPC_SEB, rs, rt);
14714 break;
14715 case SEH:
14716 gen_bshfl(ctx, OPC_SEH, rs, rt);
14717 break;
14718 case CLO:
14719 mips32_op = OPC_CLO;
14720 goto do_cl;
14721 case CLZ:
14722 mips32_op = OPC_CLZ;
14723 do_cl:
bbd5e4a2 14724 check_insn(ctx, ISA_MIPS_R1);
3c824109
NF
14725 gen_cl(ctx, mips32_op, rt, rs);
14726 break;
14727 case RDHWR:
2e211e0a 14728 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b00c7218 14729 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
14730 break;
14731 case WSBH:
14732 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14733 break;
14734 case MULT:
2e211e0a 14735 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14736 mips32_op = OPC_MULT;
26135ead 14737 goto do_mul;
3c824109 14738 case MULTU:
2e211e0a 14739 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14740 mips32_op = OPC_MULTU;
26135ead 14741 goto do_mul;
3c824109 14742 case DIV:
2e211e0a 14743 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14744 mips32_op = OPC_DIV;
26135ead 14745 goto do_div;
3c824109 14746 case DIVU:
2e211e0a 14747 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14748 mips32_op = OPC_DIVU;
26135ead
RS
14749 goto do_div;
14750 do_div:
bbd5e4a2 14751 check_insn(ctx, ISA_MIPS_R1);
26135ead
RS
14752 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14753 break;
3c824109 14754 case MADD:
2e211e0a 14755 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14756 mips32_op = OPC_MADD;
26135ead 14757 goto do_mul;
3c824109 14758 case MADDU:
2e211e0a 14759 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14760 mips32_op = OPC_MADDU;
26135ead 14761 goto do_mul;
3c824109 14762 case MSUB:
2e211e0a 14763 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14764 mips32_op = OPC_MSUB;
26135ead 14765 goto do_mul;
3c824109 14766 case MSUBU:
2e211e0a 14767 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14768 mips32_op = OPC_MSUBU;
26135ead 14769 do_mul:
bbd5e4a2 14770 check_insn(ctx, ISA_MIPS_R1);
a1fc6246 14771 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
14772 break;
14773 default:
14774 goto pool32axf_invalid;
14775 }
14776 break;
14777 case 0x34:
14778 switch (minor) {
14779 case MFC2:
14780 case MTC2:
14781 case MFHC2:
14782 case MTHC2:
14783 case CFC2:
14784 case CTC2:
14785 generate_exception_err(ctx, EXCP_CpU, 2);
14786 break;
14787 default:
14788 goto pool32axf_invalid;
14789 }
14790 break;
14791 case 0x3c:
14792 switch (minor) {
65935f07
YK
14793 case JALR: /* JALRC */
14794 case JALR_HB: /* JALRC_HB */
2e211e0a 14795 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
14796 /* JALRC, JALRC_HB */
14797 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14798 } else {
14799 /* JALR, JALR_HB */
14800 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14801 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14802 }
3c824109
NF
14803 break;
14804 case JALRS:
14805 case JALRS_HB:
2e211e0a 14806 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
14807 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14808 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14809 break;
14810 default:
14811 goto pool32axf_invalid;
14812 }
14813 break;
14814 case 0x05:
14815 switch (minor) {
14816 case RDPGPR:
2e15497c 14817 check_cp0_enabled(ctx);
7a47bae5 14818 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 14819 gen_load_srsgpr(rs, rt);
3c824109
NF
14820 break;
14821 case WRPGPR:
2e15497c 14822 check_cp0_enabled(ctx);
7a47bae5 14823 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 14824 gen_store_srsgpr(rs, rt);
3c824109
NF
14825 break;
14826 default:
14827 goto pool32axf_invalid;
14828 }
14829 break;
14830#ifndef CONFIG_USER_ONLY
14831 case 0x0d:
14832 switch (minor) {
14833 case TLBP:
14834 mips32_op = OPC_TLBP;
14835 goto do_cp0;
14836 case TLBR:
14837 mips32_op = OPC_TLBR;
14838 goto do_cp0;
14839 case TLBWI:
14840 mips32_op = OPC_TLBWI;
14841 goto do_cp0;
14842 case TLBWR:
14843 mips32_op = OPC_TLBWR;
14844 goto do_cp0;
e60ec063
YK
14845 case TLBINV:
14846 mips32_op = OPC_TLBINV;
14847 goto do_cp0;
14848 case TLBINVF:
14849 mips32_op = OPC_TLBINVF;
14850 goto do_cp0;
3c824109
NF
14851 case WAIT:
14852 mips32_op = OPC_WAIT;
14853 goto do_cp0;
14854 case DERET:
14855 mips32_op = OPC_DERET;
14856 goto do_cp0;
14857 case ERET:
14858 mips32_op = OPC_ERET;
14859 do_cp0:
14860 gen_cp0(env, ctx, mips32_op, rt, rs);
14861 break;
14862 default:
14863 goto pool32axf_invalid;
14864 }
14865 break;
14866 case 0x1d:
14867 switch (minor) {
14868 case DI:
2e15497c 14869 check_cp0_enabled(ctx);
3c824109
NF
14870 {
14871 TCGv t0 = tcg_temp_new();
14872
14873 save_cpu_state(ctx, 1);
895c2d04 14874 gen_helper_di(t0, cpu_env);
3c824109 14875 gen_store_gpr(t0, rs);
71375b59
AM
14876 /*
14877 * Stop translation as we may have switched the execution
14878 * mode.
14879 */
eeb3bba8 14880 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
14881 tcg_temp_free(t0);
14882 }
14883 break;
14884 case EI:
2e15497c 14885 check_cp0_enabled(ctx);
3c824109
NF
14886 {
14887 TCGv t0 = tcg_temp_new();
14888
14889 save_cpu_state(ctx, 1);
895c2d04 14890 gen_helper_ei(t0, cpu_env);
3c824109 14891 gen_store_gpr(t0, rs);
7480515f
AM
14892 /*
14893 * DISAS_STOP isn't sufficient, we need to ensure we break out
14894 * of translated code to check for pending interrupts.
14895 */
eeb3bba8
EC
14896 gen_save_pc(ctx->base.pc_next + 4);
14897 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
14898 tcg_temp_free(t0);
14899 }
14900 break;
14901 default:
14902 goto pool32axf_invalid;
14903 }
14904 break;
14905#endif
14906 case 0x2d:
14907 switch (minor) {
14908 case SYNC:
d208ac0c 14909 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
14910 break;
14911 case SYSCALL:
9c708c7f 14912 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
14913 break;
14914 case SDBBP:
3b3c1694
LA
14915 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14916 gen_helper_do_semihosting(cpu_env);
14917 } else {
bbd5e4a2 14918 check_insn(ctx, ISA_MIPS_R1);
e0332095 14919 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 14920 gen_reserved_instruction(ctx);
e0332095 14921 } else {
9c708c7f 14922 generate_exception_end(ctx, EXCP_DBp);
e0332095 14923 }
3b3c1694 14924 }
3c824109
NF
14925 break;
14926 default:
14927 goto pool32axf_invalid;
14928 }
14929 break;
a1fc6246 14930 case 0x01:
26135ead 14931 switch (minor & 3) {
a1fc6246 14932 case MFHI_ACC:
26135ead 14933 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 14934 break;
a1fc6246 14935 case MFLO_ACC:
26135ead 14936 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 14937 break;
a1fc6246 14938 case MTHI_ACC:
26135ead 14939 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 14940 break;
a1fc6246 14941 case MTLO_ACC:
26135ead 14942 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
14943 break;
14944 default:
14945 goto pool32axf_invalid;
14946 }
14947 break;
a1fc6246 14948 case 0x35:
2e211e0a 14949 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a1fc6246
LA
14950 switch (minor) {
14951 case MFHI32:
14952 gen_HILO(ctx, OPC_MFHI, 0, rs);
14953 break;
14954 case MFLO32:
14955 gen_HILO(ctx, OPC_MFLO, 0, rs);
14956 break;
14957 case MTHI32:
14958 gen_HILO(ctx, OPC_MTHI, 0, rs);
14959 break;
14960 case MTLO32:
14961 gen_HILO(ctx, OPC_MTLO, 0, rs);
14962 break;
14963 default:
14964 goto pool32axf_invalid;
14965 }
14966 break;
3c824109
NF
14967 default:
14968 pool32axf_invalid:
14969 MIPS_INVAL("pool32axf");
3a4ef3b7 14970 gen_reserved_instruction(ctx);
3c824109
NF
14971 break;
14972 }
14973}
14974
7480515f
AM
14975/*
14976 * Values for microMIPS fmt field. Variable-width, depending on which
14977 * formats the instruction supports.
14978 */
3c824109
NF
14979enum {
14980 FMT_SD_S = 0,
14981 FMT_SD_D = 1,
14982
14983 FMT_SDPS_S = 0,
14984 FMT_SDPS_D = 1,
14985 FMT_SDPS_PS = 2,
14986
14987 FMT_SWL_S = 0,
14988 FMT_SWL_W = 1,
14989 FMT_SWL_L = 2,
14990
14991 FMT_DWL_D = 0,
14992 FMT_DWL_W = 1,
14993 FMT_DWL_L = 2
14994};
14995
d75c135e 14996static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
14997{
14998 int extension = (ctx->opcode >> 6) & 0x3ff;
14999 uint32_t mips32_op;
15000
71375b59
AM
15001#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15002#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15003#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
15004
15005 switch (extension) {
15006 case FLOAT_1BIT_FMT(CFC1, 0):
15007 mips32_op = OPC_CFC1;
15008 goto do_cp1;
15009 case FLOAT_1BIT_FMT(CTC1, 0):
15010 mips32_op = OPC_CTC1;
15011 goto do_cp1;
15012 case FLOAT_1BIT_FMT(MFC1, 0):
15013 mips32_op = OPC_MFC1;
15014 goto do_cp1;
15015 case FLOAT_1BIT_FMT(MTC1, 0):
15016 mips32_op = OPC_MTC1;
15017 goto do_cp1;
15018 case FLOAT_1BIT_FMT(MFHC1, 0):
15019 mips32_op = OPC_MFHC1;
15020 goto do_cp1;
15021 case FLOAT_1BIT_FMT(MTHC1, 0):
15022 mips32_op = OPC_MTHC1;
15023 do_cp1:
15024 gen_cp1(ctx, mips32_op, rt, rs);
15025 break;
15026
15027 /* Reciprocal square root */
15028 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15029 mips32_op = OPC_RSQRT_S;
15030 goto do_unaryfp;
15031 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15032 mips32_op = OPC_RSQRT_D;
15033 goto do_unaryfp;
15034
15035 /* Square root */
15036 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15037 mips32_op = OPC_SQRT_S;
15038 goto do_unaryfp;
15039 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15040 mips32_op = OPC_SQRT_D;
15041 goto do_unaryfp;
15042
15043 /* Reciprocal */
15044 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15045 mips32_op = OPC_RECIP_S;
15046 goto do_unaryfp;
15047 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15048 mips32_op = OPC_RECIP_D;
15049 goto do_unaryfp;
15050
15051 /* Floor */
15052 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15053 mips32_op = OPC_FLOOR_L_S;
15054 goto do_unaryfp;
15055 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15056 mips32_op = OPC_FLOOR_L_D;
15057 goto do_unaryfp;
15058 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15059 mips32_op = OPC_FLOOR_W_S;
15060 goto do_unaryfp;
15061 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15062 mips32_op = OPC_FLOOR_W_D;
15063 goto do_unaryfp;
15064
15065 /* Ceiling */
15066 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15067 mips32_op = OPC_CEIL_L_S;
15068 goto do_unaryfp;
15069 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15070 mips32_op = OPC_CEIL_L_D;
15071 goto do_unaryfp;
15072 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15073 mips32_op = OPC_CEIL_W_S;
15074 goto do_unaryfp;
15075 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15076 mips32_op = OPC_CEIL_W_D;
15077 goto do_unaryfp;
15078
15079 /* Truncation */
15080 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15081 mips32_op = OPC_TRUNC_L_S;
15082 goto do_unaryfp;
15083 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15084 mips32_op = OPC_TRUNC_L_D;
15085 goto do_unaryfp;
15086 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15087 mips32_op = OPC_TRUNC_W_S;
15088 goto do_unaryfp;
15089 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15090 mips32_op = OPC_TRUNC_W_D;
15091 goto do_unaryfp;
15092
15093 /* Round */
15094 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15095 mips32_op = OPC_ROUND_L_S;
15096 goto do_unaryfp;
15097 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15098 mips32_op = OPC_ROUND_L_D;
15099 goto do_unaryfp;
15100 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15101 mips32_op = OPC_ROUND_W_S;
15102 goto do_unaryfp;
15103 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15104 mips32_op = OPC_ROUND_W_D;
15105 goto do_unaryfp;
15106
15107 /* Integer to floating-point conversion */
15108 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15109 mips32_op = OPC_CVT_L_S;
15110 goto do_unaryfp;
15111 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15112 mips32_op = OPC_CVT_L_D;
15113 goto do_unaryfp;
15114 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15115 mips32_op = OPC_CVT_W_S;
15116 goto do_unaryfp;
15117 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15118 mips32_op = OPC_CVT_W_D;
15119 goto do_unaryfp;
15120
15121 /* Paired-foo conversions */
15122 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15123 mips32_op = OPC_CVT_S_PL;
15124 goto do_unaryfp;
15125 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15126 mips32_op = OPC_CVT_S_PU;
15127 goto do_unaryfp;
15128 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15129 mips32_op = OPC_CVT_PW_PS;
15130 goto do_unaryfp;
15131 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15132 mips32_op = OPC_CVT_PS_PW;
15133 goto do_unaryfp;
15134
15135 /* Floating-point moves */
15136 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15137 mips32_op = OPC_MOV_S;
15138 goto do_unaryfp;
15139 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15140 mips32_op = OPC_MOV_D;
15141 goto do_unaryfp;
15142 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15143 mips32_op = OPC_MOV_PS;
15144 goto do_unaryfp;
15145
15146 /* Absolute value */
15147 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15148 mips32_op = OPC_ABS_S;
15149 goto do_unaryfp;
15150 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15151 mips32_op = OPC_ABS_D;
15152 goto do_unaryfp;
15153 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15154 mips32_op = OPC_ABS_PS;
15155 goto do_unaryfp;
15156
15157 /* Negation */
15158 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15159 mips32_op = OPC_NEG_S;
15160 goto do_unaryfp;
15161 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15162 mips32_op = OPC_NEG_D;
15163 goto do_unaryfp;
15164 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15165 mips32_op = OPC_NEG_PS;
15166 goto do_unaryfp;
15167
15168 /* Reciprocal square root step */
15169 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15170 mips32_op = OPC_RSQRT1_S;
15171 goto do_unaryfp;
15172 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15173 mips32_op = OPC_RSQRT1_D;
15174 goto do_unaryfp;
15175 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15176 mips32_op = OPC_RSQRT1_PS;
15177 goto do_unaryfp;
15178
15179 /* Reciprocal step */
15180 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15181 mips32_op = OPC_RECIP1_S;
15182 goto do_unaryfp;
15183 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15184 mips32_op = OPC_RECIP1_S;
15185 goto do_unaryfp;
15186 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15187 mips32_op = OPC_RECIP1_PS;
15188 goto do_unaryfp;
15189
15190 /* Conversions from double */
15191 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15192 mips32_op = OPC_CVT_D_S;
15193 goto do_unaryfp;
15194 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15195 mips32_op = OPC_CVT_D_W;
15196 goto do_unaryfp;
15197 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15198 mips32_op = OPC_CVT_D_L;
15199 goto do_unaryfp;
15200
15201 /* Conversions from single */
15202 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15203 mips32_op = OPC_CVT_S_D;
15204 goto do_unaryfp;
15205 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15206 mips32_op = OPC_CVT_S_W;
15207 goto do_unaryfp;
15208 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15209 mips32_op = OPC_CVT_S_L;
15210 do_unaryfp:
15211 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15212 break;
15213
15214 /* Conditional moves on floating-point codes */
15215 case COND_FLOAT_MOV(MOVT, 0):
15216 case COND_FLOAT_MOV(MOVT, 1):
15217 case COND_FLOAT_MOV(MOVT, 2):
15218 case COND_FLOAT_MOV(MOVT, 3):
15219 case COND_FLOAT_MOV(MOVT, 4):
15220 case COND_FLOAT_MOV(MOVT, 5):
15221 case COND_FLOAT_MOV(MOVT, 6):
15222 case COND_FLOAT_MOV(MOVT, 7):
2e211e0a 15223 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15224 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15225 break;
15226 case COND_FLOAT_MOV(MOVF, 0):
15227 case COND_FLOAT_MOV(MOVF, 1):
15228 case COND_FLOAT_MOV(MOVF, 2):
15229 case COND_FLOAT_MOV(MOVF, 3):
15230 case COND_FLOAT_MOV(MOVF, 4):
15231 case COND_FLOAT_MOV(MOVF, 5):
15232 case COND_FLOAT_MOV(MOVF, 6):
15233 case COND_FLOAT_MOV(MOVF, 7):
2e211e0a 15234 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15235 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15236 break;
15237 default:
15238 MIPS_INVAL("pool32fxf");
3a4ef3b7 15239 gen_reserved_instruction(ctx);
3c824109
NF
15240 break;
15241 }
15242}
15243
f60eeb0c 15244static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15245{
15246 int32_t offset;
15247 uint16_t insn;
15248 int rt, rs, rd, rr;
15249 int16_t imm;
8fffc646 15250 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
15251 uint32_t cond, fmt, cc;
15252
0ab8e33a 15253 insn = translator_lduw(env, ctx->base.pc_next + 2);
3c824109
NF
15254 ctx->opcode = (ctx->opcode << 16) | insn;
15255
15256 rt = (ctx->opcode >> 21) & 0x1f;
15257 rs = (ctx->opcode >> 16) & 0x1f;
15258 rd = (ctx->opcode >> 11) & 0x1f;
15259 rr = (ctx->opcode >> 6) & 0x1f;
15260 imm = (int16_t) ctx->opcode;
15261
15262 op = (ctx->opcode >> 26) & 0x3f;
15263 switch (op) {
15264 case POOL32A:
15265 minor = ctx->opcode & 0x3f;
15266 switch (minor) {
15267 case 0x00:
15268 minor = (ctx->opcode >> 6) & 0xf;
15269 switch (minor) {
15270 case SLL32:
15271 mips32_op = OPC_SLL;
15272 goto do_shifti;
15273 case SRA:
15274 mips32_op = OPC_SRA;
15275 goto do_shifti;
15276 case SRL32:
15277 mips32_op = OPC_SRL;
15278 goto do_shifti;
15279 case ROTR:
15280 mips32_op = OPC_ROTR;
15281 do_shifti:
d75c135e 15282 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 15283 break;
e0332095 15284 case SELEQZ:
2e211e0a 15285 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15286 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15287 break;
15288 case SELNEZ:
2e211e0a 15289 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15290 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15291 break;
b00c7218 15292 case R6_RDHWR:
2e211e0a 15293 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
15294 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15295 break;
3c824109
NF
15296 default:
15297 goto pool32a_invalid;
15298 }
15299 break;
15300 case 0x10:
15301 minor = (ctx->opcode >> 6) & 0xf;
15302 switch (minor) {
15303 /* Arithmetic */
15304 case ADD:
15305 mips32_op = OPC_ADD;
15306 goto do_arith;
15307 case ADDU32:
15308 mips32_op = OPC_ADDU;
15309 goto do_arith;
15310 case SUB:
15311 mips32_op = OPC_SUB;
15312 goto do_arith;
15313 case SUBU32:
15314 mips32_op = OPC_SUBU;
15315 goto do_arith;
15316 case MUL:
2e211e0a 15317 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15318 mips32_op = OPC_MUL;
15319 do_arith:
d75c135e 15320 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15321 break;
15322 /* Shifts */
15323 case SLLV:
15324 mips32_op = OPC_SLLV;
15325 goto do_shift;
15326 case SRLV:
15327 mips32_op = OPC_SRLV;
15328 goto do_shift;
15329 case SRAV:
15330 mips32_op = OPC_SRAV;
15331 goto do_shift;
15332 case ROTRV:
15333 mips32_op = OPC_ROTRV;
15334 do_shift:
d75c135e 15335 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15336 break;
15337 /* Logical operations */
15338 case AND:
15339 mips32_op = OPC_AND;
15340 goto do_logic;
15341 case OR32:
15342 mips32_op = OPC_OR;
15343 goto do_logic;
15344 case NOR:
15345 mips32_op = OPC_NOR;
15346 goto do_logic;
15347 case XOR32:
15348 mips32_op = OPC_XOR;
15349 do_logic:
d75c135e 15350 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15351 break;
15352 /* Set less than */
15353 case SLT:
15354 mips32_op = OPC_SLT;
15355 goto do_slt;
15356 case SLTU:
15357 mips32_op = OPC_SLTU;
15358 do_slt:
d75c135e 15359 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15360 break;
15361 default:
15362 goto pool32a_invalid;
15363 }
15364 break;
15365 case 0x18:
15366 minor = (ctx->opcode >> 6) & 0xf;
15367 switch (minor) {
15368 /* Conditional moves */
e0332095 15369 case MOVN: /* MUL */
2e211e0a 15370 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15371 /* MUL */
15372 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15373 } else {
15374 /* MOVN */
15375 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15376 }
15377 break;
15378 case MOVZ: /* MUH */
2e211e0a 15379 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15380 /* MUH */
15381 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15382 } else {
15383 /* MOVZ */
15384 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15385 }
15386 break;
15387 case MULU:
2e211e0a 15388 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15389 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15390 break;
15391 case MUHU:
2e211e0a 15392 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15393 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15394 break;
15395 case LWXS: /* DIV */
2e211e0a 15396 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15397 /* DIV */
15398 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15399 } else {
15400 /* LWXS */
15401 gen_ldxs(ctx, rs, rt, rd);
15402 }
15403 break;
15404 case MOD:
2e211e0a 15405 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15406 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15407 break;
15408 case R6_DIVU:
2e211e0a 15409 check_insn(ctx, ISA_MIPS_R6);
e0332095 15410 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 15411 break;
e0332095 15412 case MODU:
2e211e0a 15413 check_insn(ctx, ISA_MIPS_R6);
e0332095 15414 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
15415 break;
15416 default:
15417 goto pool32a_invalid;
15418 }
15419 break;
15420 case INS:
15421 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15422 return;
e0332095 15423 case LSA:
2e211e0a 15424 check_insn(ctx, ISA_MIPS_R6);
a685f7d0 15425 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
e0332095
YK
15426 break;
15427 case ALIGN:
2e211e0a 15428 check_insn(ctx, ISA_MIPS_R6);
821f2008 15429 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 15430 break;
3c824109
NF
15431 case EXT:
15432 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15433 return;
15434 case POOL32AXF:
240ce26a 15435 gen_pool32axf(env, ctx, rt, rs);
3c824109 15436 break;
dbd8af98 15437 case BREAK32:
9c708c7f 15438 generate_exception_end(ctx, EXCP_BREAK);
3c824109 15439 break;
bb238210 15440 case SIGRIE:
2e211e0a 15441 check_insn(ctx, ISA_MIPS_R6);
3a4ef3b7 15442 gen_reserved_instruction(ctx);
bb238210 15443 break;
3c824109
NF
15444 default:
15445 pool32a_invalid:
15446 MIPS_INVAL("pool32a");
3a4ef3b7 15447 gen_reserved_instruction(ctx);
3c824109
NF
15448 break;
15449 }
15450 break;
15451 case POOL32B:
15452 minor = (ctx->opcode >> 12) & 0xf;
15453 switch (minor) {
15454 case CACHE:
2e15497c 15455 check_cp0_enabled(ctx);
0d74a222
LA
15456 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15457 gen_cache_operation(ctx, rt, rs, imm);
15458 }
3c824109
NF
15459 break;
15460 case LWC2:
15461 case SWC2:
15462 /* COP2: Not implemented. */
15463 generate_exception_err(ctx, EXCP_CpU, 2);
15464 break;
3c824109
NF
15465#ifdef TARGET_MIPS64
15466 case LDP:
15467 case SDP:
d9224450
MR
15468 check_insn(ctx, ISA_MIPS3);
15469 check_mips_64(ctx);
3c824109 15470#endif
146dd620 15471 /* fall through */
d9224450
MR
15472 case LWP:
15473 case SWP:
3c824109
NF
15474 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15475 break;
3c824109
NF
15476#ifdef TARGET_MIPS64
15477 case LDM:
15478 case SDM:
d9224450
MR
15479 check_insn(ctx, ISA_MIPS3);
15480 check_mips_64(ctx);
3c824109 15481#endif
146dd620 15482 /* fall through */
d9224450
MR
15483 case LWM32:
15484 case SWM32:
3c824109
NF
15485 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15486 break;
15487 default:
15488 MIPS_INVAL("pool32b");
3a4ef3b7 15489 gen_reserved_instruction(ctx);
3c824109
NF
15490 break;
15491 }
15492 break;
15493 case POOL32F:
5ab5c041 15494 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
15495 minor = ctx->opcode & 0x3f;
15496 check_cp1_enabled(ctx);
15497 switch (minor) {
15498 case ALNV_PS:
2e211e0a 15499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15500 mips32_op = OPC_ALNV_PS;
15501 goto do_madd;
15502 case MADD_S:
2e211e0a 15503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15504 mips32_op = OPC_MADD_S;
15505 goto do_madd;
15506 case MADD_D:
2e211e0a 15507 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15508 mips32_op = OPC_MADD_D;
15509 goto do_madd;
15510 case MADD_PS:
2e211e0a 15511 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15512 mips32_op = OPC_MADD_PS;
15513 goto do_madd;
15514 case MSUB_S:
2e211e0a 15515 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15516 mips32_op = OPC_MSUB_S;
15517 goto do_madd;
15518 case MSUB_D:
2e211e0a 15519 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15520 mips32_op = OPC_MSUB_D;
15521 goto do_madd;
15522 case MSUB_PS:
2e211e0a 15523 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15524 mips32_op = OPC_MSUB_PS;
15525 goto do_madd;
15526 case NMADD_S:
2e211e0a 15527 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15528 mips32_op = OPC_NMADD_S;
15529 goto do_madd;
15530 case NMADD_D:
2e211e0a 15531 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15532 mips32_op = OPC_NMADD_D;
15533 goto do_madd;
15534 case NMADD_PS:
2e211e0a 15535 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15536 mips32_op = OPC_NMADD_PS;
15537 goto do_madd;
15538 case NMSUB_S:
2e211e0a 15539 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15540 mips32_op = OPC_NMSUB_S;
15541 goto do_madd;
15542 case NMSUB_D:
2e211e0a 15543 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15544 mips32_op = OPC_NMSUB_D;
15545 goto do_madd;
15546 case NMSUB_PS:
2e211e0a 15547 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15548 mips32_op = OPC_NMSUB_PS;
15549 do_madd:
15550 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15551 break;
15552 case CABS_COND_FMT:
2e211e0a 15553 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15554 cond = (ctx->opcode >> 6) & 0xf;
15555 cc = (ctx->opcode >> 13) & 0x7;
15556 fmt = (ctx->opcode >> 10) & 0x3;
15557 switch (fmt) {
15558 case 0x0:
15559 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15560 break;
15561 case 0x1:
15562 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15563 break;
15564 case 0x2:
15565 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15566 break;
15567 default:
15568 goto pool32f_invalid;
15569 }
15570 break;
15571 case C_COND_FMT:
2e211e0a 15572 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15573 cond = (ctx->opcode >> 6) & 0xf;
15574 cc = (ctx->opcode >> 13) & 0x7;
15575 fmt = (ctx->opcode >> 10) & 0x3;
15576 switch (fmt) {
15577 case 0x0:
15578 gen_cmp_s(ctx, cond, rt, rs, cc);
15579 break;
15580 case 0x1:
15581 gen_cmp_d(ctx, cond, rt, rs, cc);
15582 break;
15583 case 0x2:
15584 gen_cmp_ps(ctx, cond, rt, rs, cc);
15585 break;
15586 default:
15587 goto pool32f_invalid;
15588 }
15589 break;
2a24a7ba 15590 case CMP_CONDN_S:
2e211e0a 15591 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15592 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15593 break;
15594 case CMP_CONDN_D:
2e211e0a 15595 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15596 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15597 break;
3c824109 15598 case POOL32FXF:
d75c135e 15599 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
15600 break;
15601 case 0x00:
15602 /* PLL foo */
15603 switch ((ctx->opcode >> 6) & 0x7) {
15604 case PLL_PS:
15605 mips32_op = OPC_PLL_PS;
15606 goto do_ps;
15607 case PLU_PS:
15608 mips32_op = OPC_PLU_PS;
15609 goto do_ps;
15610 case PUL_PS:
15611 mips32_op = OPC_PUL_PS;
15612 goto do_ps;
15613 case PUU_PS:
15614 mips32_op = OPC_PUU_PS;
15615 goto do_ps;
15616 case CVT_PS_S:
2e211e0a 15617 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15618 mips32_op = OPC_CVT_PS_S;
15619 do_ps:
15620 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15621 break;
15622 default:
15623 goto pool32f_invalid;
15624 }
15625 break;
2a24a7ba 15626 case MIN_FMT:
2e211e0a 15627 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15628 switch ((ctx->opcode >> 9) & 0x3) {
15629 case FMT_SDPS_S:
15630 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15631 break;
15632 case FMT_SDPS_D:
15633 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15634 break;
15635 default:
15636 goto pool32f_invalid;
15637 }
15638 break;
3c824109
NF
15639 case 0x08:
15640 /* [LS][WDU]XC1 */
15641 switch ((ctx->opcode >> 6) & 0x7) {
15642 case LWXC1:
2e211e0a 15643 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15644 mips32_op = OPC_LWXC1;
15645 goto do_ldst_cp1;
15646 case SWXC1:
2e211e0a 15647 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15648 mips32_op = OPC_SWXC1;
15649 goto do_ldst_cp1;
15650 case LDXC1:
2e211e0a 15651 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15652 mips32_op = OPC_LDXC1;
15653 goto do_ldst_cp1;
15654 case SDXC1:
2e211e0a 15655 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15656 mips32_op = OPC_SDXC1;
15657 goto do_ldst_cp1;
15658 case LUXC1:
2e211e0a 15659 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15660 mips32_op = OPC_LUXC1;
15661 goto do_ldst_cp1;
15662 case SUXC1:
2e211e0a 15663 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15664 mips32_op = OPC_SUXC1;
15665 do_ldst_cp1:
15666 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15667 break;
15668 default:
15669 goto pool32f_invalid;
15670 }
15671 break;
2a24a7ba 15672 case MAX_FMT:
2e211e0a 15673 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15674 switch ((ctx->opcode >> 9) & 0x3) {
15675 case FMT_SDPS_S:
15676 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15677 break;
15678 case FMT_SDPS_D:
15679 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15680 break;
15681 default:
15682 goto pool32f_invalid;
15683 }
15684 break;
3c824109
NF
15685 case 0x18:
15686 /* 3D insns */
2e211e0a 15687 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15688 fmt = (ctx->opcode >> 9) & 0x3;
15689 switch ((ctx->opcode >> 6) & 0x7) {
15690 case RSQRT2_FMT:
15691 switch (fmt) {
15692 case FMT_SDPS_S:
15693 mips32_op = OPC_RSQRT2_S;
15694 goto do_3d;
15695 case FMT_SDPS_D:
15696 mips32_op = OPC_RSQRT2_D;
15697 goto do_3d;
15698 case FMT_SDPS_PS:
15699 mips32_op = OPC_RSQRT2_PS;
15700 goto do_3d;
15701 default:
15702 goto pool32f_invalid;
15703 }
15704 break;
15705 case RECIP2_FMT:
15706 switch (fmt) {
15707 case FMT_SDPS_S:
15708 mips32_op = OPC_RECIP2_S;
15709 goto do_3d;
15710 case FMT_SDPS_D:
15711 mips32_op = OPC_RECIP2_D;
15712 goto do_3d;
15713 case FMT_SDPS_PS:
15714 mips32_op = OPC_RECIP2_PS;
15715 goto do_3d;
15716 default:
15717 goto pool32f_invalid;
15718 }
15719 break;
15720 case ADDR_PS:
15721 mips32_op = OPC_ADDR_PS;
15722 goto do_3d;
15723 case MULR_PS:
15724 mips32_op = OPC_MULR_PS;
15725 do_3d:
15726 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15727 break;
15728 default:
15729 goto pool32f_invalid;
15730 }
15731 break;
15732 case 0x20:
2a24a7ba 15733 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
15734 cc = (ctx->opcode >> 13) & 0x7;
15735 fmt = (ctx->opcode >> 9) & 0x3;
15736 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba 15737 case MOVF_FMT: /* RINT_FMT */
2e211e0a 15738 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
15739 /* RINT_FMT */
15740 switch (fmt) {
15741 case FMT_SDPS_S:
15742 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15743 break;
15744 case FMT_SDPS_D:
15745 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15746 break;
15747 default:
15748 goto pool32f_invalid;
15749 }
15750 } else {
15751 /* MOVF_FMT */
15752 switch (fmt) {
15753 case FMT_SDPS_S:
15754 gen_movcf_s(ctx, rs, rt, cc, 0);
15755 break;
15756 case FMT_SDPS_D:
15757 gen_movcf_d(ctx, rs, rt, cc, 0);
15758 break;
15759 case FMT_SDPS_PS:
15760 check_ps(ctx);
15761 gen_movcf_ps(ctx, rs, rt, cc, 0);
15762 break;
15763 default:
15764 goto pool32f_invalid;
15765 }
3c824109
NF
15766 }
15767 break;
2a24a7ba 15768 case MOVT_FMT: /* CLASS_FMT */
2e211e0a 15769 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
15770 /* CLASS_FMT */
15771 switch (fmt) {
15772 case FMT_SDPS_S:
15773 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15774 break;
15775 case FMT_SDPS_D:
15776 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15777 break;
15778 default:
15779 goto pool32f_invalid;
15780 }
15781 } else {
15782 /* MOVT_FMT */
15783 switch (fmt) {
15784 case FMT_SDPS_S:
15785 gen_movcf_s(ctx, rs, rt, cc, 1);
15786 break;
15787 case FMT_SDPS_D:
15788 gen_movcf_d(ctx, rs, rt, cc, 1);
15789 break;
15790 case FMT_SDPS_PS:
15791 check_ps(ctx);
15792 gen_movcf_ps(ctx, rs, rt, cc, 1);
15793 break;
15794 default:
15795 goto pool32f_invalid;
15796 }
3c824109
NF
15797 }
15798 break;
15799 case PREFX:
2e211e0a 15800 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15801 break;
15802 default:
15803 goto pool32f_invalid;
15804 }
15805 break;
15806#define FINSN_3ARG_SDPS(prfx) \
15807 switch ((ctx->opcode >> 8) & 0x3) { \
15808 case FMT_SDPS_S: \
15809 mips32_op = OPC_##prfx##_S; \
15810 goto do_fpop; \
15811 case FMT_SDPS_D: \
15812 mips32_op = OPC_##prfx##_D; \
15813 goto do_fpop; \
15814 case FMT_SDPS_PS: \
e29c9628 15815 check_ps(ctx); \
3c824109
NF
15816 mips32_op = OPC_##prfx##_PS; \
15817 goto do_fpop; \
15818 default: \
15819 goto pool32f_invalid; \
15820 }
2a24a7ba 15821 case MINA_FMT:
2e211e0a 15822 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15823 switch ((ctx->opcode >> 9) & 0x3) {
15824 case FMT_SDPS_S:
15825 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15826 break;
15827 case FMT_SDPS_D:
15828 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15829 break;
15830 default:
15831 goto pool32f_invalid;
15832 }
15833 break;
15834 case MAXA_FMT:
2e211e0a 15835 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15836 switch ((ctx->opcode >> 9) & 0x3) {
15837 case FMT_SDPS_S:
15838 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15839 break;
15840 case FMT_SDPS_D:
15841 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15842 break;
15843 default:
15844 goto pool32f_invalid;
15845 }
15846 break;
3c824109
NF
15847 case 0x30:
15848 /* regular FP ops */
15849 switch ((ctx->opcode >> 6) & 0x3) {
15850 case ADD_FMT:
15851 FINSN_3ARG_SDPS(ADD);
15852 break;
15853 case SUB_FMT:
15854 FINSN_3ARG_SDPS(SUB);
15855 break;
15856 case MUL_FMT:
15857 FINSN_3ARG_SDPS(MUL);
15858 break;
15859 case DIV_FMT:
15860 fmt = (ctx->opcode >> 8) & 0x3;
15861 if (fmt == 1) {
15862 mips32_op = OPC_DIV_D;
15863 } else if (fmt == 0) {
15864 mips32_op = OPC_DIV_S;
15865 } else {
15866 goto pool32f_invalid;
15867 }
15868 goto do_fpop;
15869 default:
15870 goto pool32f_invalid;
15871 }
15872 break;
15873 case 0x38:
15874 /* cmovs */
2a24a7ba 15875 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 15876 case MOVN_FMT: /* SELEQZ_FMT */
2e211e0a 15877 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 15878 /* SELEQZ_FMT */
2a24a7ba
YK
15879 switch ((ctx->opcode >> 9) & 0x3) {
15880 case FMT_SDPS_S:
fdac60cd 15881 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
15882 break;
15883 case FMT_SDPS_D:
fdac60cd 15884 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
15885 break;
15886 default:
15887 goto pool32f_invalid;
15888 }
15889 } else {
15890 /* MOVN_FMT */
15891 FINSN_3ARG_SDPS(MOVN);
15892 }
15893 break;
15894 case MOVN_FMT_04:
2e211e0a 15895 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15896 FINSN_3ARG_SDPS(MOVN);
15897 break;
fdac60cd 15898 case MOVZ_FMT: /* SELNEZ_FMT */
2e211e0a 15899 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 15900 /* SELNEZ_FMT */
2a24a7ba
YK
15901 switch ((ctx->opcode >> 9) & 0x3) {
15902 case FMT_SDPS_S:
fdac60cd 15903 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
15904 break;
15905 case FMT_SDPS_D:
fdac60cd 15906 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
15907 break;
15908 default:
15909 goto pool32f_invalid;
15910 }
15911 } else {
15912 /* MOVZ_FMT */
15913 FINSN_3ARG_SDPS(MOVZ);
15914 }
15915 break;
15916 case MOVZ_FMT_05:
2e211e0a 15917 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15918 FINSN_3ARG_SDPS(MOVZ);
15919 break;
2a24a7ba 15920 case SEL_FMT:
2e211e0a 15921 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15922 switch ((ctx->opcode >> 9) & 0x3) {
15923 case FMT_SDPS_S:
15924 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15925 break;
15926 case FMT_SDPS_D:
15927 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15928 break;
15929 default:
15930 goto pool32f_invalid;
15931 }
15932 break;
15933 case MADDF_FMT:
2e211e0a 15934 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15935 switch ((ctx->opcode >> 9) & 0x3) {
15936 case FMT_SDPS_S:
15937 mips32_op = OPC_MADDF_S;
15938 goto do_fpop;
15939 case FMT_SDPS_D:
15940 mips32_op = OPC_MADDF_D;
15941 goto do_fpop;
15942 default:
15943 goto pool32f_invalid;
15944 }
15945 break;
15946 case MSUBF_FMT:
2e211e0a 15947 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15948 switch ((ctx->opcode >> 9) & 0x3) {
15949 case FMT_SDPS_S:
15950 mips32_op = OPC_MSUBF_S;
15951 goto do_fpop;
15952 case FMT_SDPS_D:
15953 mips32_op = OPC_MSUBF_D;
15954 goto do_fpop;
15955 default:
15956 goto pool32f_invalid;
15957 }
15958 break;
3c824109
NF
15959 default:
15960 goto pool32f_invalid;
15961 }
15962 break;
15963 do_fpop:
15964 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15965 break;
15966 default:
15967 pool32f_invalid:
15968 MIPS_INVAL("pool32f");
3a4ef3b7 15969 gen_reserved_instruction(ctx);
3c824109
NF
15970 break;
15971 }
15972 } else {
15973 generate_exception_err(ctx, EXCP_CpU, 1);
15974 }
15975 break;
15976 case POOL32I:
15977 minor = (ctx->opcode >> 21) & 0x1f;
15978 switch (minor) {
15979 case BLTZ:
2e211e0a 15980 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15981 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15982 break;
3c824109 15983 case BLTZAL:
2e211e0a 15984 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15985 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15986 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15987 break;
3c824109 15988 case BLTZALS:
2e211e0a 15989 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15990 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15991 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15992 break;
3c824109 15993 case BGEZ:
2e211e0a 15994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15995 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15996 break;
3c824109 15997 case BGEZAL:
2e211e0a 15998 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15999 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16000 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16001 break;
3c824109 16002 case BGEZALS:
2e211e0a 16003 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
16004 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16005 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16006 break;
3c824109 16007 case BLEZ:
2e211e0a 16008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
16009 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16010 break;
3c824109 16011 case BGTZ:
2e211e0a 16012 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103 16013 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16014 break;
16015
16016 /* Traps */
65935f07 16017 case TLTI: /* BC1EQZC */
2e211e0a 16018 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16019 /* BC1EQZC */
16020 check_cp1_enabled(ctx);
16021 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16022 } else {
16023 /* TLTI */
16024 mips32_op = OPC_TLTI;
16025 goto do_trapi;
16026 }
16027 break;
16028 case TGEI: /* BC1NEZC */
2e211e0a 16029 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16030 /* BC1NEZC */
16031 check_cp1_enabled(ctx);
16032 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16033 } else {
16034 /* TGEI */
16035 mips32_op = OPC_TGEI;
16036 goto do_trapi;
16037 }
16038 break;
3c824109 16039 case TLTIU:
2e211e0a 16040 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16041 mips32_op = OPC_TLTIU;
16042 goto do_trapi;
16043 case TGEIU:
2e211e0a 16044 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16045 mips32_op = OPC_TGEIU;
16046 goto do_trapi;
3b4a5489 16047 case TNEI: /* SYNCI */
2e211e0a 16048 if (ctx->insn_flags & ISA_MIPS_R6) {
3b4a5489 16049 /* SYNCI */
7480515f
AM
16050 /*
16051 * Break the TB to be able to sync copied instructions
16052 * immediately.
16053 */
eeb3bba8 16054 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16055 } else {
16056 /* TNEI */
16057 mips32_op = OPC_TNEI;
16058 goto do_trapi;
16059 }
16060 break;
3c824109 16061 case TEQI:
2e211e0a 16062 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16063 mips32_op = OPC_TEQI;
16064 do_trapi:
16065 gen_trap(ctx, mips32_op, rs, -1, imm);
16066 break;
16067
16068 case BNEZC:
16069 case BEQZC:
2e211e0a 16070 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16071 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16072 4, rs, 0, imm << 1, 0);
7480515f
AM
16073 /*
16074 * Compact branches don't have a delay slot, so just let
16075 * the normal delay slot handling take us to the branch
16076 * target.
16077 */
3c824109
NF
16078 break;
16079 case LUI:
2e211e0a 16080 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5e88759a 16081 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16082 break;
16083 case SYNCI:
2e211e0a 16084 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7480515f
AM
16085 /*
16086 * Break the TB to be able to sync copied instructions
16087 * immediately.
16088 */
eeb3bba8 16089 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16090 break;
16091 case BC2F:
16092 case BC2T:
2e211e0a 16093 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16094 /* COP2: Not implemented. */
16095 generate_exception_err(ctx, EXCP_CpU, 2);
16096 break;
16097 case BC1F:
2e211e0a 16098 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16099 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16100 goto do_cp1branch;
16101 case BC1T:
2e211e0a 16102 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16103 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16104 goto do_cp1branch;
16105 case BC1ANY4F:
2e211e0a 16106 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16107 mips32_op = OPC_BC1FANY4;
16108 goto do_cp1mips3d;
16109 case BC1ANY4T:
2e211e0a 16110 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16111 mips32_op = OPC_BC1TANY4;
16112 do_cp1mips3d:
16113 check_cop1x(ctx);
d75c135e 16114 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16115 /* Fall through */
16116 do_cp1branch:
272f458d
MR
16117 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16118 check_cp1_enabled(ctx);
16119 gen_compute_branch1(ctx, mips32_op,
16120 (ctx->opcode >> 18) & 0x7, imm << 1);
16121 } else {
16122 generate_exception_err(ctx, EXCP_CpU, 1);
16123 }
3c824109
NF
16124 break;
16125 case BPOSGE64:
16126 case BPOSGE32:
16127 /* MIPS DSP: not implemented */
16128 /* Fall through */
16129 default:
16130 MIPS_INVAL("pool32i");
3a4ef3b7 16131 gen_reserved_instruction(ctx);
3c824109
NF
16132 break;
16133 }
16134 break;
16135 case POOL32C:
16136 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489 16137 offset = sextract32(ctx->opcode, 0,
2e211e0a 16138 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
3c824109
NF
16139 switch (minor) {
16140 case LWL:
2e211e0a 16141 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16142 mips32_op = OPC_LWL;
5c13fdfd 16143 goto do_ld_lr;
3c824109 16144 case SWL:
2e211e0a 16145 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16146 mips32_op = OPC_SWL;
5c13fdfd 16147 goto do_st_lr;
3c824109 16148 case LWR:
2e211e0a 16149 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16150 mips32_op = OPC_LWR;
5c13fdfd 16151 goto do_ld_lr;
3c824109 16152 case SWR:
2e211e0a 16153 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16154 mips32_op = OPC_SWR;
5c13fdfd 16155 goto do_st_lr;
3c824109
NF
16156#if defined(TARGET_MIPS64)
16157 case LDL:
d9224450
MR
16158 check_insn(ctx, ISA_MIPS3);
16159 check_mips_64(ctx);
2e211e0a 16160 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16161 mips32_op = OPC_LDL;
5c13fdfd 16162 goto do_ld_lr;
3c824109 16163 case SDL:
d9224450
MR
16164 check_insn(ctx, ISA_MIPS3);
16165 check_mips_64(ctx);
2e211e0a 16166 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16167 mips32_op = OPC_SDL;
5c13fdfd 16168 goto do_st_lr;
3c824109 16169 case LDR:
d9224450
MR
16170 check_insn(ctx, ISA_MIPS3);
16171 check_mips_64(ctx);
2e211e0a 16172 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16173 mips32_op = OPC_LDR;
5c13fdfd 16174 goto do_ld_lr;
3c824109 16175 case SDR:
d9224450
MR
16176 check_insn(ctx, ISA_MIPS3);
16177 check_mips_64(ctx);
2e211e0a 16178 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16179 mips32_op = OPC_SDR;
5c13fdfd 16180 goto do_st_lr;
3c824109 16181 case LWU:
d9224450
MR
16182 check_insn(ctx, ISA_MIPS3);
16183 check_mips_64(ctx);
3c824109 16184 mips32_op = OPC_LWU;
5c13fdfd 16185 goto do_ld_lr;
3c824109 16186 case LLD:
d9224450
MR
16187 check_insn(ctx, ISA_MIPS3);
16188 check_mips_64(ctx);
3c824109 16189 mips32_op = OPC_LLD;
5c13fdfd 16190 goto do_ld_lr;
3c824109
NF
16191#endif
16192 case LL:
16193 mips32_op = OPC_LL;
5c13fdfd
AJ
16194 goto do_ld_lr;
16195 do_ld_lr:
3b4a5489 16196 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
16197 break;
16198 do_st_lr:
8fffc646 16199 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
16200 break;
16201 case SC:
33a07fa2 16202 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
16203 break;
16204#if defined(TARGET_MIPS64)
16205 case SCD:
d9224450
MR
16206 check_insn(ctx, ISA_MIPS3);
16207 check_mips_64(ctx);
33a07fa2 16208 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
16209 break;
16210#endif
8fffc646
JH
16211 case LD_EVA:
16212 if (!ctx->eva) {
16213 MIPS_INVAL("pool32c ld-eva");
3a4ef3b7 16214 gen_reserved_instruction(ctx);
8fffc646
JH
16215 break;
16216 }
16217 check_cp0_enabled(ctx);
16218
16219 minor2 = (ctx->opcode >> 9) & 0x7;
16220 offset = sextract32(ctx->opcode, 0, 9);
16221 switch (minor2) {
16222 case LBUE:
16223 mips32_op = OPC_LBUE;
16224 goto do_ld_lr;
16225 case LHUE:
16226 mips32_op = OPC_LHUE;
16227 goto do_ld_lr;
16228 case LWLE:
2e211e0a 16229 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16230 mips32_op = OPC_LWLE;
16231 goto do_ld_lr;
16232 case LWRE:
2e211e0a 16233 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16234 mips32_op = OPC_LWRE;
16235 goto do_ld_lr;
16236 case LBE:
16237 mips32_op = OPC_LBE;
16238 goto do_ld_lr;
16239 case LHE:
16240 mips32_op = OPC_LHE;
16241 goto do_ld_lr;
16242 case LLE:
16243 mips32_op = OPC_LLE;
16244 goto do_ld_lr;
16245 case LWE:
16246 mips32_op = OPC_LWE;
16247 goto do_ld_lr;
16248 };
16249 break;
16250 case ST_EVA:
16251 if (!ctx->eva) {
16252 MIPS_INVAL("pool32c st-eva");
3a4ef3b7 16253 gen_reserved_instruction(ctx);
8fffc646
JH
16254 break;
16255 }
16256 check_cp0_enabled(ctx);
16257
16258 minor2 = (ctx->opcode >> 9) & 0x7;
16259 offset = sextract32(ctx->opcode, 0, 9);
16260 switch (minor2) {
16261 case SWLE:
2e211e0a 16262 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16263 mips32_op = OPC_SWLE;
16264 goto do_st_lr;
16265 case SWRE:
2e211e0a 16266 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16267 mips32_op = OPC_SWRE;
16268 goto do_st_lr;
16269 case PREFE:
16270 /* Treat as no-op */
2e211e0a 16271 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
8fffc646
JH
16272 /* hint codes 24-31 are reserved and signal RI */
16273 generate_exception(ctx, EXCP_RI);
16274 }
16275 break;
16276 case CACHEE:
16277 /* Treat as no-op */
16278 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16279 gen_cache_operation(ctx, rt, rs, offset);
16280 }
16281 break;
16282 case SBE:
16283 mips32_op = OPC_SBE;
16284 goto do_st_lr;
16285 case SHE:
16286 mips32_op = OPC_SHE;
16287 goto do_st_lr;
16288 case SCE:
33a07fa2 16289 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
16290 break;
16291 case SWE:
16292 mips32_op = OPC_SWE;
16293 goto do_st_lr;
16294 };
16295 break;
3c824109
NF
16296 case PREF:
16297 /* Treat as no-op */
2e211e0a 16298 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
3b4a5489
YK
16299 /* hint codes 24-31 are reserved and signal RI */
16300 generate_exception(ctx, EXCP_RI);
16301 }
3c824109
NF
16302 break;
16303 default:
16304 MIPS_INVAL("pool32c");
3a4ef3b7 16305 gen_reserved_instruction(ctx);
3c824109
NF
16306 break;
16307 }
16308 break;
ab39ee45 16309 case ADDI32: /* AUI, LUI */
2e211e0a 16310 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
16311 /* AUI, LUI */
16312 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16313 } else {
16314 /* ADDI32 */
16315 mips32_op = OPC_ADDI;
16316 goto do_addi;
16317 }
16318 break;
3c824109
NF
16319 case ADDIU32:
16320 mips32_op = OPC_ADDIU;
16321 do_addi:
d75c135e 16322 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16323 break;
16324
16325 /* Logical operations */
16326 case ORI32:
16327 mips32_op = OPC_ORI;
16328 goto do_logici;
16329 case XORI32:
16330 mips32_op = OPC_XORI;
16331 goto do_logici;
16332 case ANDI32:
16333 mips32_op = OPC_ANDI;
16334 do_logici:
d75c135e 16335 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16336 break;
16337
16338 /* Set less than immediate */
16339 case SLTI32:
16340 mips32_op = OPC_SLTI;
16341 goto do_slti;
16342 case SLTIU32:
16343 mips32_op = OPC_SLTIU;
16344 do_slti:
d75c135e 16345 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16346 break;
16347 case JALX32:
2e211e0a 16348 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16349 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
16350 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16351 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 16352 break;
65935f07 16353 case JALS32: /* BOVC, BEQC, BEQZALC */
2e211e0a 16354 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16355 if (rs >= rt) {
16356 /* BOVC */
16357 mips32_op = OPC_BOVC;
16358 } else if (rs < rt && rs == 0) {
16359 /* BEQZALC */
16360 mips32_op = OPC_BEQZALC;
16361 } else {
16362 /* BEQC */
16363 mips32_op = OPC_BEQC;
16364 }
16365 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16366 } else {
16367 /* JALS32 */
16368 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16369 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16370 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16371 }
3c824109 16372 break;
65935f07 16373 case BEQ32: /* BC */
2e211e0a 16374 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16375 /* BC */
16376 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16377 sextract32(ctx->opcode << 1, 0, 27));
16378 } else {
16379 /* BEQ32 */
16380 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16381 }
3c824109 16382 break;
65935f07 16383 case BNE32: /* BALC */
2e211e0a 16384 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16385 /* BALC */
16386 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16387 sextract32(ctx->opcode << 1, 0, 27));
16388 } else {
16389 /* BNE32 */
16390 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16391 }
3c824109 16392 break;
65935f07 16393 case J32: /* BGTZC, BLTZC, BLTC */
2e211e0a 16394 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16395 if (rs == 0 && rt != 0) {
16396 /* BGTZC */
16397 mips32_op = OPC_BGTZC;
16398 } else if (rs != 0 && rt != 0 && rs == rt) {
16399 /* BLTZC */
16400 mips32_op = OPC_BLTZC;
16401 } else {
16402 /* BLTC */
16403 mips32_op = OPC_BLTC;
16404 }
16405 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16406 } else {
16407 /* J32 */
16408 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16409 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16410 }
3c824109 16411 break;
65935f07 16412 case JAL32: /* BLEZC, BGEZC, BGEC */
2e211e0a 16413 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16414 if (rs == 0 && rt != 0) {
16415 /* BLEZC */
16416 mips32_op = OPC_BLEZC;
16417 } else if (rs != 0 && rt != 0 && rs == rt) {
16418 /* BGEZC */
16419 mips32_op = OPC_BGEZC;
16420 } else {
16421 /* BGEC */
16422 mips32_op = OPC_BGEC;
16423 }
16424 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16425 } else {
16426 /* JAL32 */
16427 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16428 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16429 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16430 }
3c824109
NF
16431 break;
16432 /* Floating point (COP1) */
16433 case LWC132:
16434 mips32_op = OPC_LWC1;
16435 goto do_cop1;
16436 case LDC132:
16437 mips32_op = OPC_LDC1;
16438 goto do_cop1;
16439 case SWC132:
16440 mips32_op = OPC_SWC1;
16441 goto do_cop1;
16442 case SDC132:
16443 mips32_op = OPC_SDC1;
16444 do_cop1:
5ab5c041 16445 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 16446 break;
ab39ee45 16447 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
2e211e0a 16448 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
16449 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16450 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
16451 case ADDIUPC_00:
16452 case ADDIUPC_01:
16453 case ADDIUPC_02:
16454 case ADDIUPC_03:
16455 case ADDIUPC_04:
16456 case ADDIUPC_05:
16457 case ADDIUPC_06:
16458 case ADDIUPC_07:
eeb3bba8 16459 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16460 break;
16461 case AUIPC:
eeb3bba8 16462 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
16463 break;
16464 case ALUIPC:
eeb3bba8 16465 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 16466 break;
c38a1d52
AR
16467 case LWPC_08:
16468 case LWPC_09:
16469 case LWPC_0A:
16470 case LWPC_0B:
16471 case LWPC_0C:
16472 case LWPC_0D:
16473 case LWPC_0E:
16474 case LWPC_0F:
eeb3bba8 16475 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16476 break;
16477 default:
16478 generate_exception(ctx, EXCP_RI);
16479 break;
16480 }
16481 } else {
16482 /* ADDIUPC */
3c824109 16483 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 16484 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
16485
16486 gen_addiupc(ctx, reg, offset, 0, 0);
16487 }
16488 break;
65935f07 16489 case BNVC: /* BNEC, BNEZALC */
2e211e0a 16490 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16491 if (rs >= rt) {
16492 /* BNVC */
16493 mips32_op = OPC_BNVC;
16494 } else if (rs < rt && rs == 0) {
16495 /* BNEZALC */
16496 mips32_op = OPC_BNEZALC;
16497 } else {
16498 /* BNEC */
16499 mips32_op = OPC_BNEC;
16500 }
16501 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16502 break;
16503 case R6_BNEZC: /* JIALC */
2e211e0a 16504 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16505 if (rt != 0) {
16506 /* BNEZC */
16507 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16508 sextract32(ctx->opcode << 1, 0, 22));
16509 } else {
16510 /* JIALC */
16511 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16512 }
16513 break;
16514 case R6_BEQZC: /* JIC */
2e211e0a 16515 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16516 if (rt != 0) {
16517 /* BEQZC */
16518 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16519 sextract32(ctx->opcode << 1, 0, 22));
16520 } else {
16521 /* JIC */
16522 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16523 }
16524 break;
16525 case BLEZALC: /* BGEZALC, BGEUC */
2e211e0a 16526 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16527 if (rs == 0 && rt != 0) {
16528 /* BLEZALC */
16529 mips32_op = OPC_BLEZALC;
16530 } else if (rs != 0 && rt != 0 && rs == rt) {
16531 /* BGEZALC */
16532 mips32_op = OPC_BGEZALC;
16533 } else {
16534 /* BGEUC */
16535 mips32_op = OPC_BGEUC;
16536 }
16537 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16538 break;
16539 case BGTZALC: /* BLTZALC, BLTUC */
2e211e0a 16540 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16541 if (rs == 0 && rt != 0) {
16542 /* BGTZALC */
16543 mips32_op = OPC_BGTZALC;
16544 } else if (rs != 0 && rt != 0 && rs == rt) {
16545 /* BLTZALC */
16546 mips32_op = OPC_BLTZALC;
16547 } else {
16548 /* BLTUC */
16549 mips32_op = OPC_BLTUC;
16550 }
16551 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16552 break;
3c824109
NF
16553 /* Loads and stores */
16554 case LB32:
16555 mips32_op = OPC_LB;
5c13fdfd 16556 goto do_ld;
3c824109
NF
16557 case LBU32:
16558 mips32_op = OPC_LBU;
5c13fdfd 16559 goto do_ld;
3c824109
NF
16560 case LH32:
16561 mips32_op = OPC_LH;
5c13fdfd 16562 goto do_ld;
3c824109
NF
16563 case LHU32:
16564 mips32_op = OPC_LHU;
5c13fdfd 16565 goto do_ld;
3c824109
NF
16566 case LW32:
16567 mips32_op = OPC_LW;
5c13fdfd 16568 goto do_ld;
3c824109
NF
16569#ifdef TARGET_MIPS64
16570 case LD32:
d9224450
MR
16571 check_insn(ctx, ISA_MIPS3);
16572 check_mips_64(ctx);
3c824109 16573 mips32_op = OPC_LD;
5c13fdfd 16574 goto do_ld;
3c824109 16575 case SD32:
d9224450
MR
16576 check_insn(ctx, ISA_MIPS3);
16577 check_mips_64(ctx);
3c824109 16578 mips32_op = OPC_SD;
5c13fdfd 16579 goto do_st;
3c824109
NF
16580#endif
16581 case SB32:
16582 mips32_op = OPC_SB;
5c13fdfd 16583 goto do_st;
3c824109
NF
16584 case SH32:
16585 mips32_op = OPC_SH;
5c13fdfd 16586 goto do_st;
3c824109
NF
16587 case SW32:
16588 mips32_op = OPC_SW;
5c13fdfd
AJ
16589 goto do_st;
16590 do_ld:
d75c135e 16591 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
16592 break;
16593 do_st:
16594 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16595 break;
16596 default:
3a4ef3b7 16597 gen_reserved_instruction(ctx);
3c824109
NF
16598 break;
16599 }
16600}
16601
235785e8 16602static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16603{
16604 uint32_t op;
16605
16606 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
16607 if (ctx->base.pc_next & 0x1) {
16608 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 16609 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
16610 return 2;
16611 }
16612
16613 op = (ctx->opcode >> 10) & 0x3f;
16614 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
16615 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16616 switch (op & 0x7) { /* MSB-3..MSB-5 */
16617 case 0:
16618 /* POOL32A, POOL32B, POOL32I, POOL32C */
16619 case 4:
16620 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16621 case 5:
16622 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16623 case 6:
16624 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16625 case 7:
16626 /* LB32, LH32, LWC132, LDC132, LW32 */
16627 if (ctx->hflags & MIPS_HFLAG_BDS16) {
3a4ef3b7 16628 gen_reserved_instruction(ctx);
3c824109
NF
16629 return 2;
16630 }
16631 break;
b231c103
YK
16632 case 1:
16633 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16634 case 2:
16635 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16636 case 3:
16637 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16638 if (ctx->hflags & MIPS_HFLAG_BDS32) {
3a4ef3b7 16639 gen_reserved_instruction(ctx);
3c824109
NF
16640 return 2;
16641 }
16642 break;
3c824109
NF
16643 }
16644 }
b231c103 16645
3c824109
NF
16646 switch (op) {
16647 case POOL16A:
16648 {
16649 int rd = mmreg(uMIPS_RD(ctx->opcode));
16650 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16651 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16652 uint32_t opc = 0;
16653
16654 switch (ctx->opcode & 0x1) {
16655 case ADDU16:
16656 opc = OPC_ADDU;
16657 break;
16658 case SUBU16:
16659 opc = OPC_SUBU;
16660 break;
16661 }
2e211e0a 16662 if (ctx->insn_flags & ISA_MIPS_R6) {
7480515f
AM
16663 /*
16664 * In the Release 6, the register number location in
ed7ce6c0
YK
16665 * the instruction encoding has changed.
16666 */
16667 gen_arith(ctx, opc, rs1, rd, rs2);
16668 } else {
16669 gen_arith(ctx, opc, rd, rs1, rs2);
16670 }
3c824109
NF
16671 }
16672 break;
16673 case POOL16B:
16674 {
16675 int rd = mmreg(uMIPS_RD(ctx->opcode));
16676 int rs = mmreg(uMIPS_RS(ctx->opcode));
16677 int amount = (ctx->opcode >> 1) & 0x7;
16678 uint32_t opc = 0;
16679 amount = amount == 0 ? 8 : amount;
16680
16681 switch (ctx->opcode & 0x1) {
16682 case SLL16:
16683 opc = OPC_SLL;
16684 break;
16685 case SRL16:
16686 opc = OPC_SRL;
16687 break;
16688 }
16689
d75c135e 16690 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
16691 }
16692 break;
16693 case POOL16C:
2e211e0a 16694 if (ctx->insn_flags & ISA_MIPS_R6) {
ed7ce6c0
YK
16695 gen_pool16c_r6_insn(ctx);
16696 } else {
16697 gen_pool16c_insn(ctx);
16698 }
3c824109
NF
16699 break;
16700 case LWGP16:
16701 {
16702 int rd = mmreg(uMIPS_RD(ctx->opcode));
16703 int rb = 28; /* GP */
16704 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16705
d75c135e 16706 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16707 }
16708 break;
16709 case POOL16F:
2e211e0a 16710 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16711 if (ctx->opcode & 1) {
3a4ef3b7 16712 gen_reserved_instruction(ctx);
3c824109
NF
16713 } else {
16714 /* MOVEP */
16715 int enc_dest = uMIPS_RD(ctx->opcode);
16716 int enc_rt = uMIPS_RS2(ctx->opcode);
16717 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 16718 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
16719 }
16720 break;
16721 case LBU16:
16722 {
16723 int rd = mmreg(uMIPS_RD(ctx->opcode));
16724 int rb = mmreg(uMIPS_RS(ctx->opcode));
16725 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16726 offset = (offset == 0xf ? -1 : offset);
16727
d75c135e 16728 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
16729 }
16730 break;
16731 case LHU16:
16732 {
16733 int rd = mmreg(uMIPS_RD(ctx->opcode));
16734 int rb = mmreg(uMIPS_RS(ctx->opcode));
16735 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16736
d75c135e 16737 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
16738 }
16739 break;
16740 case LWSP16:
16741 {
16742 int rd = (ctx->opcode >> 5) & 0x1f;
16743 int rb = 29; /* SP */
16744 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16745
d75c135e 16746 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16747 }
16748 break;
16749 case LW16:
16750 {
16751 int rd = mmreg(uMIPS_RD(ctx->opcode));
16752 int rb = mmreg(uMIPS_RS(ctx->opcode));
16753 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16754
d75c135e 16755 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16756 }
16757 break;
16758 case SB16:
16759 {
16760 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16761 int rb = mmreg(uMIPS_RS(ctx->opcode));
16762 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16763
5c13fdfd 16764 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
16765 }
16766 break;
16767 case SH16:
16768 {
16769 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16770 int rb = mmreg(uMIPS_RS(ctx->opcode));
16771 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16772
5c13fdfd 16773 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
16774 }
16775 break;
16776 case SWSP16:
16777 {
16778 int rd = (ctx->opcode >> 5) & 0x1f;
16779 int rb = 29; /* SP */
16780 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16781
5c13fdfd 16782 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16783 }
16784 break;
16785 case SW16:
16786 {
16787 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16788 int rb = mmreg(uMIPS_RS(ctx->opcode));
16789 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16790
5c13fdfd 16791 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16792 }
16793 break;
16794 case MOVE16:
16795 {
16796 int rd = uMIPS_RD5(ctx->opcode);
16797 int rs = uMIPS_RS5(ctx->opcode);
16798
7215d7e7 16799 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
16800 }
16801 break;
16802 case ANDI16:
d75c135e 16803 gen_andi16(ctx);
3c824109
NF
16804 break;
16805 case POOL16D:
16806 switch (ctx->opcode & 0x1) {
16807 case ADDIUS5:
d75c135e 16808 gen_addius5(ctx);
3c824109
NF
16809 break;
16810 case ADDIUSP:
d75c135e 16811 gen_addiusp(ctx);
3c824109
NF
16812 break;
16813 }
16814 break;
16815 case POOL16E:
16816 switch (ctx->opcode & 0x1) {
16817 case ADDIUR2:
d75c135e 16818 gen_addiur2(ctx);
3c824109
NF
16819 break;
16820 case ADDIUR1SP:
d75c135e 16821 gen_addiur1sp(ctx);
3c824109
NF
16822 break;
16823 }
16824 break;
65935f07 16825 case B16: /* BC16 */
3c824109 16826 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07 16827 sextract32(ctx->opcode, 0, 10) << 1,
2e211e0a 16828 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
3c824109 16829 break;
65935f07
YK
16830 case BNEZ16: /* BNEZC16 */
16831 case BEQZ16: /* BEQZC16 */
3c824109
NF
16832 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16833 mmreg(uMIPS_RD(ctx->opcode)),
65935f07 16834 0, sextract32(ctx->opcode, 0, 7) << 1,
2e211e0a 16835 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
65935f07 16836
3c824109
NF
16837 break;
16838 case LI16:
16839 {
16840 int reg = mmreg(uMIPS_RD(ctx->opcode));
16841 int imm = ZIMM(ctx->opcode, 0, 7);
16842
16843 imm = (imm == 0x7f ? -1 : imm);
16844 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16845 }
16846 break;
3c824109 16847 case RES_29:
3c824109 16848 case RES_31:
3c824109 16849 case RES_39:
3a4ef3b7 16850 gen_reserved_instruction(ctx);
3c824109
NF
16851 break;
16852 default:
f60eeb0c 16853 decode_micromips32_opc(env, ctx);
3c824109
NF
16854 return 4;
16855 }
16856
16857 return 2;
16858}
16859
261c95a0
YK
16860/*
16861 *
16862 * nanoMIPS opcodes
16863 *
16864 */
16865
16866/* MAJOR, P16, and P32 pools opcodes */
16867enum {
16868 NM_P_ADDIU = 0x00,
16869 NM_ADDIUPC = 0x01,
16870 NM_MOVE_BALC = 0x02,
16871 NM_P16_MV = 0x04,
16872 NM_LW16 = 0x05,
16873 NM_BC16 = 0x06,
16874 NM_P16_SR = 0x07,
16875
16876 NM_POOL32A = 0x08,
16877 NM_P_BAL = 0x0a,
16878 NM_P16_SHIFT = 0x0c,
16879 NM_LWSP16 = 0x0d,
16880 NM_BALC16 = 0x0e,
16881 NM_P16_4X4 = 0x0f,
16882
16883 NM_P_GP_W = 0x10,
16884 NM_P_GP_BH = 0x11,
16885 NM_P_J = 0x12,
16886 NM_P16C = 0x14,
16887 NM_LWGP16 = 0x15,
16888 NM_P16_LB = 0x17,
16889
16890 NM_P48I = 0x18,
16891 NM_P16_A1 = 0x1c,
16892 NM_LW4X4 = 0x1d,
16893 NM_P16_LH = 0x1f,
16894
16895 NM_P_U12 = 0x20,
16896 NM_P_LS_U12 = 0x21,
16897 NM_P_BR1 = 0x22,
16898 NM_P16_A2 = 0x24,
16899 NM_SW16 = 0x25,
16900 NM_BEQZC16 = 0x26,
16901
16902 NM_POOL32F = 0x28,
16903 NM_P_LS_S9 = 0x29,
16904 NM_P_BR2 = 0x2a,
16905
16906 NM_P16_ADDU = 0x2c,
16907 NM_SWSP16 = 0x2d,
16908 NM_BNEZC16 = 0x2e,
16909 NM_MOVEP = 0x2f,
16910
16911 NM_POOL32S = 0x30,
16912 NM_P_BRI = 0x32,
16913 NM_LI16 = 0x34,
16914 NM_SWGP16 = 0x35,
16915 NM_P16_BR = 0x36,
16916
16917 NM_P_LUI = 0x38,
16918 NM_ANDI16 = 0x3c,
16919 NM_SW4X4 = 0x3d,
16920 NM_MOVEPREV = 0x3f,
16921};
16922
16923/* POOL32A instruction pool */
16924enum {
16925 NM_POOL32A0 = 0x00,
16926 NM_SPECIAL2 = 0x01,
16927 NM_COP2_1 = 0x02,
16928 NM_UDI = 0x03,
16929 NM_POOL32A5 = 0x05,
16930 NM_POOL32A7 = 0x07,
16931};
16932
16933/* P.GP.W instruction pool */
16934enum {
16935 NM_ADDIUGP_W = 0x00,
16936 NM_LWGP = 0x02,
16937 NM_SWGP = 0x03,
16938};
16939
16940/* P48I instruction pool */
16941enum {
16942 NM_LI48 = 0x00,
16943 NM_ADDIU48 = 0x01,
16944 NM_ADDIUGP48 = 0x02,
16945 NM_ADDIUPC48 = 0x03,
16946 NM_LWPC48 = 0x0b,
16947 NM_SWPC48 = 0x0f,
16948};
16949
16950/* P.U12 instruction pool */
16951enum {
16952 NM_ORI = 0x00,
16953 NM_XORI = 0x01,
16954 NM_ANDI = 0x02,
16955 NM_P_SR = 0x03,
16956 NM_SLTI = 0x04,
16957 NM_SLTIU = 0x05,
16958 NM_SEQI = 0x06,
16959 NM_ADDIUNEG = 0x08,
16960 NM_P_SHIFT = 0x0c,
16961 NM_P_ROTX = 0x0d,
16962 NM_P_INS = 0x0e,
16963 NM_P_EXT = 0x0f,
16964};
16965
16966/* POOL32F instruction pool */
16967enum {
16968 NM_POOL32F_0 = 0x00,
16969 NM_POOL32F_3 = 0x03,
16970 NM_POOL32F_5 = 0x05,
16971};
16972
16973/* POOL32S instruction pool */
16974enum {
16975 NM_POOL32S_0 = 0x00,
16976 NM_POOL32S_4 = 0x04,
16977};
16978
16979/* P.LUI instruction pool */
16980enum {
16981 NM_LUI = 0x00,
16982 NM_ALUIPC = 0x01,
16983};
16984
16985/* P.GP.BH instruction pool */
16986enum {
16987 NM_LBGP = 0x00,
16988 NM_SBGP = 0x01,
16989 NM_LBUGP = 0x02,
16990 NM_ADDIUGP_B = 0x03,
16991 NM_P_GP_LH = 0x04,
16992 NM_P_GP_SH = 0x05,
16993 NM_P_GP_CP1 = 0x06,
16994};
16995
16996/* P.LS.U12 instruction pool */
16997enum {
16998 NM_LB = 0x00,
16999 NM_SB = 0x01,
17000 NM_LBU = 0x02,
17001 NM_P_PREFU12 = 0x03,
17002 NM_LH = 0x04,
17003 NM_SH = 0x05,
17004 NM_LHU = 0x06,
17005 NM_LWU = 0x07,
17006 NM_LW = 0x08,
17007 NM_SW = 0x09,
17008 NM_LWC1 = 0x0a,
17009 NM_SWC1 = 0x0b,
17010 NM_LDC1 = 0x0e,
17011 NM_SDC1 = 0x0f,
17012};
17013
17014/* P.LS.S9 instruction pool */
17015enum {
17016 NM_P_LS_S0 = 0x00,
17017 NM_P_LS_S1 = 0x01,
17018 NM_P_LS_E0 = 0x02,
17019 NM_P_LS_WM = 0x04,
17020 NM_P_LS_UAWM = 0x05,
17021};
17022
17023/* P.BAL instruction pool */
17024enum {
17025 NM_BC = 0x00,
17026 NM_BALC = 0x01,
17027};
17028
17029/* P.J instruction pool */
17030enum {
17031 NM_JALRC = 0x00,
17032 NM_JALRC_HB = 0x01,
17033 NM_P_BALRSC = 0x08,
17034};
17035
17036/* P.BR1 instruction pool */
17037enum {
17038 NM_BEQC = 0x00,
17039 NM_P_BR3A = 0x01,
17040 NM_BGEC = 0x02,
17041 NM_BGEUC = 0x03,
17042};
17043
17044/* P.BR2 instruction pool */
17045enum {
17046 NM_BNEC = 0x00,
17047 NM_BLTC = 0x02,
17048 NM_BLTUC = 0x03,
17049};
17050
17051/* P.BRI instruction pool */
17052enum {
17053 NM_BEQIC = 0x00,
17054 NM_BBEQZC = 0x01,
17055 NM_BGEIC = 0x02,
17056 NM_BGEIUC = 0x03,
17057 NM_BNEIC = 0x04,
17058 NM_BBNEZC = 0x05,
17059 NM_BLTIC = 0x06,
17060 NM_BLTIUC = 0x07,
17061};
17062
17063/* P16.SHIFT instruction pool */
17064enum {
17065 NM_SLL16 = 0x00,
17066 NM_SRL16 = 0x01,
17067};
17068
17069/* POOL16C instruction pool */
17070enum {
17071 NM_POOL16C_0 = 0x00,
17072 NM_LWXS16 = 0x01,
17073};
17074
17075/* P16.A1 instruction pool */
17076enum {
17077 NM_ADDIUR1SP = 0x01,
17078};
17079
17080/* P16.A2 instruction pool */
17081enum {
17082 NM_ADDIUR2 = 0x00,
17083 NM_P_ADDIURS5 = 0x01,
17084};
17085
17086/* P16.ADDU instruction pool */
17087enum {
17088 NM_ADDU16 = 0x00,
17089 NM_SUBU16 = 0x01,
17090};
17091
17092/* P16.SR instruction pool */
17093enum {
17094 NM_SAVE16 = 0x00,
17095 NM_RESTORE_JRC16 = 0x01,
17096};
17097
17098/* P16.4X4 instruction pool */
17099enum {
17100 NM_ADDU4X4 = 0x00,
17101 NM_MUL4X4 = 0x01,
17102};
17103
17104/* P16.LB instruction pool */
17105enum {
17106 NM_LB16 = 0x00,
17107 NM_SB16 = 0x01,
17108 NM_LBU16 = 0x02,
17109};
17110
17111/* P16.LH instruction pool */
17112enum {
17113 NM_LH16 = 0x00,
17114 NM_SH16 = 0x01,
17115 NM_LHU16 = 0x02,
17116};
17117
17118/* P.RI instruction pool */
17119enum {
17120 NM_SIGRIE = 0x00,
17121 NM_P_SYSCALL = 0x01,
17122 NM_BREAK = 0x02,
17123 NM_SDBBP = 0x03,
17124};
17125
17126/* POOL32A0 instruction pool */
17127enum {
17128 NM_P_TRAP = 0x00,
17129 NM_SEB = 0x01,
17130 NM_SLLV = 0x02,
17131 NM_MUL = 0x03,
17132 NM_MFC0 = 0x06,
17133 NM_MFHC0 = 0x07,
17134 NM_SEH = 0x09,
17135 NM_SRLV = 0x0a,
17136 NM_MUH = 0x0b,
17137 NM_MTC0 = 0x0e,
17138 NM_MTHC0 = 0x0f,
17139 NM_SRAV = 0x12,
17140 NM_MULU = 0x13,
17141 NM_ROTRV = 0x1a,
17142 NM_MUHU = 0x1b,
17143 NM_ADD = 0x22,
17144 NM_DIV = 0x23,
17145 NM_ADDU = 0x2a,
17146 NM_MOD = 0x2b,
17147 NM_SUB = 0x32,
17148 NM_DIVU = 0x33,
17149 NM_RDHWR = 0x38,
17150 NM_SUBU = 0x3a,
17151 NM_MODU = 0x3b,
17152 NM_P_CMOVE = 0x42,
17153 NM_FORK = 0x45,
17154 NM_MFTR = 0x46,
17155 NM_MFHTR = 0x47,
17156 NM_AND = 0x4a,
17157 NM_YIELD = 0x4d,
17158 NM_MTTR = 0x4e,
17159 NM_MTHTR = 0x4f,
17160 NM_OR = 0x52,
17161 NM_D_E_MT_VPE = 0x56,
17162 NM_NOR = 0x5a,
17163 NM_XOR = 0x62,
17164 NM_SLT = 0x6a,
17165 NM_P_SLTU = 0x72,
17166 NM_SOV = 0x7a,
17167};
17168
ba1e8117
AM
17169/* CRC32 instruction pool */
17170enum {
17171 NM_CRC32B = 0x00,
17172 NM_CRC32H = 0x01,
17173 NM_CRC32W = 0x02,
17174 NM_CRC32CB = 0x04,
17175 NM_CRC32CH = 0x05,
17176 NM_CRC32CW = 0x06,
17177};
17178
b3979b6f
SM
17179/* POOL32A5 instruction pool */
17180enum {
17181 NM_CMP_EQ_PH = 0x00,
17182 NM_CMP_LT_PH = 0x08,
17183 NM_CMP_LE_PH = 0x10,
17184 NM_CMPGU_EQ_QB = 0x18,
17185 NM_CMPGU_LT_QB = 0x20,
17186 NM_CMPGU_LE_QB = 0x28,
17187 NM_CMPGDU_EQ_QB = 0x30,
17188 NM_CMPGDU_LT_QB = 0x38,
17189 NM_CMPGDU_LE_QB = 0x40,
17190 NM_CMPU_EQ_QB = 0x48,
17191 NM_CMPU_LT_QB = 0x50,
17192 NM_CMPU_LE_QB = 0x58,
17193 NM_ADDQ_S_W = 0x60,
17194 NM_SUBQ_S_W = 0x68,
17195 NM_ADDSC = 0x70,
17196 NM_ADDWC = 0x78,
17197
17198 NM_ADDQ_S_PH = 0x01,
17199 NM_ADDQH_R_PH = 0x09,
17200 NM_ADDQH_R_W = 0x11,
17201 NM_ADDU_S_QB = 0x19,
17202 NM_ADDU_S_PH = 0x21,
17203 NM_ADDUH_R_QB = 0x29,
17204 NM_SHRAV_R_PH = 0x31,
17205 NM_SHRAV_R_QB = 0x39,
17206 NM_SUBQ_S_PH = 0x41,
17207 NM_SUBQH_R_PH = 0x49,
17208 NM_SUBQH_R_W = 0x51,
17209 NM_SUBU_S_QB = 0x59,
17210 NM_SUBU_S_PH = 0x61,
17211 NM_SUBUH_R_QB = 0x69,
17212 NM_SHLLV_S_PH = 0x71,
17213 NM_PRECR_SRA_R_PH_W = 0x79,
17214
17215 NM_MULEU_S_PH_QBL = 0x12,
17216 NM_MULEU_S_PH_QBR = 0x1a,
17217 NM_MULQ_RS_PH = 0x22,
17218 NM_MULQ_S_PH = 0x2a,
17219 NM_MULQ_RS_W = 0x32,
17220 NM_MULQ_S_W = 0x3a,
17221 NM_APPEND = 0x42,
17222 NM_MODSUB = 0x52,
17223 NM_SHRAV_R_W = 0x5a,
17224 NM_SHRLV_PH = 0x62,
17225 NM_SHRLV_QB = 0x6a,
17226 NM_SHLLV_QB = 0x72,
17227 NM_SHLLV_S_W = 0x7a,
17228
17229 NM_SHILO = 0x03,
17230
17231 NM_MULEQ_S_W_PHL = 0x04,
17232 NM_MULEQ_S_W_PHR = 0x0c,
17233
17234 NM_MUL_S_PH = 0x05,
17235 NM_PRECR_QB_PH = 0x0d,
17236 NM_PRECRQ_QB_PH = 0x15,
17237 NM_PRECRQ_PH_W = 0x1d,
17238 NM_PRECRQ_RS_PH_W = 0x25,
17239 NM_PRECRQU_S_QB_PH = 0x2d,
17240 NM_PACKRL_PH = 0x35,
17241 NM_PICK_QB = 0x3d,
17242 NM_PICK_PH = 0x45,
17243
17244 NM_SHRA_R_W = 0x5e,
17245 NM_SHRA_R_PH = 0x66,
17246 NM_SHLL_S_PH = 0x76,
17247 NM_SHLL_S_W = 0x7e,
17248
17249 NM_REPL_PH = 0x07
17250};
17251
261c95a0
YK
17252/* POOL32A7 instruction pool */
17253enum {
17254 NM_P_LSX = 0x00,
17255 NM_LSA = 0x01,
17256 NM_EXTW = 0x03,
17257 NM_POOL32AXF = 0x07,
17258};
17259
17260/* P.SR instruction pool */
17261enum {
17262 NM_PP_SR = 0x00,
17263 NM_P_SR_F = 0x01,
17264};
17265
17266/* P.SHIFT instruction pool */
17267enum {
17268 NM_P_SLL = 0x00,
17269 NM_SRL = 0x02,
17270 NM_SRA = 0x04,
17271 NM_ROTR = 0x06,
17272};
17273
17274/* P.ROTX instruction pool */
17275enum {
17276 NM_ROTX = 0x00,
17277};
17278
17279/* P.INS instruction pool */
17280enum {
17281 NM_INS = 0x00,
17282};
17283
17284/* P.EXT instruction pool */
17285enum {
17286 NM_EXT = 0x00,
17287};
17288
17289/* POOL32F_0 (fmt) instruction pool */
17290enum {
17291 NM_RINT_S = 0x04,
17292 NM_RINT_D = 0x44,
17293 NM_ADD_S = 0x06,
17294 NM_SELEQZ_S = 0x07,
17295 NM_SELEQZ_D = 0x47,
17296 NM_CLASS_S = 0x0c,
17297 NM_CLASS_D = 0x4c,
17298 NM_SUB_S = 0x0e,
17299 NM_SELNEZ_S = 0x0f,
17300 NM_SELNEZ_D = 0x4f,
17301 NM_MUL_S = 0x16,
17302 NM_SEL_S = 0x17,
17303 NM_SEL_D = 0x57,
17304 NM_DIV_S = 0x1e,
17305 NM_ADD_D = 0x26,
17306 NM_SUB_D = 0x2e,
17307 NM_MUL_D = 0x36,
17308 NM_MADDF_S = 0x37,
17309 NM_MADDF_D = 0x77,
17310 NM_DIV_D = 0x3e,
17311 NM_MSUBF_S = 0x3f,
17312 NM_MSUBF_D = 0x7f,
17313};
17314
17315/* POOL32F_3 instruction pool */
17316enum {
17317 NM_MIN_FMT = 0x00,
17318 NM_MAX_FMT = 0x01,
17319 NM_MINA_FMT = 0x04,
17320 NM_MAXA_FMT = 0x05,
17321 NM_POOL32FXF = 0x07,
17322};
17323
17324/* POOL32F_5 instruction pool */
17325enum {
17326 NM_CMP_CONDN_S = 0x00,
17327 NM_CMP_CONDN_D = 0x02,
17328};
17329
17330/* P.GP.LH instruction pool */
17331enum {
17332 NM_LHGP = 0x00,
17333 NM_LHUGP = 0x01,
17334};
17335
17336/* P.GP.SH instruction pool */
17337enum {
17338 NM_SHGP = 0x00,
17339};
17340
17341/* P.GP.CP1 instruction pool */
17342enum {
17343 NM_LWC1GP = 0x00,
17344 NM_SWC1GP = 0x01,
17345 NM_LDC1GP = 0x02,
17346 NM_SDC1GP = 0x03,
17347};
17348
17349/* P.LS.S0 instruction pool */
17350enum {
17351 NM_LBS9 = 0x00,
17352 NM_LHS9 = 0x04,
17353 NM_LWS9 = 0x08,
17354 NM_LDS9 = 0x0c,
17355
17356 NM_SBS9 = 0x01,
17357 NM_SHS9 = 0x05,
17358 NM_SWS9 = 0x09,
17359 NM_SDS9 = 0x0d,
17360
17361 NM_LBUS9 = 0x02,
17362 NM_LHUS9 = 0x06,
17363 NM_LWC1S9 = 0x0a,
17364 NM_LDC1S9 = 0x0e,
17365
17366 NM_P_PREFS9 = 0x03,
17367 NM_LWUS9 = 0x07,
17368 NM_SWC1S9 = 0x0b,
17369 NM_SDC1S9 = 0x0f,
17370};
17371
17372/* P.LS.S1 instruction pool */
17373enum {
17374 NM_ASET_ACLR = 0x02,
17375 NM_UALH = 0x04,
17376 NM_UASH = 0x05,
17377 NM_CACHE = 0x07,
17378 NM_P_LL = 0x0a,
17379 NM_P_SC = 0x0b,
17380};
17381
0d30b3bb
DN
17382/* P.LS.E0 instruction pool */
17383enum {
17384 NM_LBE = 0x00,
17385 NM_SBE = 0x01,
17386 NM_LBUE = 0x02,
17387 NM_P_PREFE = 0x03,
17388 NM_LHE = 0x04,
17389 NM_SHE = 0x05,
17390 NM_LHUE = 0x06,
17391 NM_CACHEE = 0x07,
17392 NM_LWE = 0x08,
17393 NM_SWE = 0x09,
17394 NM_P_LLE = 0x0a,
17395 NM_P_SCE = 0x0b,
17396};
17397
17398/* P.PREFE instruction pool */
17399enum {
17400 NM_SYNCIE = 0x00,
17401 NM_PREFE = 0x01,
17402};
17403
17404/* P.LLE instruction pool */
17405enum {
17406 NM_LLE = 0x00,
17407 NM_LLWPE = 0x01,
17408};
17409
17410/* P.SCE instruction pool */
17411enum {
17412 NM_SCE = 0x00,
17413 NM_SCWPE = 0x01,
17414};
17415
261c95a0
YK
17416/* P.LS.WM instruction pool */
17417enum {
17418 NM_LWM = 0x00,
17419 NM_SWM = 0x01,
17420};
17421
17422/* P.LS.UAWM instruction pool */
17423enum {
17424 NM_UALWM = 0x00,
17425 NM_UASWM = 0x01,
17426};
17427
17428/* P.BR3A instruction pool */
17429enum {
17430 NM_BC1EQZC = 0x00,
17431 NM_BC1NEZC = 0x01,
17432 NM_BC2EQZC = 0x02,
17433 NM_BC2NEZC = 0x03,
17434 NM_BPOSGE32C = 0x04,
17435};
17436
17437/* P16.RI instruction pool */
17438enum {
17439 NM_P16_SYSCALL = 0x01,
17440 NM_BREAK16 = 0x02,
17441 NM_SDBBP16 = 0x03,
17442};
17443
17444/* POOL16C_0 instruction pool */
17445enum {
17446 NM_POOL16C_00 = 0x00,
17447};
17448
17449/* P16.JRC instruction pool */
17450enum {
17451 NM_JRC = 0x00,
17452 NM_JALRC16 = 0x01,
17453};
17454
17455/* P.SYSCALL instruction pool */
17456enum {
17457 NM_SYSCALL = 0x00,
17458 NM_HYPCALL = 0x01,
17459};
17460
17461/* P.TRAP instruction pool */
17462enum {
17463 NM_TEQ = 0x00,
17464 NM_TNE = 0x01,
17465};
17466
17467/* P.CMOVE instruction pool */
17468enum {
17469 NM_MOVZ = 0x00,
17470 NM_MOVN = 0x01,
17471};
17472
17473/* POOL32Axf instruction pool */
17474enum {
b3979b6f
SM
17475 NM_POOL32AXF_1 = 0x01,
17476 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
17477 NM_POOL32AXF_4 = 0x04,
17478 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
17479 NM_POOL32AXF_7 = 0x07,
17480};
17481
17482/* POOL32Axf_1 instruction pool */
17483enum {
17484 NM_POOL32AXF_1_0 = 0x00,
17485 NM_POOL32AXF_1_1 = 0x01,
17486 NM_POOL32AXF_1_3 = 0x03,
17487 NM_POOL32AXF_1_4 = 0x04,
17488 NM_POOL32AXF_1_5 = 0x05,
17489 NM_POOL32AXF_1_7 = 0x07,
17490};
17491
17492/* POOL32Axf_2 instruction pool */
17493enum {
17494 NM_POOL32AXF_2_0_7 = 0x00,
17495 NM_POOL32AXF_2_8_15 = 0x01,
17496 NM_POOL32AXF_2_16_23 = 0x02,
17497 NM_POOL32AXF_2_24_31 = 0x03,
17498};
17499
17500/* POOL32Axf_7 instruction pool */
17501enum {
17502 NM_SHRA_R_QB = 0x0,
17503 NM_SHRL_PH = 0x1,
17504 NM_REPL_QB = 0x2,
17505};
17506
17507/* POOL32Axf_1_0 instruction pool */
17508enum {
17509 NM_MFHI = 0x0,
17510 NM_MFLO = 0x1,
17511 NM_MTHI = 0x2,
17512 NM_MTLO = 0x3,
17513};
17514
17515/* POOL32Axf_1_1 instruction pool */
17516enum {
17517 NM_MTHLIP = 0x0,
17518 NM_SHILOV = 0x1,
17519};
17520
17521/* POOL32Axf_1_3 instruction pool */
17522enum {
17523 NM_RDDSP = 0x0,
17524 NM_WRDSP = 0x1,
17525 NM_EXTP = 0x2,
17526 NM_EXTPDP = 0x3,
17527};
17528
17529/* POOL32Axf_1_4 instruction pool */
17530enum {
17531 NM_SHLL_QB = 0x0,
17532 NM_SHRL_QB = 0x1,
17533};
17534
17535/* POOL32Axf_1_5 instruction pool */
17536enum {
17537 NM_MAQ_S_W_PHR = 0x0,
17538 NM_MAQ_S_W_PHL = 0x1,
17539 NM_MAQ_SA_W_PHR = 0x2,
17540 NM_MAQ_SA_W_PHL = 0x3,
17541};
17542
17543/* POOL32Axf_1_7 instruction pool */
17544enum {
17545 NM_EXTR_W = 0x0,
17546 NM_EXTR_R_W = 0x1,
17547 NM_EXTR_RS_W = 0x2,
17548 NM_EXTR_S_H = 0x3,
17549};
17550
17551/* POOL32Axf_2_0_7 instruction pool */
17552enum {
17553 NM_DPA_W_PH = 0x0,
17554 NM_DPAQ_S_W_PH = 0x1,
17555 NM_DPS_W_PH = 0x2,
17556 NM_DPSQ_S_W_PH = 0x3,
17557 NM_BALIGN = 0x4,
17558 NM_MADD = 0x5,
17559 NM_MULT = 0x6,
17560 NM_EXTRV_W = 0x7,
17561};
17562
17563/* POOL32Axf_2_8_15 instruction pool */
17564enum {
17565 NM_DPAX_W_PH = 0x0,
17566 NM_DPAQ_SA_L_W = 0x1,
17567 NM_DPSX_W_PH = 0x2,
17568 NM_DPSQ_SA_L_W = 0x3,
17569 NM_MADDU = 0x5,
17570 NM_MULTU = 0x6,
17571 NM_EXTRV_R_W = 0x7,
17572};
17573
17574/* POOL32Axf_2_16_23 instruction pool */
17575enum {
17576 NM_DPAU_H_QBL = 0x0,
17577 NM_DPAQX_S_W_PH = 0x1,
17578 NM_DPSU_H_QBL = 0x2,
17579 NM_DPSQX_S_W_PH = 0x3,
17580 NM_EXTPV = 0x4,
17581 NM_MSUB = 0x5,
17582 NM_MULSA_W_PH = 0x6,
17583 NM_EXTRV_RS_W = 0x7,
17584};
17585
17586/* POOL32Axf_2_24_31 instruction pool */
17587enum {
17588 NM_DPAU_H_QBR = 0x0,
17589 NM_DPAQX_SA_W_PH = 0x1,
17590 NM_DPSU_H_QBR = 0x2,
17591 NM_DPSQX_SA_W_PH = 0x3,
17592 NM_EXTPDPV = 0x4,
17593 NM_MSUBU = 0x5,
17594 NM_MULSAQ_S_W_PH = 0x6,
17595 NM_EXTRV_S_H = 0x7,
261c95a0
YK
17596};
17597
17598/* POOL32Axf_{4, 5} instruction pool */
17599enum {
17600 NM_CLO = 0x25,
17601 NM_CLZ = 0x2d,
17602
17603 NM_TLBP = 0x01,
17604 NM_TLBR = 0x09,
17605 NM_TLBWI = 0x11,
17606 NM_TLBWR = 0x19,
17607 NM_TLBINV = 0x03,
17608 NM_TLBINVF = 0x0b,
17609 NM_DI = 0x23,
17610 NM_EI = 0x2b,
17611 NM_RDPGPR = 0x70,
17612 NM_WRPGPR = 0x78,
17613 NM_WAIT = 0x61,
17614 NM_DERET = 0x71,
17615 NM_ERETX = 0x79,
b3979b6f
SM
17616
17617 /* nanoMIPS DSP instructions */
17618 NM_ABSQ_S_QB = 0x00,
17619 NM_ABSQ_S_PH = 0x08,
17620 NM_ABSQ_S_W = 0x10,
17621 NM_PRECEQ_W_PHL = 0x28,
17622 NM_PRECEQ_W_PHR = 0x30,
17623 NM_PRECEQU_PH_QBL = 0x38,
17624 NM_PRECEQU_PH_QBR = 0x48,
17625 NM_PRECEU_PH_QBL = 0x58,
17626 NM_PRECEU_PH_QBR = 0x68,
17627 NM_PRECEQU_PH_QBLA = 0x39,
17628 NM_PRECEQU_PH_QBRA = 0x49,
17629 NM_PRECEU_PH_QBLA = 0x59,
17630 NM_PRECEU_PH_QBRA = 0x69,
17631 NM_REPLV_PH = 0x01,
17632 NM_REPLV_QB = 0x09,
17633 NM_BITREV = 0x18,
17634 NM_INSV = 0x20,
17635 NM_RADDU_W_QB = 0x78,
17636
17637 NM_BITSWAP = 0x05,
17638 NM_WSBH = 0x3d,
261c95a0
YK
17639};
17640
17641/* PP.SR instruction pool */
17642enum {
17643 NM_SAVE = 0x00,
17644 NM_RESTORE = 0x02,
17645 NM_RESTORE_JRC = 0x03,
17646};
17647
17648/* P.SR.F instruction pool */
17649enum {
17650 NM_SAVEF = 0x00,
17651 NM_RESTOREF = 0x01,
17652};
17653
17654/* P16.SYSCALL instruction pool */
17655enum {
17656 NM_SYSCALL16 = 0x00,
17657 NM_HYPCALL16 = 0x01,
17658};
17659
17660/* POOL16C_00 instruction pool */
17661enum {
17662 NM_NOT16 = 0x00,
17663 NM_XOR16 = 0x01,
17664 NM_AND16 = 0x02,
17665 NM_OR16 = 0x03,
17666};
17667
17668/* PP.LSX and PP.LSXS instruction pool */
17669enum {
17670 NM_LBX = 0x00,
17671 NM_LHX = 0x04,
17672 NM_LWX = 0x08,
17673 NM_LDX = 0x0c,
17674
17675 NM_SBX = 0x01,
17676 NM_SHX = 0x05,
17677 NM_SWX = 0x09,
17678 NM_SDX = 0x0d,
17679
17680 NM_LBUX = 0x02,
17681 NM_LHUX = 0x06,
17682 NM_LWC1X = 0x0a,
17683 NM_LDC1X = 0x0e,
17684
17685 NM_LWUX = 0x07,
17686 NM_SWC1X = 0x0b,
17687 NM_SDC1X = 0x0f,
17688
17689 NM_LHXS = 0x04,
17690 NM_LWXS = 0x08,
17691 NM_LDXS = 0x0c,
17692
17693 NM_SHXS = 0x05,
17694 NM_SWXS = 0x09,
17695 NM_SDXS = 0x0d,
17696
17697 NM_LHUXS = 0x06,
17698 NM_LWC1XS = 0x0a,
17699 NM_LDC1XS = 0x0e,
17700
17701 NM_LWUXS = 0x07,
17702 NM_SWC1XS = 0x0b,
17703 NM_SDC1XS = 0x0f,
17704};
17705
17706/* ERETx instruction pool */
17707enum {
17708 NM_ERET = 0x00,
17709 NM_ERETNC = 0x01,
17710};
17711
17712/* POOL32FxF_{0, 1} insturction pool */
17713enum {
17714 NM_CFC1 = 0x40,
17715 NM_CTC1 = 0x60,
17716 NM_MFC1 = 0x80,
17717 NM_MTC1 = 0xa0,
17718 NM_MFHC1 = 0xc0,
17719 NM_MTHC1 = 0xe0,
17720
17721 NM_CVT_S_PL = 0x84,
17722 NM_CVT_S_PU = 0xa4,
17723
17724 NM_CVT_L_S = 0x004,
17725 NM_CVT_L_D = 0x104,
17726 NM_CVT_W_S = 0x024,
17727 NM_CVT_W_D = 0x124,
17728
17729 NM_RSQRT_S = 0x008,
17730 NM_RSQRT_D = 0x108,
17731
17732 NM_SQRT_S = 0x028,
17733 NM_SQRT_D = 0x128,
17734
17735 NM_RECIP_S = 0x048,
17736 NM_RECIP_D = 0x148,
17737
17738 NM_FLOOR_L_S = 0x00c,
17739 NM_FLOOR_L_D = 0x10c,
17740
17741 NM_FLOOR_W_S = 0x02c,
17742 NM_FLOOR_W_D = 0x12c,
17743
17744 NM_CEIL_L_S = 0x04c,
17745 NM_CEIL_L_D = 0x14c,
17746 NM_CEIL_W_S = 0x06c,
17747 NM_CEIL_W_D = 0x16c,
17748 NM_TRUNC_L_S = 0x08c,
17749 NM_TRUNC_L_D = 0x18c,
17750 NM_TRUNC_W_S = 0x0ac,
17751 NM_TRUNC_W_D = 0x1ac,
17752 NM_ROUND_L_S = 0x0cc,
17753 NM_ROUND_L_D = 0x1cc,
17754 NM_ROUND_W_S = 0x0ec,
17755 NM_ROUND_W_D = 0x1ec,
17756
17757 NM_MOV_S = 0x01,
17758 NM_MOV_D = 0x81,
17759 NM_ABS_S = 0x0d,
17760 NM_ABS_D = 0x8d,
17761 NM_NEG_S = 0x2d,
17762 NM_NEG_D = 0xad,
17763 NM_CVT_D_S = 0x04d,
17764 NM_CVT_D_W = 0x0cd,
17765 NM_CVT_D_L = 0x14d,
17766 NM_CVT_S_D = 0x06d,
17767 NM_CVT_S_W = 0x0ed,
17768 NM_CVT_S_L = 0x16d,
17769};
17770
17771/* P.LL instruction pool */
17772enum {
17773 NM_LL = 0x00,
17774 NM_LLWP = 0x01,
17775};
17776
17777/* P.SC instruction pool */
17778enum {
17779 NM_SC = 0x00,
17780 NM_SCWP = 0x01,
17781};
17782
17783/* P.DVP instruction pool */
17784enum {
17785 NM_DVP = 0x00,
17786 NM_EVP = 0x01,
17787};
17788
c533c0f4
AM
17789
17790/*
17791 *
17792 * nanoMIPS decoding engine
17793 *
17794 */
17795
6bfa9f4c
AM
17796
17797/* extraction utilities */
17798
99e49abf
AM
17799#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17800#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17801#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
17802#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17803#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17804
ea4ca3c2
YK
17805/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17806static inline int decode_gpr_gpr3(int r)
17807{
17808 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17809
17810 return map[r & 0x7];
17811}
17812
8bdb7029
YK
17813/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17814static inline int decode_gpr_gpr3_src_store(int r)
17815{
17816 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17817
17818 return map[r & 0x7];
17819}
17820
ea4ca3c2
YK
17821/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17822static inline int decode_gpr_gpr4(int r)
17823{
17824 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17825 16, 17, 18, 19, 20, 21, 22, 23 };
17826
17827 return map[r & 0xf];
17828}
17829
8bdb7029
YK
17830/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17831static inline int decode_gpr_gpr4_zero(int r)
17832{
17833 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17834 16, 17, 18, 19, 20, 21, 22, 23 };
17835
17836 return map[r & 0xf];
17837}
17838
6bfa9f4c 17839
bf0718c5
SM
17840static void gen_adjust_sp(DisasContext *ctx, int u)
17841{
17842 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17843}
17844
17845static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17846 uint8_t gp, uint16_t u)
17847{
17848 int counter = 0;
17849 TCGv va = tcg_temp_new();
17850 TCGv t0 = tcg_temp_new();
17851
17852 while (counter != count) {
17853 bool use_gp = gp && (counter == count - 1);
17854 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17855 int this_offset = -((counter + 1) << 2);
17856 gen_base_offset_addr(ctx, va, 29, this_offset);
17857 gen_load_gpr(t0, this_rt);
17858 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17859 (MO_TEUL | ctx->default_tcg_memop_mask));
17860 counter++;
17861 }
17862
17863 /* adjust stack pointer */
17864 gen_adjust_sp(ctx, -u);
17865
17866 tcg_temp_free(t0);
17867 tcg_temp_free(va);
17868}
17869
17870static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17871 uint8_t gp, uint16_t u)
17872{
17873 int counter = 0;
17874 TCGv va = tcg_temp_new();
17875 TCGv t0 = tcg_temp_new();
17876
17877 while (counter != count) {
17878 bool use_gp = gp && (counter == count - 1);
17879 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17880 int this_offset = u - ((counter + 1) << 2);
17881 gen_base_offset_addr(ctx, va, 29, this_offset);
17882 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17883 ctx->default_tcg_memop_mask);
17884 tcg_gen_ext32s_tl(t0, t0);
17885 gen_store_gpr(t0, this_rt);
17886 counter++;
17887 }
17888
17889 /* adjust stack pointer */
17890 gen_adjust_sp(ctx, u);
17891
17892 tcg_temp_free(t0);
17893 tcg_temp_free(va);
17894}
17895
80845edf
YK
17896static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17897{
99e49abf
AM
17898 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
17899 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
17900
17901 switch (extract32(ctx->opcode, 2, 2)) {
17902 case NM_NOT16:
17903 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17904 break;
17905 case NM_AND16:
17906 gen_logic(ctx, OPC_AND, rt, rt, rs);
17907 break;
17908 case NM_XOR16:
17909 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17910 break;
17911 case NM_OR16:
17912 gen_logic(ctx, OPC_OR, rt, rt, rs);
17913 break;
17914 }
17915}
17916
0a1a6ed7 17917static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
17918{
17919 int rt = extract32(ctx->opcode, 21, 5);
17920 int rs = extract32(ctx->opcode, 16, 5);
17921 int rd = extract32(ctx->opcode, 11, 5);
17922
17923 switch (extract32(ctx->opcode, 3, 7)) {
17924 case NM_P_TRAP:
17925 switch (extract32(ctx->opcode, 10, 1)) {
17926 case NM_TEQ:
fb32f8c8 17927 check_nms(ctx);
e0cf0e65
YK
17928 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17929 break;
17930 case NM_TNE:
fb32f8c8 17931 check_nms(ctx);
e0cf0e65
YK
17932 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17933 break;
17934 }
17935 break;
17936 case NM_RDHWR:
fb32f8c8 17937 check_nms(ctx);
e0cf0e65
YK
17938 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17939 break;
17940 case NM_SEB:
fb32f8c8 17941 check_nms(ctx);
e0cf0e65
YK
17942 gen_bshfl(ctx, OPC_SEB, rs, rt);
17943 break;
17944 case NM_SEH:
17945 gen_bshfl(ctx, OPC_SEH, rs, rt);
17946 break;
17947 case NM_SLLV:
17948 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17949 break;
17950 case NM_SRLV:
17951 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17952 break;
17953 case NM_SRAV:
17954 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17955 break;
17956 case NM_ROTRV:
17957 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17958 break;
17959 case NM_ADD:
17960 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17961 break;
17962 case NM_ADDU:
17963 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17964 break;
17965 case NM_SUB:
fb32f8c8 17966 check_nms(ctx);
e0cf0e65
YK
17967 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17968 break;
17969 case NM_SUBU:
17970 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17971 break;
17972 case NM_P_CMOVE:
17973 switch (extract32(ctx->opcode, 10, 1)) {
17974 case NM_MOVZ:
17975 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17976 break;
17977 case NM_MOVN:
17978 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17979 break;
17980 }
17981 break;
17982 case NM_AND:
17983 gen_logic(ctx, OPC_AND, rd, rs, rt);
17984 break;
17985 case NM_OR:
17986 gen_logic(ctx, OPC_OR, rd, rs, rt);
17987 break;
17988 case NM_NOR:
17989 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17990 break;
17991 case NM_XOR:
17992 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17993 break;
17994 case NM_SLT:
17995 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17996 break;
17997 case NM_P_SLTU:
17998 if (rd == 0) {
17999 /* P_DVP */
18000#ifndef CONFIG_USER_ONLY
18001 TCGv t0 = tcg_temp_new();
18002 switch (extract32(ctx->opcode, 10, 1)) {
18003 case NM_DVP:
18004 if (ctx->vp) {
18005 check_cp0_enabled(ctx);
18006 gen_helper_dvp(t0, cpu_env);
18007 gen_store_gpr(t0, rt);
18008 }
18009 break;
18010 case NM_EVP:
18011 if (ctx->vp) {
18012 check_cp0_enabled(ctx);
18013 gen_helper_evp(t0, cpu_env);
18014 gen_store_gpr(t0, rt);
18015 }
18016 break;
18017 }
18018 tcg_temp_free(t0);
18019#endif
18020 } else {
18021 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18022 }
18023 break;
18024 case NM_SOV:
18025 {
18026 TCGv t0 = tcg_temp_new();
18027 TCGv t1 = tcg_temp_new();
18028 TCGv t2 = tcg_temp_new();
18029
18030 gen_load_gpr(t1, rs);
18031 gen_load_gpr(t2, rt);
18032 tcg_gen_add_tl(t0, t1, t2);
18033 tcg_gen_ext32s_tl(t0, t0);
18034 tcg_gen_xor_tl(t1, t1, t2);
18035 tcg_gen_xor_tl(t2, t0, t2);
18036 tcg_gen_andc_tl(t1, t2, t1);
18037
18038 /* operands of same sign, result different sign */
18039 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18040 gen_store_gpr(t0, rd);
18041
18042 tcg_temp_free(t0);
18043 tcg_temp_free(t1);
18044 tcg_temp_free(t2);
18045 }
18046 break;
18047 case NM_MUL:
18048 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18049 break;
18050 case NM_MUH:
18051 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18052 break;
18053 case NM_MULU:
18054 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18055 break;
18056 case NM_MUHU:
18057 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18058 break;
18059 case NM_DIV:
18060 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18061 break;
18062 case NM_MOD:
18063 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18064 break;
18065 case NM_DIVU:
18066 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18067 break;
18068 case NM_MODU:
18069 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18070 break;
18071#ifndef CONFIG_USER_ONLY
18072 case NM_MFC0:
18073 check_cp0_enabled(ctx);
18074 if (rt == 0) {
18075 /* Treat as NOP. */
18076 break;
18077 }
18078 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18079 break;
18080 case NM_MTC0:
18081 check_cp0_enabled(ctx);
18082 {
18083 TCGv t0 = tcg_temp_new();
18084
18085 gen_load_gpr(t0, rt);
18086 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18087 tcg_temp_free(t0);
18088 }
18089 break;
0a1a6ed7
SM
18090 case NM_D_E_MT_VPE:
18091 {
18092 uint8_t sc = extract32(ctx->opcode, 10, 1);
18093 TCGv t0 = tcg_temp_new();
18094
18095 switch (sc) {
18096 case 0:
18097 if (rs == 1) {
18098 /* DMT */
18099 check_cp0_mt(ctx);
18100 gen_helper_dmt(t0);
18101 gen_store_gpr(t0, rt);
18102 } else if (rs == 0) {
18103 /* DVPE */
18104 check_cp0_mt(ctx);
18105 gen_helper_dvpe(t0, cpu_env);
18106 gen_store_gpr(t0, rt);
18107 } else {
3a4ef3b7 18108 gen_reserved_instruction(ctx);
0a1a6ed7
SM
18109 }
18110 break;
18111 case 1:
18112 if (rs == 1) {
18113 /* EMT */
18114 check_cp0_mt(ctx);
18115 gen_helper_emt(t0);
18116 gen_store_gpr(t0, rt);
18117 } else if (rs == 0) {
18118 /* EVPE */
18119 check_cp0_mt(ctx);
18120 gen_helper_evpe(t0, cpu_env);
18121 gen_store_gpr(t0, rt);
18122 } else {
3a4ef3b7 18123 gen_reserved_instruction(ctx);
0a1a6ed7
SM
18124 }
18125 break;
18126 }
18127
18128 tcg_temp_free(t0);
18129 }
18130 break;
18131 case NM_FORK:
18132 check_mt(ctx);
18133 {
18134 TCGv t0 = tcg_temp_new();
18135 TCGv t1 = tcg_temp_new();
18136
18137 gen_load_gpr(t0, rt);
18138 gen_load_gpr(t1, rs);
18139 gen_helper_fork(t0, t1);
18140 tcg_temp_free(t0);
18141 tcg_temp_free(t1);
18142 }
18143 break;
18144 case NM_MFTR:
18145 case NM_MFHTR:
18146 check_cp0_enabled(ctx);
18147 if (rd == 0) {
18148 /* Treat as NOP. */
18149 return;
18150 }
18151 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18152 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18153 break;
18154 case NM_MTTR:
18155 case NM_MTHTR:
18156 check_cp0_enabled(ctx);
18157 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18158 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18159 break;
18160 case NM_YIELD:
18161 check_mt(ctx);
18162 {
18163 TCGv t0 = tcg_temp_new();
18164
18165 gen_load_gpr(t0, rs);
18166 gen_helper_yield(t0, cpu_env, t0);
18167 gen_store_gpr(t0, rt);
18168 tcg_temp_free(t0);
18169 }
18170 break;
e0cf0e65
YK
18171#endif
18172 default:
3a4ef3b7 18173 gen_reserved_instruction(ctx);
e0cf0e65
YK
18174 break;
18175 }
18176}
18177
2ed42efa
SM
18178/* dsp */
18179static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18180 int ret, int v1, int v2)
18181{
18182 TCGv_i32 t0;
18183 TCGv v0_t;
18184 TCGv v1_t;
18185
18186 t0 = tcg_temp_new_i32();
18187
18188 v0_t = tcg_temp_new();
18189 v1_t = tcg_temp_new();
18190
18191 tcg_gen_movi_i32(t0, v2 >> 3);
18192
18193 gen_load_gpr(v0_t, ret);
18194 gen_load_gpr(v1_t, v1);
18195
18196 switch (opc) {
18197 case NM_MAQ_S_W_PHR:
18198 check_dsp(ctx);
18199 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18200 break;
18201 case NM_MAQ_S_W_PHL:
18202 check_dsp(ctx);
18203 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18204 break;
18205 case NM_MAQ_SA_W_PHR:
18206 check_dsp(ctx);
18207 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18208 break;
18209 case NM_MAQ_SA_W_PHL:
18210 check_dsp(ctx);
18211 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18212 break;
18213 default:
3a4ef3b7 18214 gen_reserved_instruction(ctx);
2ed42efa
SM
18215 break;
18216 }
18217
18218 tcg_temp_free_i32(t0);
18219
18220 tcg_temp_free(v0_t);
18221 tcg_temp_free(v1_t);
18222}
18223
18224
18225static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18226 int ret, int v1, int v2)
18227{
18228 int16_t imm;
18229 TCGv t0 = tcg_temp_new();
18230 TCGv t1 = tcg_temp_new();
18231 TCGv v0_t = tcg_temp_new();
18232
18233 gen_load_gpr(v0_t, v1);
18234
18235 switch (opc) {
18236 case NM_POOL32AXF_1_0:
18237 check_dsp(ctx);
18238 switch (extract32(ctx->opcode, 12, 2)) {
18239 case NM_MFHI:
18240 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18241 break;
18242 case NM_MFLO:
18243 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18244 break;
18245 case NM_MTHI:
18246 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18247 break;
18248 case NM_MTLO:
18249 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18250 break;
18251 }
18252 break;
18253 case NM_POOL32AXF_1_1:
18254 check_dsp(ctx);
18255 switch (extract32(ctx->opcode, 12, 2)) {
18256 case NM_MTHLIP:
18257 tcg_gen_movi_tl(t0, v2);
18258 gen_helper_mthlip(t0, v0_t, cpu_env);
18259 break;
18260 case NM_SHILOV:
18261 tcg_gen_movi_tl(t0, v2 >> 3);
18262 gen_helper_shilo(t0, v0_t, cpu_env);
18263 break;
18264 default:
3a4ef3b7 18265 gen_reserved_instruction(ctx);
2ed42efa
SM
18266 break;
18267 }
18268 break;
18269 case NM_POOL32AXF_1_3:
18270 check_dsp(ctx);
18271 imm = extract32(ctx->opcode, 14, 7);
18272 switch (extract32(ctx->opcode, 12, 2)) {
18273 case NM_RDDSP:
18274 tcg_gen_movi_tl(t0, imm);
18275 gen_helper_rddsp(t0, t0, cpu_env);
18276 gen_store_gpr(t0, ret);
18277 break;
18278 case NM_WRDSP:
18279 gen_load_gpr(t0, ret);
18280 tcg_gen_movi_tl(t1, imm);
18281 gen_helper_wrdsp(t0, t1, cpu_env);
18282 break;
18283 case NM_EXTP:
18284 tcg_gen_movi_tl(t0, v2 >> 3);
18285 tcg_gen_movi_tl(t1, v1);
18286 gen_helper_extp(t0, t0, t1, cpu_env);
18287 gen_store_gpr(t0, ret);
18288 break;
18289 case NM_EXTPDP:
18290 tcg_gen_movi_tl(t0, v2 >> 3);
18291 tcg_gen_movi_tl(t1, v1);
18292 gen_helper_extpdp(t0, t0, t1, cpu_env);
18293 gen_store_gpr(t0, ret);
18294 break;
18295 }
18296 break;
18297 case NM_POOL32AXF_1_4:
18298 check_dsp(ctx);
18299 tcg_gen_movi_tl(t0, v2 >> 2);
18300 switch (extract32(ctx->opcode, 12, 1)) {
18301 case NM_SHLL_QB:
18302 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18303 gen_store_gpr(t0, ret);
18304 break;
18305 case NM_SHRL_QB:
18306 gen_helper_shrl_qb(t0, t0, v0_t);
18307 gen_store_gpr(t0, ret);
18308 break;
18309 }
18310 break;
18311 case NM_POOL32AXF_1_5:
18312 opc = extract32(ctx->opcode, 12, 2);
18313 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18314 break;
18315 case NM_POOL32AXF_1_7:
18316 check_dsp(ctx);
18317 tcg_gen_movi_tl(t0, v2 >> 3);
18318 tcg_gen_movi_tl(t1, v1);
18319 switch (extract32(ctx->opcode, 12, 2)) {
18320 case NM_EXTR_W:
18321 gen_helper_extr_w(t0, t0, t1, cpu_env);
18322 gen_store_gpr(t0, ret);
18323 break;
18324 case NM_EXTR_R_W:
18325 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18326 gen_store_gpr(t0, ret);
18327 break;
18328 case NM_EXTR_RS_W:
18329 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18330 gen_store_gpr(t0, ret);
18331 break;
18332 case NM_EXTR_S_H:
18333 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18334 gen_store_gpr(t0, ret);
18335 break;
18336 }
18337 break;
18338 default:
3a4ef3b7 18339 gen_reserved_instruction(ctx);
2ed42efa
SM
18340 break;
18341 }
18342
18343 tcg_temp_free(t0);
18344 tcg_temp_free(t1);
18345 tcg_temp_free(v0_t);
18346}
18347
8b3698b2
SM
18348static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18349 TCGv v0, TCGv v1, int rd)
18350{
18351 TCGv_i32 t0;
18352
18353 t0 = tcg_temp_new_i32();
18354
18355 tcg_gen_movi_i32(t0, rd >> 3);
18356
18357 switch (opc) {
18358 case NM_POOL32AXF_2_0_7:
18359 switch (extract32(ctx->opcode, 9, 3)) {
18360 case NM_DPA_W_PH:
908f6be1 18361 check_dsp_r2(ctx);
8b3698b2
SM
18362 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18363 break;
18364 case NM_DPAQ_S_W_PH:
18365 check_dsp(ctx);
18366 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18367 break;
18368 case NM_DPS_W_PH:
908f6be1 18369 check_dsp_r2(ctx);
8b3698b2
SM
18370 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18371 break;
18372 case NM_DPSQ_S_W_PH:
18373 check_dsp(ctx);
18374 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18375 break;
18376 default:
3a4ef3b7 18377 gen_reserved_instruction(ctx);
8b3698b2
SM
18378 break;
18379 }
18380 break;
18381 case NM_POOL32AXF_2_8_15:
18382 switch (extract32(ctx->opcode, 9, 3)) {
18383 case NM_DPAX_W_PH:
908f6be1 18384 check_dsp_r2(ctx);
8b3698b2
SM
18385 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18386 break;
18387 case NM_DPAQ_SA_L_W:
18388 check_dsp(ctx);
18389 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18390 break;
18391 case NM_DPSX_W_PH:
908f6be1 18392 check_dsp_r2(ctx);
8b3698b2
SM
18393 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18394 break;
18395 case NM_DPSQ_SA_L_W:
18396 check_dsp(ctx);
18397 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18398 break;
18399 default:
3a4ef3b7 18400 gen_reserved_instruction(ctx);
8b3698b2
SM
18401 break;
18402 }
18403 break;
18404 case NM_POOL32AXF_2_16_23:
18405 switch (extract32(ctx->opcode, 9, 3)) {
18406 case NM_DPAU_H_QBL:
18407 check_dsp(ctx);
18408 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18409 break;
18410 case NM_DPAQX_S_W_PH:
908f6be1 18411 check_dsp_r2(ctx);
8b3698b2
SM
18412 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18413 break;
18414 case NM_DPSU_H_QBL:
18415 check_dsp(ctx);
18416 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18417 break;
18418 case NM_DPSQX_S_W_PH:
908f6be1 18419 check_dsp_r2(ctx);
8b3698b2
SM
18420 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18421 break;
18422 case NM_MULSA_W_PH:
908f6be1 18423 check_dsp_r2(ctx);
8b3698b2
SM
18424 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18425 break;
18426 default:
3a4ef3b7 18427 gen_reserved_instruction(ctx);
8b3698b2
SM
18428 break;
18429 }
18430 break;
18431 case NM_POOL32AXF_2_24_31:
18432 switch (extract32(ctx->opcode, 9, 3)) {
18433 case NM_DPAU_H_QBR:
18434 check_dsp(ctx);
18435 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18436 break;
18437 case NM_DPAQX_SA_W_PH:
908f6be1 18438 check_dsp_r2(ctx);
8b3698b2
SM
18439 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18440 break;
18441 case NM_DPSU_H_QBR:
18442 check_dsp(ctx);
18443 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18444 break;
18445 case NM_DPSQX_SA_W_PH:
908f6be1 18446 check_dsp_r2(ctx);
8b3698b2
SM
18447 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18448 break;
18449 case NM_MULSAQ_S_W_PH:
18450 check_dsp(ctx);
18451 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18452 break;
18453 default:
3a4ef3b7 18454 gen_reserved_instruction(ctx);
8b3698b2
SM
18455 break;
18456 }
18457 break;
18458 default:
3a4ef3b7 18459 gen_reserved_instruction(ctx);
8b3698b2
SM
18460 break;
18461 }
18462
18463 tcg_temp_free_i32(t0);
18464}
18465
18466static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18467 int rt, int rs, int rd)
18468{
18469 int ret = rt;
18470 TCGv t0 = tcg_temp_new();
18471 TCGv t1 = tcg_temp_new();
18472 TCGv v0_t = tcg_temp_new();
18473 TCGv v1_t = tcg_temp_new();
18474
18475 gen_load_gpr(v0_t, rt);
18476 gen_load_gpr(v1_t, rs);
18477
18478 switch (opc) {
18479 case NM_POOL32AXF_2_0_7:
18480 switch (extract32(ctx->opcode, 9, 3)) {
18481 case NM_DPA_W_PH:
18482 case NM_DPAQ_S_W_PH:
18483 case NM_DPS_W_PH:
18484 case NM_DPSQ_S_W_PH:
18485 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18486 break;
18487 case NM_BALIGN:
908f6be1 18488 check_dsp_r2(ctx);
8b3698b2
SM
18489 if (rt != 0) {
18490 gen_load_gpr(t0, rs);
18491 rd &= 3;
18492 if (rd != 0 && rd != 2) {
18493 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18494 tcg_gen_ext32u_tl(t0, t0);
18495 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18496 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18497 }
18498 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18499 }
18500 break;
18501 case NM_MADD:
18502 check_dsp(ctx);
18503 {
18504 int acc = extract32(ctx->opcode, 14, 2);
18505 TCGv_i64 t2 = tcg_temp_new_i64();
18506 TCGv_i64 t3 = tcg_temp_new_i64();
18507
18508 gen_load_gpr(t0, rt);
18509 gen_load_gpr(t1, rs);
18510 tcg_gen_ext_tl_i64(t2, t0);
18511 tcg_gen_ext_tl_i64(t3, t1);
18512 tcg_gen_mul_i64(t2, t2, t3);
18513 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18514 tcg_gen_add_i64(t2, t2, t3);
18515 tcg_temp_free_i64(t3);
18516 gen_move_low32(cpu_LO[acc], t2);
18517 gen_move_high32(cpu_HI[acc], t2);
18518 tcg_temp_free_i64(t2);
18519 }
18520 break;
18521 case NM_MULT:
18522 check_dsp(ctx);
18523 {
18524 int acc = extract32(ctx->opcode, 14, 2);
18525 TCGv_i32 t2 = tcg_temp_new_i32();
18526 TCGv_i32 t3 = tcg_temp_new_i32();
18527
18528 gen_load_gpr(t0, rs);
18529 gen_load_gpr(t1, rt);
18530 tcg_gen_trunc_tl_i32(t2, t0);
18531 tcg_gen_trunc_tl_i32(t3, t1);
18532 tcg_gen_muls2_i32(t2, t3, t2, t3);
18533 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18534 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18535 tcg_temp_free_i32(t2);
18536 tcg_temp_free_i32(t3);
18537 }
18538 break;
18539 case NM_EXTRV_W:
18540 check_dsp(ctx);
18541 gen_load_gpr(v1_t, rs);
18542 tcg_gen_movi_tl(t0, rd >> 3);
18543 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18544 gen_store_gpr(t0, ret);
18545 break;
18546 }
18547 break;
18548 case NM_POOL32AXF_2_8_15:
18549 switch (extract32(ctx->opcode, 9, 3)) {
18550 case NM_DPAX_W_PH:
18551 case NM_DPAQ_SA_L_W:
18552 case NM_DPSX_W_PH:
18553 case NM_DPSQ_SA_L_W:
18554 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18555 break;
18556 case NM_MADDU:
18557 check_dsp(ctx);
18558 {
18559 int acc = extract32(ctx->opcode, 14, 2);
18560 TCGv_i64 t2 = tcg_temp_new_i64();
18561 TCGv_i64 t3 = tcg_temp_new_i64();
18562
18563 gen_load_gpr(t0, rs);
18564 gen_load_gpr(t1, rt);
18565 tcg_gen_ext32u_tl(t0, t0);
18566 tcg_gen_ext32u_tl(t1, t1);
18567 tcg_gen_extu_tl_i64(t2, t0);
18568 tcg_gen_extu_tl_i64(t3, t1);
18569 tcg_gen_mul_i64(t2, t2, t3);
18570 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18571 tcg_gen_add_i64(t2, t2, t3);
18572 tcg_temp_free_i64(t3);
18573 gen_move_low32(cpu_LO[acc], t2);
18574 gen_move_high32(cpu_HI[acc], t2);
18575 tcg_temp_free_i64(t2);
18576 }
18577 break;
18578 case NM_MULTU:
18579 check_dsp(ctx);
18580 {
18581 int acc = extract32(ctx->opcode, 14, 2);
18582 TCGv_i32 t2 = tcg_temp_new_i32();
18583 TCGv_i32 t3 = tcg_temp_new_i32();
18584
18585 gen_load_gpr(t0, rs);
18586 gen_load_gpr(t1, rt);
18587 tcg_gen_trunc_tl_i32(t2, t0);
18588 tcg_gen_trunc_tl_i32(t3, t1);
18589 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18590 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18591 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18592 tcg_temp_free_i32(t2);
18593 tcg_temp_free_i32(t3);
18594 }
18595 break;
18596 case NM_EXTRV_R_W:
18597 check_dsp(ctx);
18598 tcg_gen_movi_tl(t0, rd >> 3);
18599 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18600 gen_store_gpr(t0, ret);
18601 break;
18602 default:
3a4ef3b7 18603 gen_reserved_instruction(ctx);
8b3698b2
SM
18604 break;
18605 }
18606 break;
18607 case NM_POOL32AXF_2_16_23:
18608 switch (extract32(ctx->opcode, 9, 3)) {
18609 case NM_DPAU_H_QBL:
18610 case NM_DPAQX_S_W_PH:
18611 case NM_DPSU_H_QBL:
18612 case NM_DPSQX_S_W_PH:
18613 case NM_MULSA_W_PH:
18614 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18615 break;
18616 case NM_EXTPV:
18617 check_dsp(ctx);
18618 tcg_gen_movi_tl(t0, rd >> 3);
18619 gen_helper_extp(t0, t0, v1_t, cpu_env);
18620 gen_store_gpr(t0, ret);
18621 break;
18622 case NM_MSUB:
18623 check_dsp(ctx);
18624 {
18625 int acc = extract32(ctx->opcode, 14, 2);
18626 TCGv_i64 t2 = tcg_temp_new_i64();
18627 TCGv_i64 t3 = tcg_temp_new_i64();
18628
18629 gen_load_gpr(t0, rs);
18630 gen_load_gpr(t1, rt);
18631 tcg_gen_ext_tl_i64(t2, t0);
18632 tcg_gen_ext_tl_i64(t3, t1);
18633 tcg_gen_mul_i64(t2, t2, t3);
18634 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18635 tcg_gen_sub_i64(t2, t3, t2);
18636 tcg_temp_free_i64(t3);
18637 gen_move_low32(cpu_LO[acc], t2);
18638 gen_move_high32(cpu_HI[acc], t2);
18639 tcg_temp_free_i64(t2);
18640 }
18641 break;
18642 case NM_EXTRV_RS_W:
18643 check_dsp(ctx);
18644 tcg_gen_movi_tl(t0, rd >> 3);
18645 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18646 gen_store_gpr(t0, ret);
18647 break;
18648 }
18649 break;
18650 case NM_POOL32AXF_2_24_31:
18651 switch (extract32(ctx->opcode, 9, 3)) {
18652 case NM_DPAU_H_QBR:
18653 case NM_DPAQX_SA_W_PH:
18654 case NM_DPSU_H_QBR:
18655 case NM_DPSQX_SA_W_PH:
18656 case NM_MULSAQ_S_W_PH:
18657 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18658 break;
18659 case NM_EXTPDPV:
18660 check_dsp(ctx);
18661 tcg_gen_movi_tl(t0, rd >> 3);
18662 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18663 gen_store_gpr(t0, ret);
18664 break;
18665 case NM_MSUBU:
18666 check_dsp(ctx);
18667 {
18668 int acc = extract32(ctx->opcode, 14, 2);
18669 TCGv_i64 t2 = tcg_temp_new_i64();
18670 TCGv_i64 t3 = tcg_temp_new_i64();
18671
18672 gen_load_gpr(t0, rs);
18673 gen_load_gpr(t1, rt);
18674 tcg_gen_ext32u_tl(t0, t0);
18675 tcg_gen_ext32u_tl(t1, t1);
18676 tcg_gen_extu_tl_i64(t2, t0);
18677 tcg_gen_extu_tl_i64(t3, t1);
18678 tcg_gen_mul_i64(t2, t2, t3);
18679 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18680 tcg_gen_sub_i64(t2, t3, t2);
18681 tcg_temp_free_i64(t3);
18682 gen_move_low32(cpu_LO[acc], t2);
18683 gen_move_high32(cpu_HI[acc], t2);
18684 tcg_temp_free_i64(t2);
18685 }
18686 break;
18687 case NM_EXTRV_S_H:
18688 check_dsp(ctx);
18689 tcg_gen_movi_tl(t0, rd >> 3);
18690 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18691 gen_store_gpr(t0, ret);
18692 break;
18693 }
18694 break;
18695 default:
3a4ef3b7 18696 gen_reserved_instruction(ctx);
8b3698b2
SM
18697 break;
18698 }
18699
18700 tcg_temp_free(t0);
18701 tcg_temp_free(t1);
18702
18703 tcg_temp_free(v0_t);
18704 tcg_temp_free(v1_t);
18705}
18706
4c75c985
SM
18707static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18708 int rt, int rs)
18709{
18710 int ret = rt;
18711 TCGv t0 = tcg_temp_new();
18712 TCGv v0_t = tcg_temp_new();
18713
18714 gen_load_gpr(v0_t, rs);
18715
18716 switch (opc) {
18717 case NM_ABSQ_S_QB:
908f6be1 18718 check_dsp_r2(ctx);
4c75c985
SM
18719 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18720 gen_store_gpr(v0_t, ret);
18721 break;
18722 case NM_ABSQ_S_PH:
18723 check_dsp(ctx);
18724 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18725 gen_store_gpr(v0_t, ret);
18726 break;
18727 case NM_ABSQ_S_W:
18728 check_dsp(ctx);
18729 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18730 gen_store_gpr(v0_t, ret);
18731 break;
18732 case NM_PRECEQ_W_PHL:
18733 check_dsp(ctx);
18734 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18735 tcg_gen_ext32s_tl(v0_t, v0_t);
18736 gen_store_gpr(v0_t, ret);
18737 break;
18738 case NM_PRECEQ_W_PHR:
18739 check_dsp(ctx);
18740 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18741 tcg_gen_shli_tl(v0_t, v0_t, 16);
18742 tcg_gen_ext32s_tl(v0_t, v0_t);
18743 gen_store_gpr(v0_t, ret);
18744 break;
18745 case NM_PRECEQU_PH_QBL:
18746 check_dsp(ctx);
18747 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18748 gen_store_gpr(v0_t, ret);
18749 break;
18750 case NM_PRECEQU_PH_QBR:
18751 check_dsp(ctx);
18752 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18753 gen_store_gpr(v0_t, ret);
18754 break;
18755 case NM_PRECEQU_PH_QBLA:
18756 check_dsp(ctx);
18757 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18758 gen_store_gpr(v0_t, ret);
18759 break;
18760 case NM_PRECEQU_PH_QBRA:
18761 check_dsp(ctx);
18762 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18763 gen_store_gpr(v0_t, ret);
18764 break;
18765 case NM_PRECEU_PH_QBL:
18766 check_dsp(ctx);
18767 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18768 gen_store_gpr(v0_t, ret);
18769 break;
18770 case NM_PRECEU_PH_QBR:
18771 check_dsp(ctx);
18772 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18773 gen_store_gpr(v0_t, ret);
18774 break;
18775 case NM_PRECEU_PH_QBLA:
18776 check_dsp(ctx);
18777 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18778 gen_store_gpr(v0_t, ret);
18779 break;
18780 case NM_PRECEU_PH_QBRA:
18781 check_dsp(ctx);
18782 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18783 gen_store_gpr(v0_t, ret);
18784 break;
18785 case NM_REPLV_PH:
18786 check_dsp(ctx);
18787 tcg_gen_ext16u_tl(v0_t, v0_t);
18788 tcg_gen_shli_tl(t0, v0_t, 16);
18789 tcg_gen_or_tl(v0_t, v0_t, t0);
18790 tcg_gen_ext32s_tl(v0_t, v0_t);
18791 gen_store_gpr(v0_t, ret);
18792 break;
18793 case NM_REPLV_QB:
18794 check_dsp(ctx);
18795 tcg_gen_ext8u_tl(v0_t, v0_t);
18796 tcg_gen_shli_tl(t0, v0_t, 8);
18797 tcg_gen_or_tl(v0_t, v0_t, t0);
18798 tcg_gen_shli_tl(t0, v0_t, 16);
18799 tcg_gen_or_tl(v0_t, v0_t, t0);
18800 tcg_gen_ext32s_tl(v0_t, v0_t);
18801 gen_store_gpr(v0_t, ret);
18802 break;
18803 case NM_BITREV:
18804 check_dsp(ctx);
18805 gen_helper_bitrev(v0_t, v0_t);
18806 gen_store_gpr(v0_t, ret);
18807 break;
18808 case NM_INSV:
18809 check_dsp(ctx);
18810 {
18811 TCGv tv0 = tcg_temp_new();
18812
18813 gen_load_gpr(tv0, rt);
18814 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18815 gen_store_gpr(v0_t, ret);
18816 tcg_temp_free(tv0);
18817 }
18818 break;
18819 case NM_RADDU_W_QB:
18820 check_dsp(ctx);
18821 gen_helper_raddu_w_qb(v0_t, v0_t);
18822 gen_store_gpr(v0_t, ret);
18823 break;
18824 case NM_BITSWAP:
18825 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18826 break;
18827 case NM_CLO:
fb32f8c8 18828 check_nms(ctx);
4c75c985
SM
18829 gen_cl(ctx, OPC_CLO, ret, rs);
18830 break;
18831 case NM_CLZ:
fb32f8c8 18832 check_nms(ctx);
4c75c985
SM
18833 gen_cl(ctx, OPC_CLZ, ret, rs);
18834 break;
18835 case NM_WSBH:
18836 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18837 break;
18838 default:
3a4ef3b7 18839 gen_reserved_instruction(ctx);
4c75c985
SM
18840 break;
18841 }
18842
18843 tcg_temp_free(v0_t);
18844 tcg_temp_free(t0);
18845}
18846
0b591184
SM
18847static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18848 int rt, int rs, int rd)
18849{
18850 TCGv t0 = tcg_temp_new();
18851 TCGv rs_t = tcg_temp_new();
18852
18853 gen_load_gpr(rs_t, rs);
18854
18855 switch (opc) {
18856 case NM_SHRA_R_QB:
908f6be1 18857 check_dsp_r2(ctx);
0b591184
SM
18858 tcg_gen_movi_tl(t0, rd >> 2);
18859 switch (extract32(ctx->opcode, 12, 1)) {
18860 case 0:
18861 /* NM_SHRA_QB */
18862 gen_helper_shra_qb(t0, t0, rs_t);
18863 gen_store_gpr(t0, rt);
18864 break;
18865 case 1:
18866 /* NM_SHRA_R_QB */
18867 gen_helper_shra_r_qb(t0, t0, rs_t);
18868 gen_store_gpr(t0, rt);
18869 break;
18870 }
18871 break;
18872 case NM_SHRL_PH:
908f6be1 18873 check_dsp_r2(ctx);
0b591184
SM
18874 tcg_gen_movi_tl(t0, rd >> 1);
18875 gen_helper_shrl_ph(t0, t0, rs_t);
18876 gen_store_gpr(t0, rt);
18877 break;
18878 case NM_REPL_QB:
18879 check_dsp(ctx);
18880 {
18881 int16_t imm;
18882 target_long result;
18883 imm = extract32(ctx->opcode, 13, 8);
18884 result = (uint32_t)imm << 24 |
18885 (uint32_t)imm << 16 |
18886 (uint32_t)imm << 8 |
18887 (uint32_t)imm;
18888 result = (int32_t)result;
18889 tcg_gen_movi_tl(t0, result);
18890 gen_store_gpr(t0, rt);
18891 }
18892 break;
18893 default:
3a4ef3b7 18894 gen_reserved_instruction(ctx);
0b591184
SM
18895 break;
18896 }
18897 tcg_temp_free(t0);
18898 tcg_temp_free(rs_t);
18899}
18900
2ed42efa 18901
64224187
YK
18902static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18903{
64224187
YK
18904 int rt = extract32(ctx->opcode, 21, 5);
18905 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 18906 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
18907
18908 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
18909 case NM_POOL32AXF_1:
18910 {
18911 int32_t op1 = extract32(ctx->opcode, 9, 3);
18912 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18913 }
18914 break;
18915 case NM_POOL32AXF_2:
8b3698b2
SM
18916 {
18917 int32_t op1 = extract32(ctx->opcode, 12, 2);
18918 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18919 }
2ed42efa 18920 break;
64224187 18921 case NM_POOL32AXF_4:
4c75c985
SM
18922 {
18923 int32_t op1 = extract32(ctx->opcode, 9, 7);
18924 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18925 }
2ed42efa 18926 break;
64224187
YK
18927 case NM_POOL32AXF_5:
18928 switch (extract32(ctx->opcode, 9, 7)) {
18929#ifndef CONFIG_USER_ONLY
18930 case NM_TLBP:
18931 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18932 break;
18933 case NM_TLBR:
18934 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18935 break;
18936 case NM_TLBWI:
18937 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18938 break;
18939 case NM_TLBWR:
18940 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18941 break;
18942 case NM_TLBINV:
18943 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18944 break;
18945 case NM_TLBINVF:
18946 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18947 break;
18948 case NM_DI:
18949 check_cp0_enabled(ctx);
18950 {
18951 TCGv t0 = tcg_temp_new();
18952
18953 save_cpu_state(ctx, 1);
18954 gen_helper_di(t0, cpu_env);
18955 gen_store_gpr(t0, rt);
18956 /* Stop translation as we may have switched the execution mode */
18957 ctx->base.is_jmp = DISAS_STOP;
18958 tcg_temp_free(t0);
18959 }
18960 break;
18961 case NM_EI:
18962 check_cp0_enabled(ctx);
18963 {
18964 TCGv t0 = tcg_temp_new();
18965
18966 save_cpu_state(ctx, 1);
18967 gen_helper_ei(t0, cpu_env);
18968 gen_store_gpr(t0, rt);
18969 /* Stop translation as we may have switched the execution mode */
18970 ctx->base.is_jmp = DISAS_STOP;
18971 tcg_temp_free(t0);
18972 }
18973 break;
18974 case NM_RDPGPR:
298d43c9 18975 check_cp0_enabled(ctx);
64224187
YK
18976 gen_load_srsgpr(rs, rt);
18977 break;
18978 case NM_WRPGPR:
298d43c9 18979 check_cp0_enabled(ctx);
64224187
YK
18980 gen_store_srsgpr(rs, rt);
18981 break;
18982 case NM_WAIT:
18983 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18984 break;
18985 case NM_DERET:
18986 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18987 break;
18988 case NM_ERETX:
18989 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18990 break;
18991#endif
18992 default:
3a4ef3b7 18993 gen_reserved_instruction(ctx);
64224187
YK
18994 break;
18995 }
18996 break;
2ed42efa 18997 case NM_POOL32AXF_7:
0b591184
SM
18998 {
18999 int32_t op1 = extract32(ctx->opcode, 9, 3);
19000 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19001 }
2ed42efa 19002 break;
64224187 19003 default:
3a4ef3b7 19004 gen_reserved_instruction(ctx);
64224187
YK
19005 break;
19006 }
19007}
19008
11d0fc10
SM
19009/* Immediate Value Compact Branches */
19010static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19011 int rt, int32_t imm, int32_t offset)
19012{
10266143 19013 TCGCond cond = TCG_COND_ALWAYS;
11d0fc10
SM
19014 TCGv t0 = tcg_temp_new();
19015 TCGv t1 = tcg_temp_new();
19016
19017 gen_load_gpr(t0, rt);
19018 tcg_gen_movi_tl(t1, imm);
19019 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19020
19021 /* Load needed operands and calculate btarget */
19022 switch (opc) {
19023 case NM_BEQIC:
19024 if (rt == 0 && imm == 0) {
19025 /* Unconditional branch */
19026 } else if (rt == 0 && imm != 0) {
19027 /* Treat as NOP */
19028 goto out;
19029 } else {
11d0fc10
SM
19030 cond = TCG_COND_EQ;
19031 }
19032 break;
19033 case NM_BBEQZC:
19034 case NM_BBNEZC:
fb32f8c8 19035 check_nms(ctx);
11d0fc10 19036 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
3a4ef3b7 19037 gen_reserved_instruction(ctx);
11d0fc10
SM
19038 goto out;
19039 } else if (rt == 0 && opc == NM_BBEQZC) {
19040 /* Unconditional branch */
19041 } else if (rt == 0 && opc == NM_BBNEZC) {
19042 /* Treat as NOP */
19043 goto out;
19044 } else {
19045 tcg_gen_shri_tl(t0, t0, imm);
19046 tcg_gen_andi_tl(t0, t0, 1);
19047 tcg_gen_movi_tl(t1, 0);
11d0fc10
SM
19048 if (opc == NM_BBEQZC) {
19049 cond = TCG_COND_EQ;
19050 } else {
19051 cond = TCG_COND_NE;
19052 }
19053 }
19054 break;
19055 case NM_BNEIC:
19056 if (rt == 0 && imm == 0) {
19057 /* Treat as NOP */
19058 goto out;
19059 } else if (rt == 0 && imm != 0) {
19060 /* Unconditional branch */
19061 } else {
11d0fc10
SM
19062 cond = TCG_COND_NE;
19063 }
19064 break;
19065 case NM_BGEIC:
19066 if (rt == 0 && imm == 0) {
19067 /* Unconditional branch */
19068 } else {
11d0fc10
SM
19069 cond = TCG_COND_GE;
19070 }
19071 break;
19072 case NM_BLTIC:
11d0fc10
SM
19073 cond = TCG_COND_LT;
19074 break;
19075 case NM_BGEIUC:
19076 if (rt == 0 && imm == 0) {
19077 /* Unconditional branch */
19078 } else {
11d0fc10
SM
19079 cond = TCG_COND_GEU;
19080 }
19081 break;
19082 case NM_BLTIUC:
11d0fc10
SM
19083 cond = TCG_COND_LTU;
19084 break;
19085 default:
19086 MIPS_INVAL("Immediate Value Compact branch");
3a4ef3b7 19087 gen_reserved_instruction(ctx);
11d0fc10
SM
19088 goto out;
19089 }
19090
697b7b6b
SM
19091 /* branch completion */
19092 clear_branch_hflags(ctx);
19093 ctx->base.is_jmp = DISAS_NORETURN;
19094
10266143 19095 if (cond == TCG_COND_ALWAYS) {
11d0fc10
SM
19096 /* Uncoditional compact branch */
19097 gen_goto_tb(ctx, 0, ctx->btarget);
19098 } else {
19099 /* Conditional compact branch */
19100 TCGLabel *fs = gen_new_label();
19101
19102 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19103
19104 gen_goto_tb(ctx, 1, ctx->btarget);
19105 gen_set_label(fs);
19106
19107 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19108 }
19109
19110out:
19111 tcg_temp_free(t0);
19112 tcg_temp_free(t1);
19113}
19114
19115/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19116static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19117 int rt)
19118{
19119 TCGv t0 = tcg_temp_new();
19120 TCGv t1 = tcg_temp_new();
19121
19122 /* load rs */
19123 gen_load_gpr(t0, rs);
19124
19125 /* link */
19126 if (rt != 0) {
19127 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19128 }
19129
19130 /* calculate btarget */
19131 tcg_gen_shli_tl(t0, t0, 1);
19132 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19133 gen_op_addr_add(ctx, btarget, t1, t0);
19134
697b7b6b
SM
19135 /* branch completion */
19136 clear_branch_hflags(ctx);
19137 ctx->base.is_jmp = DISAS_NORETURN;
19138
11d0fc10
SM
19139 /* unconditional branch to register */
19140 tcg_gen_mov_tl(cpu_PC, btarget);
19141 tcg_gen_lookup_and_goto_ptr();
19142
19143 tcg_temp_free(t0);
19144 tcg_temp_free(t1);
19145}
19146
19147/* nanoMIPS Branches */
19148static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19149 int rs, int rt, int32_t offset)
19150{
19151 int bcond_compute = 0;
19152 TCGv t0 = tcg_temp_new();
19153 TCGv t1 = tcg_temp_new();
19154
19155 /* Load needed operands and calculate btarget */
19156 switch (opc) {
19157 /* compact branch */
19158 case OPC_BGEC:
19159 case OPC_BLTC:
19160 gen_load_gpr(t0, rs);
19161 gen_load_gpr(t1, rt);
19162 bcond_compute = 1;
19163 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19164 break;
19165 case OPC_BGEUC:
19166 case OPC_BLTUC:
19167 if (rs == 0 || rs == rt) {
19168 /* OPC_BLEZALC, OPC_BGEZALC */
19169 /* OPC_BGTZALC, OPC_BLTZALC */
19170 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19171 }
19172 gen_load_gpr(t0, rs);
19173 gen_load_gpr(t1, rt);
19174 bcond_compute = 1;
19175 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19176 break;
19177 case OPC_BC:
19178 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19179 break;
19180 case OPC_BEQZC:
19181 if (rs != 0) {
19182 /* OPC_BEQZC, OPC_BNEZC */
19183 gen_load_gpr(t0, rs);
19184 bcond_compute = 1;
19185 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19186 } else {
19187 /* OPC_JIC, OPC_JIALC */
19188 TCGv tbase = tcg_temp_new();
19189 TCGv toffset = tcg_temp_new();
19190
19191 gen_load_gpr(tbase, rt);
19192 tcg_gen_movi_tl(toffset, offset);
19193 gen_op_addr_add(ctx, btarget, tbase, toffset);
19194 tcg_temp_free(tbase);
19195 tcg_temp_free(toffset);
19196 }
19197 break;
19198 default:
19199 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 19200 gen_reserved_instruction(ctx);
11d0fc10
SM
19201 goto out;
19202 }
19203
19204 if (bcond_compute == 0) {
19205 /* Uncoditional compact branch */
19206 switch (opc) {
19207 case OPC_BC:
19208 gen_goto_tb(ctx, 0, ctx->btarget);
19209 break;
19210 default:
19211 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 19212 gen_reserved_instruction(ctx);
11d0fc10
SM
19213 goto out;
19214 }
19215 } else {
19216 /* Conditional compact branch */
19217 TCGLabel *fs = gen_new_label();
19218
19219 switch (opc) {
19220 case OPC_BGEUC:
19221 if (rs == 0 && rt != 0) {
19222 /* OPC_BLEZALC */
19223 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19224 } else if (rs != 0 && rt != 0 && rs == rt) {
19225 /* OPC_BGEZALC */
19226 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19227 } else {
19228 /* OPC_BGEUC */
19229 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19230 }
19231 break;
19232 case OPC_BLTUC:
19233 if (rs == 0 && rt != 0) {
19234 /* OPC_BGTZALC */
19235 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19236 } else if (rs != 0 && rt != 0 && rs == rt) {
19237 /* OPC_BLTZALC */
19238 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19239 } else {
19240 /* OPC_BLTUC */
19241 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19242 }
19243 break;
19244 case OPC_BGEC:
19245 if (rs == 0 && rt != 0) {
19246 /* OPC_BLEZC */
19247 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19248 } else if (rs != 0 && rt != 0 && rs == rt) {
19249 /* OPC_BGEZC */
19250 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19251 } else {
19252 /* OPC_BGEC */
19253 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19254 }
19255 break;
19256 case OPC_BLTC:
19257 if (rs == 0 && rt != 0) {
19258 /* OPC_BGTZC */
19259 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19260 } else if (rs != 0 && rt != 0 && rs == rt) {
19261 /* OPC_BLTZC */
19262 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19263 } else {
19264 /* OPC_BLTC */
19265 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19266 }
19267 break;
19268 case OPC_BEQZC:
19269 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19270 break;
19271 default:
19272 MIPS_INVAL("Compact conditional branch/jump");
3a4ef3b7 19273 gen_reserved_instruction(ctx);
11d0fc10
SM
19274 goto out;
19275 }
19276
697b7b6b
SM
19277 /* branch completion */
19278 clear_branch_hflags(ctx);
19279 ctx->base.is_jmp = DISAS_NORETURN;
19280
11d0fc10
SM
19281 /* Generating branch here as compact branches don't have delay slot */
19282 gen_goto_tb(ctx, 1, ctx->btarget);
19283 gen_set_label(fs);
19284
19285 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19286 }
19287
19288out:
19289 tcg_temp_free(t0);
19290 tcg_temp_free(t1);
19291}
19292
19293
19294/* nanoMIPS CP1 Branches */
19295static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19296 int32_t ft, int32_t offset)
19297{
19298 target_ulong btarget;
19299 TCGv_i64 t0 = tcg_temp_new_i64();
19300
19301 gen_load_fpr64(ctx, t0, ft);
19302 tcg_gen_andi_i64(t0, t0, 1);
19303
19304 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19305
19306 switch (op) {
19307 case NM_BC1EQZC:
19308 tcg_gen_xori_i64(t0, t0, 1);
19309 ctx->hflags |= MIPS_HFLAG_BC;
19310 break;
19311 case NM_BC1NEZC:
19312 /* t0 already set */
19313 ctx->hflags |= MIPS_HFLAG_BC;
19314 break;
19315 default:
19316 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 19317 gen_reserved_instruction(ctx);
11d0fc10
SM
19318 goto out;
19319 }
19320
19321 tcg_gen_trunc_i64_tl(bcond, t0);
19322
19323 ctx->btarget = btarget;
19324
19325out:
19326 tcg_temp_free_i64(t0);
19327}
19328
eac52664
YK
19329
19330static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19331{
19332 TCGv t0, t1;
19333 t0 = tcg_temp_new();
19334 t1 = tcg_temp_new();
19335
19336 gen_load_gpr(t0, rs);
19337 gen_load_gpr(t1, rt);
19338
19339 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19340 /* PP.LSXS instructions require shifting */
19341 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 19342 case NM_SHXS:
fb32f8c8 19343 check_nms(ctx);
45152d05 19344 /* fall through */
fb32f8c8 19345 case NM_LHXS:
eac52664
YK
19346 case NM_LHUXS:
19347 tcg_gen_shli_tl(t0, t0, 1);
19348 break;
eac52664 19349 case NM_SWXS:
fb32f8c8 19350 check_nms(ctx);
45152d05 19351 /* fall through */
fb32f8c8 19352 case NM_LWXS:
eac52664
YK
19353 case NM_LWC1XS:
19354 case NM_SWC1XS:
19355 tcg_gen_shli_tl(t0, t0, 2);
19356 break;
19357 case NM_LDC1XS:
19358 case NM_SDC1XS:
19359 tcg_gen_shli_tl(t0, t0, 3);
19360 break;
19361 }
19362 }
19363 gen_op_addr_add(ctx, t0, t0, t1);
19364
19365 switch (extract32(ctx->opcode, 7, 4)) {
19366 case NM_LBX:
19367 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19368 MO_SB);
19369 gen_store_gpr(t0, rd);
19370 break;
19371 case NM_LHX:
19372 /*case NM_LHXS:*/
19373 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19374 MO_TESW);
19375 gen_store_gpr(t0, rd);
19376 break;
19377 case NM_LWX:
19378 /*case NM_LWXS:*/
19379 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19380 MO_TESL);
19381 gen_store_gpr(t0, rd);
19382 break;
19383 case NM_LBUX:
19384 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19385 MO_UB);
19386 gen_store_gpr(t0, rd);
19387 break;
19388 case NM_LHUX:
19389 /*case NM_LHUXS:*/
19390 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19391 MO_TEUW);
19392 gen_store_gpr(t0, rd);
19393 break;
19394 case NM_SBX:
fb32f8c8 19395 check_nms(ctx);
eac52664
YK
19396 gen_load_gpr(t1, rd);
19397 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19398 MO_8);
19399 break;
19400 case NM_SHX:
19401 /*case NM_SHXS:*/
fb32f8c8 19402 check_nms(ctx);
eac52664
YK
19403 gen_load_gpr(t1, rd);
19404 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19405 MO_TEUW);
19406 break;
19407 case NM_SWX:
19408 /*case NM_SWXS:*/
fb32f8c8 19409 check_nms(ctx);
eac52664
YK
19410 gen_load_gpr(t1, rd);
19411 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19412 MO_TEUL);
19413 break;
19414 case NM_LWC1X:
19415 /*case NM_LWC1XS:*/
19416 case NM_LDC1X:
19417 /*case NM_LDC1XS:*/
19418 case NM_SWC1X:
19419 /*case NM_SWC1XS:*/
19420 case NM_SDC1X:
19421 /*case NM_SDC1XS:*/
19422 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19423 check_cp1_enabled(ctx);
19424 switch (extract32(ctx->opcode, 7, 4)) {
19425 case NM_LWC1X:
19426 /*case NM_LWC1XS:*/
19427 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19428 break;
19429 case NM_LDC1X:
19430 /*case NM_LDC1XS:*/
19431 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19432 break;
19433 case NM_SWC1X:
19434 /*case NM_SWC1XS:*/
19435 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19436 break;
19437 case NM_SDC1X:
19438 /*case NM_SDC1XS:*/
19439 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19440 break;
19441 }
19442 } else {
19443 generate_exception_err(ctx, EXCP_CpU, 1);
19444 }
19445 break;
19446 default:
3a4ef3b7 19447 gen_reserved_instruction(ctx);
eac52664
YK
19448 break;
19449 }
19450
19451 tcg_temp_free(t0);
19452 tcg_temp_free(t1);
19453}
19454
579b8ea9
YK
19455static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19456{
19457 int rt, rs, rd;
19458
19459 rt = extract32(ctx->opcode, 21, 5);
19460 rs = extract32(ctx->opcode, 16, 5);
19461 rd = extract32(ctx->opcode, 11, 5);
19462
19463 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
3a4ef3b7 19464 gen_reserved_instruction(ctx);
579b8ea9
YK
19465 return;
19466 }
19467 check_cp1_enabled(ctx);
19468 switch (extract32(ctx->opcode, 0, 3)) {
19469 case NM_POOL32F_0:
19470 switch (extract32(ctx->opcode, 3, 7)) {
19471 case NM_RINT_S:
19472 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19473 break;
19474 case NM_RINT_D:
19475 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19476 break;
19477 case NM_CLASS_S:
19478 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19479 break;
19480 case NM_CLASS_D:
19481 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19482 break;
19483 case NM_ADD_S:
19484 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19485 break;
19486 case NM_ADD_D:
19487 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19488 break;
19489 case NM_SUB_S:
19490 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19491 break;
19492 case NM_SUB_D:
19493 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19494 break;
19495 case NM_MUL_S:
19496 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19497 break;
19498 case NM_MUL_D:
19499 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19500 break;
19501 case NM_DIV_S:
19502 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19503 break;
19504 case NM_DIV_D:
19505 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19506 break;
19507 case NM_SELEQZ_S:
19508 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19509 break;
19510 case NM_SELEQZ_D:
19511 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19512 break;
19513 case NM_SELNEZ_S:
19514 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19515 break;
19516 case NM_SELNEZ_D:
19517 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19518 break;
19519 case NM_SEL_S:
19520 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19521 break;
19522 case NM_SEL_D:
19523 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19524 break;
19525 case NM_MADDF_S:
19526 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19527 break;
19528 case NM_MADDF_D:
19529 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19530 break;
19531 case NM_MSUBF_S:
19532 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19533 break;
19534 case NM_MSUBF_D:
19535 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19536 break;
19537 default:
3a4ef3b7 19538 gen_reserved_instruction(ctx);
579b8ea9
YK
19539 break;
19540 }
19541 break;
19542 case NM_POOL32F_3:
19543 switch (extract32(ctx->opcode, 3, 3)) {
19544 case NM_MIN_FMT:
19545 switch (extract32(ctx->opcode, 9, 1)) {
19546 case FMT_SDPS_S:
19547 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19548 break;
19549 case FMT_SDPS_D:
19550 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19551 break;
19552 }
19553 break;
19554 case NM_MAX_FMT:
19555 switch (extract32(ctx->opcode, 9, 1)) {
19556 case FMT_SDPS_S:
19557 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19558 break;
19559 case FMT_SDPS_D:
19560 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19561 break;
19562 }
19563 break;
19564 case NM_MINA_FMT:
19565 switch (extract32(ctx->opcode, 9, 1)) {
19566 case FMT_SDPS_S:
19567 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19568 break;
19569 case FMT_SDPS_D:
19570 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19571 break;
19572 }
19573 break;
19574 case NM_MAXA_FMT:
19575 switch (extract32(ctx->opcode, 9, 1)) {
19576 case FMT_SDPS_S:
19577 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19578 break;
19579 case FMT_SDPS_D:
19580 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19581 break;
19582 }
19583 break;
19584 case NM_POOL32FXF:
19585 switch (extract32(ctx->opcode, 6, 8)) {
19586 case NM_CFC1:
19587 gen_cp1(ctx, OPC_CFC1, rt, rs);
19588 break;
19589 case NM_CTC1:
19590 gen_cp1(ctx, OPC_CTC1, rt, rs);
19591 break;
19592 case NM_MFC1:
19593 gen_cp1(ctx, OPC_MFC1, rt, rs);
19594 break;
19595 case NM_MTC1:
19596 gen_cp1(ctx, OPC_MTC1, rt, rs);
19597 break;
19598 case NM_MFHC1:
19599 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19600 break;
19601 case NM_MTHC1:
19602 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19603 break;
19604 case NM_CVT_S_PL:
19605 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19606 break;
19607 case NM_CVT_S_PU:
19608 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19609 break;
19610 default:
19611 switch (extract32(ctx->opcode, 6, 9)) {
19612 case NM_CVT_L_S:
19613 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19614 break;
19615 case NM_CVT_L_D:
19616 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19617 break;
19618 case NM_CVT_W_S:
19619 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19620 break;
19621 case NM_CVT_W_D:
19622 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19623 break;
19624 case NM_RSQRT_S:
19625 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19626 break;
19627 case NM_RSQRT_D:
19628 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19629 break;
19630 case NM_SQRT_S:
19631 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19632 break;
19633 case NM_SQRT_D:
19634 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19635 break;
19636 case NM_RECIP_S:
19637 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19638 break;
19639 case NM_RECIP_D:
19640 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19641 break;
19642 case NM_FLOOR_L_S:
19643 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19644 break;
19645 case NM_FLOOR_L_D:
19646 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19647 break;
19648 case NM_FLOOR_W_S:
19649 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19650 break;
19651 case NM_FLOOR_W_D:
19652 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19653 break;
19654 case NM_CEIL_L_S:
19655 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19656 break;
19657 case NM_CEIL_L_D:
19658 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19659 break;
19660 case NM_CEIL_W_S:
19661 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19662 break;
19663 case NM_CEIL_W_D:
19664 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19665 break;
19666 case NM_TRUNC_L_S:
19667 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19668 break;
19669 case NM_TRUNC_L_D:
19670 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19671 break;
19672 case NM_TRUNC_W_S:
19673 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19674 break;
19675 case NM_TRUNC_W_D:
19676 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19677 break;
19678 case NM_ROUND_L_S:
19679 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19680 break;
19681 case NM_ROUND_L_D:
19682 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19683 break;
19684 case NM_ROUND_W_S:
19685 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19686 break;
19687 case NM_ROUND_W_D:
19688 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19689 break;
19690 case NM_MOV_S:
19691 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19692 break;
19693 case NM_MOV_D:
19694 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19695 break;
19696 case NM_ABS_S:
19697 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19698 break;
19699 case NM_ABS_D:
19700 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19701 break;
19702 case NM_NEG_S:
19703 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19704 break;
19705 case NM_NEG_D:
19706 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19707 break;
19708 case NM_CVT_D_S:
19709 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19710 break;
19711 case NM_CVT_D_W:
19712 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19713 break;
19714 case NM_CVT_D_L:
19715 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19716 break;
19717 case NM_CVT_S_D:
19718 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19719 break;
19720 case NM_CVT_S_W:
19721 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19722 break;
19723 case NM_CVT_S_L:
19724 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19725 break;
19726 default:
3a4ef3b7 19727 gen_reserved_instruction(ctx);
579b8ea9
YK
19728 break;
19729 }
19730 break;
19731 }
19732 break;
19733 }
19734 break;
19735 case NM_POOL32F_5:
19736 switch (extract32(ctx->opcode, 3, 3)) {
19737 case NM_CMP_CONDN_S:
19738 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19739 break;
19740 case NM_CMP_CONDN_D:
19741 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19742 break;
19743 default:
3a4ef3b7 19744 gen_reserved_instruction(ctx);
579b8ea9
YK
19745 break;
19746 }
19747 break;
19748 default:
3a4ef3b7 19749 gen_reserved_instruction(ctx);
579b8ea9
YK
19750 break;
19751 }
19752}
19753
3285a3e4
SM
19754static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19755 int rd, int rs, int rt)
19756{
19757 int ret = rd;
19758 TCGv t0 = tcg_temp_new();
19759 TCGv v1_t = tcg_temp_new();
19760 TCGv v2_t = tcg_temp_new();
19761
19762 gen_load_gpr(v1_t, rs);
19763 gen_load_gpr(v2_t, rt);
19764
19765 switch (opc) {
19766 case NM_CMP_EQ_PH:
19767 check_dsp(ctx);
19768 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19769 break;
19770 case NM_CMP_LT_PH:
19771 check_dsp(ctx);
19772 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19773 break;
19774 case NM_CMP_LE_PH:
19775 check_dsp(ctx);
19776 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19777 break;
19778 case NM_CMPU_EQ_QB:
19779 check_dsp(ctx);
19780 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19781 break;
19782 case NM_CMPU_LT_QB:
19783 check_dsp(ctx);
19784 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19785 break;
19786 case NM_CMPU_LE_QB:
19787 check_dsp(ctx);
19788 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19789 break;
19790 case NM_CMPGU_EQ_QB:
19791 check_dsp(ctx);
19792 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19793 gen_store_gpr(v1_t, ret);
19794 break;
19795 case NM_CMPGU_LT_QB:
19796 check_dsp(ctx);
19797 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19798 gen_store_gpr(v1_t, ret);
19799 break;
19800 case NM_CMPGU_LE_QB:
19801 check_dsp(ctx);
19802 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19803 gen_store_gpr(v1_t, ret);
19804 break;
19805 case NM_CMPGDU_EQ_QB:
908f6be1 19806 check_dsp_r2(ctx);
3285a3e4
SM
19807 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19808 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19809 gen_store_gpr(v1_t, ret);
19810 break;
19811 case NM_CMPGDU_LT_QB:
908f6be1 19812 check_dsp_r2(ctx);
3285a3e4
SM
19813 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19814 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19815 gen_store_gpr(v1_t, ret);
19816 break;
19817 case NM_CMPGDU_LE_QB:
908f6be1 19818 check_dsp_r2(ctx);
3285a3e4
SM
19819 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19820 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19821 gen_store_gpr(v1_t, ret);
19822 break;
19823 case NM_PACKRL_PH:
19824 check_dsp(ctx);
19825 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19826 gen_store_gpr(v1_t, ret);
19827 break;
19828 case NM_PICK_QB:
19829 check_dsp(ctx);
19830 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19831 gen_store_gpr(v1_t, ret);
19832 break;
19833 case NM_PICK_PH:
19834 check_dsp(ctx);
19835 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19836 gen_store_gpr(v1_t, ret);
19837 break;
19838 case NM_ADDQ_S_W:
19839 check_dsp(ctx);
19840 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19841 gen_store_gpr(v1_t, ret);
19842 break;
19843 case NM_SUBQ_S_W:
19844 check_dsp(ctx);
19845 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19846 gen_store_gpr(v1_t, ret);
19847 break;
19848 case NM_ADDSC:
19849 check_dsp(ctx);
19850 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19851 gen_store_gpr(v1_t, ret);
19852 break;
19853 case NM_ADDWC:
19854 check_dsp(ctx);
19855 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19856 gen_store_gpr(v1_t, ret);
19857 break;
19858 case NM_ADDQ_S_PH:
19859 check_dsp(ctx);
19860 switch (extract32(ctx->opcode, 10, 1)) {
19861 case 0:
19862 /* ADDQ_PH */
19863 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19864 gen_store_gpr(v1_t, ret);
19865 break;
19866 case 1:
19867 /* ADDQ_S_PH */
19868 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19869 gen_store_gpr(v1_t, ret);
19870 break;
19871 }
19872 break;
19873 case NM_ADDQH_R_PH:
908f6be1 19874 check_dsp_r2(ctx);
3285a3e4
SM
19875 switch (extract32(ctx->opcode, 10, 1)) {
19876 case 0:
19877 /* ADDQH_PH */
19878 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19879 gen_store_gpr(v1_t, ret);
19880 break;
19881 case 1:
19882 /* ADDQH_R_PH */
19883 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19884 gen_store_gpr(v1_t, ret);
19885 break;
19886 }
19887 break;
19888 case NM_ADDQH_R_W:
908f6be1 19889 check_dsp_r2(ctx);
3285a3e4
SM
19890 switch (extract32(ctx->opcode, 10, 1)) {
19891 case 0:
19892 /* ADDQH_W */
19893 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19894 gen_store_gpr(v1_t, ret);
19895 break;
19896 case 1:
19897 /* ADDQH_R_W */
19898 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19899 gen_store_gpr(v1_t, ret);
19900 break;
19901 }
19902 break;
19903 case NM_ADDU_S_QB:
19904 check_dsp(ctx);
19905 switch (extract32(ctx->opcode, 10, 1)) {
19906 case 0:
19907 /* ADDU_QB */
19908 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19909 gen_store_gpr(v1_t, ret);
19910 break;
19911 case 1:
19912 /* ADDU_S_QB */
19913 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19914 gen_store_gpr(v1_t, ret);
19915 break;
19916 }
19917 break;
19918 case NM_ADDU_S_PH:
908f6be1 19919 check_dsp_r2(ctx);
3285a3e4
SM
19920 switch (extract32(ctx->opcode, 10, 1)) {
19921 case 0:
19922 /* ADDU_PH */
19923 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19924 gen_store_gpr(v1_t, ret);
19925 break;
19926 case 1:
19927 /* ADDU_S_PH */
19928 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19929 gen_store_gpr(v1_t, ret);
19930 break;
19931 }
19932 break;
19933 case NM_ADDUH_R_QB:
908f6be1 19934 check_dsp_r2(ctx);
3285a3e4
SM
19935 switch (extract32(ctx->opcode, 10, 1)) {
19936 case 0:
19937 /* ADDUH_QB */
19938 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19939 gen_store_gpr(v1_t, ret);
19940 break;
19941 case 1:
19942 /* ADDUH_R_QB */
19943 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19944 gen_store_gpr(v1_t, ret);
19945 break;
19946 }
19947 break;
19948 case NM_SHRAV_R_PH:
19949 check_dsp(ctx);
19950 switch (extract32(ctx->opcode, 10, 1)) {
19951 case 0:
19952 /* SHRAV_PH */
19953 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19954 gen_store_gpr(v1_t, ret);
19955 break;
19956 case 1:
19957 /* SHRAV_R_PH */
19958 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19959 gen_store_gpr(v1_t, ret);
19960 break;
19961 }
19962 break;
19963 case NM_SHRAV_R_QB:
908f6be1 19964 check_dsp_r2(ctx);
3285a3e4
SM
19965 switch (extract32(ctx->opcode, 10, 1)) {
19966 case 0:
19967 /* SHRAV_QB */
19968 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19969 gen_store_gpr(v1_t, ret);
19970 break;
19971 case 1:
19972 /* SHRAV_R_QB */
19973 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19974 gen_store_gpr(v1_t, ret);
19975 break;
19976 }
19977 break;
19978 case NM_SUBQ_S_PH:
19979 check_dsp(ctx);
19980 switch (extract32(ctx->opcode, 10, 1)) {
19981 case 0:
19982 /* SUBQ_PH */
19983 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19984 gen_store_gpr(v1_t, ret);
19985 break;
19986 case 1:
19987 /* SUBQ_S_PH */
19988 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19989 gen_store_gpr(v1_t, ret);
19990 break;
19991 }
19992 break;
19993 case NM_SUBQH_R_PH:
908f6be1 19994 check_dsp_r2(ctx);
3285a3e4
SM
19995 switch (extract32(ctx->opcode, 10, 1)) {
19996 case 0:
19997 /* SUBQH_PH */
19998 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19999 gen_store_gpr(v1_t, ret);
20000 break;
20001 case 1:
20002 /* SUBQH_R_PH */
20003 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20004 gen_store_gpr(v1_t, ret);
20005 break;
20006 }
20007 break;
20008 case NM_SUBQH_R_W:
908f6be1 20009 check_dsp_r2(ctx);
3285a3e4
SM
20010 switch (extract32(ctx->opcode, 10, 1)) {
20011 case 0:
20012 /* SUBQH_W */
20013 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20014 gen_store_gpr(v1_t, ret);
20015 break;
20016 case 1:
20017 /* SUBQH_R_W */
20018 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20019 gen_store_gpr(v1_t, ret);
20020 break;
20021 }
20022 break;
20023 case NM_SUBU_S_QB:
20024 check_dsp(ctx);
20025 switch (extract32(ctx->opcode, 10, 1)) {
20026 case 0:
20027 /* SUBU_QB */
20028 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20029 gen_store_gpr(v1_t, ret);
20030 break;
20031 case 1:
20032 /* SUBU_S_QB */
20033 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20034 gen_store_gpr(v1_t, ret);
20035 break;
20036 }
20037 break;
20038 case NM_SUBU_S_PH:
908f6be1 20039 check_dsp_r2(ctx);
3285a3e4
SM
20040 switch (extract32(ctx->opcode, 10, 1)) {
20041 case 0:
20042 /* SUBU_PH */
20043 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20044 gen_store_gpr(v1_t, ret);
20045 break;
20046 case 1:
20047 /* SUBU_S_PH */
20048 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20049 gen_store_gpr(v1_t, ret);
20050 break;
20051 }
20052 break;
20053 case NM_SUBUH_R_QB:
908f6be1 20054 check_dsp_r2(ctx);
3285a3e4
SM
20055 switch (extract32(ctx->opcode, 10, 1)) {
20056 case 0:
20057 /* SUBUH_QB */
20058 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20059 gen_store_gpr(v1_t, ret);
20060 break;
20061 case 1:
20062 /* SUBUH_R_QB */
20063 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20064 gen_store_gpr(v1_t, ret);
20065 break;
20066 }
20067 break;
20068 case NM_SHLLV_S_PH:
20069 check_dsp(ctx);
20070 switch (extract32(ctx->opcode, 10, 1)) {
20071 case 0:
20072 /* SHLLV_PH */
20073 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20074 gen_store_gpr(v1_t, ret);
20075 break;
20076 case 1:
20077 /* SHLLV_S_PH */
20078 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20079 gen_store_gpr(v1_t, ret);
20080 break;
20081 }
20082 break;
20083 case NM_PRECR_SRA_R_PH_W:
908f6be1 20084 check_dsp_r2(ctx);
3285a3e4
SM
20085 switch (extract32(ctx->opcode, 10, 1)) {
20086 case 0:
20087 /* PRECR_SRA_PH_W */
20088 {
20089 TCGv_i32 sa_t = tcg_const_i32(rd);
20090 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20091 cpu_gpr[rt]);
20092 gen_store_gpr(v1_t, rt);
20093 tcg_temp_free_i32(sa_t);
20094 }
20095 break;
20096 case 1:
20097 /* PRECR_SRA_R_PH_W */
20098 {
20099 TCGv_i32 sa_t = tcg_const_i32(rd);
20100 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20101 cpu_gpr[rt]);
20102 gen_store_gpr(v1_t, rt);
20103 tcg_temp_free_i32(sa_t);
20104 }
20105 break;
20106 }
20107 break;
20108 case NM_MULEU_S_PH_QBL:
20109 check_dsp(ctx);
20110 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20111 gen_store_gpr(v1_t, ret);
20112 break;
20113 case NM_MULEU_S_PH_QBR:
20114 check_dsp(ctx);
20115 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20116 gen_store_gpr(v1_t, ret);
20117 break;
20118 case NM_MULQ_RS_PH:
20119 check_dsp(ctx);
20120 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_MULQ_S_PH:
908f6be1 20124 check_dsp_r2(ctx);
3285a3e4
SM
20125 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20126 gen_store_gpr(v1_t, ret);
20127 break;
20128 case NM_MULQ_RS_W:
908f6be1 20129 check_dsp_r2(ctx);
3285a3e4
SM
20130 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20131 gen_store_gpr(v1_t, ret);
20132 break;
20133 case NM_MULQ_S_W:
908f6be1 20134 check_dsp_r2(ctx);
3285a3e4
SM
20135 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20136 gen_store_gpr(v1_t, ret);
20137 break;
20138 case NM_APPEND:
908f6be1 20139 check_dsp_r2(ctx);
3285a3e4
SM
20140 gen_load_gpr(t0, rs);
20141 if (rd != 0) {
20142 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20143 }
20144 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20145 break;
20146 case NM_MODSUB:
20147 check_dsp(ctx);
20148 gen_helper_modsub(v1_t, v1_t, v2_t);
20149 gen_store_gpr(v1_t, ret);
20150 break;
20151 case NM_SHRAV_R_W:
20152 check_dsp(ctx);
20153 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20154 gen_store_gpr(v1_t, ret);
20155 break;
20156 case NM_SHRLV_PH:
908f6be1 20157 check_dsp_r2(ctx);
3285a3e4
SM
20158 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20159 gen_store_gpr(v1_t, ret);
20160 break;
20161 case NM_SHRLV_QB:
20162 check_dsp(ctx);
20163 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20164 gen_store_gpr(v1_t, ret);
20165 break;
20166 case NM_SHLLV_QB:
20167 check_dsp(ctx);
20168 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20169 gen_store_gpr(v1_t, ret);
20170 break;
20171 case NM_SHLLV_S_W:
20172 check_dsp(ctx);
20173 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20174 gen_store_gpr(v1_t, ret);
20175 break;
20176 case NM_SHILO:
20177 check_dsp(ctx);
20178 {
20179 TCGv tv0 = tcg_temp_new();
20180 TCGv tv1 = tcg_temp_new();
20181 int16_t imm = extract32(ctx->opcode, 16, 7);
20182
20183 tcg_gen_movi_tl(tv0, rd >> 3);
20184 tcg_gen_movi_tl(tv1, imm);
20185 gen_helper_shilo(tv0, tv1, cpu_env);
20186 }
20187 break;
20188 case NM_MULEQ_S_W_PHL:
20189 check_dsp(ctx);
20190 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20191 gen_store_gpr(v1_t, ret);
20192 break;
20193 case NM_MULEQ_S_W_PHR:
20194 check_dsp(ctx);
20195 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20196 gen_store_gpr(v1_t, ret);
20197 break;
20198 case NM_MUL_S_PH:
908f6be1 20199 check_dsp_r2(ctx);
3285a3e4
SM
20200 switch (extract32(ctx->opcode, 10, 1)) {
20201 case 0:
20202 /* MUL_PH */
20203 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20206 case 1:
20207 /* MUL_S_PH */
20208 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20209 gen_store_gpr(v1_t, ret);
20210 break;
20211 }
20212 break;
20213 case NM_PRECR_QB_PH:
908f6be1 20214 check_dsp_r2(ctx);
3285a3e4
SM
20215 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20216 gen_store_gpr(v1_t, ret);
20217 break;
20218 case NM_PRECRQ_QB_PH:
20219 check_dsp(ctx);
20220 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20221 gen_store_gpr(v1_t, ret);
20222 break;
20223 case NM_PRECRQ_PH_W:
20224 check_dsp(ctx);
20225 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20226 gen_store_gpr(v1_t, ret);
20227 break;
20228 case NM_PRECRQ_RS_PH_W:
20229 check_dsp(ctx);
20230 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20231 gen_store_gpr(v1_t, ret);
20232 break;
20233 case NM_PRECRQU_S_QB_PH:
20234 check_dsp(ctx);
20235 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20236 gen_store_gpr(v1_t, ret);
20237 break;
20238 case NM_SHRA_R_W:
20239 check_dsp(ctx);
20240 tcg_gen_movi_tl(t0, rd);
20241 gen_helper_shra_r_w(v1_t, t0, v1_t);
20242 gen_store_gpr(v1_t, rt);
20243 break;
20244 case NM_SHRA_R_PH:
20245 check_dsp(ctx);
20246 tcg_gen_movi_tl(t0, rd >> 1);
20247 switch (extract32(ctx->opcode, 10, 1)) {
20248 case 0:
20249 /* SHRA_PH */
20250 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 20251 gen_store_gpr(v1_t, rt);
d5ebcbaf 20252 break;
3285a3e4
SM
20253 case 1:
20254 /* SHRA_R_PH */
20255 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20256 gen_store_gpr(v1_t, rt);
20257 break;
20258 }
20259 break;
20260 case NM_SHLL_S_PH:
20261 check_dsp(ctx);
20262 tcg_gen_movi_tl(t0, rd >> 1);
20263 switch (extract32(ctx->opcode, 10, 2)) {
20264 case 0:
20265 /* SHLL_PH */
20266 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20267 gen_store_gpr(v1_t, rt);
20268 break;
20269 case 2:
20270 /* SHLL_S_PH */
20271 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20272 gen_store_gpr(v1_t, rt);
20273 break;
20274 default:
3a4ef3b7 20275 gen_reserved_instruction(ctx);
3285a3e4
SM
20276 break;
20277 }
20278 break;
20279 case NM_SHLL_S_W:
20280 check_dsp(ctx);
20281 tcg_gen_movi_tl(t0, rd);
20282 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20283 gen_store_gpr(v1_t, rt);
20284 break;
20285 case NM_REPL_PH:
20286 check_dsp(ctx);
20287 {
20288 int16_t imm;
20289 imm = sextract32(ctx->opcode, 11, 11);
20290 imm = (int16_t)(imm << 6) >> 6;
20291 if (rt != 0) {
20292 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20293 }
20294 }
20295 break;
20296 default:
3a4ef3b7 20297 gen_reserved_instruction(ctx);
3285a3e4
SM
20298 break;
20299 }
20300}
20301
c0280983
YK
20302static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20303{
20304 uint16_t insn;
20305 uint32_t op;
eac52664 20306 int rt, rs, rd;
c0280983
YK
20307 int offset;
20308 int imm;
20309
0ab8e33a 20310 insn = translator_lduw(env, ctx->base.pc_next + 2);
c0280983
YK
20311 ctx->opcode = (ctx->opcode << 16) | insn;
20312
20313 rt = extract32(ctx->opcode, 21, 5);
20314 rs = extract32(ctx->opcode, 16, 5);
eac52664 20315 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
20316
20317 op = extract32(ctx->opcode, 26, 6);
20318 switch (op) {
20319 case NM_P_ADDIU:
20320 if (rt == 0) {
20321 /* P.RI */
20322 switch (extract32(ctx->opcode, 19, 2)) {
20323 case NM_SIGRIE:
20324 default:
3a4ef3b7 20325 gen_reserved_instruction(ctx);
c0280983
YK
20326 break;
20327 case NM_P_SYSCALL:
20328 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20329 generate_exception_end(ctx, EXCP_SYSCALL);
20330 } else {
3a4ef3b7 20331 gen_reserved_instruction(ctx);
c0280983
YK
20332 }
20333 break;
20334 case NM_BREAK:
20335 generate_exception_end(ctx, EXCP_BREAK);
20336 break;
20337 case NM_SDBBP:
20338 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20339 gen_helper_do_semihosting(cpu_env);
20340 } else {
20341 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 20342 gen_reserved_instruction(ctx);
c0280983
YK
20343 } else {
20344 generate_exception_end(ctx, EXCP_DBp);
20345 }
20346 }
20347 break;
20348 }
20349 } else {
20350 /* NM_ADDIU */
20351 imm = extract32(ctx->opcode, 0, 16);
20352 if (rs != 0) {
20353 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20354 } else {
20355 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20356 }
20357 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20358 }
20359 break;
20360 case NM_ADDIUPC:
20361 if (rt != 0) {
20362 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20363 extract32(ctx->opcode, 1, 20) << 1;
20364 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20365 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20366 }
20367 break;
20368 case NM_POOL32A:
e0cf0e65
YK
20369 switch (ctx->opcode & 0x07) {
20370 case NM_POOL32A0:
0a1a6ed7 20371 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 20372 break;
3285a3e4
SM
20373 case NM_POOL32A5:
20374 {
20375 int32_t op1 = extract32(ctx->opcode, 3, 7);
20376 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20377 }
20378 break;
e0cf0e65 20379 case NM_POOL32A7:
64224187 20380 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
20381 case NM_P_LSX:
20382 gen_p_lsx(ctx, rd, rs, rt);
20383 break;
20384 case NM_LSA:
7480515f
AM
20385 /*
20386 * In nanoMIPS, the shift field directly encodes the shift
eac52664 20387 * amount, meaning that the supported shift values are in
7480515f
AM
20388 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20389 */
a685f7d0 20390 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
eac52664 20391 break;
821f2008
JH
20392 case NM_EXTW:
20393 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20394 break;
64224187
YK
20395 case NM_POOL32AXF:
20396 gen_pool32axf_nanomips_insn(env, ctx);
20397 break;
20398 default:
3a4ef3b7 20399 gen_reserved_instruction(ctx);
64224187
YK
20400 break;
20401 }
e0cf0e65
YK
20402 break;
20403 default:
3a4ef3b7 20404 gen_reserved_instruction(ctx);
e0cf0e65
YK
20405 break;
20406 }
c0280983
YK
20407 break;
20408 case NM_P_GP_W:
20409 switch (ctx->opcode & 0x03) {
20410 case NM_ADDIUGP_W:
20411 if (rt != 0) {
20412 offset = extract32(ctx->opcode, 0, 21);
20413 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20414 }
20415 break;
20416 case NM_LWGP:
20417 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20418 break;
20419 case NM_SWGP:
20420 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20421 break;
20422 default:
3a4ef3b7 20423 gen_reserved_instruction(ctx);
c0280983
YK
20424 break;
20425 }
20426 break;
20427 case NM_P48I:
7ef009b2 20428 {
0ab8e33a 20429 insn = translator_lduw(env, ctx->base.pc_next + 4);
7ef009b2
YK
20430 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20431 switch (extract32(ctx->opcode, 16, 5)) {
20432 case NM_LI48:
fb32f8c8 20433 check_nms(ctx);
7ef009b2
YK
20434 if (rt != 0) {
20435 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20436 }
20437 break;
20438 case NM_ADDIU48:
fb32f8c8 20439 check_nms(ctx);
7ef009b2
YK
20440 if (rt != 0) {
20441 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20442 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20443 }
20444 break;
20445 case NM_ADDIUGP48:
fb32f8c8 20446 check_nms(ctx);
7ef009b2
YK
20447 if (rt != 0) {
20448 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20449 }
20450 break;
20451 case NM_ADDIUPC48:
fb32f8c8 20452 check_nms(ctx);
7ef009b2
YK
20453 if (rt != 0) {
20454 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20455 addr_off);
20456
20457 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20458 }
20459 break;
20460 case NM_LWPC48:
fb32f8c8 20461 check_nms(ctx);
7ef009b2
YK
20462 if (rt != 0) {
20463 TCGv t0;
20464 t0 = tcg_temp_new();
20465
20466 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20467 addr_off);
20468
20469 tcg_gen_movi_tl(t0, addr);
20470 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20471 tcg_temp_free(t0);
20472 }
20473 break;
20474 case NM_SWPC48:
fb32f8c8 20475 check_nms(ctx);
7ef009b2
YK
20476 {
20477 TCGv t0, t1;
20478 t0 = tcg_temp_new();
20479 t1 = tcg_temp_new();
20480
20481 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20482 addr_off);
20483
20484 tcg_gen_movi_tl(t0, addr);
20485 gen_load_gpr(t1, rt);
20486
20487 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20488
20489 tcg_temp_free(t0);
20490 tcg_temp_free(t1);
20491 }
20492 break;
20493 default:
3a4ef3b7 20494 gen_reserved_instruction(ctx);
7ef009b2
YK
20495 break;
20496 }
20497 return 6;
20498 }
c0280983
YK
20499 case NM_P_U12:
20500 switch (extract32(ctx->opcode, 12, 4)) {
20501 case NM_ORI:
20502 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20503 break;
20504 case NM_XORI:
20505 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20506 break;
20507 case NM_ANDI:
20508 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20509 break;
20510 case NM_P_SR:
20511 switch (extract32(ctx->opcode, 20, 1)) {
20512 case NM_PP_SR:
20513 switch (ctx->opcode & 3) {
20514 case NM_SAVE:
20515 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20516 extract32(ctx->opcode, 2, 1),
20517 extract32(ctx->opcode, 3, 9) << 3);
20518 break;
20519 case NM_RESTORE:
20520 case NM_RESTORE_JRC:
20521 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20522 extract32(ctx->opcode, 2, 1),
20523 extract32(ctx->opcode, 3, 9) << 3);
20524 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20525 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20526 }
20527 break;
20528 default:
3a4ef3b7 20529 gen_reserved_instruction(ctx);
c0280983
YK
20530 break;
20531 }
20532 break;
20533 case NM_P_SR_F:
3a4ef3b7 20534 gen_reserved_instruction(ctx);
c0280983
YK
20535 break;
20536 }
20537 break;
20538 case NM_SLTI:
20539 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20540 break;
20541 case NM_SLTIU:
20542 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20543 break;
20544 case NM_SEQI:
20545 {
20546 TCGv t0 = tcg_temp_new();
20547
20548 imm = extract32(ctx->opcode, 0, 12);
20549 gen_load_gpr(t0, rs);
20550 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20551 gen_store_gpr(t0, rt);
20552
20553 tcg_temp_free(t0);
20554 }
20555 break;
20556 case NM_ADDIUNEG:
20557 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20558 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20559 break;
20560 case NM_P_SHIFT:
20561 {
20562 int shift = extract32(ctx->opcode, 0, 5);
20563 switch (extract32(ctx->opcode, 5, 4)) {
20564 case NM_P_SLL:
20565 if (rt == 0 && shift == 0) {
20566 /* NOP */
20567 } else if (rt == 0 && shift == 3) {
20568 /* EHB - treat as NOP */
20569 } else if (rt == 0 && shift == 5) {
20570 /* PAUSE - treat as NOP */
20571 } else if (rt == 0 && shift == 6) {
20572 /* SYNC */
20573 gen_sync(extract32(ctx->opcode, 16, 5));
20574 } else {
20575 /* SLL */
20576 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20577 extract32(ctx->opcode, 0, 5));
20578 }
20579 break;
20580 case NM_SRL:
20581 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20582 extract32(ctx->opcode, 0, 5));
20583 break;
20584 case NM_SRA:
20585 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20586 extract32(ctx->opcode, 0, 5));
20587 break;
20588 case NM_ROTR:
20589 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20590 extract32(ctx->opcode, 0, 5));
20591 break;
20592 }
20593 }
20594 break;
20595 case NM_P_ROTX:
fb32f8c8 20596 check_nms(ctx);
e222f506
MF
20597 if (rt != 0) {
20598 TCGv t0 = tcg_temp_new();
20599 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20600 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20601 << 1);
20602 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20603
20604 gen_load_gpr(t0, rs);
20605 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20606 tcg_temp_free(t0);
20607
20608 tcg_temp_free_i32(shift);
20609 tcg_temp_free_i32(shiftx);
20610 tcg_temp_free_i32(stripe);
20611 }
c0280983
YK
20612 break;
20613 case NM_P_INS:
20614 switch (((ctx->opcode >> 10) & 2) |
20615 (extract32(ctx->opcode, 5, 1))) {
20616 case NM_INS:
fb32f8c8 20617 check_nms(ctx);
c0280983
YK
20618 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20619 extract32(ctx->opcode, 6, 5));
20620 break;
20621 default:
3a4ef3b7 20622 gen_reserved_instruction(ctx);
c0280983
YK
20623 break;
20624 }
20625 break;
20626 case NM_P_EXT:
20627 switch (((ctx->opcode >> 10) & 2) |
20628 (extract32(ctx->opcode, 5, 1))) {
20629 case NM_EXT:
fb32f8c8 20630 check_nms(ctx);
c0280983
YK
20631 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20632 extract32(ctx->opcode, 6, 5));
20633 break;
20634 default:
3a4ef3b7 20635 gen_reserved_instruction(ctx);
c0280983
YK
20636 break;
20637 }
20638 break;
20639 default:
3a4ef3b7 20640 gen_reserved_instruction(ctx);
c0280983
YK
20641 break;
20642 }
20643 break;
20644 case NM_POOL32F:
579b8ea9 20645 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
20646 break;
20647 case NM_POOL32S:
20648 break;
20649 case NM_P_LUI:
20650 switch (extract32(ctx->opcode, 1, 1)) {
20651 case NM_LUI:
20652 if (rt != 0) {
20653 tcg_gen_movi_tl(cpu_gpr[rt],
20654 sextract32(ctx->opcode, 0, 1) << 31 |
20655 extract32(ctx->opcode, 2, 10) << 21 |
20656 extract32(ctx->opcode, 12, 9) << 12);
20657 }
20658 break;
20659 case NM_ALUIPC:
20660 if (rt != 0) {
20661 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20662 extract32(ctx->opcode, 2, 10) << 21 |
20663 extract32(ctx->opcode, 12, 9) << 12;
20664 target_long addr;
20665 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20666 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20667 }
20668 break;
20669 }
20670 break;
20671 case NM_P_GP_BH:
8f1d9b6d
YK
20672 {
20673 uint32_t u = extract32(ctx->opcode, 0, 18);
20674
20675 switch (extract32(ctx->opcode, 18, 3)) {
20676 case NM_LBGP:
20677 gen_ld(ctx, OPC_LB, rt, 28, u);
20678 break;
20679 case NM_SBGP:
20680 gen_st(ctx, OPC_SB, rt, 28, u);
20681 break;
20682 case NM_LBUGP:
20683 gen_ld(ctx, OPC_LBU, rt, 28, u);
20684 break;
20685 case NM_ADDIUGP_B:
20686 if (rt != 0) {
20687 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20688 }
20689 break;
20690 case NM_P_GP_LH:
20691 u &= ~1;
20692 switch (ctx->opcode & 1) {
20693 case NM_LHGP:
20694 gen_ld(ctx, OPC_LH, rt, 28, u);
20695 break;
20696 case NM_LHUGP:
20697 gen_ld(ctx, OPC_LHU, rt, 28, u);
20698 break;
20699 }
20700 break;
20701 case NM_P_GP_SH:
20702 u &= ~1;
20703 switch (ctx->opcode & 1) {
20704 case NM_SHGP:
20705 gen_st(ctx, OPC_SH, rt, 28, u);
20706 break;
20707 default:
3a4ef3b7 20708 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20709 break;
20710 }
20711 break;
20712 case NM_P_GP_CP1:
20713 u &= ~0x3;
20714 switch (ctx->opcode & 0x3) {
20715 case NM_LWC1GP:
20716 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20717 break;
20718 case NM_LDC1GP:
20719 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20720 break;
20721 case NM_SWC1GP:
20722 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20723 break;
20724 case NM_SDC1GP:
20725 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20726 break;
20727 }
20728 break;
20729 default:
3a4ef3b7 20730 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20731 break;
20732 }
20733 }
c0280983
YK
20734 break;
20735 case NM_P_LS_U12:
8f1d9b6d
YK
20736 {
20737 uint32_t u = extract32(ctx->opcode, 0, 12);
20738
20739 switch (extract32(ctx->opcode, 12, 4)) {
20740 case NM_P_PREFU12:
20741 if (rt == 31) {
20742 /* SYNCI */
7480515f
AM
20743 /*
20744 * Break the TB to be able to sync copied instructions
20745 * immediately.
20746 */
8f1d9b6d
YK
20747 ctx->base.is_jmp = DISAS_STOP;
20748 } else {
20749 /* PREF */
20750 /* Treat as NOP. */
20751 }
20752 break;
20753 case NM_LB:
20754 gen_ld(ctx, OPC_LB, rt, rs, u);
20755 break;
20756 case NM_LH:
20757 gen_ld(ctx, OPC_LH, rt, rs, u);
20758 break;
20759 case NM_LW:
20760 gen_ld(ctx, OPC_LW, rt, rs, u);
20761 break;
20762 case NM_LBU:
20763 gen_ld(ctx, OPC_LBU, rt, rs, u);
20764 break;
20765 case NM_LHU:
20766 gen_ld(ctx, OPC_LHU, rt, rs, u);
20767 break;
20768 case NM_SB:
20769 gen_st(ctx, OPC_SB, rt, rs, u);
20770 break;
20771 case NM_SH:
20772 gen_st(ctx, OPC_SH, rt, rs, u);
20773 break;
20774 case NM_SW:
20775 gen_st(ctx, OPC_SW, rt, rs, u);
20776 break;
20777 case NM_LWC1:
20778 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20779 break;
20780 case NM_LDC1:
20781 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20782 break;
20783 case NM_SWC1:
20784 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20785 break;
20786 case NM_SDC1:
20787 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20788 break;
20789 default:
3a4ef3b7 20790 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20791 break;
20792 }
20793 }
c0280983
YK
20794 break;
20795 case NM_P_LS_S9:
8f1d9b6d
YK
20796 {
20797 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20798 extract32(ctx->opcode, 0, 8);
20799
20800 switch (extract32(ctx->opcode, 8, 3)) {
20801 case NM_P_LS_S0:
20802 switch (extract32(ctx->opcode, 11, 4)) {
20803 case NM_LBS9:
20804 gen_ld(ctx, OPC_LB, rt, rs, s);
20805 break;
20806 case NM_LHS9:
20807 gen_ld(ctx, OPC_LH, rt, rs, s);
20808 break;
20809 case NM_LWS9:
20810 gen_ld(ctx, OPC_LW, rt, rs, s);
20811 break;
20812 case NM_LBUS9:
20813 gen_ld(ctx, OPC_LBU, rt, rs, s);
20814 break;
20815 case NM_LHUS9:
20816 gen_ld(ctx, OPC_LHU, rt, rs, s);
20817 break;
20818 case NM_SBS9:
20819 gen_st(ctx, OPC_SB, rt, rs, s);
20820 break;
20821 case NM_SHS9:
20822 gen_st(ctx, OPC_SH, rt, rs, s);
20823 break;
20824 case NM_SWS9:
20825 gen_st(ctx, OPC_SW, rt, rs, s);
20826 break;
20827 case NM_LWC1S9:
20828 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20829 break;
20830 case NM_LDC1S9:
20831 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20832 break;
20833 case NM_SWC1S9:
20834 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20835 break;
20836 case NM_SDC1S9:
20837 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20838 break;
20839 case NM_P_PREFS9:
20840 if (rt == 31) {
20841 /* SYNCI */
7480515f
AM
20842 /*
20843 * Break the TB to be able to sync copied instructions
20844 * immediately.
20845 */
8f1d9b6d
YK
20846 ctx->base.is_jmp = DISAS_STOP;
20847 } else {
20848 /* PREF */
20849 /* Treat as NOP. */
20850 }
20851 break;
20852 default:
3a4ef3b7 20853 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20854 break;
20855 }
20856 break;
20857 case NM_P_LS_S1:
20858 switch (extract32(ctx->opcode, 11, 4)) {
20859 case NM_UALH:
20860 case NM_UASH:
fb32f8c8 20861 check_nms(ctx);
8f1d9b6d
YK
20862 {
20863 TCGv t0 = tcg_temp_new();
20864 TCGv t1 = tcg_temp_new();
20865
20866 gen_base_offset_addr(ctx, t0, rs, s);
20867
20868 switch (extract32(ctx->opcode, 11, 4)) {
20869 case NM_UALH:
20870 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20871 MO_UNALN);
20872 gen_store_gpr(t0, rt);
20873 break;
20874 case NM_UASH:
20875 gen_load_gpr(t1, rt);
20876 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20877 MO_UNALN);
20878 break;
20879 }
20880 tcg_temp_free(t0);
20881 tcg_temp_free(t1);
20882 }
20883 break;
20884 case NM_P_LL:
20885 switch (ctx->opcode & 0x03) {
20886 case NM_LL:
20887 gen_ld(ctx, OPC_LL, rt, rs, s);
20888 break;
20889 case NM_LLWP:
0b16dcd1
AR
20890 check_xnp(ctx);
20891 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
20892 break;
20893 }
20894 break;
20895 case NM_P_SC:
20896 switch (ctx->opcode & 0x03) {
20897 case NM_SC:
33a07fa2 20898 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
20899 break;
20900 case NM_SCWP:
0b16dcd1 20901 check_xnp(ctx);
8d5388c1
AM
20902 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20903 false);
8f1d9b6d
YK
20904 break;
20905 }
20906 break;
20907 case NM_CACHE:
20908 check_cp0_enabled(ctx);
20909 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20910 gen_cache_operation(ctx, rt, rs, s);
20911 }
20912 break;
20913 }
20914 break;
d046a9ea
DN
20915 case NM_P_LS_E0:
20916 switch (extract32(ctx->opcode, 11, 4)) {
20917 case NM_LBE:
20918 check_eva(ctx);
20919 check_cp0_enabled(ctx);
20920 gen_ld(ctx, OPC_LBE, rt, rs, s);
20921 break;
20922 case NM_SBE:
20923 check_eva(ctx);
20924 check_cp0_enabled(ctx);
20925 gen_st(ctx, OPC_SBE, rt, rs, s);
20926 break;
20927 case NM_LBUE:
20928 check_eva(ctx);
20929 check_cp0_enabled(ctx);
20930 gen_ld(ctx, OPC_LBUE, rt, rs, s);
20931 break;
20932 case NM_P_PREFE:
20933 if (rt == 31) {
20934 /* case NM_SYNCIE */
20935 check_eva(ctx);
20936 check_cp0_enabled(ctx);
7480515f
AM
20937 /*
20938 * Break the TB to be able to sync copied instructions
20939 * immediately.
20940 */
d046a9ea
DN
20941 ctx->base.is_jmp = DISAS_STOP;
20942 } else {
20943 /* case NM_PREFE */
20944 check_eva(ctx);
20945 check_cp0_enabled(ctx);
20946 /* Treat as NOP. */
20947 }
20948 break;
20949 case NM_LHE:
20950 check_eva(ctx);
20951 check_cp0_enabled(ctx);
20952 gen_ld(ctx, OPC_LHE, rt, rs, s);
20953 break;
20954 case NM_SHE:
20955 check_eva(ctx);
20956 check_cp0_enabled(ctx);
20957 gen_st(ctx, OPC_SHE, rt, rs, s);
20958 break;
20959 case NM_LHUE:
20960 check_eva(ctx);
20961 check_cp0_enabled(ctx);
20962 gen_ld(ctx, OPC_LHUE, rt, rs, s);
20963 break;
20964 case NM_CACHEE:
84c2fdc3
PMD
20965 check_eva(ctx);
20966 check_cp0_enabled(ctx);
d046a9ea
DN
20967 check_nms_dl_il_sl_tl_l2c(ctx);
20968 gen_cache_operation(ctx, rt, rs, s);
20969 break;
20970 case NM_LWE:
20971 check_eva(ctx);
20972 check_cp0_enabled(ctx);
20973 gen_ld(ctx, OPC_LWE, rt, rs, s);
20974 break;
20975 case NM_SWE:
20976 check_eva(ctx);
20977 check_cp0_enabled(ctx);
20978 gen_st(ctx, OPC_SWE, rt, rs, s);
20979 break;
20980 case NM_P_LLE:
20981 switch (extract32(ctx->opcode, 2, 2)) {
20982 case NM_LLE:
20983 check_xnp(ctx);
20984 check_eva(ctx);
20985 check_cp0_enabled(ctx);
20986 gen_ld(ctx, OPC_LLE, rt, rs, s);
20987 break;
20988 case NM_LLWPE:
20989 check_xnp(ctx);
20990 check_eva(ctx);
20991 check_cp0_enabled(ctx);
20992 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 20993 break;
d046a9ea 20994 default:
3a4ef3b7 20995 gen_reserved_instruction(ctx);
d046a9ea
DN
20996 break;
20997 }
20998 break;
20999 case NM_P_SCE:
21000 switch (extract32(ctx->opcode, 2, 2)) {
21001 case NM_SCE:
21002 check_xnp(ctx);
21003 check_eva(ctx);
21004 check_cp0_enabled(ctx);
33a07fa2 21005 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
21006 break;
21007 case NM_SCWPE:
21008 check_xnp(ctx);
21009 check_eva(ctx);
21010 check_cp0_enabled(ctx);
8d5388c1
AM
21011 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21012 true);
2431a422 21013 break;
d046a9ea 21014 default:
3a4ef3b7 21015 gen_reserved_instruction(ctx);
d046a9ea
DN
21016 break;
21017 }
21018 break;
21019 }
21020 break;
8f1d9b6d
YK
21021 case NM_P_LS_WM:
21022 case NM_P_LS_UAWM:
fb32f8c8 21023 check_nms(ctx);
8f1d9b6d
YK
21024 {
21025 int count = extract32(ctx->opcode, 12, 3);
21026 int counter = 0;
21027
21028 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21029 extract32(ctx->opcode, 0, 8);
21030 TCGv va = tcg_temp_new();
21031 TCGv t1 = tcg_temp_new();
14776ab5 21032 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
21033 NM_P_LS_UAWM ? MO_UNALN : 0;
21034
21035 count = (count == 0) ? 8 : count;
21036 while (counter != count) {
21037 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21038 int this_offset = offset + (counter << 2);
21039
21040 gen_base_offset_addr(ctx, va, rs, this_offset);
21041
21042 switch (extract32(ctx->opcode, 11, 1)) {
21043 case NM_LWM:
21044 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21045 memop | MO_TESL);
21046 gen_store_gpr(t1, this_rt);
21047 if ((this_rt == rs) &&
21048 (counter != (count - 1))) {
21049 /* UNPREDICTABLE */
21050 }
21051 break;
21052 case NM_SWM:
21053 this_rt = (rt == 0) ? 0 : this_rt;
21054 gen_load_gpr(t1, this_rt);
21055 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21056 memop | MO_TEUL);
21057 break;
21058 }
21059 counter++;
21060 }
21061 tcg_temp_free(va);
21062 tcg_temp_free(t1);
21063 }
21064 break;
21065 default:
3a4ef3b7 21066 gen_reserved_instruction(ctx);
8f1d9b6d
YK
21067 break;
21068 }
21069 }
c0280983
YK
21070 break;
21071 case NM_MOVE_BALC:
fb32f8c8 21072 check_nms(ctx);
11d0fc10
SM
21073 {
21074 TCGv t0 = tcg_temp_new();
21075 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21076 extract32(ctx->opcode, 1, 20) << 1;
21077 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21078 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21079 extract32(ctx->opcode, 21, 3));
21080 gen_load_gpr(t0, rt);
21081 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21082 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21083 tcg_temp_free(t0);
21084 }
c0280983
YK
21085 break;
21086 case NM_P_BAL:
11d0fc10
SM
21087 {
21088 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21089 extract32(ctx->opcode, 1, 24) << 1;
21090
21091 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21092 /* BC */
21093 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21094 } else {
21095 /* BALC */
21096 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21097 }
21098 }
c0280983
YK
21099 break;
21100 case NM_P_J:
11d0fc10
SM
21101 switch (extract32(ctx->opcode, 12, 4)) {
21102 case NM_JALRC:
21103 case NM_JALRC_HB:
21104 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21105 break;
21106 case NM_P_BALRSC:
21107 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21108 break;
21109 default:
3a4ef3b7 21110 gen_reserved_instruction(ctx);
11d0fc10
SM
21111 break;
21112 }
c0280983
YK
21113 break;
21114 case NM_P_BR1:
11d0fc10
SM
21115 {
21116 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21117 extract32(ctx->opcode, 1, 13) << 1;
21118 switch (extract32(ctx->opcode, 14, 2)) {
21119 case NM_BEQC:
fb32f8c8 21120 check_nms(ctx);
11d0fc10
SM
21121 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21122 break;
21123 case NM_P_BR3A:
21124 s = sextract32(ctx->opcode, 0, 1) << 14 |
21125 extract32(ctx->opcode, 1, 13) << 1;
21126 check_cp1_enabled(ctx);
21127 switch (extract32(ctx->opcode, 16, 5)) {
21128 case NM_BC1EQZC:
21129 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21130 break;
21131 case NM_BC1NEZC:
21132 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21133 break;
6d033ca7 21134 case NM_BPOSGE32C:
908f6be1 21135 check_dsp_r3(ctx);
6d033ca7
SM
21136 {
21137 int32_t imm = extract32(ctx->opcode, 1, 13) |
21138 extract32(ctx->opcode, 0, 1) << 13;
21139
21140 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21141 imm);
21142 }
21143 break;
11d0fc10 21144 default:
3a4ef3b7 21145 gen_reserved_instruction(ctx);
11d0fc10
SM
21146 break;
21147 }
21148 break;
21149 case NM_BGEC:
21150 if (rs == rt) {
21151 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21152 } else {
21153 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21154 }
21155 break;
21156 case NM_BGEUC:
21157 if (rs == rt || rt == 0) {
21158 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21159 } else if (rs == 0) {
21160 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21161 } else {
21162 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21163 }
21164 break;
21165 }
21166 }
c0280983
YK
21167 break;
21168 case NM_P_BR2:
11d0fc10
SM
21169 {
21170 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21171 extract32(ctx->opcode, 1, 13) << 1;
21172 switch (extract32(ctx->opcode, 14, 2)) {
21173 case NM_BNEC:
fb32f8c8 21174 check_nms(ctx);
11d0fc10
SM
21175 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21176 break;
21177 case NM_BLTC:
21178 if (rs != 0 && rt != 0 && rs == rt) {
21179 /* NOP */
21180 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21181 } else {
21182 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21183 }
21184 break;
21185 case NM_BLTUC:
21186 if (rs == 0 || rs == rt) {
21187 /* NOP */
21188 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21189 } else {
21190 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21191 }
21192 break;
21193 default:
3a4ef3b7 21194 gen_reserved_instruction(ctx);
11d0fc10
SM
21195 break;
21196 }
21197 }
c0280983
YK
21198 break;
21199 case NM_P_BRI:
11d0fc10
SM
21200 {
21201 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21202 extract32(ctx->opcode, 1, 10) << 1;
21203 uint32_t u = extract32(ctx->opcode, 11, 7);
21204
21205 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21206 rt, u, s);
21207 }
c0280983
YK
21208 break;
21209 default:
3a4ef3b7 21210 gen_reserved_instruction(ctx);
c0280983
YK
21211 break;
21212 }
21213 return 4;
21214}
21215
c533c0f4
AM
21216static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21217{
ea4ca3c2 21218 uint32_t op;
99e49abf
AM
21219 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21220 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21221 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 21222 int offset;
ea4ca3c2
YK
21223 int imm;
21224
21225 /* make sure instructions are on a halfword boundary */
21226 if (ctx->base.pc_next & 0x1) {
21227 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21228 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21229 tcg_temp_free(tmp);
21230 generate_exception_end(ctx, EXCP_AdEL);
21231 return 2;
21232 }
21233
21234 op = extract32(ctx->opcode, 10, 6);
21235 switch (op) {
21236 case NM_P16_MV:
8869ad02
YK
21237 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21238 if (rt != 0) {
21239 /* MOVE */
21240 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21241 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21242 } else {
21243 /* P16.RI */
21244 switch (extract32(ctx->opcode, 3, 2)) {
21245 case NM_P16_SYSCALL:
21246 if (extract32(ctx->opcode, 2, 1) == 0) {
21247 generate_exception_end(ctx, EXCP_SYSCALL);
21248 } else {
3a4ef3b7 21249 gen_reserved_instruction(ctx);
8869ad02
YK
21250 }
21251 break;
21252 case NM_BREAK16:
21253 generate_exception_end(ctx, EXCP_BREAK);
21254 break;
21255 case NM_SDBBP16:
21256 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21257 gen_helper_do_semihosting(cpu_env);
21258 } else {
21259 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 21260 gen_reserved_instruction(ctx);
8869ad02
YK
21261 } else {
21262 generate_exception_end(ctx, EXCP_DBp);
21263 }
21264 }
21265 break;
21266 default:
3a4ef3b7 21267 gen_reserved_instruction(ctx);
8869ad02
YK
21268 break;
21269 }
21270 }
ea4ca3c2
YK
21271 break;
21272 case NM_P16_SHIFT:
c46562fb
YK
21273 {
21274 int shift = extract32(ctx->opcode, 0, 3);
21275 uint32_t opc = 0;
21276 shift = (shift == 0) ? 8 : shift;
21277
21278 switch (extract32(ctx->opcode, 3, 1)) {
21279 case NM_SLL16:
21280 opc = OPC_SLL;
21281 break;
21282 case NM_SRL16:
21283 opc = OPC_SRL;
21284 break;
21285 }
21286 gen_shift_imm(ctx, opc, rt, rs, shift);
21287 }
ea4ca3c2
YK
21288 break;
21289 case NM_P16C:
8bdb7029
YK
21290 switch (ctx->opcode & 1) {
21291 case NM_POOL16C_0:
80845edf 21292 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
21293 break;
21294 case NM_LWXS16:
21295 gen_ldxs(ctx, rt, rs, rd);
21296 break;
21297 }
ea4ca3c2
YK
21298 break;
21299 case NM_P16_A1:
21300 switch (extract32(ctx->opcode, 6, 1)) {
21301 case NM_ADDIUR1SP:
21302 imm = extract32(ctx->opcode, 0, 6) << 2;
21303 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21304 break;
21305 default:
3a4ef3b7 21306 gen_reserved_instruction(ctx);
ea4ca3c2
YK
21307 break;
21308 }
21309 break;
21310 case NM_P16_A2:
21311 switch (extract32(ctx->opcode, 3, 1)) {
21312 case NM_ADDIUR2:
21313 imm = extract32(ctx->opcode, 0, 3) << 2;
21314 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21315 break;
21316 case NM_P_ADDIURS5:
21317 rt = extract32(ctx->opcode, 5, 5);
21318 if (rt != 0) {
21319 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21320 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21321 (extract32(ctx->opcode, 0, 3));
21322 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21323 }
21324 break;
21325 }
21326 break;
21327 case NM_P16_ADDU:
21328 switch (ctx->opcode & 0x1) {
21329 case NM_ADDU16:
21330 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21331 break;
21332 case NM_SUBU16:
21333 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21334 break;
21335 }
21336 break;
21337 case NM_P16_4X4:
21338 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21339 extract32(ctx->opcode, 5, 3);
21340 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21341 extract32(ctx->opcode, 0, 3);
21342 rt = decode_gpr_gpr4(rt);
21343 rs = decode_gpr_gpr4(rs);
21344 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21345 (extract32(ctx->opcode, 3, 1))) {
21346 case NM_ADDU4X4:
fb32f8c8 21347 check_nms(ctx);
ea4ca3c2
YK
21348 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21349 break;
21350 case NM_MUL4X4:
fb32f8c8 21351 check_nms(ctx);
ea4ca3c2
YK
21352 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21353 break;
21354 default:
3a4ef3b7 21355 gen_reserved_instruction(ctx);
ea4ca3c2
YK
21356 break;
21357 }
21358 break;
21359 case NM_LI16:
8869ad02
YK
21360 {
21361 int imm = extract32(ctx->opcode, 0, 7);
21362 imm = (imm == 0x7f ? -1 : imm);
21363 if (rt != 0) {
21364 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21365 }
21366 }
ea4ca3c2
YK
21367 break;
21368 case NM_ANDI16:
80845edf
YK
21369 {
21370 uint32_t u = extract32(ctx->opcode, 0, 4);
21371 u = (u == 12) ? 0xff :
21372 (u == 13) ? 0xffff : u;
21373 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21374 }
ea4ca3c2
YK
21375 break;
21376 case NM_P16_LB:
8bdb7029
YK
21377 offset = extract32(ctx->opcode, 0, 2);
21378 switch (extract32(ctx->opcode, 2, 2)) {
21379 case NM_LB16:
21380 gen_ld(ctx, OPC_LB, rt, rs, offset);
21381 break;
21382 case NM_SB16:
21383 rt = decode_gpr_gpr3_src_store(
99e49abf 21384 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21385 gen_st(ctx, OPC_SB, rt, rs, offset);
21386 break;
21387 case NM_LBU16:
21388 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21389 break;
21390 default:
3a4ef3b7 21391 gen_reserved_instruction(ctx);
8bdb7029
YK
21392 break;
21393 }
ea4ca3c2
YK
21394 break;
21395 case NM_P16_LH:
8bdb7029
YK
21396 offset = extract32(ctx->opcode, 1, 2) << 1;
21397 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21398 case NM_LH16:
21399 gen_ld(ctx, OPC_LH, rt, rs, offset);
21400 break;
21401 case NM_SH16:
21402 rt = decode_gpr_gpr3_src_store(
99e49abf 21403 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21404 gen_st(ctx, OPC_SH, rt, rs, offset);
21405 break;
21406 case NM_LHU16:
21407 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21408 break;
21409 default:
3a4ef3b7 21410 gen_reserved_instruction(ctx);
8bdb7029
YK
21411 break;
21412 }
ea4ca3c2
YK
21413 break;
21414 case NM_LW16:
8bdb7029
YK
21415 offset = extract32(ctx->opcode, 0, 4) << 2;
21416 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21417 break;
21418 case NM_LWSP16:
8bdb7029
YK
21419 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21420 offset = extract32(ctx->opcode, 0, 5) << 2;
21421 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
21422 break;
21423 case NM_LW4X4:
fb32f8c8 21424 check_nms(ctx);
8bdb7029
YK
21425 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21426 extract32(ctx->opcode, 5, 3);
21427 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21428 extract32(ctx->opcode, 0, 3);
21429 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21430 (extract32(ctx->opcode, 8, 1) << 2);
21431 rt = decode_gpr_gpr4(rt);
21432 rs = decode_gpr_gpr4(rs);
21433 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21434 break;
21435 case NM_SW4X4:
fb32f8c8 21436 check_nms(ctx);
8bdb7029
YK
21437 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21438 extract32(ctx->opcode, 5, 3);
21439 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21440 extract32(ctx->opcode, 0, 3);
21441 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21442 (extract32(ctx->opcode, 8, 1) << 2);
21443 rt = decode_gpr_gpr4_zero(rt);
21444 rs = decode_gpr_gpr4(rs);
21445 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21446 break;
21447 case NM_LWGP16:
8bdb7029
YK
21448 offset = extract32(ctx->opcode, 0, 7) << 2;
21449 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
21450 break;
21451 case NM_SWSP16:
8bdb7029
YK
21452 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21453 offset = extract32(ctx->opcode, 0, 5) << 2;
21454 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
21455 break;
21456 case NM_SW16:
8bdb7029 21457 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
21458 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21459 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
21460 offset = extract32(ctx->opcode, 0, 4) << 2;
21461 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21462 break;
21463 case NM_SWGP16:
8bdb7029 21464 rt = decode_gpr_gpr3_src_store(
99e49abf 21465 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21466 offset = extract32(ctx->opcode, 0, 7) << 2;
21467 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
21468 break;
21469 case NM_BC16:
764371d2
SM
21470 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21471 (sextract32(ctx->opcode, 0, 1) << 10) |
21472 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21473 break;
21474 case NM_BALC16:
764371d2
SM
21475 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21476 (sextract32(ctx->opcode, 0, 1) << 10) |
21477 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21478 break;
21479 case NM_BEQZC16:
764371d2
SM
21480 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21481 (sextract32(ctx->opcode, 0, 1) << 7) |
21482 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21483 break;
21484 case NM_BNEZC16:
764371d2
SM
21485 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21486 (sextract32(ctx->opcode, 0, 1) << 7) |
21487 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21488 break;
21489 case NM_P16_BR:
764371d2
SM
21490 switch (ctx->opcode & 0xf) {
21491 case 0:
21492 /* P16.JRC */
21493 switch (extract32(ctx->opcode, 4, 1)) {
21494 case NM_JRC:
21495 gen_compute_branch_nm(ctx, OPC_JR, 2,
21496 extract32(ctx->opcode, 5, 5), 0, 0);
21497 break;
21498 case NM_JALRC16:
21499 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21500 extract32(ctx->opcode, 5, 5), 31, 0);
21501 break;
21502 }
21503 break;
21504 default:
21505 {
21506 /* P16.BRI */
21507 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21508 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21509 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21510 extract32(ctx->opcode, 0, 4) << 1);
21511 }
21512 break;
21513 }
ea4ca3c2
YK
21514 break;
21515 case NM_P16_SR:
bf0718c5
SM
21516 {
21517 int count = extract32(ctx->opcode, 0, 4);
21518 int u = extract32(ctx->opcode, 4, 4) << 4;
21519
21520 rt = 30 + extract32(ctx->opcode, 9, 1);
21521 switch (extract32(ctx->opcode, 8, 1)) {
21522 case NM_SAVE16:
21523 gen_save(ctx, rt, count, 0, u);
21524 break;
21525 case NM_RESTORE_JRC16:
21526 gen_restore(ctx, rt, count, 0, u);
21527 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21528 break;
21529 }
21530 }
ea4ca3c2
YK
21531 break;
21532 case NM_MOVEP:
ea4ca3c2 21533 case NM_MOVEPREV:
fb32f8c8 21534 check_nms(ctx);
4d18232c
YK
21535 {
21536 static const int gpr2reg1[] = {4, 5, 6, 7};
21537 static const int gpr2reg2[] = {5, 6, 7, 8};
21538 int re;
21539 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21540 extract32(ctx->opcode, 8, 1);
21541 int r1 = gpr2reg1[rd2];
21542 int r2 = gpr2reg2[rd2];
21543 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21544 extract32(ctx->opcode, 0, 3);
21545 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21546 extract32(ctx->opcode, 5, 3);
21547 TCGv t0 = tcg_temp_new();
21548 TCGv t1 = tcg_temp_new();
21549 if (op == NM_MOVEP) {
21550 rd = r1;
21551 re = r2;
21552 rs = decode_gpr_gpr4_zero(r3);
21553 rt = decode_gpr_gpr4_zero(r4);
21554 } else {
21555 rd = decode_gpr_gpr4(r3);
21556 re = decode_gpr_gpr4(r4);
21557 rs = r1;
21558 rt = r2;
21559 }
21560 gen_load_gpr(t0, rs);
21561 gen_load_gpr(t1, rt);
21562 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21563 tcg_gen_mov_tl(cpu_gpr[re], t1);
21564 tcg_temp_free(t0);
21565 tcg_temp_free(t1);
21566 }
ea4ca3c2
YK
21567 break;
21568 default:
c0280983 21569 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
21570 }
21571
c533c0f4
AM
21572 return 2;
21573}
21574
21575
3c824109
NF
21576/* SmartMIPS extension to MIPS32 */
21577
21578#if defined(TARGET_MIPS64)
21579
21580/* MDMX extension to MIPS64 */
21581
21582#endif
21583
9b1a1d68 21584/* MIPSDSP functions. */
d75c135e 21585static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
21586 int rd, int base, int offset)
21587{
9b1a1d68
JL
21588 TCGv t0;
21589
9b1a1d68
JL
21590 check_dsp(ctx);
21591 t0 = tcg_temp_new();
21592
21593 if (base == 0) {
21594 gen_load_gpr(t0, offset);
21595 } else if (offset == 0) {
21596 gen_load_gpr(t0, base);
21597 } else {
21598 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21599 }
21600
9b1a1d68
JL
21601 switch (opc) {
21602 case OPC_LBUX:
5f68f5ae 21603 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 21604 gen_store_gpr(t0, rd);
9b1a1d68
JL
21605 break;
21606 case OPC_LHX:
5f68f5ae 21607 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 21608 gen_store_gpr(t0, rd);
9b1a1d68
JL
21609 break;
21610 case OPC_LWX:
5f68f5ae 21611 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 21612 gen_store_gpr(t0, rd);
9b1a1d68
JL
21613 break;
21614#if defined(TARGET_MIPS64)
21615 case OPC_LDX:
5f68f5ae 21616 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 21617 gen_store_gpr(t0, rd);
9b1a1d68
JL
21618 break;
21619#endif
21620 }
9b1a1d68
JL
21621 tcg_temp_free(t0);
21622}
21623
461c08df
JL
21624static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21625 int ret, int v1, int v2)
21626{
461c08df
JL
21627 TCGv v1_t;
21628 TCGv v2_t;
21629
21630 if (ret == 0) {
21631 /* Treat as NOP. */
461c08df
JL
21632 return;
21633 }
21634
21635 v1_t = tcg_temp_new();
21636 v2_t = tcg_temp_new();
21637
21638 gen_load_gpr(v1_t, v1);
21639 gen_load_gpr(v2_t, v2);
21640
21641 switch (op1) {
21642 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21643 case OPC_MULT_G_2E:
908f6be1 21644 check_dsp_r2(ctx);
461c08df
JL
21645 switch (op2) {
21646 case OPC_ADDUH_QB:
21647 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21648 break;
21649 case OPC_ADDUH_R_QB:
21650 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21651 break;
21652 case OPC_ADDQH_PH:
21653 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21654 break;
21655 case OPC_ADDQH_R_PH:
21656 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21657 break;
21658 case OPC_ADDQH_W:
21659 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21660 break;
21661 case OPC_ADDQH_R_W:
21662 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21663 break;
21664 case OPC_SUBUH_QB:
21665 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21666 break;
21667 case OPC_SUBUH_R_QB:
21668 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21669 break;
21670 case OPC_SUBQH_PH:
21671 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21672 break;
21673 case OPC_SUBQH_R_PH:
21674 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21675 break;
21676 case OPC_SUBQH_W:
21677 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21678 break;
21679 case OPC_SUBQH_R_W:
21680 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21681 break;
21682 }
21683 break;
21684 case OPC_ABSQ_S_PH_DSP:
21685 switch (op2) {
21686 case OPC_ABSQ_S_QB:
908f6be1 21687 check_dsp_r2(ctx);
461c08df
JL
21688 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21689 break;
21690 case OPC_ABSQ_S_PH:
21691 check_dsp(ctx);
21692 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21693 break;
21694 case OPC_ABSQ_S_W:
21695 check_dsp(ctx);
21696 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21697 break;
21698 case OPC_PRECEQ_W_PHL:
21699 check_dsp(ctx);
21700 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21701 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21702 break;
21703 case OPC_PRECEQ_W_PHR:
21704 check_dsp(ctx);
21705 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21706 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21707 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21708 break;
21709 case OPC_PRECEQU_PH_QBL:
21710 check_dsp(ctx);
21711 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21712 break;
21713 case OPC_PRECEQU_PH_QBR:
21714 check_dsp(ctx);
21715 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21716 break;
21717 case OPC_PRECEQU_PH_QBLA:
21718 check_dsp(ctx);
21719 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21720 break;
21721 case OPC_PRECEQU_PH_QBRA:
21722 check_dsp(ctx);
21723 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21724 break;
21725 case OPC_PRECEU_PH_QBL:
21726 check_dsp(ctx);
21727 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21728 break;
21729 case OPC_PRECEU_PH_QBR:
21730 check_dsp(ctx);
21731 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21732 break;
21733 case OPC_PRECEU_PH_QBLA:
21734 check_dsp(ctx);
21735 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21736 break;
21737 case OPC_PRECEU_PH_QBRA:
21738 check_dsp(ctx);
21739 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21740 break;
21741 }
21742 break;
21743 case OPC_ADDU_QB_DSP:
21744 switch (op2) {
21745 case OPC_ADDQ_PH:
21746 check_dsp(ctx);
21747 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21748 break;
21749 case OPC_ADDQ_S_PH:
21750 check_dsp(ctx);
21751 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21752 break;
21753 case OPC_ADDQ_S_W:
21754 check_dsp(ctx);
21755 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21756 break;
21757 case OPC_ADDU_QB:
21758 check_dsp(ctx);
21759 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21760 break;
21761 case OPC_ADDU_S_QB:
21762 check_dsp(ctx);
21763 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21764 break;
21765 case OPC_ADDU_PH:
908f6be1 21766 check_dsp_r2(ctx);
461c08df
JL
21767 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21768 break;
21769 case OPC_ADDU_S_PH:
908f6be1 21770 check_dsp_r2(ctx);
461c08df
JL
21771 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21772 break;
21773 case OPC_SUBQ_PH:
21774 check_dsp(ctx);
21775 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21776 break;
21777 case OPC_SUBQ_S_PH:
21778 check_dsp(ctx);
21779 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21780 break;
21781 case OPC_SUBQ_S_W:
21782 check_dsp(ctx);
21783 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21784 break;
21785 case OPC_SUBU_QB:
21786 check_dsp(ctx);
21787 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21788 break;
21789 case OPC_SUBU_S_QB:
21790 check_dsp(ctx);
21791 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21792 break;
21793 case OPC_SUBU_PH:
908f6be1 21794 check_dsp_r2(ctx);
461c08df
JL
21795 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21796 break;
21797 case OPC_SUBU_S_PH:
908f6be1 21798 check_dsp_r2(ctx);
461c08df
JL
21799 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21800 break;
21801 case OPC_ADDSC:
21802 check_dsp(ctx);
21803 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21804 break;
21805 case OPC_ADDWC:
21806 check_dsp(ctx);
21807 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21808 break;
21809 case OPC_MODSUB:
21810 check_dsp(ctx);
21811 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21812 break;
21813 case OPC_RADDU_W_QB:
21814 check_dsp(ctx);
21815 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21816 break;
21817 }
21818 break;
21819 case OPC_CMPU_EQ_QB_DSP:
21820 switch (op2) {
21821 case OPC_PRECR_QB_PH:
908f6be1 21822 check_dsp_r2(ctx);
461c08df
JL
21823 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21824 break;
21825 case OPC_PRECRQ_QB_PH:
21826 check_dsp(ctx);
21827 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21828 break;
21829 case OPC_PRECR_SRA_PH_W:
908f6be1 21830 check_dsp_r2(ctx);
461c08df
JL
21831 {
21832 TCGv_i32 sa_t = tcg_const_i32(v2);
21833 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21834 cpu_gpr[ret]);
21835 tcg_temp_free_i32(sa_t);
21836 break;
21837 }
21838 case OPC_PRECR_SRA_R_PH_W:
908f6be1 21839 check_dsp_r2(ctx);
461c08df
JL
21840 {
21841 TCGv_i32 sa_t = tcg_const_i32(v2);
21842 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21843 cpu_gpr[ret]);
21844 tcg_temp_free_i32(sa_t);
21845 break;
21846 }
21847 case OPC_PRECRQ_PH_W:
21848 check_dsp(ctx);
21849 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21850 break;
21851 case OPC_PRECRQ_RS_PH_W:
21852 check_dsp(ctx);
21853 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21854 break;
21855 case OPC_PRECRQU_S_QB_PH:
21856 check_dsp(ctx);
21857 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21858 break;
21859 }
21860 break;
21861#ifdef TARGET_MIPS64
21862 case OPC_ABSQ_S_QH_DSP:
21863 switch (op2) {
21864 case OPC_PRECEQ_L_PWL:
21865 check_dsp(ctx);
21866 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21867 break;
21868 case OPC_PRECEQ_L_PWR:
21869 check_dsp(ctx);
21870 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21871 break;
21872 case OPC_PRECEQ_PW_QHL:
21873 check_dsp(ctx);
21874 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21875 break;
21876 case OPC_PRECEQ_PW_QHR:
21877 check_dsp(ctx);
21878 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21879 break;
21880 case OPC_PRECEQ_PW_QHLA:
21881 check_dsp(ctx);
21882 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21883 break;
21884 case OPC_PRECEQ_PW_QHRA:
21885 check_dsp(ctx);
21886 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21887 break;
21888 case OPC_PRECEQU_QH_OBL:
21889 check_dsp(ctx);
21890 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21891 break;
21892 case OPC_PRECEQU_QH_OBR:
21893 check_dsp(ctx);
21894 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21895 break;
21896 case OPC_PRECEQU_QH_OBLA:
21897 check_dsp(ctx);
21898 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21899 break;
21900 case OPC_PRECEQU_QH_OBRA:
21901 check_dsp(ctx);
21902 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21903 break;
21904 case OPC_PRECEU_QH_OBL:
21905 check_dsp(ctx);
21906 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21907 break;
21908 case OPC_PRECEU_QH_OBR:
21909 check_dsp(ctx);
21910 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21911 break;
21912 case OPC_PRECEU_QH_OBLA:
21913 check_dsp(ctx);
21914 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21915 break;
21916 case OPC_PRECEU_QH_OBRA:
21917 check_dsp(ctx);
21918 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21919 break;
21920 case OPC_ABSQ_S_OB:
908f6be1 21921 check_dsp_r2(ctx);
461c08df
JL
21922 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21923 break;
21924 case OPC_ABSQ_S_PW:
21925 check_dsp(ctx);
21926 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21927 break;
21928 case OPC_ABSQ_S_QH:
21929 check_dsp(ctx);
21930 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21931 break;
21932 }
21933 break;
21934 case OPC_ADDU_OB_DSP:
21935 switch (op2) {
21936 case OPC_RADDU_L_OB:
21937 check_dsp(ctx);
21938 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21939 break;
21940 case OPC_SUBQ_PW:
21941 check_dsp(ctx);
21942 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21943 break;
21944 case OPC_SUBQ_S_PW:
21945 check_dsp(ctx);
21946 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21947 break;
21948 case OPC_SUBQ_QH:
21949 check_dsp(ctx);
21950 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21951 break;
21952 case OPC_SUBQ_S_QH:
21953 check_dsp(ctx);
21954 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21955 break;
21956 case OPC_SUBU_OB:
21957 check_dsp(ctx);
21958 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21960 case OPC_SUBU_S_OB:
21961 check_dsp(ctx);
21962 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21963 break;
21964 case OPC_SUBU_QH:
908f6be1 21965 check_dsp_r2(ctx);
461c08df
JL
21966 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21967 break;
21968 case OPC_SUBU_S_QH:
908f6be1 21969 check_dsp_r2(ctx);
461c08df
JL
21970 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21971 break;
21972 case OPC_SUBUH_OB:
908f6be1 21973 check_dsp_r2(ctx);
461c08df
JL
21974 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21975 break;
21976 case OPC_SUBUH_R_OB:
908f6be1 21977 check_dsp_r2(ctx);
461c08df
JL
21978 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21979 break;
21980 case OPC_ADDQ_PW:
21981 check_dsp(ctx);
21982 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21983 break;
21984 case OPC_ADDQ_S_PW:
21985 check_dsp(ctx);
21986 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21987 break;
21988 case OPC_ADDQ_QH:
21989 check_dsp(ctx);
21990 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21991 break;
21992 case OPC_ADDQ_S_QH:
21993 check_dsp(ctx);
21994 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21995 break;
21996 case OPC_ADDU_OB:
21997 check_dsp(ctx);
21998 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21999 break;
22000 case OPC_ADDU_S_OB:
22001 check_dsp(ctx);
22002 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22003 break;
22004 case OPC_ADDU_QH:
908f6be1 22005 check_dsp_r2(ctx);
461c08df
JL
22006 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22007 break;
22008 case OPC_ADDU_S_QH:
908f6be1 22009 check_dsp_r2(ctx);
461c08df
JL
22010 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22011 break;
22012 case OPC_ADDUH_OB:
908f6be1 22013 check_dsp_r2(ctx);
461c08df
JL
22014 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22015 break;
22016 case OPC_ADDUH_R_OB:
908f6be1 22017 check_dsp_r2(ctx);
461c08df
JL
22018 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22019 break;
22020 }
22021 break;
22022 case OPC_CMPU_EQ_OB_DSP:
22023 switch (op2) {
22024 case OPC_PRECR_OB_QH:
908f6be1 22025 check_dsp_r2(ctx);
461c08df
JL
22026 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22027 break;
22028 case OPC_PRECR_SRA_QH_PW:
908f6be1 22029 check_dsp_r2(ctx);
461c08df
JL
22030 {
22031 TCGv_i32 ret_t = tcg_const_i32(ret);
22032 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22033 tcg_temp_free_i32(ret_t);
22034 break;
22035 }
22036 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22037 check_dsp_r2(ctx);
461c08df
JL
22038 {
22039 TCGv_i32 sa_v = tcg_const_i32(ret);
22040 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22041 tcg_temp_free_i32(sa_v);
22042 break;
22043 }
22044 case OPC_PRECRQ_OB_QH:
22045 check_dsp(ctx);
22046 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22047 break;
22048 case OPC_PRECRQ_PW_L:
22049 check_dsp(ctx);
22050 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22051 break;
22052 case OPC_PRECRQ_QH_PW:
22053 check_dsp(ctx);
22054 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22055 break;
22056 case OPC_PRECRQ_RS_QH_PW:
22057 check_dsp(ctx);
22058 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22059 break;
22060 case OPC_PRECRQU_S_OB_QH:
22061 check_dsp(ctx);
22062 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22063 break;
22064 }
22065 break;
22066#endif
22067 }
22068
22069 tcg_temp_free(v1_t);
22070 tcg_temp_free(v2_t);
461c08df 22071}
9b1a1d68 22072
77c5fa8b
JL
22073static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22074 int ret, int v1, int v2)
22075{
22076 uint32_t op2;
77c5fa8b
JL
22077 TCGv t0;
22078 TCGv v1_t;
22079 TCGv v2_t;
22080
22081 if (ret == 0) {
22082 /* Treat as NOP. */
77c5fa8b
JL
22083 return;
22084 }
22085
22086 t0 = tcg_temp_new();
22087 v1_t = tcg_temp_new();
22088 v2_t = tcg_temp_new();
22089
22090 tcg_gen_movi_tl(t0, v1);
22091 gen_load_gpr(v1_t, v1);
22092 gen_load_gpr(v2_t, v2);
22093
22094 switch (opc) {
22095 case OPC_SHLL_QB_DSP:
22096 {
22097 op2 = MASK_SHLL_QB(ctx->opcode);
22098 switch (op2) {
22099 case OPC_SHLL_QB:
22100 check_dsp(ctx);
22101 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22102 break;
22103 case OPC_SHLLV_QB:
22104 check_dsp(ctx);
22105 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_SHLL_PH:
22108 check_dsp(ctx);
22109 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22110 break;
22111 case OPC_SHLLV_PH:
22112 check_dsp(ctx);
22113 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_SHLL_S_PH:
22116 check_dsp(ctx);
22117 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22118 break;
22119 case OPC_SHLLV_S_PH:
22120 check_dsp(ctx);
22121 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SHLL_S_W:
22124 check_dsp(ctx);
22125 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22126 break;
22127 case OPC_SHLLV_S_W:
22128 check_dsp(ctx);
22129 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22130 break;
22131 case OPC_SHRL_QB:
22132 check_dsp(ctx);
22133 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22134 break;
22135 case OPC_SHRLV_QB:
22136 check_dsp(ctx);
22137 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22138 break;
22139 case OPC_SHRL_PH:
908f6be1 22140 check_dsp_r2(ctx);
77c5fa8b
JL
22141 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22142 break;
22143 case OPC_SHRLV_PH:
908f6be1 22144 check_dsp_r2(ctx);
77c5fa8b
JL
22145 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22146 break;
22147 case OPC_SHRA_QB:
908f6be1 22148 check_dsp_r2(ctx);
77c5fa8b
JL
22149 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22150 break;
22151 case OPC_SHRA_R_QB:
908f6be1 22152 check_dsp_r2(ctx);
77c5fa8b
JL
22153 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22154 break;
22155 case OPC_SHRAV_QB:
908f6be1 22156 check_dsp_r2(ctx);
77c5fa8b
JL
22157 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22158 break;
22159 case OPC_SHRAV_R_QB:
908f6be1 22160 check_dsp_r2(ctx);
77c5fa8b
JL
22161 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22162 break;
22163 case OPC_SHRA_PH:
22164 check_dsp(ctx);
22165 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22166 break;
22167 case OPC_SHRA_R_PH:
22168 check_dsp(ctx);
22169 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22170 break;
22171 case OPC_SHRAV_PH:
22172 check_dsp(ctx);
22173 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22174 break;
22175 case OPC_SHRAV_R_PH:
22176 check_dsp(ctx);
22177 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22178 break;
22179 case OPC_SHRA_R_W:
22180 check_dsp(ctx);
22181 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22182 break;
22183 case OPC_SHRAV_R_W:
22184 check_dsp(ctx);
22185 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22186 break;
22187 default: /* Invalid */
22188 MIPS_INVAL("MASK SHLL.QB");
3a4ef3b7 22189 gen_reserved_instruction(ctx);
77c5fa8b
JL
22190 break;
22191 }
22192 break;
22193 }
22194#ifdef TARGET_MIPS64
22195 case OPC_SHLL_OB_DSP:
22196 op2 = MASK_SHLL_OB(ctx->opcode);
22197 switch (op2) {
22198 case OPC_SHLL_PW:
22199 check_dsp(ctx);
22200 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22201 break;
22202 case OPC_SHLLV_PW:
22203 check_dsp(ctx);
22204 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22205 break;
22206 case OPC_SHLL_S_PW:
22207 check_dsp(ctx);
22208 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22209 break;
22210 case OPC_SHLLV_S_PW:
22211 check_dsp(ctx);
22212 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22213 break;
22214 case OPC_SHLL_OB:
22215 check_dsp(ctx);
22216 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22217 break;
22218 case OPC_SHLLV_OB:
22219 check_dsp(ctx);
22220 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22221 break;
22222 case OPC_SHLL_QH:
22223 check_dsp(ctx);
22224 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22225 break;
22226 case OPC_SHLLV_QH:
22227 check_dsp(ctx);
22228 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22229 break;
22230 case OPC_SHLL_S_QH:
22231 check_dsp(ctx);
22232 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22233 break;
22234 case OPC_SHLLV_S_QH:
22235 check_dsp(ctx);
22236 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22237 break;
22238 case OPC_SHRA_OB:
908f6be1 22239 check_dsp_r2(ctx);
77c5fa8b
JL
22240 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22241 break;
22242 case OPC_SHRAV_OB:
908f6be1 22243 check_dsp_r2(ctx);
77c5fa8b
JL
22244 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22245 break;
22246 case OPC_SHRA_R_OB:
908f6be1 22247 check_dsp_r2(ctx);
77c5fa8b
JL
22248 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22249 break;
22250 case OPC_SHRAV_R_OB:
908f6be1 22251 check_dsp_r2(ctx);
77c5fa8b
JL
22252 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22253 break;
22254 case OPC_SHRA_PW:
22255 check_dsp(ctx);
22256 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22257 break;
22258 case OPC_SHRAV_PW:
22259 check_dsp(ctx);
22260 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22261 break;
22262 case OPC_SHRA_R_PW:
22263 check_dsp(ctx);
22264 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22265 break;
22266 case OPC_SHRAV_R_PW:
22267 check_dsp(ctx);
22268 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22269 break;
22270 case OPC_SHRA_QH:
22271 check_dsp(ctx);
22272 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22273 break;
22274 case OPC_SHRAV_QH:
22275 check_dsp(ctx);
22276 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22277 break;
22278 case OPC_SHRA_R_QH:
22279 check_dsp(ctx);
22280 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22281 break;
22282 case OPC_SHRAV_R_QH:
22283 check_dsp(ctx);
22284 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22285 break;
22286 case OPC_SHRL_OB:
22287 check_dsp(ctx);
22288 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22289 break;
22290 case OPC_SHRLV_OB:
22291 check_dsp(ctx);
22292 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22293 break;
22294 case OPC_SHRL_QH:
908f6be1 22295 check_dsp_r2(ctx);
77c5fa8b
JL
22296 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22297 break;
22298 case OPC_SHRLV_QH:
908f6be1 22299 check_dsp_r2(ctx);
77c5fa8b
JL
22300 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22301 break;
22302 default: /* Invalid */
22303 MIPS_INVAL("MASK SHLL.OB");
3a4ef3b7 22304 gen_reserved_instruction(ctx);
77c5fa8b
JL
22305 break;
22306 }
22307 break;
22308#endif
22309 }
22310
22311 tcg_temp_free(t0);
22312 tcg_temp_free(v1_t);
22313 tcg_temp_free(v2_t);
77c5fa8b
JL
22314}
22315
a22260ae
JL
22316static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22317 int ret, int v1, int v2, int check_ret)
22318{
a22260ae
JL
22319 TCGv_i32 t0;
22320 TCGv v1_t;
22321 TCGv v2_t;
22322
22323 if ((ret == 0) && (check_ret == 1)) {
22324 /* Treat as NOP. */
a22260ae
JL
22325 return;
22326 }
22327
22328 t0 = tcg_temp_new_i32();
22329 v1_t = tcg_temp_new();
22330 v2_t = tcg_temp_new();
22331
22332 tcg_gen_movi_i32(t0, ret);
22333 gen_load_gpr(v1_t, v1);
22334 gen_load_gpr(v2_t, v2);
22335
22336 switch (op1) {
7480515f
AM
22337 /*
22338 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22339 * the same mask and op1.
22340 */
a22260ae 22341 case OPC_MULT_G_2E:
908f6be1 22342 check_dsp_r2(ctx);
a22260ae
JL
22343 switch (op2) {
22344 case OPC_MUL_PH:
22345 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22346 break;
22347 case OPC_MUL_S_PH:
22348 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22349 break;
22350 case OPC_MULQ_S_W:
22351 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22352 break;
22353 case OPC_MULQ_RS_W:
22354 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22355 break;
22356 }
22357 break;
22358 case OPC_DPA_W_PH_DSP:
22359 switch (op2) {
22360 case OPC_DPAU_H_QBL:
22361 check_dsp(ctx);
22362 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22363 break;
22364 case OPC_DPAU_H_QBR:
22365 check_dsp(ctx);
22366 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22367 break;
22368 case OPC_DPSU_H_QBL:
22369 check_dsp(ctx);
22370 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22371 break;
22372 case OPC_DPSU_H_QBR:
22373 check_dsp(ctx);
22374 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22375 break;
22376 case OPC_DPA_W_PH:
908f6be1 22377 check_dsp_r2(ctx);
a22260ae
JL
22378 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22379 break;
22380 case OPC_DPAX_W_PH:
908f6be1 22381 check_dsp_r2(ctx);
a22260ae
JL
22382 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22383 break;
22384 case OPC_DPAQ_S_W_PH:
22385 check_dsp(ctx);
22386 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22387 break;
22388 case OPC_DPAQX_S_W_PH:
908f6be1 22389 check_dsp_r2(ctx);
a22260ae
JL
22390 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22391 break;
22392 case OPC_DPAQX_SA_W_PH:
908f6be1 22393 check_dsp_r2(ctx);
a22260ae
JL
22394 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22395 break;
22396 case OPC_DPS_W_PH:
908f6be1 22397 check_dsp_r2(ctx);
a22260ae
JL
22398 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22399 break;
22400 case OPC_DPSX_W_PH:
908f6be1 22401 check_dsp_r2(ctx);
a22260ae
JL
22402 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22403 break;
22404 case OPC_DPSQ_S_W_PH:
22405 check_dsp(ctx);
22406 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22407 break;
22408 case OPC_DPSQX_S_W_PH:
908f6be1 22409 check_dsp_r2(ctx);
a22260ae
JL
22410 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22411 break;
22412 case OPC_DPSQX_SA_W_PH:
908f6be1 22413 check_dsp_r2(ctx);
a22260ae
JL
22414 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22415 break;
22416 case OPC_MULSAQ_S_W_PH:
22417 check_dsp(ctx);
22418 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22419 break;
22420 case OPC_DPAQ_SA_L_W:
22421 check_dsp(ctx);
22422 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22423 break;
22424 case OPC_DPSQ_SA_L_W:
22425 check_dsp(ctx);
22426 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22427 break;
22428 case OPC_MAQ_S_W_PHL:
22429 check_dsp(ctx);
22430 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22431 break;
22432 case OPC_MAQ_S_W_PHR:
22433 check_dsp(ctx);
22434 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22435 break;
22436 case OPC_MAQ_SA_W_PHL:
22437 check_dsp(ctx);
22438 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22439 break;
22440 case OPC_MAQ_SA_W_PHR:
22441 check_dsp(ctx);
22442 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22443 break;
22444 case OPC_MULSA_W_PH:
908f6be1 22445 check_dsp_r2(ctx);
a22260ae
JL
22446 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22447 break;
22448 }
22449 break;
22450#ifdef TARGET_MIPS64
22451 case OPC_DPAQ_W_QH_DSP:
22452 {
22453 int ac = ret & 0x03;
22454 tcg_gen_movi_i32(t0, ac);
22455
22456 switch (op2) {
22457 case OPC_DMADD:
22458 check_dsp(ctx);
22459 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22460 break;
22461 case OPC_DMADDU:
22462 check_dsp(ctx);
22463 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22464 break;
22465 case OPC_DMSUB:
22466 check_dsp(ctx);
22467 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22468 break;
22469 case OPC_DMSUBU:
22470 check_dsp(ctx);
22471 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22472 break;
22473 case OPC_DPA_W_QH:
908f6be1 22474 check_dsp_r2(ctx);
a22260ae
JL
22475 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22476 break;
22477 case OPC_DPAQ_S_W_QH:
22478 check_dsp(ctx);
22479 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22480 break;
22481 case OPC_DPAQ_SA_L_PW:
22482 check_dsp(ctx);
22483 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22484 break;
22485 case OPC_DPAU_H_OBL:
22486 check_dsp(ctx);
22487 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22488 break;
22489 case OPC_DPAU_H_OBR:
22490 check_dsp(ctx);
22491 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22492 break;
22493 case OPC_DPS_W_QH:
908f6be1 22494 check_dsp_r2(ctx);
a22260ae
JL
22495 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22496 break;
22497 case OPC_DPSQ_S_W_QH:
22498 check_dsp(ctx);
22499 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22500 break;
22501 case OPC_DPSQ_SA_L_PW:
22502 check_dsp(ctx);
22503 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22504 break;
22505 case OPC_DPSU_H_OBL:
22506 check_dsp(ctx);
22507 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22508 break;
22509 case OPC_DPSU_H_OBR:
22510 check_dsp(ctx);
22511 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22512 break;
22513 case OPC_MAQ_S_L_PWL:
22514 check_dsp(ctx);
22515 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22516 break;
22517 case OPC_MAQ_S_L_PWR:
22518 check_dsp(ctx);
22519 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22520 break;
22521 case OPC_MAQ_S_W_QHLL:
22522 check_dsp(ctx);
22523 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22524 break;
22525 case OPC_MAQ_SA_W_QHLL:
22526 check_dsp(ctx);
22527 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22528 break;
22529 case OPC_MAQ_S_W_QHLR:
22530 check_dsp(ctx);
22531 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22532 break;
22533 case OPC_MAQ_SA_W_QHLR:
22534 check_dsp(ctx);
22535 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22536 break;
22537 case OPC_MAQ_S_W_QHRL:
22538 check_dsp(ctx);
22539 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22540 break;
22541 case OPC_MAQ_SA_W_QHRL:
22542 check_dsp(ctx);
22543 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22544 break;
22545 case OPC_MAQ_S_W_QHRR:
22546 check_dsp(ctx);
22547 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22548 break;
22549 case OPC_MAQ_SA_W_QHRR:
22550 check_dsp(ctx);
22551 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22552 break;
22553 case OPC_MULSAQ_S_L_PW:
22554 check_dsp(ctx);
22555 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22556 break;
22557 case OPC_MULSAQ_S_W_QH:
22558 check_dsp(ctx);
22559 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22560 break;
22561 }
22562 }
22563 break;
22564#endif
22565 case OPC_ADDU_QB_DSP:
22566 switch (op2) {
22567 case OPC_MULEU_S_PH_QBL:
22568 check_dsp(ctx);
22569 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22570 break;
22571 case OPC_MULEU_S_PH_QBR:
22572 check_dsp(ctx);
22573 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22574 break;
22575 case OPC_MULQ_RS_PH:
22576 check_dsp(ctx);
22577 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22578 break;
22579 case OPC_MULEQ_S_W_PHL:
22580 check_dsp(ctx);
22581 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22582 break;
22583 case OPC_MULEQ_S_W_PHR:
22584 check_dsp(ctx);
22585 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22586 break;
22587 case OPC_MULQ_S_PH:
908f6be1 22588 check_dsp_r2(ctx);
a22260ae
JL
22589 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22590 break;
22591 }
22592 break;
22593#ifdef TARGET_MIPS64
22594 case OPC_ADDU_OB_DSP:
22595 switch (op2) {
22596 case OPC_MULEQ_S_PW_QHL:
22597 check_dsp(ctx);
22598 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22599 break;
22600 case OPC_MULEQ_S_PW_QHR:
22601 check_dsp(ctx);
22602 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22603 break;
22604 case OPC_MULEU_S_QH_OBL:
22605 check_dsp(ctx);
22606 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22607 break;
22608 case OPC_MULEU_S_QH_OBR:
22609 check_dsp(ctx);
22610 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22611 break;
22612 case OPC_MULQ_RS_QH:
22613 check_dsp(ctx);
22614 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22615 break;
22616 }
22617 break;
22618#endif
22619 }
22620
22621 tcg_temp_free_i32(t0);
22622 tcg_temp_free(v1_t);
22623 tcg_temp_free(v2_t);
a22260ae
JL
22624}
22625
d75c135e 22626static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
22627 int ret, int val)
22628{
1cb6686c
JL
22629 int16_t imm;
22630 TCGv t0;
22631 TCGv val_t;
22632
22633 if (ret == 0) {
22634 /* Treat as NOP. */
1cb6686c
JL
22635 return;
22636 }
22637
22638 t0 = tcg_temp_new();
22639 val_t = tcg_temp_new();
22640 gen_load_gpr(val_t, val);
22641
22642 switch (op1) {
22643 case OPC_ABSQ_S_PH_DSP:
22644 switch (op2) {
22645 case OPC_BITREV:
22646 check_dsp(ctx);
22647 gen_helper_bitrev(cpu_gpr[ret], val_t);
22648 break;
22649 case OPC_REPL_QB:
22650 check_dsp(ctx);
22651 {
22652 target_long result;
22653 imm = (ctx->opcode >> 16) & 0xFF;
22654 result = (uint32_t)imm << 24 |
22655 (uint32_t)imm << 16 |
22656 (uint32_t)imm << 8 |
22657 (uint32_t)imm;
22658 result = (int32_t)result;
22659 tcg_gen_movi_tl(cpu_gpr[ret], result);
22660 }
22661 break;
22662 case OPC_REPLV_QB:
22663 check_dsp(ctx);
22664 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22665 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22666 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22667 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22668 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22669 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22670 break;
22671 case OPC_REPL_PH:
22672 check_dsp(ctx);
22673 {
22674 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 22675 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
22676 tcg_gen_movi_tl(cpu_gpr[ret], \
22677 (target_long)((int32_t)imm << 16 | \
c4aaba92 22678 (uint16_t)imm));
1cb6686c
JL
22679 }
22680 break;
22681 case OPC_REPLV_PH:
22682 check_dsp(ctx);
22683 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22684 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22685 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22686 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22687 break;
22688 }
22689 break;
22690#ifdef TARGET_MIPS64
22691 case OPC_ABSQ_S_QH_DSP:
22692 switch (op2) {
22693 case OPC_REPL_OB:
22694 check_dsp(ctx);
22695 {
22696 target_long temp;
22697
22698 imm = (ctx->opcode >> 16) & 0xFF;
22699 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22700 temp = (temp << 16) | temp;
22701 temp = (temp << 32) | temp;
22702 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22703 break;
22704 }
22705 case OPC_REPL_PW:
22706 check_dsp(ctx);
22707 {
22708 target_long temp;
22709
22710 imm = (ctx->opcode >> 16) & 0x03FF;
22711 imm = (int16_t)(imm << 6) >> 6;
22712 temp = ((target_long)imm << 32) \
22713 | ((target_long)imm & 0xFFFFFFFF);
22714 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22715 break;
22716 }
22717 case OPC_REPL_QH:
22718 check_dsp(ctx);
22719 {
22720 target_long temp;
22721
22722 imm = (ctx->opcode >> 16) & 0x03FF;
22723 imm = (int16_t)(imm << 6) >> 6;
22724
22725 temp = ((uint64_t)(uint16_t)imm << 48) |
22726 ((uint64_t)(uint16_t)imm << 32) |
22727 ((uint64_t)(uint16_t)imm << 16) |
22728 (uint64_t)(uint16_t)imm;
22729 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22730 break;
22731 }
22732 case OPC_REPLV_OB:
22733 check_dsp(ctx);
22734 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22735 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22736 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22737 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22738 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22739 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22740 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22741 break;
22742 case OPC_REPLV_PW:
22743 check_dsp(ctx);
22744 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22745 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22746 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22747 break;
22748 case OPC_REPLV_QH:
22749 check_dsp(ctx);
22750 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22751 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22752 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22753 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22754 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22755 break;
22756 }
22757 break;
22758#endif
22759 }
22760 tcg_temp_free(t0);
22761 tcg_temp_free(val_t);
1cb6686c
JL
22762}
22763
26690560
JL
22764static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22765 uint32_t op1, uint32_t op2,
22766 int ret, int v1, int v2, int check_ret)
22767{
26690560
JL
22768 TCGv t1;
22769 TCGv v1_t;
22770 TCGv v2_t;
22771
22772 if ((ret == 0) && (check_ret == 1)) {
22773 /* Treat as NOP. */
26690560
JL
22774 return;
22775 }
22776
26690560
JL
22777 t1 = tcg_temp_new();
22778 v1_t = tcg_temp_new();
22779 v2_t = tcg_temp_new();
22780
22781 gen_load_gpr(v1_t, v1);
22782 gen_load_gpr(v2_t, v2);
22783
22784 switch (op1) {
26690560
JL
22785 case OPC_CMPU_EQ_QB_DSP:
22786 switch (op2) {
22787 case OPC_CMPU_EQ_QB:
22788 check_dsp(ctx);
22789 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22790 break;
22791 case OPC_CMPU_LT_QB:
22792 check_dsp(ctx);
22793 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22794 break;
22795 case OPC_CMPU_LE_QB:
22796 check_dsp(ctx);
22797 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22798 break;
22799 case OPC_CMPGU_EQ_QB:
22800 check_dsp(ctx);
22801 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22802 break;
22803 case OPC_CMPGU_LT_QB:
22804 check_dsp(ctx);
22805 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22806 break;
22807 case OPC_CMPGU_LE_QB:
22808 check_dsp(ctx);
22809 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22810 break;
22811 case OPC_CMPGDU_EQ_QB:
908f6be1 22812 check_dsp_r2(ctx);
26690560
JL
22813 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22814 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22815 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22816 tcg_gen_shli_tl(t1, t1, 24);
22817 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22818 break;
22819 case OPC_CMPGDU_LT_QB:
908f6be1 22820 check_dsp_r2(ctx);
26690560
JL
22821 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22822 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22823 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22824 tcg_gen_shli_tl(t1, t1, 24);
22825 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22826 break;
22827 case OPC_CMPGDU_LE_QB:
908f6be1 22828 check_dsp_r2(ctx);
26690560
JL
22829 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22830 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22831 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22832 tcg_gen_shli_tl(t1, t1, 24);
22833 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22834 break;
22835 case OPC_CMP_EQ_PH:
22836 check_dsp(ctx);
22837 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22838 break;
22839 case OPC_CMP_LT_PH:
22840 check_dsp(ctx);
22841 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22842 break;
22843 case OPC_CMP_LE_PH:
22844 check_dsp(ctx);
22845 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22846 break;
22847 case OPC_PICK_QB:
22848 check_dsp(ctx);
22849 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22850 break;
22851 case OPC_PICK_PH:
22852 check_dsp(ctx);
22853 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22854 break;
22855 case OPC_PACKRL_PH:
22856 check_dsp(ctx);
22857 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22858 break;
22859 }
22860 break;
22861#ifdef TARGET_MIPS64
22862 case OPC_CMPU_EQ_OB_DSP:
22863 switch (op2) {
22864 case OPC_CMP_EQ_PW:
22865 check_dsp(ctx);
22866 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22867 break;
22868 case OPC_CMP_LT_PW:
22869 check_dsp(ctx);
22870 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22871 break;
22872 case OPC_CMP_LE_PW:
22873 check_dsp(ctx);
22874 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22875 break;
22876 case OPC_CMP_EQ_QH:
22877 check_dsp(ctx);
22878 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22879 break;
22880 case OPC_CMP_LT_QH:
22881 check_dsp(ctx);
22882 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22883 break;
22884 case OPC_CMP_LE_QH:
22885 check_dsp(ctx);
22886 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22887 break;
22888 case OPC_CMPGDU_EQ_OB:
908f6be1 22889 check_dsp_r2(ctx);
26690560
JL
22890 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22891 break;
22892 case OPC_CMPGDU_LT_OB:
908f6be1 22893 check_dsp_r2(ctx);
26690560
JL
22894 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22895 break;
22896 case OPC_CMPGDU_LE_OB:
908f6be1 22897 check_dsp_r2(ctx);
26690560
JL
22898 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22899 break;
22900 case OPC_CMPGU_EQ_OB:
22901 check_dsp(ctx);
22902 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22903 break;
22904 case OPC_CMPGU_LT_OB:
22905 check_dsp(ctx);
22906 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22907 break;
22908 case OPC_CMPGU_LE_OB:
22909 check_dsp(ctx);
22910 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22911 break;
22912 case OPC_CMPU_EQ_OB:
22913 check_dsp(ctx);
22914 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22915 break;
22916 case OPC_CMPU_LT_OB:
22917 check_dsp(ctx);
22918 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22919 break;
22920 case OPC_CMPU_LE_OB:
22921 check_dsp(ctx);
22922 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22923 break;
22924 case OPC_PACKRL_PW:
22925 check_dsp(ctx);
22926 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22927 break;
22928 case OPC_PICK_OB:
22929 check_dsp(ctx);
22930 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22931 break;
22932 case OPC_PICK_PW:
22933 check_dsp(ctx);
22934 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22935 break;
22936 case OPC_PICK_QH:
22937 check_dsp(ctx);
22938 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22939 break;
22940 }
22941 break;
df6126a7
AJ
22942#endif
22943 }
22944
22945 tcg_temp_free(t1);
22946 tcg_temp_free(v1_t);
22947 tcg_temp_free(v2_t);
df6126a7
AJ
22948}
22949
22950static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22951 uint32_t op1, int rt, int rs, int sa)
22952{
df6126a7
AJ
22953 TCGv t0;
22954
908f6be1 22955 check_dsp_r2(ctx);
df6126a7
AJ
22956
22957 if (rt == 0) {
22958 /* Treat as NOP. */
df6126a7
AJ
22959 return;
22960 }
22961
22962 t0 = tcg_temp_new();
22963 gen_load_gpr(t0, rs);
22964
22965 switch (op1) {
22966 case OPC_APPEND_DSP:
22967 switch (MASK_APPEND(ctx->opcode)) {
22968 case OPC_APPEND:
22969 if (sa != 0) {
22970 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22971 }
22972 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22973 break;
22974 case OPC_PREPEND:
22975 if (sa != 0) {
22976 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22977 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22978 tcg_gen_shli_tl(t0, t0, 32 - sa);
22979 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22980 }
22981 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22982 break;
22983 case OPC_BALIGN:
22984 sa &= 3;
22985 if (sa != 0 && sa != 2) {
22986 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22987 tcg_gen_ext32u_tl(t0, t0);
22988 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22989 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22990 }
22991 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22992 break;
22993 default: /* Invalid */
22994 MIPS_INVAL("MASK APPEND");
3a4ef3b7 22995 gen_reserved_instruction(ctx);
df6126a7
AJ
22996 break;
22997 }
22998 break;
22999#ifdef TARGET_MIPS64
26690560 23000 case OPC_DAPPEND_DSP:
df6126a7 23001 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23002 case OPC_DAPPEND:
df6126a7
AJ
23003 if (sa != 0) {
23004 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23005 }
26690560
JL
23006 break;
23007 case OPC_PREPENDD:
df6126a7
AJ
23008 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23009 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23010 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23011 break;
23012 case OPC_PREPENDW:
df6126a7
AJ
23013 if (sa != 0) {
23014 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23015 tcg_gen_shli_tl(t0, t0, 64 - sa);
23016 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23017 }
26690560
JL
23018 break;
23019 case OPC_DBALIGN:
df6126a7
AJ
23020 sa &= 7;
23021 if (sa != 0 && sa != 2 && sa != 4) {
23022 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23023 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23024 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23025 }
26690560
JL
23026 break;
23027 default: /* Invalid */
23028 MIPS_INVAL("MASK DAPPEND");
3a4ef3b7 23029 gen_reserved_instruction(ctx);
26690560
JL
23030 break;
23031 }
23032 break;
23033#endif
23034 }
df6126a7 23035 tcg_temp_free(t0);
26690560
JL
23036}
23037
b53371ed
JL
23038static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23039 int ret, int v1, int v2, int check_ret)
23040
23041{
b53371ed
JL
23042 TCGv t0;
23043 TCGv t1;
23044 TCGv v1_t;
23045 TCGv v2_t;
23046 int16_t imm;
23047
23048 if ((ret == 0) && (check_ret == 1)) {
23049 /* Treat as NOP. */
b53371ed
JL
23050 return;
23051 }
23052
23053 t0 = tcg_temp_new();
23054 t1 = tcg_temp_new();
23055 v1_t = tcg_temp_new();
23056 v2_t = tcg_temp_new();
23057
23058 gen_load_gpr(v1_t, v1);
23059 gen_load_gpr(v2_t, v2);
23060
23061 switch (op1) {
23062 case OPC_EXTR_W_DSP:
23063 check_dsp(ctx);
23064 switch (op2) {
23065 case OPC_EXTR_W:
23066 tcg_gen_movi_tl(t0, v2);
23067 tcg_gen_movi_tl(t1, v1);
23068 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23069 break;
23070 case OPC_EXTR_R_W:
23071 tcg_gen_movi_tl(t0, v2);
23072 tcg_gen_movi_tl(t1, v1);
23073 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23074 break;
23075 case OPC_EXTR_RS_W:
23076 tcg_gen_movi_tl(t0, v2);
23077 tcg_gen_movi_tl(t1, v1);
23078 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23079 break;
23080 case OPC_EXTR_S_H:
23081 tcg_gen_movi_tl(t0, v2);
23082 tcg_gen_movi_tl(t1, v1);
23083 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23084 break;
23085 case OPC_EXTRV_S_H:
23086 tcg_gen_movi_tl(t0, v2);
23087 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23088 break;
23089 case OPC_EXTRV_W:
23090 tcg_gen_movi_tl(t0, v2);
23091 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23092 break;
23093 case OPC_EXTRV_R_W:
23094 tcg_gen_movi_tl(t0, v2);
23095 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23096 break;
23097 case OPC_EXTRV_RS_W:
23098 tcg_gen_movi_tl(t0, v2);
23099 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23100 break;
23101 case OPC_EXTP:
23102 tcg_gen_movi_tl(t0, v2);
23103 tcg_gen_movi_tl(t1, v1);
23104 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23105 break;
23106 case OPC_EXTPV:
23107 tcg_gen_movi_tl(t0, v2);
23108 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23109 break;
23110 case OPC_EXTPDP:
23111 tcg_gen_movi_tl(t0, v2);
23112 tcg_gen_movi_tl(t1, v1);
23113 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23114 break;
23115 case OPC_EXTPDPV:
23116 tcg_gen_movi_tl(t0, v2);
23117 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23118 break;
23119 case OPC_SHILO:
23120 imm = (ctx->opcode >> 20) & 0x3F;
23121 tcg_gen_movi_tl(t0, ret);
23122 tcg_gen_movi_tl(t1, imm);
23123 gen_helper_shilo(t0, t1, cpu_env);
23124 break;
23125 case OPC_SHILOV:
23126 tcg_gen_movi_tl(t0, ret);
23127 gen_helper_shilo(t0, v1_t, cpu_env);
23128 break;
23129 case OPC_MTHLIP:
23130 tcg_gen_movi_tl(t0, ret);
23131 gen_helper_mthlip(t0, v1_t, cpu_env);
23132 break;
23133 case OPC_WRDSP:
23134 imm = (ctx->opcode >> 11) & 0x3FF;
23135 tcg_gen_movi_tl(t0, imm);
23136 gen_helper_wrdsp(v1_t, t0, cpu_env);
23137 break;
23138 case OPC_RDDSP:
23139 imm = (ctx->opcode >> 16) & 0x03FF;
23140 tcg_gen_movi_tl(t0, imm);
23141 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23142 break;
23143 }
23144 break;
23145#ifdef TARGET_MIPS64
23146 case OPC_DEXTR_W_DSP:
23147 check_dsp(ctx);
23148 switch (op2) {
23149 case OPC_DMTHLIP:
23150 tcg_gen_movi_tl(t0, ret);
23151 gen_helper_dmthlip(v1_t, t0, cpu_env);
23152 break;
23153 case OPC_DSHILO:
23154 {
23155 int shift = (ctx->opcode >> 19) & 0x7F;
23156 int ac = (ctx->opcode >> 11) & 0x03;
23157 tcg_gen_movi_tl(t0, shift);
23158 tcg_gen_movi_tl(t1, ac);
23159 gen_helper_dshilo(t0, t1, cpu_env);
23160 break;
23161 }
23162 case OPC_DSHILOV:
23163 {
23164 int ac = (ctx->opcode >> 11) & 0x03;
23165 tcg_gen_movi_tl(t0, ac);
23166 gen_helper_dshilo(v1_t, t0, cpu_env);
23167 break;
23168 }
23169 case OPC_DEXTP:
23170 tcg_gen_movi_tl(t0, v2);
23171 tcg_gen_movi_tl(t1, v1);
23172
23173 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23174 break;
23175 case OPC_DEXTPV:
23176 tcg_gen_movi_tl(t0, v2);
23177 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23178 break;
23179 case OPC_DEXTPDP:
23180 tcg_gen_movi_tl(t0, v2);
23181 tcg_gen_movi_tl(t1, v1);
23182 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23183 break;
23184 case OPC_DEXTPDPV:
23185 tcg_gen_movi_tl(t0, v2);
23186 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23187 break;
23188 case OPC_DEXTR_L:
23189 tcg_gen_movi_tl(t0, v2);
23190 tcg_gen_movi_tl(t1, v1);
23191 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23192 break;
23193 case OPC_DEXTR_R_L:
23194 tcg_gen_movi_tl(t0, v2);
23195 tcg_gen_movi_tl(t1, v1);
23196 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23197 break;
23198 case OPC_DEXTR_RS_L:
23199 tcg_gen_movi_tl(t0, v2);
23200 tcg_gen_movi_tl(t1, v1);
23201 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23202 break;
23203 case OPC_DEXTR_W:
23204 tcg_gen_movi_tl(t0, v2);
23205 tcg_gen_movi_tl(t1, v1);
23206 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23207 break;
23208 case OPC_DEXTR_R_W:
23209 tcg_gen_movi_tl(t0, v2);
23210 tcg_gen_movi_tl(t1, v1);
23211 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23212 break;
23213 case OPC_DEXTR_RS_W:
23214 tcg_gen_movi_tl(t0, v2);
23215 tcg_gen_movi_tl(t1, v1);
23216 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23217 break;
23218 case OPC_DEXTR_S_H:
23219 tcg_gen_movi_tl(t0, v2);
23220 tcg_gen_movi_tl(t1, v1);
23221 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23222 break;
23223 case OPC_DEXTRV_S_H:
23224 tcg_gen_movi_tl(t0, v2);
23225 tcg_gen_movi_tl(t1, v1);
23226 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23227 break;
23228 case OPC_DEXTRV_L:
23229 tcg_gen_movi_tl(t0, v2);
23230 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23231 break;
23232 case OPC_DEXTRV_R_L:
23233 tcg_gen_movi_tl(t0, v2);
23234 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23235 break;
23236 case OPC_DEXTRV_RS_L:
23237 tcg_gen_movi_tl(t0, v2);
23238 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23239 break;
23240 case OPC_DEXTRV_W:
23241 tcg_gen_movi_tl(t0, v2);
23242 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23243 break;
23244 case OPC_DEXTRV_R_W:
23245 tcg_gen_movi_tl(t0, v2);
23246 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23247 break;
23248 case OPC_DEXTRV_RS_W:
23249 tcg_gen_movi_tl(t0, v2);
23250 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23251 break;
23252 }
23253 break;
23254#endif
23255 }
23256
23257 tcg_temp_free(t0);
23258 tcg_temp_free(t1);
23259 tcg_temp_free(v1_t);
23260 tcg_temp_free(v2_t);
b53371ed
JL
23261}
23262
9b1a1d68
JL
23263/* End MIPSDSP functions. */
23264
10dc65db
LA
23265static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23266{
4267d3e6 23267 int rs, rt, rd, sa;
b42ee5e1 23268 uint32_t op1, op2;
10dc65db
LA
23269
23270 rs = (ctx->opcode >> 21) & 0x1f;
23271 rt = (ctx->opcode >> 16) & 0x1f;
23272 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 23273 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23274
23275 op1 = MASK_SPECIAL(ctx->opcode);
23276 switch (op1) {
c2e19f3c
AM
23277 case OPC_MULT:
23278 case OPC_MULTU:
23279 case OPC_DIV:
23280 case OPC_DIVU:
b42ee5e1
LA
23281 op2 = MASK_R6_MULDIV(ctx->opcode);
23282 switch (op2) {
23283 case R6_OPC_MUL:
23284 case R6_OPC_MUH:
23285 case R6_OPC_MULU:
23286 case R6_OPC_MUHU:
23287 case R6_OPC_DIV:
23288 case R6_OPC_MOD:
23289 case R6_OPC_DIVU:
23290 case R6_OPC_MODU:
23291 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23292 break;
23293 default:
23294 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 23295 gen_reserved_instruction(ctx);
b42ee5e1
LA
23296 break;
23297 }
23298 break;
10dc65db
LA
23299 case OPC_SELEQZ:
23300 case OPC_SELNEZ:
23301 gen_cond_move(ctx, op1, rd, rs, rt);
23302 break;
4267d3e6
LA
23303 case R6_OPC_CLO:
23304 case R6_OPC_CLZ:
23305 if (rt == 0 && sa == 1) {
7480515f
AM
23306 /*
23307 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23308 * We need additionally to check other fields.
23309 */
4267d3e6
LA
23310 gen_cl(ctx, op1, rd, rs);
23311 } else {
3a4ef3b7 23312 gen_reserved_instruction(ctx);
4267d3e6
LA
23313 }
23314 break;
23315 case R6_OPC_SDBBP:
3b3c1694
LA
23316 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23317 gen_helper_do_semihosting(cpu_env);
faf1f68b 23318 } else {
3b3c1694 23319 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 23320 gen_reserved_instruction(ctx);
3b3c1694 23321 } else {
9c708c7f 23322 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23323 }
faf1f68b 23324 }
4267d3e6 23325 break;
b42ee5e1 23326#if defined(TARGET_MIPS64)
4267d3e6
LA
23327 case R6_OPC_DCLO:
23328 case R6_OPC_DCLZ:
23329 if (rt == 0 && sa == 1) {
7480515f
AM
23330 /*
23331 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23332 * We need additionally to check other fields.
23333 */
4267d3e6
LA
23334 check_mips_64(ctx);
23335 gen_cl(ctx, op1, rd, rs);
23336 } else {
3a4ef3b7 23337 gen_reserved_instruction(ctx);
4267d3e6
LA
23338 }
23339 break;
c2e19f3c
AM
23340 case OPC_DMULT:
23341 case OPC_DMULTU:
23342 case OPC_DDIV:
23343 case OPC_DDIVU:
23344
b42ee5e1
LA
23345 op2 = MASK_R6_MULDIV(ctx->opcode);
23346 switch (op2) {
23347 case R6_OPC_DMUL:
23348 case R6_OPC_DMUH:
23349 case R6_OPC_DMULU:
23350 case R6_OPC_DMUHU:
23351 case R6_OPC_DDIV:
23352 case R6_OPC_DMOD:
23353 case R6_OPC_DDIVU:
23354 case R6_OPC_DMODU:
23355 check_mips_64(ctx);
23356 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23357 break;
23358 default:
23359 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 23360 gen_reserved_instruction(ctx);
b42ee5e1
LA
23361 break;
23362 }
23363 break;
23364#endif
10dc65db
LA
23365 default: /* Invalid */
23366 MIPS_INVAL("special_r6");
3a4ef3b7 23367 gen_reserved_instruction(ctx);
10dc65db
LA
23368 break;
23369 }
23370}
23371
9dc324ce
FN
23372static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23373{
23374 int rs = extract32(ctx->opcode, 21, 5);
23375 int rt = extract32(ctx->opcode, 16, 5);
23376 int rd = extract32(ctx->opcode, 11, 5);
23377 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23378
23379 switch (op1) {
23380 case OPC_MOVN: /* Conditional move */
23381 case OPC_MOVZ:
23382 gen_cond_move(ctx, op1, rd, rs, rt);
23383 break;
23384 case OPC_MFHI: /* Move from HI/LO */
23385 case OPC_MFLO:
23386 gen_HILO(ctx, op1, 0, rd);
23387 break;
23388 case OPC_MTHI:
23389 case OPC_MTLO: /* Move to HI/LO */
23390 gen_HILO(ctx, op1, 0, rs);
23391 break;
23392 case OPC_MULT:
23393 case OPC_MULTU:
23394 gen_mul_txx9(ctx, op1, rd, rs, rt);
23395 break;
23396 case OPC_DIV:
23397 case OPC_DIVU:
23398 gen_muldiv(ctx, op1, 0, rs, rt);
23399 break;
23400#if defined(TARGET_MIPS64)
23401 case OPC_DMULT:
23402 case OPC_DMULTU:
23403 case OPC_DDIV:
23404 case OPC_DDIVU:
23405 check_insn_opc_user_only(ctx, INSN_R5900);
23406 gen_muldiv(ctx, op1, 0, rs, rt);
23407 break;
23408#endif
23409 case OPC_JR:
23410 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23411 break;
23412 default: /* Invalid */
23413 MIPS_INVAL("special_tx79");
3a4ef3b7 23414 gen_reserved_instruction(ctx);
9dc324ce
FN
23415 break;
23416 }
23417}
23418
10dc65db
LA
23419static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23420{
b42ee5e1 23421 int rs, rt, rd, sa;
10dc65db
LA
23422 uint32_t op1;
23423
23424 rs = (ctx->opcode >> 21) & 0x1f;
23425 rt = (ctx->opcode >> 16) & 0x1f;
23426 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 23427 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23428
23429 op1 = MASK_SPECIAL(ctx->opcode);
23430 switch (op1) {
23431 case OPC_MOVN: /* Conditional move */
23432 case OPC_MOVZ:
bbd5e4a2 23433 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
9dc324ce 23434 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
23435 gen_cond_move(ctx, op1, rd, rs, rt);
23436 break;
23437 case OPC_MFHI: /* Move from HI/LO */
23438 case OPC_MFLO:
23439 gen_HILO(ctx, op1, rs & 3, rd);
23440 break;
23441 case OPC_MTHI:
23442 case OPC_MTLO: /* Move to HI/LO */
23443 gen_HILO(ctx, op1, rd & 3, rs);
23444 break;
23445 case OPC_MOVCI:
bbd5e4a2 23446 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10dc65db
LA
23447 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23448 check_cp1_enabled(ctx);
23449 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23450 (ctx->opcode >> 16) & 1);
23451 } else {
23452 generate_exception_err(ctx, EXCP_CpU, 1);
23453 }
23454 break;
b42ee5e1
LA
23455 case OPC_MULT:
23456 case OPC_MULTU:
23457 if (sa) {
23458 check_insn(ctx, INSN_VR54XX);
23459 op1 = MASK_MUL_VR54XX(ctx->opcode);
23460 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23461 } else {
23462 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23463 }
23464 break;
23465 case OPC_DIV:
23466 case OPC_DIVU:
23467 gen_muldiv(ctx, op1, 0, rs, rt);
23468 break;
23469#if defined(TARGET_MIPS64)
c2e19f3c
AM
23470 case OPC_DMULT:
23471 case OPC_DMULTU:
23472 case OPC_DDIV:
23473 case OPC_DDIVU:
b42ee5e1
LA
23474 check_insn(ctx, ISA_MIPS3);
23475 check_mips_64(ctx);
23476 gen_muldiv(ctx, op1, 0, rs, rt);
23477 break;
23478#endif
0aefa333 23479 case OPC_JR:
b231c103 23480 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 23481 break;
4267d3e6
LA
23482 case OPC_SPIM:
23483#ifdef MIPS_STRICT_STANDARD
23484 MIPS_INVAL("SPIM");
3a4ef3b7 23485 gen_reserved_instruction(ctx);
4267d3e6
LA
23486#else
23487 /* Implemented as RI exception for now. */
23488 MIPS_INVAL("spim (unofficial)");
3a4ef3b7 23489 gen_reserved_instruction(ctx);
4267d3e6
LA
23490#endif
23491 break;
10dc65db
LA
23492 default: /* Invalid */
23493 MIPS_INVAL("special_legacy");
3a4ef3b7 23494 gen_reserved_instruction(ctx);
10dc65db
LA
23495 break;
23496 }
23497}
23498
099e5b4d 23499static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 23500{
3c824109 23501 int rs, rt, rd, sa;
099e5b4d 23502 uint32_t op1;
3c824109 23503
3c824109
NF
23504 rs = (ctx->opcode >> 21) & 0x1f;
23505 rt = (ctx->opcode >> 16) & 0x1f;
23506 rd = (ctx->opcode >> 11) & 0x1f;
23507 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
23508
23509 op1 = MASK_SPECIAL(ctx->opcode);
23510 switch (op1) {
23511 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
23512 if (sa == 5 && rd == 0 &&
23513 rs == 0 && rt == 0) { /* PAUSE */
2e211e0a 23514 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 23515 (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 23516 gen_reserved_instruction(ctx);
339cd2a8
LA
23517 break;
23518 }
23519 }
23520 /* Fallthrough */
099e5b4d
LA
23521 case OPC_SRA:
23522 gen_shift_imm(ctx, op1, rd, rt, sa);
23523 break;
23524 case OPC_SRL:
23525 switch ((ctx->opcode >> 21) & 0x1f) {
23526 case 1:
23527 /* rotr is decoded as srl on non-R2 CPUs */
7a47bae5 23528 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23529 op1 = OPC_ROTR;
ea63e2c3 23530 }
099e5b4d
LA
23531 /* Fallthrough */
23532 case 0:
23533 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 23534 break;
099e5b4d 23535 default:
3a4ef3b7 23536 gen_reserved_instruction(ctx);
ea63e2c3 23537 break;
099e5b4d
LA
23538 }
23539 break;
c2e19f3c
AM
23540 case OPC_ADD:
23541 case OPC_ADDU:
23542 case OPC_SUB:
23543 case OPC_SUBU:
099e5b4d
LA
23544 gen_arith(ctx, op1, rd, rs, rt);
23545 break;
23546 case OPC_SLLV: /* Shifts */
23547 case OPC_SRAV:
23548 gen_shift(ctx, op1, rd, rs, rt);
23549 break;
23550 case OPC_SRLV:
23551 switch ((ctx->opcode >> 6) & 0x1f) {
23552 case 1:
23553 /* rotrv is decoded as srlv on non-R2 CPUs */
7a47bae5 23554 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23555 op1 = OPC_ROTRV;
26135ead 23556 }
099e5b4d
LA
23557 /* Fallthrough */
23558 case 0:
23559 gen_shift(ctx, op1, rd, rs, rt);
26135ead 23560 break;
099e5b4d 23561 default:
3a4ef3b7 23562 gen_reserved_instruction(ctx);
6af0bf9c 23563 break;
099e5b4d
LA
23564 }
23565 break;
23566 case OPC_SLT: /* Set on less than */
23567 case OPC_SLTU:
23568 gen_slt(ctx, op1, rd, rs, rt);
23569 break;
23570 case OPC_AND: /* Logic*/
23571 case OPC_OR:
23572 case OPC_NOR:
23573 case OPC_XOR:
23574 gen_logic(ctx, op1, rd, rs, rt);
23575 break;
0aefa333 23576 case OPC_JALR:
b231c103 23577 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 23578 break;
c2e19f3c
AM
23579 case OPC_TGE: /* Traps */
23580 case OPC_TGEU:
23581 case OPC_TLT:
23582 case OPC_TLTU:
23583 case OPC_TEQ:
099e5b4d 23584 case OPC_TNE:
d9224450 23585 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
23586 gen_trap(ctx, op1, rs, rt, -1);
23587 break;
0e9524af
PMD
23588 case OPC_PMON:
23589 /* Pmon entry point, also R4010 selsl */
b48cfdff 23590#ifdef MIPS_STRICT_STANDARD
0e9524af
PMD
23591 MIPS_INVAL("PMON / selsl");
23592 gen_reserved_instruction(ctx);
b48cfdff 23593#else
0e9524af 23594 gen_helper_0e0i(pmon, sa);
b48cfdff 23595#endif
099e5b4d
LA
23596 break;
23597 case OPC_SYSCALL:
9c708c7f 23598 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
23599 break;
23600 case OPC_BREAK:
9c708c7f 23601 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 23602 break;
099e5b4d 23603 case OPC_SYNC:
d9224450 23604 check_insn(ctx, ISA_MIPS2);
d208ac0c 23605 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 23606 break;
4ad40f36 23607
d26bc211 23608#if defined(TARGET_MIPS64)
099e5b4d
LA
23609 /* MIPS64 specific opcodes */
23610 case OPC_DSLL:
23611 case OPC_DSRA:
23612 case OPC_DSLL32:
23613 case OPC_DSRA32:
23614 check_insn(ctx, ISA_MIPS3);
23615 check_mips_64(ctx);
23616 gen_shift_imm(ctx, op1, rd, rt, sa);
23617 break;
23618 case OPC_DSRL:
23619 switch ((ctx->opcode >> 21) & 0x1f) {
23620 case 1:
23621 /* drotr is decoded as dsrl on non-R2 CPUs */
7a47bae5 23622 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23623 op1 = OPC_DROTR;
ea63e2c3 23624 }
099e5b4d
LA
23625 /* Fallthrough */
23626 case 0:
d75c135e 23627 check_insn(ctx, ISA_MIPS3);
e189e748 23628 check_mips_64(ctx);
099e5b4d 23629 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23630 break;
099e5b4d 23631 default:
3a4ef3b7 23632 gen_reserved_instruction(ctx);
460f00c4 23633 break;
099e5b4d
LA
23634 }
23635 break;
23636 case OPC_DSRL32:
23637 switch ((ctx->opcode >> 21) & 0x1f) {
23638 case 1:
23639 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
7a47bae5 23640 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23641 op1 = OPC_DROTR32;
ea63e2c3 23642 }
099e5b4d
LA
23643 /* Fallthrough */
23644 case 0:
d75c135e 23645 check_insn(ctx, ISA_MIPS3);
e189e748 23646 check_mips_64(ctx);
099e5b4d 23647 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23648 break;
099e5b4d 23649 default:
3a4ef3b7 23650 gen_reserved_instruction(ctx);
6af0bf9c
FB
23651 break;
23652 }
23653 break;
c2e19f3c
AM
23654 case OPC_DADD:
23655 case OPC_DADDU:
23656 case OPC_DSUB:
23657 case OPC_DSUBU:
099e5b4d
LA
23658 check_insn(ctx, ISA_MIPS3);
23659 check_mips_64(ctx);
23660 gen_arith(ctx, op1, rd, rs, rt);
23661 break;
23662 case OPC_DSLLV:
23663 case OPC_DSRAV:
23664 check_insn(ctx, ISA_MIPS3);
23665 check_mips_64(ctx);
23666 gen_shift(ctx, op1, rd, rs, rt);
23667 break;
23668 case OPC_DSRLV:
23669 switch ((ctx->opcode >> 6) & 0x1f) {
23670 case 1:
23671 /* drotrv is decoded as dsrlv on non-R2 CPUs */
7a47bae5 23672 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23673 op1 = OPC_DROTRV;
6af0bf9c 23674 }
099e5b4d
LA
23675 /* Fallthrough */
23676 case 0:
23677 check_insn(ctx, ISA_MIPS3);
e189e748 23678 check_mips_64(ctx);
099e5b4d 23679 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 23680 break;
099e5b4d 23681 default:
3a4ef3b7 23682 gen_reserved_instruction(ctx);
6af0bf9c
FB
23683 break;
23684 }
23685 break;
099e5b4d 23686#endif
10dc65db 23687 default:
2e211e0a 23688 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db 23689 decode_opc_special_r6(env, ctx);
9dc324ce
FN
23690 } else if (ctx->insn_flags & INSN_R5900) {
23691 decode_opc_special_tx79(env, ctx);
10dc65db
LA
23692 } else {
23693 decode_opc_special_legacy(env, ctx);
23694 }
23695 }
23696}
23697
d67da337 23698
10dc65db 23699static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
23700{
23701 int rs, rt, rd;
23702 uint32_t op1;
6c5c1e20 23703
099e5b4d
LA
23704 rs = (ctx->opcode >> 21) & 0x1f;
23705 rt = (ctx->opcode >> 16) & 0x1f;
23706 rd = (ctx->opcode >> 11) & 0x1f;
23707
23708 op1 = MASK_SPECIAL2(ctx->opcode);
23709 switch (op1) {
c2e19f3c
AM
23710 case OPC_MADD: /* Multiply and add/sub */
23711 case OPC_MADDU:
23712 case OPC_MSUB:
23713 case OPC_MSUBU:
bbd5e4a2 23714 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23715 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23716 break;
23717 case OPC_MUL:
099e5b4d
LA
23718 gen_arith(ctx, op1, rd, rs, rt);
23719 break;
fac5a073
LA
23720 case OPC_DIV_G_2F:
23721 case OPC_DIVU_G_2F:
23722 case OPC_MULT_G_2F:
23723 case OPC_MULTU_G_2F:
23724 case OPC_MOD_G_2F:
23725 case OPC_MODU_G_2F:
8e2d5831 23726 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
fac5a073
LA
23727 gen_loongson_integer(ctx, op1, rd, rs, rt);
23728 break;
099e5b4d
LA
23729 case OPC_CLO:
23730 case OPC_CLZ:
bbd5e4a2 23731 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23732 gen_cl(ctx, op1, rd, rs);
23733 break;
23734 case OPC_SDBBP:
3b3c1694
LA
23735 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23736 gen_helper_do_semihosting(cpu_env);
23737 } else {
7480515f
AM
23738 /*
23739 * XXX: not clear which exception should be raised
3b3c1694
LA
23740 * when in debug mode...
23741 */
bbd5e4a2 23742 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 23743 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23744 }
099e5b4d 23745 break;
9b1a1d68 23746#if defined(TARGET_MIPS64)
099e5b4d
LA
23747 case OPC_DCLO:
23748 case OPC_DCLZ:
bbd5e4a2 23749 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23750 check_mips_64(ctx);
23751 gen_cl(ctx, op1, rd, rs);
23752 break;
4267d3e6
LA
23753 case OPC_DMULT_G_2F:
23754 case OPC_DMULTU_G_2F:
23755 case OPC_DDIV_G_2F:
23756 case OPC_DDIVU_G_2F:
23757 case OPC_DMOD_G_2F:
23758 case OPC_DMODU_G_2F:
8e2d5831 23759 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
4267d3e6
LA
23760 gen_loongson_integer(ctx, op1, rd, rs, rt);
23761 break;
10dc65db 23762#endif
4267d3e6
LA
23763 default: /* Invalid */
23764 MIPS_INVAL("special2_legacy");
3a4ef3b7 23765 gen_reserved_instruction(ctx);
4267d3e6 23766 break;
10dc65db
LA
23767 }
23768}
23769
23770static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23771{
15eacb9b
YK
23772 int rs, rt, rd, sa;
23773 uint32_t op1, op2;
10dc65db
LA
23774 int16_t imm;
23775
23776 rs = (ctx->opcode >> 21) & 0x1f;
23777 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
23778 rd = (ctx->opcode >> 11) & 0x1f;
23779 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23780 imm = (int16_t)ctx->opcode >> 7;
23781
23782 op1 = MASK_SPECIAL3(ctx->opcode);
23783 switch (op1) {
bf7910c6
LA
23784 case R6_OPC_PREF:
23785 if (rt >= 24) {
23786 /* hint codes 24-31 are reserved and signal RI */
3a4ef3b7 23787 gen_reserved_instruction(ctx);
bf7910c6
LA
23788 }
23789 /* Treat as NOP. */
23790 break;
23791 case R6_OPC_CACHE:
40d48212 23792 check_cp0_enabled(ctx);
0d74a222
LA
23793 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23794 gen_cache_operation(ctx, rt, rs, imm);
23795 }
bf7910c6 23796 break;
10dc65db 23797 case R6_OPC_SC:
33a07fa2 23798 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
23799 break;
23800 case R6_OPC_LL:
23801 gen_ld(ctx, op1, rt, rs, imm);
23802 break;
15eacb9b
YK
23803 case OPC_BSHFL:
23804 {
23805 if (rd == 0) {
23806 /* Treat as NOP. */
23807 break;
23808 }
15eacb9b
YK
23809 op2 = MASK_BSHFL(ctx->opcode);
23810 switch (op2) {
c2e19f3c 23811 case OPC_ALIGN:
373ecd38
AM
23812 case OPC_ALIGN_1:
23813 case OPC_ALIGN_2:
23814 case OPC_ALIGN_3:
821f2008 23815 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
23816 break;
23817 case OPC_BITSWAP:
1f1b4c00 23818 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23819 break;
23820 }
15eacb9b
YK
23821 }
23822 break;
99029be1
YK
23823#ifndef CONFIG_USER_ONLY
23824 case OPC_GINV:
23825 if (unlikely(ctx->gi <= 1)) {
3a4ef3b7 23826 gen_reserved_instruction(ctx);
99029be1
YK
23827 }
23828 check_cp0_enabled(ctx);
23829 switch ((ctx->opcode >> 6) & 3) {
23830 case 0: /* GINVI */
23831 /* Treat as NOP. */
23832 break;
23833 case 2: /* GINVT */
23834 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23835 break;
23836 default:
3a4ef3b7 23837 gen_reserved_instruction(ctx);
99029be1
YK
23838 break;
23839 }
23840 break;
23841#endif
bf7910c6
LA
23842#if defined(TARGET_MIPS64)
23843 case R6_OPC_SCD:
33a07fa2 23844 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
23845 break;
23846 case R6_OPC_LLD:
23847 gen_ld(ctx, op1, rt, rs, imm);
23848 break;
15eacb9b
YK
23849 case OPC_DBSHFL:
23850 check_mips_64(ctx);
23851 {
23852 if (rd == 0) {
23853 /* Treat as NOP. */
23854 break;
23855 }
15eacb9b
YK
23856 op2 = MASK_DBSHFL(ctx->opcode);
23857 switch (op2) {
c2e19f3c 23858 case OPC_DALIGN:
373ecd38
AM
23859 case OPC_DALIGN_1:
23860 case OPC_DALIGN_2:
23861 case OPC_DALIGN_3:
23862 case OPC_DALIGN_4:
23863 case OPC_DALIGN_5:
23864 case OPC_DALIGN_6:
23865 case OPC_DALIGN_7:
821f2008 23866 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
23867 break;
23868 case OPC_DBITSWAP:
1f1b4c00 23869 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23870 break;
23871 }
1f1b4c00 23872
15eacb9b
YK
23873 }
23874 break;
bf7910c6 23875#endif
10dc65db
LA
23876 default: /* Invalid */
23877 MIPS_INVAL("special3_r6");
3a4ef3b7 23878 gen_reserved_instruction(ctx);
10dc65db
LA
23879 break;
23880 }
23881}
23882
23883static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23884{
fac5a073 23885 int rs, rt, rd;
099e5b4d 23886 uint32_t op1, op2;
099e5b4d
LA
23887
23888 rs = (ctx->opcode >> 21) & 0x1f;
23889 rt = (ctx->opcode >> 16) & 0x1f;
23890 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
23891
23892 op1 = MASK_SPECIAL3(ctx->opcode);
23893 switch (op1) {
c2e19f3c
AM
23894 case OPC_DIV_G_2E:
23895 case OPC_DIVU_G_2E:
23896 case OPC_MOD_G_2E:
23897 case OPC_MODU_G_2E:
23898 case OPC_MULT_G_2E:
23899 case OPC_MULTU_G_2E:
7480515f
AM
23900 /*
23901 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23902 * the same mask and op1.
23903 */
908f6be1 23904 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 23905 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 23906 switch (op2) {
099e5b4d
LA
23907 case OPC_ADDUH_QB:
23908 case OPC_ADDUH_R_QB:
23909 case OPC_ADDQH_PH:
23910 case OPC_ADDQH_R_PH:
23911 case OPC_ADDQH_W:
23912 case OPC_ADDQH_R_W:
23913 case OPC_SUBUH_QB:
23914 case OPC_SUBUH_R_QB:
23915 case OPC_SUBQH_PH:
23916 case OPC_SUBQH_R_PH:
23917 case OPC_SUBQH_W:
23918 case OPC_SUBQH_R_W:
461c08df
JL
23919 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23920 break;
099e5b4d
LA
23921 case OPC_MUL_PH:
23922 case OPC_MUL_S_PH:
23923 case OPC_MULQ_S_W:
23924 case OPC_MULQ_RS_W:
23925 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 23926 break;
461c08df 23927 default:
099e5b4d 23928 MIPS_INVAL("MASK ADDUH.QB");
3a4ef3b7 23929 gen_reserved_instruction(ctx);
461c08df
JL
23930 break;
23931 }
099e5b4d
LA
23932 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23933 gen_loongson_integer(ctx, op1, rd, rs, rt);
23934 } else {
3a4ef3b7 23935 gen_reserved_instruction(ctx);
099e5b4d
LA
23936 }
23937 break;
23938 case OPC_LX_DSP:
23939 op2 = MASK_LX(ctx->opcode);
23940 switch (op2) {
23941#if defined(TARGET_MIPS64)
23942 case OPC_LDX:
23943#endif
23944 case OPC_LBUX:
23945 case OPC_LHX:
23946 case OPC_LWX:
23947 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23948 break;
23949 default: /* Invalid */
23950 MIPS_INVAL("MASK LX");
3a4ef3b7 23951 gen_reserved_instruction(ctx);
099e5b4d
LA
23952 break;
23953 }
23954 break;
23955 case OPC_ABSQ_S_PH_DSP:
23956 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23957 switch (op2) {
23958 case OPC_ABSQ_S_QB:
23959 case OPC_ABSQ_S_PH:
23960 case OPC_ABSQ_S_W:
23961 case OPC_PRECEQ_W_PHL:
23962 case OPC_PRECEQ_W_PHR:
23963 case OPC_PRECEQU_PH_QBL:
23964 case OPC_PRECEQU_PH_QBR:
23965 case OPC_PRECEQU_PH_QBLA:
23966 case OPC_PRECEQU_PH_QBRA:
23967 case OPC_PRECEU_PH_QBL:
23968 case OPC_PRECEU_PH_QBR:
23969 case OPC_PRECEU_PH_QBLA:
23970 case OPC_PRECEU_PH_QBRA:
23971 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23972 break;
23973 case OPC_BITREV:
23974 case OPC_REPL_QB:
23975 case OPC_REPLV_QB:
23976 case OPC_REPL_PH:
23977 case OPC_REPLV_PH:
23978 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23979 break;
23980 default:
23981 MIPS_INVAL("MASK ABSQ_S.PH");
3a4ef3b7 23982 gen_reserved_instruction(ctx);
099e5b4d
LA
23983 break;
23984 }
23985 break;
23986 case OPC_ADDU_QB_DSP:
23987 op2 = MASK_ADDU_QB(ctx->opcode);
23988 switch (op2) {
23989 case OPC_ADDQ_PH:
23990 case OPC_ADDQ_S_PH:
23991 case OPC_ADDQ_S_W:
23992 case OPC_ADDU_QB:
23993 case OPC_ADDU_S_QB:
23994 case OPC_ADDU_PH:
23995 case OPC_ADDU_S_PH:
23996 case OPC_SUBQ_PH:
23997 case OPC_SUBQ_S_PH:
23998 case OPC_SUBQ_S_W:
23999 case OPC_SUBU_QB:
24000 case OPC_SUBU_S_QB:
24001 case OPC_SUBU_PH:
24002 case OPC_SUBU_S_PH:
24003 case OPC_ADDSC:
24004 case OPC_ADDWC:
24005 case OPC_MODSUB:
24006 case OPC_RADDU_W_QB:
24007 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24008 break;
24009 case OPC_MULEU_S_PH_QBL:
24010 case OPC_MULEU_S_PH_QBR:
24011 case OPC_MULQ_RS_PH:
24012 case OPC_MULEQ_S_W_PHL:
24013 case OPC_MULEQ_S_W_PHR:
24014 case OPC_MULQ_S_PH:
24015 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24016 break;
24017 default: /* Invalid */
24018 MIPS_INVAL("MASK ADDU.QB");
3a4ef3b7 24019 gen_reserved_instruction(ctx);
461c08df 24020 break;
461c08df 24021
099e5b4d
LA
24022 }
24023 break;
24024 case OPC_CMPU_EQ_QB_DSP:
24025 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24026 switch (op2) {
24027 case OPC_PRECR_SRA_PH_W:
24028 case OPC_PRECR_SRA_R_PH_W:
24029 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 24030 break;
099e5b4d
LA
24031 case OPC_PRECR_QB_PH:
24032 case OPC_PRECRQ_QB_PH:
24033 case OPC_PRECRQ_PH_W:
24034 case OPC_PRECRQ_RS_PH_W:
24035 case OPC_PRECRQU_S_QB_PH:
24036 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 24037 break;
099e5b4d
LA
24038 case OPC_CMPU_EQ_QB:
24039 case OPC_CMPU_LT_QB:
24040 case OPC_CMPU_LE_QB:
24041 case OPC_CMP_EQ_PH:
24042 case OPC_CMP_LT_PH:
24043 case OPC_CMP_LE_PH:
24044 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 24045 break;
099e5b4d
LA
24046 case OPC_CMPGU_EQ_QB:
24047 case OPC_CMPGU_LT_QB:
24048 case OPC_CMPGU_LE_QB:
24049 case OPC_CMPGDU_EQ_QB:
24050 case OPC_CMPGDU_LT_QB:
24051 case OPC_CMPGDU_LE_QB:
24052 case OPC_PICK_QB:
24053 case OPC_PICK_PH:
24054 case OPC_PACKRL_PH:
24055 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24056 break;
24057 default: /* Invalid */
24058 MIPS_INVAL("MASK CMPU.EQ.QB");
3a4ef3b7 24059 gen_reserved_instruction(ctx);
099e5b4d
LA
24060 break;
24061 }
24062 break;
24063 case OPC_SHLL_QB_DSP:
24064 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24065 break;
24066 case OPC_DPA_W_PH_DSP:
24067 op2 = MASK_DPA_W_PH(ctx->opcode);
24068 switch (op2) {
24069 case OPC_DPAU_H_QBL:
24070 case OPC_DPAU_H_QBR:
24071 case OPC_DPSU_H_QBL:
24072 case OPC_DPSU_H_QBR:
24073 case OPC_DPA_W_PH:
24074 case OPC_DPAX_W_PH:
24075 case OPC_DPAQ_S_W_PH:
24076 case OPC_DPAQX_S_W_PH:
24077 case OPC_DPAQX_SA_W_PH:
24078 case OPC_DPS_W_PH:
24079 case OPC_DPSX_W_PH:
24080 case OPC_DPSQ_S_W_PH:
24081 case OPC_DPSQX_S_W_PH:
24082 case OPC_DPSQX_SA_W_PH:
24083 case OPC_MULSAQ_S_W_PH:
24084 case OPC_DPAQ_SA_L_W:
24085 case OPC_DPSQ_SA_L_W:
24086 case OPC_MAQ_S_W_PHL:
24087 case OPC_MAQ_S_W_PHR:
24088 case OPC_MAQ_SA_W_PHL:
24089 case OPC_MAQ_SA_W_PHR:
24090 case OPC_MULSA_W_PH:
24091 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24092 break;
24093 default: /* Invalid */
24094 MIPS_INVAL("MASK DPAW.PH");
3a4ef3b7 24095 gen_reserved_instruction(ctx);
099e5b4d
LA
24096 break;
24097 }
24098 break;
24099 case OPC_INSV_DSP:
24100 op2 = MASK_INSV(ctx->opcode);
24101 switch (op2) {
24102 case OPC_INSV:
24103 check_dsp(ctx);
24104 {
24105 TCGv t0, t1;
24106
24107 if (rt == 0) {
099e5b4d
LA
24108 break;
24109 }
24110
24111 t0 = tcg_temp_new();
24112 t1 = tcg_temp_new();
24113
24114 gen_load_gpr(t0, rt);
24115 gen_load_gpr(t1, rs);
24116
24117 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24118
24119 tcg_temp_free(t0);
24120 tcg_temp_free(t1);
a22260ae
JL
24121 break;
24122 }
099e5b4d
LA
24123 default: /* Invalid */
24124 MIPS_INVAL("MASK INSV");
3a4ef3b7 24125 gen_reserved_instruction(ctx);
099e5b4d
LA
24126 break;
24127 }
24128 break;
24129 case OPC_APPEND_DSP:
24130 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24131 break;
24132 case OPC_EXTR_W_DSP:
24133 op2 = MASK_EXTR_W(ctx->opcode);
24134 switch (op2) {
24135 case OPC_EXTR_W:
24136 case OPC_EXTR_R_W:
24137 case OPC_EXTR_RS_W:
24138 case OPC_EXTR_S_H:
24139 case OPC_EXTRV_S_H:
24140 case OPC_EXTRV_W:
24141 case OPC_EXTRV_R_W:
24142 case OPC_EXTRV_RS_W:
24143 case OPC_EXTP:
24144 case OPC_EXTPV:
24145 case OPC_EXTPDP:
24146 case OPC_EXTPDPV:
24147 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24148 break;
24149 case OPC_RDDSP:
24150 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24151 break;
24152 case OPC_SHILO:
24153 case OPC_SHILOV:
24154 case OPC_MTHLIP:
24155 case OPC_WRDSP:
24156 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24157 break;
24158 default: /* Invalid */
24159 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 24160 gen_reserved_instruction(ctx);
099e5b4d
LA
24161 break;
24162 }
24163 break;
099e5b4d 24164#if defined(TARGET_MIPS64)
c2e19f3c
AM
24165 case OPC_DDIV_G_2E:
24166 case OPC_DDIVU_G_2E:
24167 case OPC_DMULT_G_2E:
24168 case OPC_DMULTU_G_2E:
24169 case OPC_DMOD_G_2E:
24170 case OPC_DMODU_G_2E:
fac5a073
LA
24171 check_insn(ctx, INSN_LOONGSON2E);
24172 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 24173 break;
099e5b4d
LA
24174 case OPC_ABSQ_S_QH_DSP:
24175 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24176 switch (op2) {
24177 case OPC_PRECEQ_L_PWL:
24178 case OPC_PRECEQ_L_PWR:
24179 case OPC_PRECEQ_PW_QHL:
24180 case OPC_PRECEQ_PW_QHR:
24181 case OPC_PRECEQ_PW_QHLA:
24182 case OPC_PRECEQ_PW_QHRA:
24183 case OPC_PRECEQU_QH_OBL:
24184 case OPC_PRECEQU_QH_OBR:
24185 case OPC_PRECEQU_QH_OBLA:
24186 case OPC_PRECEQU_QH_OBRA:
24187 case OPC_PRECEU_QH_OBL:
24188 case OPC_PRECEU_QH_OBR:
24189 case OPC_PRECEU_QH_OBLA:
24190 case OPC_PRECEU_QH_OBRA:
24191 case OPC_ABSQ_S_OB:
24192 case OPC_ABSQ_S_PW:
24193 case OPC_ABSQ_S_QH:
24194 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24195 break;
24196 case OPC_REPL_OB:
24197 case OPC_REPL_PW:
24198 case OPC_REPL_QH:
24199 case OPC_REPLV_OB:
24200 case OPC_REPLV_PW:
24201 case OPC_REPLV_QH:
24202 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24203 break;
24204 default: /* Invalid */
24205 MIPS_INVAL("MASK ABSQ_S.QH");
3a4ef3b7 24206 gen_reserved_instruction(ctx);
099e5b4d
LA
24207 break;
24208 }
24209 break;
24210 case OPC_ADDU_OB_DSP:
24211 op2 = MASK_ADDU_OB(ctx->opcode);
24212 switch (op2) {
24213 case OPC_RADDU_L_OB:
24214 case OPC_SUBQ_PW:
24215 case OPC_SUBQ_S_PW:
24216 case OPC_SUBQ_QH:
24217 case OPC_SUBQ_S_QH:
24218 case OPC_SUBU_OB:
24219 case OPC_SUBU_S_OB:
24220 case OPC_SUBU_QH:
24221 case OPC_SUBU_S_QH:
24222 case OPC_SUBUH_OB:
24223 case OPC_SUBUH_R_OB:
24224 case OPC_ADDQ_PW:
24225 case OPC_ADDQ_S_PW:
24226 case OPC_ADDQ_QH:
24227 case OPC_ADDQ_S_QH:
24228 case OPC_ADDU_OB:
24229 case OPC_ADDU_S_OB:
24230 case OPC_ADDU_QH:
24231 case OPC_ADDU_S_QH:
24232 case OPC_ADDUH_OB:
24233 case OPC_ADDUH_R_OB:
24234 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 24235 break;
099e5b4d
LA
24236 case OPC_MULEQ_S_PW_QHL:
24237 case OPC_MULEQ_S_PW_QHR:
24238 case OPC_MULEU_S_QH_OBL:
24239 case OPC_MULEU_S_QH_OBR:
24240 case OPC_MULQ_RS_QH:
24241 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 24242 break;
099e5b4d
LA
24243 default: /* Invalid */
24244 MIPS_INVAL("MASK ADDU.OB");
3a4ef3b7 24245 gen_reserved_instruction(ctx);
26690560 24246 break;
099e5b4d
LA
24247 }
24248 break;
24249 case OPC_CMPU_EQ_OB_DSP:
24250 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24251 switch (op2) {
24252 case OPC_PRECR_SRA_QH_PW:
24253 case OPC_PRECR_SRA_R_QH_PW:
24254 /* Return value is rt. */
24255 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 24256 break;
099e5b4d
LA
24257 case OPC_PRECR_OB_QH:
24258 case OPC_PRECRQ_OB_QH:
24259 case OPC_PRECRQ_PW_L:
24260 case OPC_PRECRQ_QH_PW:
24261 case OPC_PRECRQ_RS_QH_PW:
24262 case OPC_PRECRQU_S_OB_QH:
24263 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 24264 break;
099e5b4d
LA
24265 case OPC_CMPU_EQ_OB:
24266 case OPC_CMPU_LT_OB:
24267 case OPC_CMPU_LE_OB:
24268 case OPC_CMP_EQ_QH:
24269 case OPC_CMP_LT_QH:
24270 case OPC_CMP_LE_QH:
24271 case OPC_CMP_EQ_PW:
24272 case OPC_CMP_LT_PW:
24273 case OPC_CMP_LE_PW:
24274 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 24275 break;
099e5b4d
LA
24276 case OPC_CMPGDU_EQ_OB:
24277 case OPC_CMPGDU_LT_OB:
24278 case OPC_CMPGDU_LE_OB:
24279 case OPC_CMPGU_EQ_OB:
24280 case OPC_CMPGU_LT_OB:
24281 case OPC_CMPGU_LE_OB:
24282 case OPC_PACKRL_PW:
24283 case OPC_PICK_OB:
24284 case OPC_PICK_PW:
24285 case OPC_PICK_QH:
24286 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 24287 break;
099e5b4d
LA
24288 default: /* Invalid */
24289 MIPS_INVAL("MASK CMPU_EQ.OB");
3a4ef3b7 24290 gen_reserved_instruction(ctx);
161f85e6 24291 break;
099e5b4d
LA
24292 }
24293 break;
24294 case OPC_DAPPEND_DSP:
24295 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24296 break;
24297 case OPC_DEXTR_W_DSP:
24298 op2 = MASK_DEXTR_W(ctx->opcode);
24299 switch (op2) {
24300 case OPC_DEXTP:
24301 case OPC_DEXTPDP:
24302 case OPC_DEXTPDPV:
24303 case OPC_DEXTPV:
24304 case OPC_DEXTR_L:
24305 case OPC_DEXTR_R_L:
24306 case OPC_DEXTR_RS_L:
24307 case OPC_DEXTR_W:
24308 case OPC_DEXTR_R_W:
24309 case OPC_DEXTR_RS_W:
24310 case OPC_DEXTR_S_H:
24311 case OPC_DEXTRV_L:
24312 case OPC_DEXTRV_R_L:
24313 case OPC_DEXTRV_RS_L:
24314 case OPC_DEXTRV_S_H:
24315 case OPC_DEXTRV_W:
24316 case OPC_DEXTRV_R_W:
24317 case OPC_DEXTRV_RS_W:
24318 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 24319 break;
099e5b4d
LA
24320 case OPC_DMTHLIP:
24321 case OPC_DSHILO:
24322 case OPC_DSHILOV:
24323 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 24324 break;
099e5b4d
LA
24325 default: /* Invalid */
24326 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 24327 gen_reserved_instruction(ctx);
461c08df 24328 break;
099e5b4d
LA
24329 }
24330 break;
24331 case OPC_DPAQ_W_QH_DSP:
24332 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24333 switch (op2) {
24334 case OPC_DPAU_H_OBL:
24335 case OPC_DPAU_H_OBR:
24336 case OPC_DPSU_H_OBL:
24337 case OPC_DPSU_H_OBR:
24338 case OPC_DPA_W_QH:
24339 case OPC_DPAQ_S_W_QH:
24340 case OPC_DPS_W_QH:
24341 case OPC_DPSQ_S_W_QH:
24342 case OPC_MULSAQ_S_W_QH:
24343 case OPC_DPAQ_SA_L_PW:
24344 case OPC_DPSQ_SA_L_PW:
24345 case OPC_MULSAQ_S_L_PW:
24346 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24347 break;
24348 case OPC_MAQ_S_W_QHLL:
24349 case OPC_MAQ_S_W_QHLR:
24350 case OPC_MAQ_S_W_QHRL:
24351 case OPC_MAQ_S_W_QHRR:
24352 case OPC_MAQ_SA_W_QHLL:
24353 case OPC_MAQ_SA_W_QHLR:
24354 case OPC_MAQ_SA_W_QHRL:
24355 case OPC_MAQ_SA_W_QHRR:
24356 case OPC_MAQ_S_L_PWL:
24357 case OPC_MAQ_S_L_PWR:
24358 case OPC_DMADD:
24359 case OPC_DMADDU:
24360 case OPC_DMSUB:
24361 case OPC_DMSUBU:
24362 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 24363 break;
099e5b4d
LA
24364 default: /* Invalid */
24365 MIPS_INVAL("MASK DPAQ.W.QH");
3a4ef3b7 24366 gen_reserved_instruction(ctx);
b53371ed 24367 break;
099e5b4d
LA
24368 }
24369 break;
24370 case OPC_DINSV_DSP:
24371 op2 = MASK_INSV(ctx->opcode);
24372 switch (op2) {
24373 case OPC_DINSV:
24374 {
24375 TCGv t0, t1;
24376
24377 if (rt == 0) {
a22260ae
JL
24378 break;
24379 }
099e5b4d 24380 check_dsp(ctx);
1cb6686c 24381
099e5b4d
LA
24382 t0 = tcg_temp_new();
24383 t1 = tcg_temp_new();
1cb6686c 24384
099e5b4d
LA
24385 gen_load_gpr(t0, rt);
24386 gen_load_gpr(t1, rs);
1cb6686c 24387
099e5b4d 24388 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 24389
099e5b4d
LA
24390 tcg_temp_free(t0);
24391 tcg_temp_free(t1);
77c5fa8b 24392 break;
099e5b4d 24393 }
7a387fff 24394 default: /* Invalid */
099e5b4d 24395 MIPS_INVAL("MASK DINSV");
3a4ef3b7 24396 gen_reserved_instruction(ctx);
7a387fff
TS
24397 break;
24398 }
24399 break;
099e5b4d
LA
24400 case OPC_SHLL_OB_DSP:
24401 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24402 break;
24403#endif
fac5a073
LA
24404 default: /* Invalid */
24405 MIPS_INVAL("special3_legacy");
3a4ef3b7 24406 gen_reserved_instruction(ctx);
fac5a073
LA
24407 break;
24408 }
24409}
24410
37b9aae2
MM
24411
24412#if defined(TARGET_MIPS64)
24413
874b2879 24414static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 24415{
c8341e00 24416 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
24417 int rs = extract32(ctx->opcode, 21, 5);
24418 int rt = extract32(ctx->opcode, 16, 5);
24419 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
24420
24421 switch (opc) {
baa609db
AM
24422 case MMI_OPC_MULT1:
24423 case MMI_OPC_MULTU1:
3b948f05
PMD
24424 case MMI_OPC_MADD:
24425 case MMI_OPC_MADDU:
a95c4c26
FN
24426 case MMI_OPC_MADD1:
24427 case MMI_OPC_MADDU1:
06de726b
FN
24428 gen_mul_txx9(ctx, opc, rd, rs, rt);
24429 break;
baa609db
AM
24430 case MMI_OPC_DIV1:
24431 case MMI_OPC_DIVU1:
c42171c3 24432 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 24433 break;
71b8a6b3
FN
24434 default:
24435 MIPS_INVAL("TX79 MMI class");
3a4ef3b7 24436 gen_reserved_instruction(ctx);
71b8a6b3
FN
24437 break;
24438 }
24439}
24440
874b2879 24441static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 24442{
3a4ef3b7 24443 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
f08099ad
FN
24444}
24445
874b2879 24446static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 24447{
3a4ef3b7 24448 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
24449}
24450
24451/*
24452 * The TX79-specific instruction Store Quadword
24453 *
24454 * +--------+-------+-------+------------------------+
24455 * | 011111 | base | rt | offset | SQ
24456 * +--------+-------+-------+------------------------+
24457 * 6 5 5 16
24458 *
24459 * has the same opcode as the Read Hardware Register instruction
24460 *
24461 * +--------+-------+-------+-------+-------+--------+
24462 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24463 * +--------+-------+-------+-------+-------+--------+
24464 * 6 5 5 5 5 6
24465 *
24466 * that is required, trapped and emulated by the Linux kernel. However, all
24467 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24468 * offset is odd. Therefore all valid SQ instructions can execute normally.
24469 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24470 * between SQ and RDHWR, as the Linux kernel does.
24471 */
874b2879 24472static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
24473{
24474 int base = extract32(ctx->opcode, 21, 5);
24475 int rt = extract32(ctx->opcode, 16, 5);
24476 int offset = extract32(ctx->opcode, 0, 16);
24477
24478#ifdef CONFIG_USER_ONLY
24479 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24480 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24481
24482 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24483 int rd = extract32(ctx->opcode, 11, 5);
24484
24485 gen_rdhwr(ctx, rt, rd, 0);
24486 return;
24487 }
24488#endif
24489
874b2879 24490 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
24491}
24492
37b9aae2
MM
24493#endif
24494
fac5a073
LA
24495static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24496{
24497 int rs, rt, rd, sa;
24498 uint32_t op1, op2;
76964147 24499 int16_t imm;
fac5a073
LA
24500
24501 rs = (ctx->opcode >> 21) & 0x1f;
24502 rt = (ctx->opcode >> 16) & 0x1f;
24503 rd = (ctx->opcode >> 11) & 0x1f;
24504 sa = (ctx->opcode >> 6) & 0x1f;
76964147 24505 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
24506
24507 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
24508
24509 /*
24510 * EVA loads and stores overlap Loongson 2E instructions decoded by
24511 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24512 * EVA is absent.
24513 */
24514 if (ctx->eva) {
24515 switch (op1) {
c2e19f3c
AM
24516 case OPC_LWLE:
24517 case OPC_LWRE:
c2e19f3c
AM
24518 case OPC_LBUE:
24519 case OPC_LHUE:
24520 case OPC_LBE:
24521 case OPC_LHE:
24522 case OPC_LLE:
24523 case OPC_LWE:
76964147
JH
24524 check_cp0_enabled(ctx);
24525 gen_ld(ctx, op1, rt, rs, imm);
24526 return;
c2e19f3c
AM
24527 case OPC_SWLE:
24528 case OPC_SWRE:
c2e19f3c
AM
24529 case OPC_SBE:
24530 case OPC_SHE:
76964147
JH
24531 case OPC_SWE:
24532 check_cp0_enabled(ctx);
24533 gen_st(ctx, op1, rt, rs, imm);
24534 return;
24535 case OPC_SCE:
24536 check_cp0_enabled(ctx);
33a07fa2 24537 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
24538 return;
24539 case OPC_CACHEE:
84c2fdc3 24540 check_eva(ctx);
76964147
JH
24541 check_cp0_enabled(ctx);
24542 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24543 gen_cache_operation(ctx, rt, rs, imm);
24544 }
76964147
JH
24545 return;
24546 case OPC_PREFE:
24547 check_cp0_enabled(ctx);
24548 /* Treat as NOP. */
24549 return;
24550 }
24551 }
24552
fac5a073
LA
24553 switch (op1) {
24554 case OPC_EXT:
24555 case OPC_INS:
7a47bae5 24556 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
24557 gen_bitops(ctx, op1, rt, rs, sa, rd);
24558 break;
24559 case OPC_BSHFL:
fac5a073 24560 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 24561 switch (op2) {
c2e19f3c 24562 case OPC_ALIGN:
373ecd38
AM
24563 case OPC_ALIGN_1:
24564 case OPC_ALIGN_2:
24565 case OPC_ALIGN_3:
15eacb9b 24566 case OPC_BITSWAP:
2e211e0a 24567 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
24568 decode_opc_special3_r6(env, ctx);
24569 break;
24570 default:
7a47bae5 24571 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
24572 gen_bshfl(ctx, op2, rt, rd);
24573 break;
24574 }
fac5a073
LA
24575 break;
24576#if defined(TARGET_MIPS64)
c2e19f3c
AM
24577 case OPC_DEXTM:
24578 case OPC_DEXTU:
24579 case OPC_DEXT:
24580 case OPC_DINSM:
24581 case OPC_DINSU:
24582 case OPC_DINS:
7a47bae5 24583 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
24584 check_mips_64(ctx);
24585 gen_bitops(ctx, op1, rt, rs, sa, rd);
24586 break;
24587 case OPC_DBSHFL:
fac5a073 24588 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 24589 switch (op2) {
c2e19f3c 24590 case OPC_DALIGN:
373ecd38
AM
24591 case OPC_DALIGN_1:
24592 case OPC_DALIGN_2:
24593 case OPC_DALIGN_3:
24594 case OPC_DALIGN_4:
24595 case OPC_DALIGN_5:
24596 case OPC_DALIGN_6:
24597 case OPC_DALIGN_7:
15eacb9b 24598 case OPC_DBITSWAP:
2e211e0a 24599 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
24600 decode_opc_special3_r6(env, ctx);
24601 break;
24602 default:
7a47bae5 24603 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
24604 check_mips_64(ctx);
24605 op2 = MASK_DBSHFL(ctx->opcode);
24606 gen_bshfl(ctx, op2, rt, rd);
24607 break;
24608 }
fac5a073
LA
24609 break;
24610#endif
24611 case OPC_RDHWR:
b00c7218 24612 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
24613 break;
24614 case OPC_FORK:
9affc1c5 24615 check_mt(ctx);
fac5a073
LA
24616 {
24617 TCGv t0 = tcg_temp_new();
24618 TCGv t1 = tcg_temp_new();
24619
24620 gen_load_gpr(t0, rt);
24621 gen_load_gpr(t1, rs);
24622 gen_helper_fork(t0, t1);
24623 tcg_temp_free(t0);
24624 tcg_temp_free(t1);
24625 }
24626 break;
24627 case OPC_YIELD:
9affc1c5 24628 check_mt(ctx);
fac5a073
LA
24629 {
24630 TCGv t0 = tcg_temp_new();
24631
fac5a073
LA
24632 gen_load_gpr(t0, rs);
24633 gen_helper_yield(t0, cpu_env, t0);
24634 gen_store_gpr(t0, rd);
24635 tcg_temp_free(t0);
24636 }
24637 break;
10dc65db 24638 default:
2e211e0a 24639 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db
LA
24640 decode_opc_special3_r6(env, ctx);
24641 } else {
24642 decode_opc_special3_legacy(env, ctx);
24643 }
099e5b4d
LA
24644 }
24645}
24646
80e64a38 24647static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
4c789546 24648{
80e64a38
PMD
24649 int32_t offset;
24650 int rs, rt, rd, sa;
24651 uint32_t op, op1;
24652 int16_t imm;
4c789546 24653
80e64a38
PMD
24654 op = MASK_OP_MAJOR(ctx->opcode);
24655 rs = (ctx->opcode >> 21) & 0x1f;
24656 rt = (ctx->opcode >> 16) & 0x1f;
24657 rd = (ctx->opcode >> 11) & 0x1f;
24658 sa = (ctx->opcode >> 6) & 0x1f;
24659 imm = (int16_t)ctx->opcode;
24660 switch (op) {
24661 case OPC_SPECIAL:
24662 decode_opc_special(env, ctx);
4c789546 24663 break;
80e64a38
PMD
24664 case OPC_SPECIAL2:
24665#if defined(TARGET_MIPS64)
24666 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24667 decode_mmi(env, ctx);
4f57f43c
PMD
24668 break;
24669 }
24670#endif
c7abe00a 24671 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
22345286
PMD
24672 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24673 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24674 } else {
e31b43ec 24675 decode_ase_mxu(ctx, ctx->opcode);
22345286 24676 }
4f57f43c 24677 break;
4c789546 24678 }
4f57f43c 24679 decode_opc_special2_legacy(env, ctx);
4c789546 24680 break;
80e64a38
PMD
24681 case OPC_SPECIAL3:
24682#if defined(TARGET_MIPS64)
24683 if (ctx->insn_flags & INSN_R5900) {
24684 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24685 } else {
24686 decode_opc_special3(env, ctx);
80e71591 24687 }
80e64a38
PMD
24688#else
24689 decode_opc_special3(env, ctx);
24690#endif
80e71591 24691 break;
80e64a38
PMD
24692 case OPC_REGIMM:
24693 op1 = MASK_REGIMM(ctx->opcode);
24694 switch (op1) {
24695 case OPC_BLTZL: /* REGIMM branches */
24696 case OPC_BGEZL:
24697 case OPC_BLTZALL:
24698 case OPC_BGEZALL:
24699 check_insn(ctx, ISA_MIPS2);
24700 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24701 /* Fallthrough */
24702 case OPC_BLTZ:
24703 case OPC_BGEZ:
24704 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
2e3eddb0 24705 break;
80e64a38
PMD
24706 case OPC_BLTZAL:
24707 case OPC_BGEZAL:
24708 if (ctx->insn_flags & ISA_MIPS_R6) {
24709 if (rs == 0) {
24710 /* OPC_NAL, OPC_BAL */
24711 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24712 } else {
24713 gen_reserved_instruction(ctx);
24714 }
24715 } else {
24716 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24717 }
2e3eddb0 24718 break;
80e64a38
PMD
24719 case OPC_TGEI: /* REGIMM traps */
24720 case OPC_TGEIU:
24721 case OPC_TLTI:
24722 case OPC_TLTIU:
24723 case OPC_TEQI:
24724
24725 case OPC_TNEI:
24726 check_insn(ctx, ISA_MIPS2);
24727 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24728 gen_trap(ctx, op1, rs, -1, imm);
2e3eddb0 24729 break;
80e64a38
PMD
24730 case OPC_SIGRIE:
24731 check_insn(ctx, ISA_MIPS_R6);
24732 gen_reserved_instruction(ctx);
2e3eddb0 24733 break;
80e64a38
PMD
24734 case OPC_SYNCI:
24735 check_insn(ctx, ISA_MIPS_R2);
24736 /*
24737 * Break the TB to be able to sync copied instructions
24738 * immediately.
24739 */
24740 ctx->base.is_jmp = DISAS_STOP;
2e3eddb0 24741 break;
80e64a38
PMD
24742 case OPC_BPOSGE32: /* MIPS DSP branch */
24743#if defined(TARGET_MIPS64)
24744 case OPC_BPOSGE64:
24745#endif
24746 check_dsp(ctx);
24747 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
a44d6d14 24748 break;
80e64a38
PMD
24749#if defined(TARGET_MIPS64)
24750 case OPC_DAHI:
24751 check_insn(ctx, ISA_MIPS_R6);
24752 check_mips_64(ctx);
24753 if (rs != 0) {
24754 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24755 }
a44d6d14 24756 break;
80e64a38
PMD
24757 case OPC_DATI:
24758 check_insn(ctx, ISA_MIPS_R6);
24759 check_mips_64(ctx);
24760 if (rs != 0) {
24761 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24762 }
a44d6d14 24763 break;
80e64a38
PMD
24764#endif
24765 default: /* Invalid */
24766 MIPS_INVAL("regimm");
24767 gen_reserved_instruction(ctx);
a44d6d14
AM
24768 break;
24769 }
24770 break;
80e64a38
PMD
24771 case OPC_CP0:
24772 check_cp0_enabled(ctx);
24773 op1 = MASK_CP0(ctx->opcode);
24774 switch (op1) {
24775 case OPC_MFC0:
24776 case OPC_MTC0:
24777 case OPC_MFTR:
24778 case OPC_MTTR:
24779 case OPC_MFHC0:
24780 case OPC_MTHC0:
24781#if defined(TARGET_MIPS64)
24782 case OPC_DMFC0:
24783 case OPC_DMTC0:
24784#endif
24785#ifndef CONFIG_USER_ONLY
24786 gen_cp0(env, ctx, op1, rt, rd);
24787#endif /* !CONFIG_USER_ONLY */
7a387fff 24788 break;
c38a1d52
AR
24789 case OPC_C0:
24790 case OPC_C0_1:
24791 case OPC_C0_2:
24792 case OPC_C0_3:
24793 case OPC_C0_4:
24794 case OPC_C0_5:
24795 case OPC_C0_6:
24796 case OPC_C0_7:
24797 case OPC_C0_8:
24798 case OPC_C0_9:
24799 case OPC_C0_A:
24800 case OPC_C0_B:
24801 case OPC_C0_C:
24802 case OPC_C0_D:
24803 case OPC_C0_E:
24804 case OPC_C0_F:
f1aa6320 24805#ifndef CONFIG_USER_ONLY
932e71cd 24806 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 24807#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
24808 break;
24809 case OPC_MFMC0:
8706c382 24810#ifndef CONFIG_USER_ONLY
932e71cd 24811 {
099e5b4d 24812 uint32_t op2;
35fbce2c 24813 TCGv t0 = tcg_temp_new();
6c5c1e20 24814
0eaef5aa 24815 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
24816 switch (op2) {
24817 case OPC_DMT:
9affc1c5 24818 check_cp0_mt(ctx);
9ed5726c 24819 gen_helper_dmt(t0);
35fbce2c 24820 gen_store_gpr(t0, rt);
6c5c1e20
TS
24821 break;
24822 case OPC_EMT:
9affc1c5 24823 check_cp0_mt(ctx);
9ed5726c 24824 gen_helper_emt(t0);
35fbce2c 24825 gen_store_gpr(t0, rt);
da80682b 24826 break;
6c5c1e20 24827 case OPC_DVPE:
9affc1c5 24828 check_cp0_mt(ctx);
895c2d04 24829 gen_helper_dvpe(t0, cpu_env);
35fbce2c 24830 gen_store_gpr(t0, rt);
6c5c1e20
TS
24831 break;
24832 case OPC_EVPE:
9affc1c5 24833 check_cp0_mt(ctx);
895c2d04 24834 gen_helper_evpe(t0, cpu_env);
35fbce2c 24835 gen_store_gpr(t0, rt);
6c5c1e20 24836 break;
01bc435b 24837 case OPC_DVP:
2e211e0a 24838 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
24839 if (ctx->vp) {
24840 gen_helper_dvp(t0, cpu_env);
24841 gen_store_gpr(t0, rt);
24842 }
24843 break;
24844 case OPC_EVP:
2e211e0a 24845 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
24846 if (ctx->vp) {
24847 gen_helper_evp(t0, cpu_env);
24848 gen_store_gpr(t0, rt);
24849 }
24850 break;
6c5c1e20 24851 case OPC_DI:
7a47bae5 24852 check_insn(ctx, ISA_MIPS_R2);
867abc7e 24853 save_cpu_state(ctx, 1);
895c2d04 24854 gen_helper_di(t0, cpu_env);
35fbce2c 24855 gen_store_gpr(t0, rt);
7480515f
AM
24856 /*
24857 * Stop translation as we may have switched
24858 * the execution mode.
24859 */
eeb3bba8 24860 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
24861 break;
24862 case OPC_EI:
7a47bae5 24863 check_insn(ctx, ISA_MIPS_R2);
867abc7e 24864 save_cpu_state(ctx, 1);
895c2d04 24865 gen_helper_ei(t0, cpu_env);
35fbce2c 24866 gen_store_gpr(t0, rt);
7480515f
AM
24867 /*
24868 * DISAS_STOP isn't sufficient, we need to ensure we break
24869 * out of translated code to check for pending interrupts.
24870 */
eeb3bba8
EC
24871 gen_save_pc(ctx->base.pc_next + 4);
24872 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
24873 break;
24874 default: /* Invalid */
24875 MIPS_INVAL("mfmc0");
3a4ef3b7 24876 gen_reserved_instruction(ctx);
6c5c1e20
TS
24877 break;
24878 }
6c5c1e20 24879 tcg_temp_free(t0);
7a387fff 24880 }
0eaef5aa 24881#endif /* !CONFIG_USER_ONLY */
6af0bf9c 24882 break;
7a387fff 24883 case OPC_RDPGPR:
7a47bae5 24884 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 24885 gen_load_srsgpr(rt, rd);
ead9360e 24886 break;
7a387fff 24887 case OPC_WRPGPR:
7a47bae5 24888 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 24889 gen_store_srsgpr(rt, rd);
38121543 24890 break;
6af0bf9c 24891 default:
923617a3 24892 MIPS_INVAL("cp0");
3a4ef3b7 24893 gen_reserved_instruction(ctx);
6af0bf9c
FB
24894 break;
24895 }
24896 break;
31837be3 24897 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
2e211e0a 24898 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
24899 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24900 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24901 } else {
24902 /* OPC_ADDI */
24903 /* Arithmetic with immediate opcode */
24904 gen_arith_imm(ctx, op, rt, rs, imm);
24905 }
24906 break;
324d9e32 24907 case OPC_ADDIU:
d75c135e 24908 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 24909 break;
324d9e32
AJ
24910 case OPC_SLTI: /* Set on less than with immediate opcode */
24911 case OPC_SLTIU:
d75c135e 24912 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
24913 break;
24914 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 24915 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
24916 case OPC_ORI:
24917 case OPC_XORI:
d75c135e 24918 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 24919 break;
c2e19f3c
AM
24920 case OPC_J: /* Jump */
24921 case OPC_JAL:
7a387fff 24922 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 24923 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 24924 break;
31837be3
YK
24925 /* Branch */
24926 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
2e211e0a 24927 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 24928 if (rt == 0) {
3a4ef3b7 24929 gen_reserved_instruction(ctx);
31837be3
YK
24930 break;
24931 }
24932 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24933 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24934 } else {
24935 /* OPC_BLEZL */
b231c103 24936 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
24937 }
24938 break;
24939 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
2e211e0a 24940 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 24941 if (rt == 0) {
3a4ef3b7 24942 gen_reserved_instruction(ctx);
31837be3
YK
24943 break;
24944 }
24945 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24946 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24947 } else {
24948 /* OPC_BGTZL */
b231c103 24949 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
24950 }
24951 break;
24952 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24953 if (rt == 0) {
24954 /* OPC_BLEZ */
b231c103 24955 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 24956 } else {
2e211e0a 24957 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
24958 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24959 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24960 }
24961 break;
24962 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24963 if (rt == 0) {
24964 /* OPC_BGTZ */
b231c103 24965 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 24966 } else {
2e211e0a 24967 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
24968 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24969 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24970 }
24971 break;
24972 case OPC_BEQL:
24973 case OPC_BNEL:
d9224450 24974 check_insn(ctx, ISA_MIPS2);
2e211e0a 24975 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 24976 /* Fallthrough */
31837be3
YK
24977 case OPC_BEQ:
24978 case OPC_BNE:
b231c103 24979 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 24980 break;
d9224450
MR
24981 case OPC_LL: /* Load and stores */
24982 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
24983 if (ctx->insn_flags & INSN_R5900) {
24984 check_insn_opc_user_only(ctx, INSN_R5900);
24985 }
d9224450
MR
24986 /* Fallthrough */
24987 case OPC_LWL:
fecd2646 24988 case OPC_LWR:
c2e19f3c
AM
24989 case OPC_LB:
24990 case OPC_LH:
24991 case OPC_LW:
24992 case OPC_LWPC:
24993 case OPC_LBU:
24994 case OPC_LHU:
d75c135e 24995 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 24996 break;
fecd2646 24997 case OPC_SWL:
7a387fff 24998 case OPC_SWR:
c2e19f3c
AM
24999 case OPC_SB:
25000 case OPC_SH:
fecd2646 25001 case OPC_SW:
5c13fdfd 25002 gen_st(ctx, op, rt, rs, imm);
7a387fff 25003 break;
d66c7132 25004 case OPC_SC:
d9224450 25005 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
25006 if (ctx->insn_flags & INSN_R5900) {
25007 check_insn_opc_user_only(ctx, INSN_R5900);
25008 }
33a07fa2
LA
25009 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25010 break;
7a387fff 25011 case OPC_CACHE:
2e15497c 25012 check_cp0_enabled(ctx);
bbd5e4a2 25013 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
0d74a222
LA
25014 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25015 gen_cache_operation(ctx, rt, rs, imm);
25016 }
ead9360e 25017 /* Treat as NOP. */
34ae7b51 25018 break;
7a387fff 25019 case OPC_PREF:
992e8176
FN
25020 if (ctx->insn_flags & INSN_R5900) {
25021 /* Treat as NOP. */
25022 } else {
bbd5e4a2 25023 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
992e8176
FN
25024 /* Treat as NOP. */
25025 }
6af0bf9c 25026 break;
4ad40f36 25027
923617a3 25028 /* Floating point (COP1). */
7a387fff
TS
25029 case OPC_LWC1:
25030 case OPC_LDC1:
25031 case OPC_SWC1:
25032 case OPC_SDC1:
5ab5c041 25033 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
25034 break;
25035
7a387fff 25036 case OPC_CP1:
5692c6e1
YK
25037 op1 = MASK_CP1(ctx->opcode);
25038
25039 switch (op1) {
25040 case OPC_MFHC1:
25041 case OPC_MTHC1:
5e755519 25042 check_cp1_enabled(ctx);
7a47bae5 25043 check_insn(ctx, ISA_MIPS_R2);
146dd620 25044 /* fall through */
5692c6e1
YK
25045 case OPC_MFC1:
25046 case OPC_CFC1:
25047 case OPC_MTC1:
25048 case OPC_CTC1:
25049 check_cp1_enabled(ctx);
25050 gen_cp1(ctx, op1, rt, rd);
25051 break;
d26bc211 25052#if defined(TARGET_MIPS64)
5692c6e1
YK
25053 case OPC_DMFC1:
25054 case OPC_DMTC1:
25055 check_cp1_enabled(ctx);
25056 check_insn(ctx, ISA_MIPS3);
d9224450 25057 check_mips_64(ctx);
5692c6e1
YK
25058 gen_cp1(ctx, op1, rt, rd);
25059 break;
e189e748 25060#endif
5692c6e1
YK
25061 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25062 check_cp1_enabled(ctx);
2e211e0a 25063 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1 25064 /* OPC_BC1EQZ */
31837be3 25065 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25066 rt, imm << 2, 4);
5692c6e1
YK
25067 } else {
25068 /* OPC_BC1ANY2 */
b8aa4598 25069 check_cop1x(ctx);
d75c135e 25070 check_insn(ctx, ASE_MIPS3D);
d75c135e 25071 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 25072 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
25073 }
25074 break;
25075 case OPC_BC1NEZ:
25076 check_cp1_enabled(ctx);
2e211e0a 25077 check_insn(ctx, ISA_MIPS_R6);
5692c6e1 25078 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25079 rt, imm << 2, 4);
5692c6e1
YK
25080 break;
25081 case OPC_BC1ANY4:
25082 check_cp1_enabled(ctx);
2e211e0a 25083 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
25084 check_cop1x(ctx);
25085 check_insn(ctx, ASE_MIPS3D);
25086 /* fall through */
25087 case OPC_BC1:
25088 check_cp1_enabled(ctx);
2e211e0a 25089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
25090 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25091 (rt >> 2) & 0x7, imm << 2);
25092 break;
25093 case OPC_PS_FMT:
e29c9628 25094 check_ps(ctx);
b6f3b233 25095 /* fall through */
5692c6e1
YK
25096 case OPC_S_FMT:
25097 case OPC_D_FMT:
25098 check_cp1_enabled(ctx);
25099 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25100 (imm >> 8) & 0x7);
25101 break;
25102 case OPC_W_FMT:
25103 case OPC_L_FMT:
25104 {
25105 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25106 check_cp1_enabled(ctx);
2e211e0a 25107 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1
YK
25108 switch (r6_op) {
25109 case R6_OPC_CMP_AF_S:
25110 case R6_OPC_CMP_UN_S:
25111 case R6_OPC_CMP_EQ_S:
25112 case R6_OPC_CMP_UEQ_S:
25113 case R6_OPC_CMP_LT_S:
25114 case R6_OPC_CMP_ULT_S:
25115 case R6_OPC_CMP_LE_S:
25116 case R6_OPC_CMP_ULE_S:
25117 case R6_OPC_CMP_SAF_S:
25118 case R6_OPC_CMP_SUN_S:
25119 case R6_OPC_CMP_SEQ_S:
25120 case R6_OPC_CMP_SEUQ_S:
25121 case R6_OPC_CMP_SLT_S:
25122 case R6_OPC_CMP_SULT_S:
25123 case R6_OPC_CMP_SLE_S:
25124 case R6_OPC_CMP_SULE_S:
25125 case R6_OPC_CMP_OR_S:
25126 case R6_OPC_CMP_UNE_S:
25127 case R6_OPC_CMP_NE_S:
25128 case R6_OPC_CMP_SOR_S:
25129 case R6_OPC_CMP_SUNE_S:
25130 case R6_OPC_CMP_SNE_S:
25131 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25132 break;
25133 case R6_OPC_CMP_AF_D:
25134 case R6_OPC_CMP_UN_D:
25135 case R6_OPC_CMP_EQ_D:
25136 case R6_OPC_CMP_UEQ_D:
25137 case R6_OPC_CMP_LT_D:
25138 case R6_OPC_CMP_ULT_D:
25139 case R6_OPC_CMP_LE_D:
25140 case R6_OPC_CMP_ULE_D:
25141 case R6_OPC_CMP_SAF_D:
25142 case R6_OPC_CMP_SUN_D:
25143 case R6_OPC_CMP_SEQ_D:
25144 case R6_OPC_CMP_SEUQ_D:
25145 case R6_OPC_CMP_SLT_D:
25146 case R6_OPC_CMP_SULT_D:
25147 case R6_OPC_CMP_SLE_D:
25148 case R6_OPC_CMP_SULE_D:
25149 case R6_OPC_CMP_OR_D:
25150 case R6_OPC_CMP_UNE_D:
25151 case R6_OPC_CMP_NE_D:
25152 case R6_OPC_CMP_SOR_D:
25153 case R6_OPC_CMP_SUNE_D:
25154 case R6_OPC_CMP_SNE_D:
25155 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25156 break;
25157 default:
d2bfa6e6
MR
25158 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25159 rt, rd, sa, (imm >> 8) & 0x7);
25160
5692c6e1 25161 break;
3f493883 25162 }
5692c6e1
YK
25163 } else {
25164 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25165 (imm >> 8) & 0x7);
36d23958 25166 }
5692c6e1
YK
25167 break;
25168 }
5692c6e1
YK
25169 default:
25170 MIPS_INVAL("cp1");
3a4ef3b7 25171 gen_reserved_instruction(ctx);
5692c6e1 25172 break;
6ea83fed 25173 }
4ad40f36
FB
25174 break;
25175
31837be3
YK
25176 /* Compact branches [R6] and COP2 [non-R6] */
25177 case OPC_BC: /* OPC_LWC2 */
25178 case OPC_BALC: /* OPC_SWC2 */
2e211e0a 25179 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25180 /* OPC_BC, OPC_BALC */
25181 gen_compute_compact_branch(ctx, op, 0, 0,
25182 sextract32(ctx->opcode << 2, 0, 28));
e10a0ca1
JY
25183 } else if (ctx->insn_flags & ASE_LEXT) {
25184 gen_loongson_lswc2(ctx, rt, rs, rd);
31837be3
YK
25185 } else {
25186 /* OPC_LWC2, OPC_SWC2 */
25187 /* COP2: Not implemented. */
25188 generate_exception_err(ctx, EXCP_CpU, 2);
25189 }
25190 break;
25191 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25192 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
2e211e0a 25193 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25194 if (rs != 0) {
25195 /* OPC_BEQZC, OPC_BNEZC */
25196 gen_compute_compact_branch(ctx, op, rs, 0,
25197 sextract32(ctx->opcode << 2, 0, 23));
25198 } else {
25199 /* OPC_JIC, OPC_JIALC */
25200 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25201 }
90e22a57
JY
25202 } else if (ctx->insn_flags & ASE_LEXT) {
25203 gen_loongson_lsdc2(ctx, rt, rs, rd);
31837be3
YK
25204 } else {
25205 /* OPC_LWC2, OPC_SWC2 */
25206 /* COP2: Not implemented. */
25207 generate_exception_err(ctx, EXCP_CpU, 2);
25208 }
4ad40f36 25209 break;
bd277fa1 25210 case OPC_CP2:
8e2d5831 25211 check_insn(ctx, ASE_LMMI);
bd277fa1
RH
25212 /* Note that these instructions use different fields. */
25213 gen_loongson_multimedia(ctx, sa, rd, rt);
25214 break;
4ad40f36 25215
7a387fff 25216 case OPC_CP3:
5ab5c041 25217 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 25218 check_cp1_enabled(ctx);
36d23958
TS
25219 op1 = MASK_CP3(ctx->opcode);
25220 switch (op1) {
d9224450
MR
25221 case OPC_LUXC1:
25222 case OPC_SUXC1:
7a47bae5 25223 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 25224 /* Fallthrough */
5a5012ec
TS
25225 case OPC_LWXC1:
25226 case OPC_LDXC1:
5a5012ec
TS
25227 case OPC_SWXC1:
25228 case OPC_SDXC1:
7a47bae5 25229 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
93b12ccc 25230 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 25231 break;
e0c84da7 25232 case OPC_PREFX:
7a47bae5 25233 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
ead9360e 25234 /* Treat as NOP. */
e0c84da7 25235 break;
5a5012ec 25236 case OPC_ALNV_PS:
7a47bae5 25237 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 25238 /* Fallthrough */
5a5012ec
TS
25239 case OPC_MADD_S:
25240 case OPC_MADD_D:
25241 case OPC_MADD_PS:
25242 case OPC_MSUB_S:
25243 case OPC_MSUB_D:
25244 case OPC_MSUB_PS:
25245 case OPC_NMADD_S:
25246 case OPC_NMADD_D:
25247 case OPC_NMADD_PS:
25248 case OPC_NMSUB_S:
25249 case OPC_NMSUB_D:
25250 case OPC_NMSUB_PS:
7a47bae5 25251 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
5a5012ec
TS
25252 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25253 break;
36d23958 25254 default:
923617a3 25255 MIPS_INVAL("cp3");
3a4ef3b7 25256 gen_reserved_instruction(ctx);
36d23958
TS
25257 break;
25258 }
25259 } else {
e397ee33 25260 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 25261 }
4ad40f36
FB
25262 break;
25263
d26bc211 25264#if defined(TARGET_MIPS64)
7a387fff 25265 /* MIPS64 opcodes */
96631327 25266 case OPC_LLD:
55fc7a69
FN
25267 if (ctx->insn_flags & INSN_R5900) {
25268 check_insn_opc_user_only(ctx, INSN_R5900);
25269 }
96631327 25270 /* fall through */
c2e19f3c
AM
25271 case OPC_LDL:
25272 case OPC_LDR:
fecd2646 25273 case OPC_LWU:
7a387fff 25274 case OPC_LD:
d75c135e 25275 check_insn(ctx, ISA_MIPS3);
5c13fdfd 25276 check_mips_64(ctx);
d75c135e 25277 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 25278 break;
c2e19f3c
AM
25279 case OPC_SDL:
25280 case OPC_SDR:
7a387fff 25281 case OPC_SD:
d75c135e 25282 check_insn(ctx, ISA_MIPS3);
e189e748 25283 check_mips_64(ctx);
5c13fdfd 25284 gen_st(ctx, op, rt, rs, imm);
7a387fff 25285 break;
d66c7132 25286 case OPC_SCD:
d75c135e 25287 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
25288 if (ctx->insn_flags & INSN_R5900) {
25289 check_insn_opc_user_only(ctx, INSN_R5900);
25290 }
d66c7132 25291 check_mips_64(ctx);
33a07fa2 25292 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 25293 break;
31837be3 25294 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
2e211e0a 25295 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25296 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25297 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25298 } else {
25299 /* OPC_DADDI */
25300 check_insn(ctx, ISA_MIPS3);
25301 check_mips_64(ctx);
25302 gen_arith_imm(ctx, op, rt, rs, imm);
25303 }
25304 break;
324d9e32 25305 case OPC_DADDIU:
d75c135e 25306 check_insn(ctx, ISA_MIPS3);
e189e748 25307 check_mips_64(ctx);
d75c135e 25308 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 25309 break;
31837be3
YK
25310#else
25311 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
2e211e0a 25312 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25313 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25314 } else {
25315 MIPS_INVAL("major opcode");
3a4ef3b7 25316 gen_reserved_instruction(ctx);
31837be3
YK
25317 }
25318 break;
6af0bf9c 25319#endif
d4ea6acd 25320 case OPC_DAUI: /* OPC_JALX */
2e211e0a 25321 if (ctx->insn_flags & ISA_MIPS_R6) {
d4ea6acd
LA
25322#if defined(TARGET_MIPS64)
25323 /* OPC_DAUI */
25324 check_mips_64(ctx);
db77d852
LA
25325 if (rs == 0) {
25326 generate_exception(ctx, EXCP_RI);
25327 } else if (rt != 0) {
d4ea6acd
LA
25328 TCGv t0 = tcg_temp_new();
25329 gen_load_gpr(t0, rs);
25330 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25331 tcg_temp_free(t0);
25332 }
d4ea6acd 25333#else
3a4ef3b7 25334 gen_reserved_instruction(ctx);
d4ea6acd
LA
25335 MIPS_INVAL("major opcode");
25336#endif
25337 } else {
25338 /* OPC_JALX */
25339 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25340 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 25341 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 25342 }
364d4831 25343 break;
96e5b4c7 25344 case OPC_MDMX: /* MMI_OPC_LQ */
f08099ad 25345 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 25346#if defined(TARGET_MIPS64)
96e5b4c7 25347 gen_mmi_lq(env, ctx);
37b9aae2 25348#endif
f08099ad
FN
25349 } else {
25350 /* MDMX: Not implemented. */
f08099ad 25351 }
d4ea6acd
LA
25352 break;
25353 case OPC_PCREL:
2e211e0a 25354 check_insn(ctx, ISA_MIPS_R6);
eeb3bba8 25355 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 25356 break;
6af0bf9c 25357 default: /* Invalid */
923617a3 25358 MIPS_INVAL("major opcode");
311edee7 25359 return false;
6af0bf9c 25360 }
311edee7
PMD
25361 return true;
25362}
25363
25364static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25365{
25366 /* make sure instructions are on a word boundary */
25367 if (ctx->base.pc_next & 0x3) {
25368 env->CP0_BadVAddr = ctx->base.pc_next;
25369 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25370 return;
25371 }
25372
25373 /* Handle blikely not taken case */
25374 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25375 TCGLabel *l1 = gen_new_label();
25376
25377 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25378 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25379 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25380 gen_set_label(l1);
25381 }
25382
96e5b4c7
PMD
25383 /* Transition to the auto-generated decoder. */
25384
25385 /* ISA extensions */
25386 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25387 return;
25388 }
25389
3f7a9278
PMD
25390 /* ISA (from latest to oldest) */
25391 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25392 return;
25393 }
ffc672aa
PMD
25394 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25395 return;
25396 }
3f7a9278 25397
311edee7
PMD
25398 if (decode_opc_legacy(env, ctx)) {
25399 return;
25400 }
25401
25402 gen_reserved_instruction(ctx);
6af0bf9c
FB
25403}
25404
18f440ed 25405static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 25406{
18f440ed 25407 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 25408 CPUMIPSState *env = cs->env_ptr;
12be9258 25409
18f440ed 25410 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
25411 ctx->saved_pc = -1;
25412 ctx->insn_flags = env->insn_flags;
25413 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 25414 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
25415 ctx->CP0_Config3 = env->CP0_Config3;
25416 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
25417 ctx->btarget = 0;
25418 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25419 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25420 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25421 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25422 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25423 ctx->PAMask = env->PAMask;
25424 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25425 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25426 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25427 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25428 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 25429 /* Restore delay slot state from the tb context. */
12be9258
EC
25430 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25431 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25432 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 25433 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
25434 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25435 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25436 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25437 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 25438 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
99029be1 25439 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
12be9258 25440 restore_cpu_state(env, ctx);
932e71cd 25441#ifdef CONFIG_USER_ONLY
12be9258 25442 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 25443#else
12be9258 25444 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 25445#endif
2e211e0a 25446 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
8a805609 25447 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
190ce7fb 25448
18f440ed
EC
25449 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25450 ctx->hflags);
25451}
12be9258 25452
18f440ed
EC
25453static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25454{
25455}
b933066a 25456
18f440ed
EC
25457static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25458{
25459 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25460
18f440ed
EC
25461 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25462 ctx->btarget);
25463}
31837be3 25464
18f440ed
EC
25465static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25466 const CPUBreakpoint *bp)
25467{
25468 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25469
18f440ed
EC
25470 save_cpu_state(ctx, 1);
25471 ctx->base.is_jmp = DISAS_NORETURN;
25472 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
25473 /*
25474 * The address covered by the breakpoint must be included in
25475 * [tb->pc, tb->pc + tb->size) in order to for it to be
25476 * properly cleared -- thus we increment the PC here so that
25477 * the logic setting tb->size below does the right thing.
25478 */
18f440ed
EC
25479 ctx->base.pc_next += 4;
25480 return true;
25481}
4ad40f36 25482
18f440ed
EC
25483static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25484{
25485 CPUMIPSState *env = cs->env_ptr;
25486 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25487 int insn_bytes;
25488 int is_slot;
4ad40f36 25489
18f440ed 25490 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4 25491 if (ctx->insn_flags & ISA_NANOMIPS32) {
0ab8e33a 25492 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
c533c0f4
AM
25493 insn_bytes = decode_nanomips_opc(env, ctx);
25494 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
0ab8e33a 25495 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
18f440ed
EC
25496 insn_bytes = 4;
25497 decode_opc(env, ctx);
25498 } else if (ctx->insn_flags & ASE_MICROMIPS) {
0ab8e33a 25499 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
18f440ed
EC
25500 insn_bytes = decode_micromips_opc(env, ctx);
25501 } else if (ctx->insn_flags & ASE_MIPS16) {
0ab8e33a 25502 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
18f440ed
EC
25503 insn_bytes = decode_mips16_opc(env, ctx);
25504 } else {
3a4ef3b7 25505 gen_reserved_instruction(ctx);
18f440ed
EC
25506 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25507 return;
25508 }
faf7aaa9 25509
18f440ed
EC
25510 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25511 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25512 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
25513 /*
25514 * Force to generate branch as there is neither delay nor
25515 * forbidden slot.
25516 */
18f440ed
EC
25517 is_slot = 1;
25518 }
25519 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25520 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
25521 /*
25522 * Force to generate branch as microMIPS R6 doesn't restrict
25523 * branches in the forbidden slot.
25524 */
18f440ed 25525 is_slot = 1;
eeb3bba8 25526 }
18f440ed
EC
25527 }
25528 if (is_slot) {
25529 gen_branch(ctx, insn_bytes);
25530 }
25531 ctx->base.pc_next += insn_bytes;
1b530a6d 25532
18f440ed
EC
25533 if (ctx->base.is_jmp != DISAS_NEXT) {
25534 return;
6af0bf9c 25535 }
7480515f
AM
25536 /*
25537 * Execute a branch and its delay slot as a single instruction.
25538 * This is what GDB expects and is consistent with what the
25539 * hardware does (e.g. if a delay slot instruction faults, the
25540 * reported PC is the PC of the branch).
25541 */
18f440ed
EC
25542 if (ctx->base.singlestep_enabled &&
25543 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25544 ctx->base.is_jmp = DISAS_TOO_MANY;
25545 }
25546 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25547 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 25548 }
18f440ed
EC
25549}
25550
25551static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25552{
25553 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25554
12be9258
EC
25555 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25556 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 25557 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 25558 } else {
12be9258 25559 switch (ctx->base.is_jmp) {
b28425ba 25560 case DISAS_STOP:
12be9258 25561 gen_save_pc(ctx->base.pc_next);
cd314a7d 25562 tcg_gen_lookup_and_goto_ptr();
df1561e2 25563 break;
b28425ba 25564 case DISAS_NEXT:
18f440ed 25565 case DISAS_TOO_MANY:
12be9258
EC
25566 save_cpu_state(ctx, 0);
25567 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 25568 break;
b28425ba 25569 case DISAS_EXIT:
07ea28b4 25570 tcg_gen_exit_tb(NULL, 0);
16c00cb2 25571 break;
b28425ba 25572 case DISAS_NORETURN:
5a5012ec 25573 break;
18f440ed
EC
25574 default:
25575 g_assert_not_reached();
6958549d 25576 }
6af0bf9c 25577 }
18f440ed
EC
25578}
25579
25580static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25581{
25582 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25583 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25584}
25585
25586static const TranslatorOps mips_tr_ops = {
25587 .init_disas_context = mips_tr_init_disas_context,
25588 .tb_start = mips_tr_tb_start,
25589 .insn_start = mips_tr_insn_start,
25590 .breakpoint_check = mips_tr_breakpoint_check,
25591 .translate_insn = mips_tr_translate_insn,
25592 .tb_stop = mips_tr_tb_stop,
25593 .disas_log = mips_tr_disas_log,
25594};
25595
8b86d6d2 25596void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
25597{
25598 DisasContext ctx;
25599
8b86d6d2 25600 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
25601}
25602
71375b59 25603static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
6ea83fed
FB
25604{
25605 int i;
5e755519 25606 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 25607
2a5612e6
SW
25608#define printfpr(fp) \
25609 do { \
25610 if (is_fpu64) \
90c84c56
MA
25611 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25612 " fd:%13g fs:%13g psu: %13g\n", \
25613 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25614 (double)(fp)->fd, \
25615 (double)(fp)->fs[FP_ENDIAN_IDX], \
25616 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
2a5612e6
SW
25617 else { \
25618 fpr_t tmp; \
25619 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25620 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
90c84c56
MA
25621 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25622 " fd:%13g fs:%13g psu:%13g\n", \
25623 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25624 (double)tmp.fd, \
25625 (double)tmp.fs[FP_ENDIAN_IDX], \
25626 (double)tmp.fs[!FP_ENDIAN_IDX]); \
2a5612e6 25627 } \
71375b59 25628 } while (0)
6ea83fed 25629
5a5012ec 25630
90c84c56
MA
25631 qemu_fprintf(f,
25632 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25633 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
25634 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec 25635 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
90c84c56 25636 qemu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 25637 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
25638 }
25639
25640#undef printfpr
25641}
25642
90c84c56 25643void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6af0bf9c 25644{
878096ee
AF
25645 MIPSCPU *cpu = MIPS_CPU(cs);
25646 CPUMIPSState *env = &cpu->env;
6af0bf9c 25647 int i;
3b46e624 25648
90c84c56
MA
25649 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25650 " LO=0x" TARGET_FMT_lx " ds %04x "
25651 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
25652 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25653 env->hflags, env->btarget, env->bcond);
6af0bf9c 25654 for (i = 0; i < 32; i++) {
1f8929d2 25655 if ((i & 3) == 0) {
90c84c56 25656 qemu_fprintf(f, "GPR%02d:", i);
1f8929d2 25657 }
90c84c56
MA
25658 qemu_fprintf(f, " %s " TARGET_FMT_lx,
25659 regnames[i], env->active_tc.gpr[i]);
1f8929d2 25660 if ((i & 3) == 3) {
90c84c56 25661 qemu_fprintf(f, "\n");
1f8929d2 25662 }
90c84c56
MA
25663 }
25664
71375b59
AM
25665 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
25666 TARGET_FMT_lx "\n",
90c84c56
MA
25667 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
25668 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25669 PRIx64 "\n",
25670 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
25671 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25672 env->CP0_Config2, env->CP0_Config3);
25673 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25674 env->CP0_Config4, env->CP0_Config5);
1cc5af69 25675 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
90c84c56 25676 fpu_dump_state(env, f, flags);
1cc5af69 25677 }
6af0bf9c
FB
25678}
25679
959c5da2
PMD
25680void mips_tcg_init(void)
25681{
25682 int i;
25683
25684 cpu_gpr[0] = NULL;
25685 for (i = 1; i < 32; i++)
25686 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25687 offsetof(CPUMIPSState,
25688 active_tc.gpr[i]),
25689 regnames[i]);
cefd68f6
PMD
25690#if defined(TARGET_MIPS64)
25691 cpu_gpr_hi[0] = NULL;
25692
25693 for (unsigned i = 1; i < 32; i++) {
b5b63d43
PMD
25694 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25695
cefd68f6
PMD
25696 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25697 offsetof(CPUMIPSState,
25698 active_tc.gpr_hi[i]),
b5b63d43 25699 rname);
cefd68f6
PMD
25700 }
25701#endif /* !TARGET_MIPS64 */
959c5da2
PMD
25702 for (i = 0; i < 32; i++) {
25703 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
863f264d 25704
959c5da2
PMD
25705 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25706 }
25707 msa_translate_init();
e1ccc054 25708 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 25709 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 25710 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 25711 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 25712 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 25713 regnames_HI[i]);
e1ccc054 25714 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 25715 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 25716 regnames_LO[i]);
4b2eb8d2 25717 }
e1ccc054 25718 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
25719 offsetof(CPUMIPSState,
25720 active_tc.DSPControl),
4b2eb8d2 25721 "DSPControl");
e1ccc054 25722 bcond = tcg_global_mem_new(cpu_env,
7db13fae 25723 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 25724 btarget = tcg_global_mem_new(cpu_env,
7db13fae 25725 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 25726 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 25727 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 25728
e1ccc054 25729 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25730 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 25731 "fcr0");
e1ccc054 25732 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25733 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 25734 "fcr31");
33a07fa2
LA
25735 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25736 "lladdr");
25737 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25738 "llval");
a168a796 25739
fe35ea94
PMD
25740 if (TARGET_LONG_BITS == 32) {
25741 mxu_translate_init();
eb5559f6 25742 }
39454628
TS
25743}
25744
bad729e2
RH
25745void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25746 target_ulong *data)
d2856f1a 25747{
bad729e2 25748 env->active_tc.PC = data[0];
d2856f1a 25749 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 25750 env->hflags |= data[1];
4636401d
AJ
25751 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25752 case MIPS_HFLAG_BR:
25753 break;
25754 case MIPS_HFLAG_BC:
25755 case MIPS_HFLAG_BL:
25756 case MIPS_HFLAG_B:
bad729e2 25757 env->btarget = data[2];
4636401d
AJ
25758 break;
25759 }
d2856f1a 25760}