]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/tcg/translate.c
target/mips: Add declarations for generic TCG helpers
[mirror_qemu.git] / target / mips / tcg / 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
34b8ff25 34#include "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
ecdbcb0a
PMD
42/*
43 * Many sysemu-only helpers are not reachable for user-only.
44 * Define stub generators here, so that we need not either sprinkle
45 * ifdefs through the translator, nor provide the helper function.
46 */
47#define STUB_HELPER(NAME, ...) \
48 static inline void gen_helper_##NAME(__VA_ARGS__) \
49 { g_assert_not_reached(); }
50
51#ifdef CONFIG_USER_ONLY
52STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
53#endif
54
e37e863f
FB
55enum {
56 /* indirect opcode tables */
7a387fff
TS
57 OPC_SPECIAL = (0x00 << 26),
58 OPC_REGIMM = (0x01 << 26),
59 OPC_CP0 = (0x10 << 26),
7a387fff
TS
60 OPC_CP2 = (0x12 << 26),
61 OPC_CP3 = (0x13 << 26),
62 OPC_SPECIAL2 = (0x1C << 26),
63 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 64 /* arithmetic with immediate */
7a387fff
TS
65 OPC_ADDI = (0x08 << 26),
66 OPC_ADDIU = (0x09 << 26),
67 OPC_SLTI = (0x0A << 26),
68 OPC_SLTIU = (0x0B << 26),
324d9e32 69 /* logic with immediate */
7a387fff
TS
70 OPC_ANDI = (0x0C << 26),
71 OPC_ORI = (0x0D << 26),
72 OPC_XORI = (0x0E << 26),
73 OPC_LUI = (0x0F << 26),
324d9e32 74 /* arithmetic with immediate */
7a387fff
TS
75 OPC_DADDI = (0x18 << 26),
76 OPC_DADDIU = (0x19 << 26),
e37e863f 77 /* Jump and branches */
7a387fff
TS
78 OPC_J = (0x02 << 26),
79 OPC_JAL = (0x03 << 26),
80 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
81 OPC_BEQL = (0x14 << 26),
82 OPC_BNE = (0x05 << 26),
83 OPC_BNEL = (0x15 << 26),
84 OPC_BLEZ = (0x06 << 26),
85 OPC_BLEZL = (0x16 << 26),
86 OPC_BGTZ = (0x07 << 26),
87 OPC_BGTZL = (0x17 << 26),
b231c103 88 OPC_JALX = (0x1D << 26),
d4ea6acd 89 OPC_DAUI = (0x1D << 26),
e37e863f 90 /* Load and stores */
7a387fff
TS
91 OPC_LDL = (0x1A << 26),
92 OPC_LDR = (0x1B << 26),
93 OPC_LB = (0x20 << 26),
94 OPC_LH = (0x21 << 26),
95 OPC_LWL = (0x22 << 26),
96 OPC_LW = (0x23 << 26),
364d4831 97 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
98 OPC_LBU = (0x24 << 26),
99 OPC_LHU = (0x25 << 26),
100 OPC_LWR = (0x26 << 26),
101 OPC_LWU = (0x27 << 26),
102 OPC_SB = (0x28 << 26),
103 OPC_SH = (0x29 << 26),
104 OPC_SWL = (0x2A << 26),
105 OPC_SW = (0x2B << 26),
106 OPC_SDL = (0x2C << 26),
107 OPC_SDR = (0x2D << 26),
108 OPC_SWR = (0x2E << 26),
109 OPC_LL = (0x30 << 26),
110 OPC_LLD = (0x34 << 26),
111 OPC_LD = (0x37 << 26),
364d4831 112 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
113 OPC_SC = (0x38 << 26),
114 OPC_SCD = (0x3C << 26),
115 OPC_SD = (0x3F << 26),
e37e863f 116 /* Floating point load/store */
7a387fff
TS
117 OPC_LWC1 = (0x31 << 26),
118 OPC_LWC2 = (0x32 << 26),
119 OPC_LDC1 = (0x35 << 26),
120 OPC_LDC2 = (0x36 << 26),
121 OPC_SWC1 = (0x39 << 26),
122 OPC_SWC2 = (0x3A << 26),
123 OPC_SDC1 = (0x3D << 26),
124 OPC_SDC2 = (0x3E << 26),
31837be3
YK
125 /* Compact Branches */
126 OPC_BLEZALC = (0x06 << 26),
127 OPC_BGEZALC = (0x06 << 26),
128 OPC_BGEUC = (0x06 << 26),
129 OPC_BGTZALC = (0x07 << 26),
130 OPC_BLTZALC = (0x07 << 26),
131 OPC_BLTUC = (0x07 << 26),
132 OPC_BOVC = (0x08 << 26),
133 OPC_BEQZALC = (0x08 << 26),
134 OPC_BEQC = (0x08 << 26),
135 OPC_BLEZC = (0x16 << 26),
136 OPC_BGEZC = (0x16 << 26),
137 OPC_BGEC = (0x16 << 26),
138 OPC_BGTZC = (0x17 << 26),
139 OPC_BLTZC = (0x17 << 26),
140 OPC_BLTC = (0x17 << 26),
141 OPC_BNVC = (0x18 << 26),
142 OPC_BNEZALC = (0x18 << 26),
143 OPC_BNEC = (0x18 << 26),
144 OPC_BC = (0x32 << 26),
145 OPC_BEQZC = (0x36 << 26),
146 OPC_JIC = (0x36 << 26),
147 OPC_BALC = (0x3A << 26),
148 OPC_BNEZC = (0x3E << 26),
149 OPC_JIALC = (0x3E << 26),
7a387fff
TS
150 /* MDMX ASE specific */
151 OPC_MDMX = (0x1E << 26),
e37e863f 152 /* Cache and prefetch */
7a387fff
TS
153 OPC_CACHE = (0x2F << 26),
154 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
155 /* PC-relative address computation / loads */
156 OPC_PCREL = (0x3B << 26),
157};
158
159/* PC-relative address computation / loads */
71375b59
AM
160#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
161#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
162enum {
163 /* Instructions determined by bits 19 and 20 */
164 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
165 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
166 OPC_LWUPC = OPC_PCREL | (2 << 19),
167
168 /* Instructions determined by bits 16 ... 20 */
169 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
170 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
171
172 /* Other */
173 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
174};
175
176/* MIPS special opcodes */
71375b59 177#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 178
e37e863f
FB
179enum {
180 /* Shifts */
7a387fff 181 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
182 /* NOP is SLL r0, r0, 0 */
183 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
184 /* EHB is SLL r0, r0, 3 */
185 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 186 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
187 OPC_SRA = 0x03 | OPC_SPECIAL,
188 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 189 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 190 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
191 OPC_SRAV = 0x07 | OPC_SPECIAL,
192 OPC_DSLLV = 0x14 | OPC_SPECIAL,
193 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 194 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
195 OPC_DSRAV = 0x17 | OPC_SPECIAL,
196 OPC_DSLL = 0x38 | OPC_SPECIAL,
197 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 198 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
199 OPC_DSRA = 0x3B | OPC_SPECIAL,
200 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
201 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 202 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 203 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 204 /* Multiplication / division */
7a387fff
TS
205 OPC_MULT = 0x18 | OPC_SPECIAL,
206 OPC_MULTU = 0x19 | OPC_SPECIAL,
207 OPC_DIV = 0x1A | OPC_SPECIAL,
208 OPC_DIVU = 0x1B | OPC_SPECIAL,
209 OPC_DMULT = 0x1C | OPC_SPECIAL,
210 OPC_DMULTU = 0x1D | OPC_SPECIAL,
211 OPC_DDIV = 0x1E | OPC_SPECIAL,
212 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 213
e37e863f 214 /* 2 registers arithmetic / logic */
7a387fff
TS
215 OPC_ADD = 0x20 | OPC_SPECIAL,
216 OPC_ADDU = 0x21 | OPC_SPECIAL,
217 OPC_SUB = 0x22 | OPC_SPECIAL,
218 OPC_SUBU = 0x23 | OPC_SPECIAL,
219 OPC_AND = 0x24 | OPC_SPECIAL,
220 OPC_OR = 0x25 | OPC_SPECIAL,
221 OPC_XOR = 0x26 | OPC_SPECIAL,
222 OPC_NOR = 0x27 | OPC_SPECIAL,
223 OPC_SLT = 0x2A | OPC_SPECIAL,
224 OPC_SLTU = 0x2B | OPC_SPECIAL,
225 OPC_DADD = 0x2C | OPC_SPECIAL,
226 OPC_DADDU = 0x2D | OPC_SPECIAL,
227 OPC_DSUB = 0x2E | OPC_SPECIAL,
228 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 229 /* Jumps */
7a387fff
TS
230 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
231 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 232 /* Traps */
7a387fff
TS
233 OPC_TGE = 0x30 | OPC_SPECIAL,
234 OPC_TGEU = 0x31 | OPC_SPECIAL,
235 OPC_TLT = 0x32 | OPC_SPECIAL,
236 OPC_TLTU = 0x33 | OPC_SPECIAL,
237 OPC_TEQ = 0x34 | OPC_SPECIAL,
238 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 239 /* HI / LO registers load & stores */
7a387fff
TS
240 OPC_MFHI = 0x10 | OPC_SPECIAL,
241 OPC_MTHI = 0x11 | OPC_SPECIAL,
242 OPC_MFLO = 0x12 | OPC_SPECIAL,
243 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 244 /* Conditional moves */
7a387fff
TS
245 OPC_MOVZ = 0x0A | OPC_SPECIAL,
246 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 247
b691d9d2
LA
248 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
249 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
250
7a387fff 251 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
252
253 /* Special */
a0d700e4 254 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
255 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
256 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 257 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
258 OPC_SYNC = 0x0F | OPC_SPECIAL,
259
7a387fff
TS
260 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
261 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
262 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
263 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
264};
265
7480515f
AM
266/*
267 * R6 Multiply and Divide instructions have the same opcode
268 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
269 */
71375b59 270#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
271
272enum {
273 R6_OPC_MUL = OPC_MULT | (2 << 6),
274 R6_OPC_MUH = OPC_MULT | (3 << 6),
275 R6_OPC_MULU = OPC_MULTU | (2 << 6),
276 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
277 R6_OPC_DIV = OPC_DIV | (2 << 6),
278 R6_OPC_MOD = OPC_DIV | (3 << 6),
279 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
280 R6_OPC_MODU = OPC_DIVU | (3 << 6),
281
282 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
283 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
284 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
285 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
286 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
287 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
288 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
289 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
290
291 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
292 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
293 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
294 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
295 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
b42ee5e1
LA
296};
297
e9c71dd1 298/* Multiplication variants of the vr54xx. */
71375b59 299#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
e9c71dd1
TS
300
301enum {
302 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
303 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
304 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
305 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
306 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
307 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
308 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
309 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
310 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
311 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
312 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
313 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
314 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
315 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
316};
317
7a387fff 318/* REGIMM (rt field) opcodes */
71375b59 319#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
320
321enum {
322 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
323 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
324 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
325 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
326 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
327 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
328 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
329 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
330 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
331 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
332 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
333 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
334 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
335 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 336 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 337 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
338
339 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
340 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
341};
342
7a387fff 343/* Special2 opcodes */
71375b59 344#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 345
e37e863f 346enum {
7a387fff
TS
347 /* Multiply & xxx operations */
348 OPC_MADD = 0x00 | OPC_SPECIAL2,
349 OPC_MADDU = 0x01 | OPC_SPECIAL2,
350 OPC_MUL = 0x02 | OPC_SPECIAL2,
351 OPC_MSUB = 0x04 | OPC_SPECIAL2,
352 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
353 /* Loongson 2F */
354 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
355 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
356 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
357 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
358 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
359 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
360 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
361 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
362 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
363 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
364 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
365 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 366 /* Misc */
7a387fff
TS
367 OPC_CLZ = 0x20 | OPC_SPECIAL2,
368 OPC_CLO = 0x21 | OPC_SPECIAL2,
369 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
370 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 371 /* Special */
7a387fff
TS
372 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
373};
374
375/* Special3 opcodes */
71375b59 376#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
377
378enum {
379 OPC_EXT = 0x00 | OPC_SPECIAL3,
380 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
381 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
382 OPC_DEXT = 0x03 | OPC_SPECIAL3,
383 OPC_INS = 0x04 | OPC_SPECIAL3,
384 OPC_DINSM = 0x05 | OPC_SPECIAL3,
385 OPC_DINSU = 0x06 | OPC_SPECIAL3,
386 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
387 OPC_FORK = 0x08 | OPC_SPECIAL3,
388 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
389 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
390 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
391 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
99029be1 392 OPC_GINV = 0x3D | OPC_SPECIAL3,
161f85e6
AJ
393
394 /* Loongson 2E */
395 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
396 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
397 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
398 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
399 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
400 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
401 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
402 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
403 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
404 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
405 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
406 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
407
408 /* MIPS DSP Load */
409 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
410 /* MIPS DSP Arithmetic */
411 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 412 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 413 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 414 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
415 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
416 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 418 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
419 /* MIPS DSP GPR-Based Shift Sub-class */
420 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 421 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
422 /* MIPS DSP Multiply Sub-class insns */
423 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
424 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
425 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 426 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
427 /* DSP Bit/Manipulation Sub-class */
428 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 429 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 430 /* MIPS DSP Append Sub-class */
26690560 431 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 432 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
433 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
434 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 435 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 436
76964147
JH
437 /* EVA */
438 OPC_LWLE = 0x19 | OPC_SPECIAL3,
439 OPC_LWRE = 0x1A | OPC_SPECIAL3,
440 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
441 OPC_SBE = 0x1C | OPC_SPECIAL3,
442 OPC_SHE = 0x1D | OPC_SPECIAL3,
443 OPC_SCE = 0x1E | OPC_SPECIAL3,
444 OPC_SWE = 0x1F | OPC_SPECIAL3,
445 OPC_SWLE = 0x21 | OPC_SPECIAL3,
446 OPC_SWRE = 0x22 | OPC_SPECIAL3,
447 OPC_PREFE = 0x23 | OPC_SPECIAL3,
448 OPC_LBUE = 0x28 | OPC_SPECIAL3,
449 OPC_LHUE = 0x29 | OPC_SPECIAL3,
450 OPC_LBE = 0x2C | OPC_SPECIAL3,
451 OPC_LHE = 0x2D | OPC_SPECIAL3,
452 OPC_LLE = 0x2E | OPC_SPECIAL3,
453 OPC_LWE = 0x2F | OPC_SPECIAL3,
454
4368b29a 455 /* R6 */
bf7910c6
LA
456 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
457 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
458 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
459 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
460 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
461 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
462};
463
e10a0ca1
JY
464/* Loongson EXT load/store quad word opcodes */
465#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
466enum {
467 OPC_GSLQ = 0x0020 | OPC_LWC2,
468 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
469 OPC_GSSHFL = OPC_LWC2,
470 OPC_GSSQ = 0x0020 | OPC_SWC2,
471 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
472 OPC_GSSHFS = OPC_SWC2,
473};
474
fd723105
JY
475/* Loongson EXT shifted load/store opcodes */
476#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
477enum {
478 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
479 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
480 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
481 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
482 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
483 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
484 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
485 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
486};
487
90e22a57
JY
488/* Loongson EXT LDC2/SDC2 opcodes */
489#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
490
491enum {
492 OPC_GSLBX = 0x0 | OPC_LDC2,
493 OPC_GSLHX = 0x1 | OPC_LDC2,
494 OPC_GSLWX = 0x2 | OPC_LDC2,
495 OPC_GSLDX = 0x3 | OPC_LDC2,
496 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
497 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
498 OPC_GSSBX = 0x0 | OPC_SDC2,
499 OPC_GSSHX = 0x1 | OPC_SDC2,
500 OPC_GSSWX = 0x2 | OPC_SDC2,
501 OPC_GSSDX = 0x3 | OPC_SDC2,
502 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
503 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
504};
505
7a387fff 506/* BSHFL opcodes */
71375b59 507#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 508
e37e863f 509enum {
15eacb9b
YK
510 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
511 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
512 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
513 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
514 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
515 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
516 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 517 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
518};
519
7a387fff 520/* DBSHFL opcodes */
71375b59 521#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 522
e37e863f 523enum {
15eacb9b
YK
524 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
525 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
526 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
527 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
528 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
529 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
530 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
531 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
532 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
533 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 534 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
535};
536
e45a93e2
JL
537/* MIPS DSP REGIMM opcodes */
538enum {
539 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 540 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
541};
542
71375b59 543#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
544/* MIPS DSP Load */
545enum {
546 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
547 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
548 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 549 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
550};
551
71375b59 552#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
553enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
558 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
559 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
561 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
564 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
565 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
566 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
567 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
568 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
569 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
570 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
571 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
572 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
573 /* MIPS DSP Multiply Sub-class insns */
574 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
575 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
576 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
577 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
578 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
579 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
580};
581
582#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 583#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
584enum {
585 /* MIPS DSP Arithmetic Sub-class */
586 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
590 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
591 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
594 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
595 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
596 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
597 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
598 /* MIPS DSP Multiply Sub-class insns */
599 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
600 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
601 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
602 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
603};
604
71375b59 605#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
606enum {
607 /* MIPS DSP Arithmetic Sub-class */
608 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
620 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
621 /* DSP Bit/Manipulation Sub-class */
622 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
623 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
624 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
625 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
626 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
627};
628
71375b59 629#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
630enum {
631 /* MIPS DSP Arithmetic Sub-class */
632 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
639 /* DSP Compare-Pick Sub-class */
640 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
650 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
651 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
652 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
653 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
654 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 655};
a22260ae 656
71375b59 657#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
658enum {
659 /* MIPS DSP GPR-Based Shift Sub-class */
660 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
677 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
678 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
679 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
680 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
681 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
682};
461c08df 683
71375b59 684#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
685enum {
686 /* MIPS DSP Multiply Sub-class insns */
687 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
696 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
700 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
701 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
702 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
703 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
704 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
705 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
706 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
707 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
708 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
709};
710
71375b59 711#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
712enum {
713 /* DSP Bit/Manipulation Sub-class */
714 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
715};
716
71375b59 717#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 718enum {
df6126a7 719 /* MIPS DSP Append Sub-class */
26690560
JL
720 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
721 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
722 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
723};
724
71375b59 725#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
726enum {
727 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
728 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
735 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
736 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
737 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
738 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
739 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
740 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
741 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
742 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
743 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
744 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
745};
746
71375b59 747#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
748enum {
749 /* MIPS DSP Arithmetic Sub-class */
750 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
766 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
767 /* DSP Bit/Manipulation Sub-class */
768 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
769 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
770 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
771 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
772 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
773 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 774};
461c08df 775
71375b59 776#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 777enum {
a22260ae
JL
778 /* MIPS DSP Multiply Sub-class insns */
779 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
780 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
781 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
782 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
783 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
784 /* MIPS DSP Arithmetic Sub-class */
785 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
791 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
792 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
793 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
794 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
795 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
801 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
802 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
803 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
804 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
805 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
806};
461c08df 807
71375b59 808#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 809enum {
26690560
JL
810 /* DSP Compare-Pick Sub-class */
811 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
830 /* MIPS DSP Arithmetic Sub-class */
831 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
834 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
835 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
836 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
837 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
838 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
839};
461c08df 840
71375b59 841#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 842enum {
df6126a7 843 /* DSP Append Sub-class */
26690560
JL
844 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
845 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
846 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
847 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
848};
26690560 849
71375b59 850#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
851enum {
852 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
853 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
854 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
869 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
870 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
871 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
872 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
873 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
874};
875
71375b59 876#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
877enum {
878 /* DSP Bit/Manipulation Sub-class */
879 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
880};
1cb6686c 881
71375b59 882#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
883enum {
884 /* MIPS DSP Multiply Sub-class insns */
885 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
906 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
907 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
908 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
909 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
910 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
911};
a22260ae 912
71375b59 913#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
914enum {
915 /* MIPS DSP GPR-Based Shift Sub-class */
916 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
937 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
938 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
939 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
940 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
941 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
942};
77c5fa8b 943
7a387fff 944/* Coprocessor 0 (rs field) */
71375b59 945#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 946
6ea83fed 947enum {
7a387fff
TS
948 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
949 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 950 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
951 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
952 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 953 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 954 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
955 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
956 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 957 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
958 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
959 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
960 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
961 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
962 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
963 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
964 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
965 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
966 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
967 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
968 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
969 OPC_C0_A = (0x1A << 21) | OPC_CP0,
970 OPC_C0_B = (0x1B << 21) | OPC_CP0,
971 OPC_C0_C = (0x1C << 21) | OPC_CP0,
972 OPC_C0_D = (0x1D << 21) | OPC_CP0,
973 OPC_C0_E = (0x1E << 21) | OPC_CP0,
974 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 975};
7a387fff
TS
976
977/* MFMC0 opcodes */
71375b59 978#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
979
980enum {
ead9360e
TS
981 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
982 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
983 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
984 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
985 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
986 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
987 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
988 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
989};
990
991/* Coprocessor 0 (with rs == C0) */
71375b59 992#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
993
994enum {
995 OPC_TLBR = 0x01 | OPC_C0,
996 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
997 OPC_TLBINV = 0x03 | OPC_C0,
998 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
999 OPC_TLBWR = 0x06 | OPC_C0,
1000 OPC_TLBP = 0x08 | OPC_C0,
1001 OPC_RFE = 0x10 | OPC_C0,
1002 OPC_ERET = 0x18 | OPC_C0,
1003 OPC_DERET = 0x1F | OPC_C0,
1004 OPC_WAIT = 0x20 | OPC_C0,
1005};
1006
71375b59 1007#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
1008
1009enum {
1010 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1011 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1012 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1013 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1014 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1015 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1016 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1017 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1018 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1019 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1020 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1021};
1022
8e2d5831 1023#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1024
1025enum {
71375b59
AM
1026 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1027 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1028 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1029 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1030 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1031 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1032 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1033 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1034
1035 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1036 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1037 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1038 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1039 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1040 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1041 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1042 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1043
1044 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1045 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1046 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1047 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1048 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1049 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1050 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1051 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1052
1053 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1054 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1055 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1056 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1057 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1058 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1059 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1060 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1061
1062 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1063 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1064 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1065 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1066 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1067 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1068
1069 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1070 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1071 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1072 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1073 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1074 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1075
1076 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1077 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1078 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1079 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1080 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1081 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1082
1083 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1084 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1085 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1086 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1087 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1088 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1089
1090 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1091 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1092 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1093 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1094 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1095 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1096
1097 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1098 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1099 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1100 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1101 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1102 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1103
1104 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1105 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1106 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1107 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1108 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1109 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1110
1111 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1112 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1113 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1114 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1115 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1116 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1117};
1118
1119
71375b59 1120#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1121
1122enum {
71375b59
AM
1123 OPC_LWXC1 = 0x00 | OPC_CP3,
1124 OPC_LDXC1 = 0x01 | OPC_CP3,
1125 OPC_LUXC1 = 0x05 | OPC_CP3,
1126 OPC_SWXC1 = 0x08 | OPC_CP3,
1127 OPC_SDXC1 = 0x09 | OPC_CP3,
1128 OPC_SUXC1 = 0x0D | OPC_CP3,
1129 OPC_PREFX = 0x0F | OPC_CP3,
1130 OPC_ALNV_PS = 0x1E | OPC_CP3,
1131 OPC_MADD_S = 0x20 | OPC_CP3,
1132 OPC_MADD_D = 0x21 | OPC_CP3,
1133 OPC_MADD_PS = 0x26 | OPC_CP3,
1134 OPC_MSUB_S = 0x28 | OPC_CP3,
1135 OPC_MSUB_D = 0x29 | OPC_CP3,
1136 OPC_MSUB_PS = 0x2E | OPC_CP3,
1137 OPC_NMADD_S = 0x30 | OPC_CP3,
1138 OPC_NMADD_D = 0x31 | OPC_CP3,
1139 OPC_NMADD_PS = 0x36 | OPC_CP3,
1140 OPC_NMSUB_S = 0x38 | OPC_CP3,
1141 OPC_NMSUB_D = 0x39 | OPC_CP3,
1142 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1143};
1144
497f072b 1145/*
baa609db
AM
1146 * MMI (MultiMedia Instruction) encodings
1147 * ======================================
f99c0d6d 1148 *
baa609db 1149 * MMI instructions encoding table keys:
f99c0d6d
FN
1150 *
1151 * * This code is reserved for future use. An attempt to execute it
1152 * causes a Reserved Instruction exception.
1153 * % This code indicates an instruction class. The instruction word
1154 * must be further decoded by examining additional tables that show
1155 * the values for other instruction fields.
1156 * # This code is reserved for the unsupported instructions DMULT,
1157 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1158 * to execute it causes a Reserved Instruction exception.
1159 *
baa609db 1160 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
1161 *
1162 * 31 26 0
1163 * +--------+----------------------------------------+
1164 * | opcode | |
1165 * +--------+----------------------------------------+
1166 *
1167 * opcode bits 28..26
1168 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1169 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1170 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1171 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1172 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1173 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1174 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1175 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1176 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1177 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1178 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 1179 */
b158d449 1180
f99c0d6d 1181enum {
baa609db
AM
1182 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1183 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1184 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
1185};
1186
d3297211 1187/*
baa609db 1188 * MMI instructions with opcode field = MMI:
d3297211
FN
1189 *
1190 * 31 26 5 0
1191 * +--------+-------------------------------+--------+
1192 * | MMI | |function|
1193 * +--------+-------------------------------+--------+
1194 *
1195 * function bits 2..0
1196 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1197 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1198 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1199 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1200 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1201 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1202 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1203 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1204 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1205 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1206 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1207 */
1208
c8341e00 1209#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 1210enum {
baa609db
AM
1211 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1212 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
baa609db
AM
1213 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1214 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1215 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1216 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1217 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1218 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
dd581bf9
FN
1219};
1220
39454628 1221/* global register indices */
46c9e2b3 1222TCGv cpu_gpr[32], cpu_PC;
cefd68f6
PMD
1223/*
1224 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1225 * and the upper halves in cpu_gpr_hi[].
1226 */
1227TCGv_i64 cpu_gpr_hi[32];
9f5f7691 1228TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
46c9e2b3
PMD
1229static TCGv cpu_dspctrl, btarget;
1230TCGv bcond;
33a07fa2 1231static TCGv cpu_lladdr, cpu_llval;
41db4607 1232static TCGv_i32 hflags;
8758d1b8
PMD
1233TCGv_i32 fpu_fcr0, fpu_fcr31;
1234TCGv_i64 fpu_f64[32];
aa0bf00b 1235
022c62cb 1236#include "exec/gen-icount.h"
2e70f6ef 1237
895c2d04 1238#define gen_helper_0e0i(name, arg) do { \
a7812ae4 1239 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 1240 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4 1241 tcg_temp_free_i32(helper_tmp); \
71375b59 1242 } while (0)
be24bb4f 1243
895c2d04 1244#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 1245 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 1246 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4 1247 tcg_temp_free_i32(helper_tmp); \
71375b59 1248 } while (0)
be24bb4f 1249
895c2d04
BS
1250#define gen_helper_1e0i(name, ret, arg1) do { \
1251 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1252 gen_helper_##name(ret, cpu_env, helper_tmp); \
1253 tcg_temp_free_i32(helper_tmp); \
71375b59 1254 } while (0)
895c2d04
BS
1255
1256#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1257 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1258 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1259 tcg_temp_free_i32(helper_tmp); \
71375b59 1260 } while (0)
895c2d04
BS
1261
1262#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1263 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1264 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1265 tcg_temp_free_i32(helper_tmp); \
71375b59 1266 } while (0)
895c2d04
BS
1267
1268#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 1269 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 1270 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4 1271 tcg_temp_free_i32(helper_tmp); \
71375b59 1272 } while (0)
be24bb4f 1273
895c2d04 1274#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 1275 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 1276 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4 1277 tcg_temp_free_i32(helper_tmp); \
71375b59 1278 } while (0)
c239529e 1279
b28425ba
EC
1280#define DISAS_STOP DISAS_TARGET_0
1281#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 1282
06106772 1283static const char regnames_HI[][4] = {
d73ee8a2
RH
1284 "HI0", "HI1", "HI2", "HI3",
1285};
4b2eb8d2 1286
06106772 1287static const char regnames_LO[][4] = {
d73ee8a2
RH
1288 "LO0", "LO1", "LO2", "LO3",
1289};
4b2eb8d2 1290
8e9ade68 1291/* General purpose registers moves. */
46c9e2b3 1292void gen_load_gpr(TCGv t, int reg)
aaa9128a 1293{
1f8929d2 1294 if (reg == 0) {
8e9ade68 1295 tcg_gen_movi_tl(t, 0);
1f8929d2 1296 } else {
4b2eb8d2 1297 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 1298 }
aaa9128a
TS
1299}
1300
46c9e2b3 1301void gen_store_gpr(TCGv t, int reg)
aaa9128a 1302{
1f8929d2 1303 if (reg != 0) {
4b2eb8d2 1304 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 1305 }
aaa9128a
TS
1306}
1307
61f4e0ec
PMD
1308#if defined(TARGET_MIPS64)
1309void gen_load_gpr_hi(TCGv_i64 t, int reg)
1310{
1311 if (reg == 0) {
1312 tcg_gen_movi_i64(t, 0);
1313 } else {
1314 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1315 }
1316}
1317
1318void gen_store_gpr_hi(TCGv_i64 t, int reg)
1319{
1320 if (reg != 0) {
1321 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1322 }
1323}
1324#endif /* TARGET_MIPS64 */
1325
8e9ade68 1326/* Moves to/from shadow registers. */
235785e8 1327static inline void gen_load_srsgpr(int from, int to)
aaa9128a 1328{
d9bea114 1329 TCGv t0 = tcg_temp_new();
be24bb4f 1330
1f8929d2 1331 if (from == 0) {
d9bea114 1332 tcg_gen_movi_tl(t0, 0);
1f8929d2 1333 } else {
d9bea114 1334 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1335 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1336
7db13fae 1337 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1338 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1339 tcg_gen_andi_i32(t2, t2, 0xf);
1340 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1341 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1342 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1343
d9bea114 1344 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1345 tcg_temp_free_ptr(addr);
d9bea114 1346 tcg_temp_free_i32(t2);
8e9ade68 1347 }
d9bea114
AJ
1348 gen_store_gpr(t0, to);
1349 tcg_temp_free(t0);
aaa9128a
TS
1350}
1351
71375b59 1352static inline void gen_store_srsgpr(int from, int to)
aaa9128a 1353{
be24bb4f 1354 if (to != 0) {
d9bea114
AJ
1355 TCGv t0 = tcg_temp_new();
1356 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1357 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1358
d9bea114 1359 gen_load_gpr(t0, from);
7db13fae 1360 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1361 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1362 tcg_gen_andi_i32(t2, t2, 0xf);
1363 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1364 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1365 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1366
d9bea114 1367 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1368 tcg_temp_free_ptr(addr);
d9bea114
AJ
1369 tcg_temp_free_i32(t2);
1370 tcg_temp_free(t0);
8e9ade68 1371 }
aaa9128a
TS
1372}
1373
eab9944c
LA
1374/* Tests */
1375static inline void gen_save_pc(target_ulong pc)
1376{
1377 tcg_gen_movi_tl(cpu_PC, pc);
1378}
1379
1380static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1381{
1382 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
1383 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1384 gen_save_pc(ctx->base.pc_next);
1385 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
1386 }
1387 if (ctx->hflags != ctx->saved_hflags) {
1388 tcg_gen_movi_i32(hflags, ctx->hflags);
1389 ctx->saved_hflags = ctx->hflags;
1390 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1391 case MIPS_HFLAG_BR:
1392 break;
1393 case MIPS_HFLAG_BC:
1394 case MIPS_HFLAG_BL:
1395 case MIPS_HFLAG_B:
1396 tcg_gen_movi_tl(btarget, ctx->btarget);
1397 break;
1398 }
1399 }
1400}
1401
1402static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1403{
1404 ctx->saved_hflags = ctx->hflags;
1405 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1406 case MIPS_HFLAG_BR:
1407 break;
1408 case MIPS_HFLAG_BC:
1409 case MIPS_HFLAG_BL:
1410 case MIPS_HFLAG_B:
1411 ctx->btarget = env->btarget;
1412 break;
1413 }
1414}
1415
46c9e2b3 1416void generate_exception_err(DisasContext *ctx, int excp, int err)
eab9944c
LA
1417{
1418 TCGv_i32 texcp = tcg_const_i32(excp);
1419 TCGv_i32 terr = tcg_const_i32(err);
1420 save_cpu_state(ctx, 1);
1421 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1422 tcg_temp_free_i32(terr);
1423 tcg_temp_free_i32(texcp);
eeb3bba8 1424 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
1425}
1426
46c9e2b3 1427void generate_exception(DisasContext *ctx, int excp)
eab9944c 1428{
eab9944c
LA
1429 gen_helper_0e0i(raise_exception, excp);
1430}
1431
46c9e2b3 1432void generate_exception_end(DisasContext *ctx, int excp)
9c708c7f
PD
1433{
1434 generate_exception_err(ctx, excp, 0);
1435}
1436
3a4ef3b7
PMD
1437void gen_reserved_instruction(DisasContext *ctx)
1438{
1439 generate_exception_end(ctx, EXCP_RI);
1440}
1441
aaa9128a 1442/* Floating point register moves. */
8758d1b8 1443void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1444{
7c979afd
LA
1445 if (ctx->hflags & MIPS_HFLAG_FRE) {
1446 generate_exception(ctx, EXCP_RI);
1447 }
ecc7b3aa 1448 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1449}
1450
8758d1b8 1451void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1452{
7c979afd
LA
1453 TCGv_i64 t64;
1454 if (ctx->hflags & MIPS_HFLAG_FRE) {
1455 generate_exception(ctx, EXCP_RI);
1456 }
1457 t64 = tcg_temp_new_i64();
d73ee8a2
RH
1458 tcg_gen_extu_i32_i64(t64, t);
1459 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1460 tcg_temp_free_i64(t64);
6d066274
AJ
1461}
1462
7f6613ce 1463static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1464{
7f6613ce 1465 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 1466 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 1467 } else {
7c979afd 1468 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 1469 }
6d066274
AJ
1470}
1471
7f6613ce 1472static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1473{
7f6613ce
PJ
1474 if (ctx->hflags & MIPS_HFLAG_F64) {
1475 TCGv_i64 t64 = tcg_temp_new_i64();
1476 tcg_gen_extu_i32_i64(t64, t);
1477 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1478 tcg_temp_free_i64(t64);
1479 } else {
7c979afd 1480 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 1481 }
aa0bf00b 1482}
6ea83fed 1483
8758d1b8 1484void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1485{
f364515c 1486 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1487 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1488 } else {
d73ee8a2 1489 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1490 }
1491}
6ea83fed 1492
8758d1b8 1493void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1494{
f364515c 1495 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1496 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1497 } else {
d73ee8a2
RH
1498 TCGv_i64 t0;
1499 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1500 t0 = tcg_temp_new_i64();
6d066274 1501 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1502 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1503 tcg_temp_free_i64(t0);
aa0bf00b
TS
1504 }
1505}
6ea83fed 1506
8758d1b8 1507int get_fp_bit(int cc)
a16336e4 1508{
1f8929d2 1509 if (cc) {
d94536f4 1510 return 24 + cc;
1f8929d2 1511 } else {
d94536f4 1512 return 23;
1f8929d2 1513 }
a16336e4
TS
1514}
1515
48d38ca5 1516/* Addresses computation */
46c9e2b3 1517void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1518{
941694d0 1519 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1520
1521#if defined(TARGET_MIPS64)
01f72885 1522 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 1523 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1524 }
1525#endif
4ad40f36
FB
1526}
1527
bf0718c5
SM
1528static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1529 target_long ofs)
1530{
1531 tcg_gen_addi_tl(ret, base, ofs);
1532
1533#if defined(TARGET_MIPS64)
1534 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1535 tcg_gen_ext32s_i64(ret, ret);
1536 }
1537#endif
1538}
1539
31837be3
YK
1540/* Addresses computation (translation time) */
1541static target_long addr_add(DisasContext *ctx, target_long base,
1542 target_long offset)
1543{
1544 target_long sum = base + offset;
1545
1546#if defined(TARGET_MIPS64)
1547 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1548 sum = (int32_t)sum;
1549 }
1550#endif
1551 return sum;
1552}
1553
71f303cd 1554/* Sign-extract the low 32-bits to a target_long. */
46c9e2b3 1555void gen_move_low32(TCGv ret, TCGv_i64 arg)
1f1b4c00
YK
1556{
1557#if defined(TARGET_MIPS64)
71f303cd
RH
1558 tcg_gen_ext32s_i64(ret, arg);
1559#else
1560 tcg_gen_extrl_i64_i32(ret, arg);
1561#endif
1562}
1563
1564/* Sign-extract the high 32-bits to a target_long. */
46c9e2b3 1565void gen_move_high32(TCGv ret, TCGv_i64 arg)
71f303cd
RH
1566{
1567#if defined(TARGET_MIPS64)
1568 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 1569#else
71f303cd 1570 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
1571#endif
1572}
1573
905bdf72 1574bool check_cp0_enabled(DisasContext *ctx)
387a8fe5 1575{
1f8929d2 1576 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1577 generate_exception_end(ctx, EXCP_CpU);
905bdf72 1578 return false;
1f8929d2 1579 }
905bdf72 1580 return true;
387a8fe5
TS
1581}
1582
8758d1b8 1583void check_cp1_enabled(DisasContext *ctx)
5e755519 1584{
1f8929d2 1585 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 1586 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 1587 }
5e755519
TS
1588}
1589
7480515f
AM
1590/*
1591 * Verify that the processor is running with COP1X instructions enabled.
1592 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1593 * opcode tables.
1594 */
8758d1b8 1595void check_cop1x(DisasContext *ctx)
b8aa4598 1596{
1f8929d2 1597 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
3a4ef3b7 1598 gen_reserved_instruction(ctx);
1f8929d2 1599 }
b8aa4598
TS
1600}
1601
7480515f
AM
1602/*
1603 * Verify that the processor is running with 64-bit floating-point
1604 * operations enabled.
1605 */
8758d1b8 1606void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1607{
1f8929d2 1608 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
3a4ef3b7 1609 gen_reserved_instruction(ctx);
1f8929d2 1610 }
5e755519
TS
1611}
1612
1613/*
1614 * Verify if floating point register is valid; an operation is not defined
1615 * if bit 0 of any register specification is set and the FR bit in the
1616 * Status register equals zero, since the register numbers specify an
1617 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1618 * in the Status register equals one, both even and odd register numbers
1619 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1620 *
1621 * Multiple 64 bit wide registers can be checked by calling
1622 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1623 */
8758d1b8 1624void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1625{
1f8929d2 1626 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
3a4ef3b7 1627 gen_reserved_instruction(ctx);
1f8929d2 1628 }
5e755519
TS
1629}
1630
7480515f
AM
1631/*
1632 * Verify that the processor is running with DSP instructions enabled.
1633 * This is enabled by CP0 Status register MX(24) bit.
853c3240 1634 */
853c3240
JL
1635static inline void check_dsp(DisasContext *ctx)
1636{
1637 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 1638 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1639 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1640 } else {
3a4ef3b7 1641 gen_reserved_instruction(ctx);
ad153f15 1642 }
853c3240
JL
1643 }
1644}
1645
908f6be1 1646static inline void check_dsp_r2(DisasContext *ctx)
853c3240 1647{
908f6be1 1648 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 1649 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1650 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1651 } else {
3a4ef3b7 1652 gen_reserved_instruction(ctx);
ad153f15 1653 }
853c3240
JL
1654 }
1655}
1656
908f6be1 1657static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 1658{
908f6be1 1659 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
1660 if (ctx->insn_flags & ASE_DSP) {
1661 generate_exception_end(ctx, EXCP_DSPDIS);
1662 } else {
3a4ef3b7 1663 gen_reserved_instruction(ctx);
59e781fb
SM
1664 }
1665 }
1666}
1667
7480515f
AM
1668/*
1669 * This code generates a "reserved instruction" exception if the
1670 * CPU does not support the instruction set corresponding to flags.
1671 */
46c9e2b3 1672void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 1673{
d75c135e 1674 if (unlikely(!(ctx->insn_flags & flags))) {
3a4ef3b7 1675 gen_reserved_instruction(ctx);
d75c135e 1676 }
3a95e3a7
TS
1677}
1678
7480515f
AM
1679/*
1680 * This code generates a "reserved instruction" exception if the
1681 * CPU has corresponding flag set which indicates that the instruction
1682 * has been removed.
1683 */
f9c9cd63 1684static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
1685{
1686 if (unlikely(ctx->insn_flags & flags)) {
3a4ef3b7 1687 gen_reserved_instruction(ctx);
fecd2646
LA
1688 }
1689}
1690
96631327
FN
1691/*
1692 * The Linux kernel traps certain reserved instruction exceptions to
1693 * emulate the corresponding instructions. QEMU is the kernel in user
1694 * mode, so those traps are emulated by accepting the instructions.
1695 *
1696 * A reserved instruction exception is generated for flagged CPUs if
1697 * QEMU runs in system mode.
1698 */
1699static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1700{
1701#ifndef CONFIG_USER_ONLY
1702 check_insn_opc_removed(ctx, flags);
1703#endif
1704}
1705
7480515f
AM
1706/*
1707 * This code generates a "reserved instruction" exception if the
1708 * CPU does not support 64-bit paired-single (PS) floating point data type.
1709 */
e29c9628
YK
1710static inline void check_ps(DisasContext *ctx)
1711{
1712 if (unlikely(!ctx->ps)) {
1713 generate_exception(ctx, EXCP_RI);
1714 }
1715 check_cp1_64bitmode(ctx);
1716}
1717
7480515f 1718/*
d7efb693
PMD
1719 * This code generates a "reserved instruction" exception if cpu is not
1720 * 64-bit or 64-bit instructions are not enabled.
7480515f 1721 */
46c9e2b3 1722void check_mips_64(DisasContext *ctx)
e189e748 1723{
d7efb693 1724 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
3a4ef3b7 1725 gen_reserved_instruction(ctx);
1f8929d2 1726 }
e189e748
TS
1727}
1728
5204ea79
LA
1729#ifndef CONFIG_USER_ONLY
1730static inline void check_mvh(DisasContext *ctx)
1731{
1732 if (unlikely(!ctx->mvh)) {
1733 generate_exception(ctx, EXCP_RI);
1734 }
1735}
1736#endif
1737
0b16dcd1
AR
1738/*
1739 * This code generates a "reserved instruction" exception if the
1740 * Config5 XNP bit is set.
1741 */
1742static inline void check_xnp(DisasContext *ctx)
1743{
1744 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3a4ef3b7 1745 gen_reserved_instruction(ctx);
0b16dcd1
AR
1746 }
1747}
1748
5e31fdd5
YK
1749#ifndef CONFIG_USER_ONLY
1750/*
1751 * This code generates a "reserved instruction" exception if the
1752 * Config3 PW bit is NOT set.
1753 */
1754static inline void check_pw(DisasContext *ctx)
1755{
1756 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3a4ef3b7 1757 gen_reserved_instruction(ctx);
5e31fdd5
YK
1758 }
1759}
1760#endif
1761
9affc1c5
AR
1762/*
1763 * This code generates a "reserved instruction" exception if the
1764 * Config3 MT bit is NOT set.
1765 */
1766static inline void check_mt(DisasContext *ctx)
1767{
1768 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1769 gen_reserved_instruction(ctx);
9affc1c5
AR
1770 }
1771}
1772
1773#ifndef CONFIG_USER_ONLY
1774/*
1775 * This code generates a "coprocessor unusable" exception if CP0 is not
1776 * available, and, if that is not the case, generates a "reserved instruction"
1777 * exception if the Config5 MT bit is NOT set. This is needed for availability
1778 * control of some of MT ASE instructions.
1779 */
1780static inline void check_cp0_mt(DisasContext *ctx)
1781{
1782 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1783 generate_exception_end(ctx, EXCP_CpU);
9affc1c5
AR
1784 } else {
1785 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1786 gen_reserved_instruction(ctx);
9affc1c5
AR
1787 }
1788 }
1789}
1790#endif
1791
fb32f8c8
DN
1792/*
1793 * This code generates a "reserved instruction" exception if the
1794 * Config5 NMS bit is set.
1795 */
1796static inline void check_nms(DisasContext *ctx)
1797{
1798 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3a4ef3b7 1799 gen_reserved_instruction(ctx);
fb32f8c8
DN
1800 }
1801}
1802
d046a9ea
DN
1803/*
1804 * This code generates a "reserved instruction" exception if the
1805 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1806 * Config2 TL, and Config5 L2C are unset.
1807 */
1808static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1809{
1f8929d2
AM
1810 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1811 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1812 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1813 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1814 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1815 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3a4ef3b7 1816 gen_reserved_instruction(ctx);
d046a9ea
DN
1817 }
1818}
1819
1820/*
1821 * This code generates a "reserved instruction" exception if the
1822 * Config5 EVA bit is NOT set.
1823 */
1824static inline void check_eva(DisasContext *ctx)
1825{
1826 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3a4ef3b7 1827 gen_reserved_instruction(ctx);
d046a9ea
DN
1828 }
1829}
1830
0b16dcd1 1831
7480515f
AM
1832/*
1833 * Define small wrappers for gen_load_fpr* so that we have a uniform
1834 * calling interface for 32 and 64-bit FPRs. No sense in changing
1835 * all callers for gen_load_fpr32 when we need the CTX parameter for
1836 * this one use.
1837 */
7c979afd 1838#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
1839#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1840#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1841static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1842 int ft, int fs, int cc) \
1843{ \
71375b59
AM
1844 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1845 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
1846 switch (ifmt) { \
1847 case FMT_PS: \
e29c9628 1848 check_ps(ctx); \
8153667c
NF
1849 break; \
1850 case FMT_D: \
1851 if (abs) { \
1852 check_cop1x(ctx); \
1853 } \
1854 check_cp1_registers(ctx, fs | ft); \
1855 break; \
1856 case FMT_S: \
1857 if (abs) { \
1858 check_cop1x(ctx); \
1859 } \
1860 break; \
1861 } \
71375b59
AM
1862 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1863 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 1864 switch (n) { \
1f8929d2
AM
1865 case 0: \
1866 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1867 break; \
1868 case 1: \
1869 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1870 break; \
1871 case 2: \
1872 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1873 break; \
1874 case 3: \
1875 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1876 break; \
1877 case 4: \
1878 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1879 break; \
1880 case 5: \
1881 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1882 break; \
1883 case 6: \
1884 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1885 break; \
1886 case 7: \
1887 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1888 break; \
1889 case 8: \
1890 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1891 break; \
1892 case 9: \
1893 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1894 break; \
1895 case 10: \
1896 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1897 break; \
1898 case 11: \
1899 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1900 break; \
1901 case 12: \
1902 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1903 break; \
1904 case 13: \
1905 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1906 break; \
1907 case 14: \
1908 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1909 break; \
1910 case 15: \
1911 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1912 break; \
1913 default: \
1914 abort(); \
8153667c 1915 } \
71375b59
AM
1916 tcg_temp_free_i##bits(fp0); \
1917 tcg_temp_free_i##bits(fp1); \
8153667c
NF
1918}
1919
1920FOP_CONDS(, 0, d, FMT_D, 64)
1921FOP_CONDS(abs, 1, d, FMT_D, 64)
1922FOP_CONDS(, 0, s, FMT_S, 32)
1923FOP_CONDS(abs, 1, s, FMT_S, 32)
1924FOP_CONDS(, 0, ps, FMT_PS, 64)
1925FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1926#undef FOP_CONDS
3f493883
YK
1927
1928#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 1929static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
1930 int ft, int fs, int fd) \
1931{ \
1932 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1933 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 1934 if (ifmt == FMT_D) { \
3f493883 1935 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
1936 } \
1937 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1938 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1939 switch (n) { \
1940 case 0: \
1941 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1942 break; \
1943 case 1: \
1944 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1945 break; \
1946 case 2: \
1947 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1948 break; \
1949 case 3: \
1950 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 4: \
1953 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 5: \
1956 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 6: \
1959 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 7: \
1962 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 8: \
1965 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 9: \
1968 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 10: \
1971 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 11: \
1974 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 12: \
1977 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 13: \
1980 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 14: \
1983 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 15: \
1986 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 17: \
1989 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 18: \
1992 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 19: \
1995 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 25: \
1998 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 26: \
2001 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 27: \
2004 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 default: \
2007 abort(); \
2008 } \
2009 STORE; \
71375b59
AM
2010 tcg_temp_free_i ## bits(fp0); \
2011 tcg_temp_free_i ## bits(fp1); \
3f493883
YK
2012}
2013
2014FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 2015FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 2016#undef FOP_CONDNS
8153667c
NF
2017#undef gen_ldcmp_fpr32
2018#undef gen_ldcmp_fpr64
2019
958fb4a9 2020/* load/store instructions. */
e7139c44 2021#ifdef CONFIG_USER_ONLY
71375b59 2022#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
2023static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2024 DisasContext *ctx) \
d9bea114
AJ
2025{ \
2026 TCGv t0 = tcg_temp_new(); \
2027 tcg_gen_mov_tl(t0, arg1); \
2028 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
71375b59
AM
2029 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2030 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 2031 tcg_temp_free(t0); \
aaa9128a 2032}
e7139c44 2033#else
71375b59 2034#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
2035static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2036 DisasContext *ctx) \
e7139c44 2037{ \
dd4096cd 2038 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
2039}
2040#endif
71375b59 2041OP_LD_ATOMIC(ll, ld32s);
aaa9128a 2042#if defined(TARGET_MIPS64)
71375b59 2043OP_LD_ATOMIC(lld, ld64);
aaa9128a
TS
2044#endif
2045#undef OP_LD_ATOMIC
2046
46c9e2b3 2047void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
662d7485
NF
2048{
2049 if (base == 0) {
2050 tcg_gen_movi_tl(addr, offset);
2051 } else if (offset == 0) {
2052 gen_load_gpr(addr, base);
2053 } else {
2054 tcg_gen_movi_tl(addr, offset);
2055 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2056 }
2057}
2058
235785e8 2059static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 2060{
eeb3bba8 2061 target_ulong pc = ctx->base.pc_next;
364d4831
NF
2062
2063 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2064 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2065
2066 pc -= branch_bytes;
2067 }
2068
2069 pc &= ~(target_ulong)3;
2070 return pc;
2071}
2072
5c13fdfd 2073/* Load */
d75c135e 2074static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 2075 int rt, int base, int offset)
6af0bf9c 2076{
fc40787a 2077 TCGv t0, t1, t2;
dd4096cd 2078 int mem_idx = ctx->mem_idx;
afa88c3a 2079
8e2d5831
JY
2080 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2081 INSN_LOONGSON3A)) {
7480515f
AM
2082 /*
2083 * Loongson CPU uses a load to zero register for prefetch.
2084 * We emulate it as a NOP. On other CPU we must perform the
2085 * actual memory access.
2086 */
afa88c3a
AJ
2087 return;
2088 }
6af0bf9c 2089
afa88c3a 2090 t0 = tcg_temp_new();
662d7485 2091 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 2092
6af0bf9c 2093 switch (opc) {
d26bc211 2094#if defined(TARGET_MIPS64)
6e473128 2095 case OPC_LWU:
dd4096cd 2096 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 2097 ctx->default_tcg_memop_mask);
78723684 2098 gen_store_gpr(t0, rt);
6e473128 2099 break;
6af0bf9c 2100 case OPC_LD:
dd4096cd 2101 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 2102 ctx->default_tcg_memop_mask);
78723684 2103 gen_store_gpr(t0, rt);
6af0bf9c 2104 break;
7a387fff 2105 case OPC_LLD:
bf7910c6 2106 case R6_OPC_LLD:
dd4096cd 2107 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 2108 gen_store_gpr(t0, rt);
7a387fff 2109 break;
6af0bf9c 2110 case OPC_LDL:
3cee3050 2111 t1 = tcg_temp_new();
7480515f
AM
2112 /*
2113 * Do a byte access to possibly trigger a page
2114 * fault with the unaligned address.
2115 */
dd4096cd 2116 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2117 tcg_gen_andi_tl(t1, t0, 7);
2118#ifndef TARGET_WORDS_BIGENDIAN
2119 tcg_gen_xori_tl(t1, t1, 7);
2120#endif
2121 tcg_gen_shli_tl(t1, t1, 3);
2122 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2123 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 2124 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2125 t2 = tcg_const_tl(-1);
2126 tcg_gen_shl_tl(t2, t2, t1);
78723684 2127 gen_load_gpr(t1, rt);
eb02cc3f 2128 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2129 tcg_temp_free(t2);
2130 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2131 tcg_temp_free(t1);
fc40787a 2132 gen_store_gpr(t0, rt);
6af0bf9c 2133 break;
6af0bf9c 2134 case OPC_LDR:
3cee3050 2135 t1 = tcg_temp_new();
7480515f
AM
2136 /*
2137 * Do a byte access to possibly trigger a page
2138 * fault with the unaligned address.
2139 */
dd4096cd 2140 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2141 tcg_gen_andi_tl(t1, t0, 7);
2142#ifdef TARGET_WORDS_BIGENDIAN
2143 tcg_gen_xori_tl(t1, t1, 7);
2144#endif
2145 tcg_gen_shli_tl(t1, t1, 3);
2146 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2147 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
2148 tcg_gen_shr_tl(t0, t0, t1);
2149 tcg_gen_xori_tl(t1, t1, 63);
2150 t2 = tcg_const_tl(0xfffffffffffffffeull);
2151 tcg_gen_shl_tl(t2, t2, t1);
78723684 2152 gen_load_gpr(t1, rt);
fc40787a
AJ
2153 tcg_gen_and_tl(t1, t1, t2);
2154 tcg_temp_free(t2);
2155 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2156 tcg_temp_free(t1);
fc40787a 2157 gen_store_gpr(t0, rt);
6af0bf9c 2158 break;
364d4831 2159 case OPC_LDPC:
3cee3050 2160 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2161 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2162 tcg_temp_free(t1);
dd4096cd 2163 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
2164 gen_store_gpr(t0, rt);
2165 break;
6af0bf9c 2166#endif
364d4831 2167 case OPC_LWPC:
3cee3050 2168 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2169 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2170 tcg_temp_free(t1);
dd4096cd 2171 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
2172 gen_store_gpr(t0, rt);
2173 break;
76964147
JH
2174 case OPC_LWE:
2175 mem_idx = MIPS_HFLAG_UM;
2176 /* fall through */
6af0bf9c 2177 case OPC_LW:
dd4096cd 2178 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 2179 ctx->default_tcg_memop_mask);
78723684 2180 gen_store_gpr(t0, rt);
6af0bf9c 2181 break;
76964147
JH
2182 case OPC_LHE:
2183 mem_idx = MIPS_HFLAG_UM;
2184 /* fall through */
6af0bf9c 2185 case OPC_LH:
dd4096cd 2186 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 2187 ctx->default_tcg_memop_mask);
78723684 2188 gen_store_gpr(t0, rt);
6af0bf9c 2189 break;
76964147
JH
2190 case OPC_LHUE:
2191 mem_idx = MIPS_HFLAG_UM;
2192 /* fall through */
6af0bf9c 2193 case OPC_LHU:
dd4096cd 2194 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 2195 ctx->default_tcg_memop_mask);
78723684 2196 gen_store_gpr(t0, rt);
6af0bf9c 2197 break;
76964147
JH
2198 case OPC_LBE:
2199 mem_idx = MIPS_HFLAG_UM;
2200 /* fall through */
6af0bf9c 2201 case OPC_LB:
dd4096cd 2202 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 2203 gen_store_gpr(t0, rt);
6af0bf9c 2204 break;
76964147
JH
2205 case OPC_LBUE:
2206 mem_idx = MIPS_HFLAG_UM;
2207 /* fall through */
6af0bf9c 2208 case OPC_LBU:
dd4096cd 2209 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 2210 gen_store_gpr(t0, rt);
6af0bf9c 2211 break;
76964147
JH
2212 case OPC_LWLE:
2213 mem_idx = MIPS_HFLAG_UM;
2214 /* fall through */
6af0bf9c 2215 case OPC_LWL:
3cee3050 2216 t1 = tcg_temp_new();
7480515f
AM
2217 /*
2218 * Do a byte access to possibly trigger a page
2219 * fault with the unaligned address.
2220 */
dd4096cd 2221 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2222 tcg_gen_andi_tl(t1, t0, 3);
2223#ifndef TARGET_WORDS_BIGENDIAN
2224 tcg_gen_xori_tl(t1, t1, 3);
2225#endif
2226 tcg_gen_shli_tl(t1, t1, 3);
2227 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2228 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 2229 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2230 t2 = tcg_const_tl(-1);
2231 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2232 gen_load_gpr(t1, rt);
eb02cc3f 2233 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2234 tcg_temp_free(t2);
2235 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2236 tcg_temp_free(t1);
fc40787a
AJ
2237 tcg_gen_ext32s_tl(t0, t0);
2238 gen_store_gpr(t0, rt);
6af0bf9c 2239 break;
76964147
JH
2240 case OPC_LWRE:
2241 mem_idx = MIPS_HFLAG_UM;
2242 /* fall through */
6af0bf9c 2243 case OPC_LWR:
3cee3050 2244 t1 = tcg_temp_new();
7480515f
AM
2245 /*
2246 * Do a byte access to possibly trigger a page
2247 * fault with the unaligned address.
2248 */
dd4096cd 2249 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2250 tcg_gen_andi_tl(t1, t0, 3);
2251#ifdef TARGET_WORDS_BIGENDIAN
2252 tcg_gen_xori_tl(t1, t1, 3);
2253#endif
2254 tcg_gen_shli_tl(t1, t1, 3);
2255 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2256 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
2257 tcg_gen_shr_tl(t0, t0, t1);
2258 tcg_gen_xori_tl(t1, t1, 31);
2259 t2 = tcg_const_tl(0xfffffffeull);
2260 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2261 gen_load_gpr(t1, rt);
fc40787a
AJ
2262 tcg_gen_and_tl(t1, t1, t2);
2263 tcg_temp_free(t2);
2264 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2265 tcg_temp_free(t1);
c728154b 2266 tcg_gen_ext32s_tl(t0, t0);
fc40787a 2267 gen_store_gpr(t0, rt);
6af0bf9c 2268 break;
76964147
JH
2269 case OPC_LLE:
2270 mem_idx = MIPS_HFLAG_UM;
2271 /* fall through */
6af0bf9c 2272 case OPC_LL:
4368b29a 2273 case R6_OPC_LL:
dd4096cd 2274 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 2275 gen_store_gpr(t0, rt);
6af0bf9c 2276 break;
d66c7132 2277 }
d66c7132 2278 tcg_temp_free(t0);
d66c7132
AJ
2279}
2280
0b16dcd1
AR
2281static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2282 uint32_t reg1, uint32_t reg2)
2283{
2284 TCGv taddr = tcg_temp_new();
2285 TCGv_i64 tval = tcg_temp_new_i64();
2286 TCGv tmp1 = tcg_temp_new();
2287 TCGv tmp2 = tcg_temp_new();
2288
2289 gen_base_offset_addr(ctx, taddr, base, offset);
2290 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2291#ifdef TARGET_WORDS_BIGENDIAN
2292 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2293#else
2294 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2295#endif
2296 gen_store_gpr(tmp1, reg1);
2297 tcg_temp_free(tmp1);
2298 gen_store_gpr(tmp2, reg2);
2299 tcg_temp_free(tmp2);
2300 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2301 tcg_temp_free_i64(tval);
2302 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2303 tcg_temp_free(taddr);
2304}
2305
5c13fdfd 2306/* Store */
235785e8
AM
2307static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2308 int base, int offset)
5c13fdfd 2309{
5c13fdfd
AJ
2310 TCGv t0 = tcg_temp_new();
2311 TCGv t1 = tcg_temp_new();
dd4096cd 2312 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
2313
2314 gen_base_offset_addr(ctx, t0, base, offset);
2315 gen_load_gpr(t1, rt);
2316 switch (opc) {
2317#if defined(TARGET_MIPS64)
2318 case OPC_SD:
dd4096cd 2319 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 2320 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
2321 break;
2322 case OPC_SDL:
dd4096cd 2323 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
2324 break;
2325 case OPC_SDR:
dd4096cd 2326 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
2327 break;
2328#endif
76964147
JH
2329 case OPC_SWE:
2330 mem_idx = MIPS_HFLAG_UM;
2331 /* fall through */
5c13fdfd 2332 case OPC_SW:
dd4096cd 2333 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 2334 ctx->default_tcg_memop_mask);
5c13fdfd 2335 break;
76964147
JH
2336 case OPC_SHE:
2337 mem_idx = MIPS_HFLAG_UM;
2338 /* fall through */
5c13fdfd 2339 case OPC_SH:
dd4096cd 2340 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 2341 ctx->default_tcg_memop_mask);
5c13fdfd 2342 break;
76964147
JH
2343 case OPC_SBE:
2344 mem_idx = MIPS_HFLAG_UM;
2345 /* fall through */
5c13fdfd 2346 case OPC_SB:
dd4096cd 2347 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 2348 break;
76964147
JH
2349 case OPC_SWLE:
2350 mem_idx = MIPS_HFLAG_UM;
2351 /* fall through */
5c13fdfd 2352 case OPC_SWL:
dd4096cd 2353 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 2354 break;
76964147
JH
2355 case OPC_SWRE:
2356 mem_idx = MIPS_HFLAG_UM;
2357 /* fall through */
5c13fdfd 2358 case OPC_SWR:
dd4096cd 2359 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
2360 break;
2361 }
5c13fdfd
AJ
2362 tcg_temp_free(t0);
2363 tcg_temp_free(t1);
2364}
2365
2366
d66c7132 2367/* Store conditional */
33a07fa2 2368static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 2369 MemOp tcg_mo, bool eva)
d66c7132 2370{
33a07fa2
LA
2371 TCGv addr, t0, val;
2372 TCGLabel *l1 = gen_new_label();
2373 TCGLabel *done = gen_new_label();
d66c7132 2374
2d2826b9 2375 t0 = tcg_temp_new();
33a07fa2 2376 addr = tcg_temp_new();
8cdf8869 2377 /* compare the address against that of the preceding LL */
33a07fa2
LA
2378 gen_base_offset_addr(ctx, addr, base, offset);
2379 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2380 tcg_temp_free(addr);
2381 tcg_gen_movi_tl(t0, 0);
2382 gen_store_gpr(t0, rt);
2383 tcg_gen_br(done);
2384
2385 gen_set_label(l1);
2386 /* generate cmpxchg */
2387 val = tcg_temp_new();
2388 gen_load_gpr(val, rt);
2389 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2390 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2391 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2392 gen_store_gpr(t0, rt);
2393 tcg_temp_free(val);
2394
2395 gen_set_label(done);
d66c7132 2396 tcg_temp_free(t0);
6af0bf9c
FB
2397}
2398
33a07fa2 2399
0b16dcd1 2400static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
8d5388c1 2401 uint32_t reg1, uint32_t reg2, bool eva)
0b16dcd1
AR
2402{
2403 TCGv taddr = tcg_temp_local_new();
2404 TCGv lladdr = tcg_temp_local_new();
2405 TCGv_i64 tval = tcg_temp_new_i64();
2406 TCGv_i64 llval = tcg_temp_new_i64();
2407 TCGv_i64 val = tcg_temp_new_i64();
2408 TCGv tmp1 = tcg_temp_new();
2409 TCGv tmp2 = tcg_temp_new();
2410 TCGLabel *lab_fail = gen_new_label();
2411 TCGLabel *lab_done = gen_new_label();
2412
2413 gen_base_offset_addr(ctx, taddr, base, offset);
2414
2415 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2416 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2417
2418 gen_load_gpr(tmp1, reg1);
2419 gen_load_gpr(tmp2, reg2);
2420
2421#ifdef TARGET_WORDS_BIGENDIAN
2422 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2423#else
2424 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2425#endif
2426
2427 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2428 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
8d5388c1 2429 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
0b16dcd1
AR
2430 if (reg1 != 0) {
2431 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2432 }
2433 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2434
2435 gen_set_label(lab_fail);
2436
2437 if (reg1 != 0) {
2438 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2439 }
2440 gen_set_label(lab_done);
2441 tcg_gen_movi_tl(lladdr, -1);
2442 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2443}
2444
6ea83fed 2445/* Load and store */
235785e8
AM
2446static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2447 TCGv t0)
6ea83fed 2448{
7480515f
AM
2449 /*
2450 * Don't do NOP if destination is zero: we must perform the actual
2451 * memory access.
2452 */
6ea83fed
FB
2453 switch (opc) {
2454 case OPC_LWC1:
b6d96bed 2455 {
a7812ae4 2456 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
2457 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2458 ctx->default_tcg_memop_mask);
7c979afd 2459 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 2460 tcg_temp_free_i32(fp0);
b6d96bed 2461 }
6ea83fed
FB
2462 break;
2463 case OPC_SWC1:
b6d96bed 2464 {
a7812ae4 2465 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 2466 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
2467 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2468 ctx->default_tcg_memop_mask);
a7812ae4 2469 tcg_temp_free_i32(fp0);
b6d96bed 2470 }
6ea83fed
FB
2471 break;
2472 case OPC_LDC1:
b6d96bed 2473 {
a7812ae4 2474 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
2475 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2476 ctx->default_tcg_memop_mask);
b6d96bed 2477 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 2478 tcg_temp_free_i64(fp0);
b6d96bed 2479 }
6ea83fed
FB
2480 break;
2481 case OPC_SDC1:
b6d96bed 2482 {
a7812ae4 2483 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2484 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
2485 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2486 ctx->default_tcg_memop_mask);
a7812ae4 2487 tcg_temp_free_i64(fp0);
b6d96bed 2488 }
6ea83fed
FB
2489 break;
2490 default:
9d68ac14 2491 MIPS_INVAL("flt_ldst");
3a4ef3b7 2492 gen_reserved_instruction(ctx);
b52d3bfa 2493 break;
6ea83fed 2494 }
6ea83fed 2495}
6ea83fed 2496
5ab5c041
AJ
2497static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2498 int rs, int16_t imm)
26ebe468 2499{
b52d3bfa
YK
2500 TCGv t0 = tcg_temp_new();
2501
5ab5c041 2502 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 2503 check_cp1_enabled(ctx);
d9224450
MR
2504 switch (op) {
2505 case OPC_LDC1:
2506 case OPC_SDC1:
2507 check_insn(ctx, ISA_MIPS2);
2508 /* Fallthrough */
2509 default:
b52d3bfa
YK
2510 gen_base_offset_addr(ctx, t0, rs, imm);
2511 gen_flt_ldst(ctx, op, rt, t0);
d9224450 2512 }
26ebe468
NF
2513 } else {
2514 generate_exception_err(ctx, EXCP_CpU, 1);
2515 }
b52d3bfa 2516 tcg_temp_free(t0);
26ebe468
NF
2517}
2518
6af0bf9c 2519/* Arithmetic with immediate operand */
d75c135e 2520static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 2521 int rt, int rs, int imm)
6af0bf9c 2522{
324d9e32 2523 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 2524
7a387fff 2525 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
2526 /*
2527 * If no destination, treat it as a NOP.
2528 * For addi, we must generate the overflow exception when needed.
2529 */
324d9e32 2530 return;
6af0bf9c
FB
2531 }
2532 switch (opc) {
2533 case OPC_ADDI:
48d38ca5 2534 {
324d9e32
AJ
2535 TCGv t0 = tcg_temp_local_new();
2536 TCGv t1 = tcg_temp_new();
2537 TCGv t2 = tcg_temp_new();
42a268c2 2538 TCGLabel *l1 = gen_new_label();
48d38ca5 2539
324d9e32
AJ
2540 gen_load_gpr(t1, rs);
2541 tcg_gen_addi_tl(t0, t1, uimm);
2542 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2543
324d9e32
AJ
2544 tcg_gen_xori_tl(t1, t1, ~uimm);
2545 tcg_gen_xori_tl(t2, t0, uimm);
2546 tcg_gen_and_tl(t1, t1, t2);
2547 tcg_temp_free(t2);
2548 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2549 tcg_temp_free(t1);
48d38ca5
TS
2550 /* operands of same sign, result different sign */
2551 generate_exception(ctx, EXCP_OVERFLOW);
2552 gen_set_label(l1);
78723684 2553 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
2554 gen_store_gpr(t0, rt);
2555 tcg_temp_free(t0);
48d38ca5 2556 }
6af0bf9c
FB
2557 break;
2558 case OPC_ADDIU:
324d9e32
AJ
2559 if (rs != 0) {
2560 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2561 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2562 } else {
2563 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2564 }
6af0bf9c 2565 break;
d26bc211 2566#if defined(TARGET_MIPS64)
7a387fff 2567 case OPC_DADDI:
48d38ca5 2568 {
324d9e32
AJ
2569 TCGv t0 = tcg_temp_local_new();
2570 TCGv t1 = tcg_temp_new();
2571 TCGv t2 = tcg_temp_new();
42a268c2 2572 TCGLabel *l1 = gen_new_label();
48d38ca5 2573
324d9e32
AJ
2574 gen_load_gpr(t1, rs);
2575 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2576
324d9e32
AJ
2577 tcg_gen_xori_tl(t1, t1, ~uimm);
2578 tcg_gen_xori_tl(t2, t0, uimm);
2579 tcg_gen_and_tl(t1, t1, t2);
2580 tcg_temp_free(t2);
2581 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2582 tcg_temp_free(t1);
48d38ca5
TS
2583 /* operands of same sign, result different sign */
2584 generate_exception(ctx, EXCP_OVERFLOW);
2585 gen_set_label(l1);
324d9e32
AJ
2586 gen_store_gpr(t0, rt);
2587 tcg_temp_free(t0);
48d38ca5 2588 }
7a387fff
TS
2589 break;
2590 case OPC_DADDIU:
324d9e32
AJ
2591 if (rs != 0) {
2592 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2593 } else {
2594 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2595 }
7a387fff
TS
2596 break;
2597#endif
324d9e32 2598 }
324d9e32
AJ
2599}
2600
2601/* Logic with immediate operand */
d75c135e 2602static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2603 int rt, int rs, int16_t imm)
324d9e32
AJ
2604{
2605 target_ulong uimm;
324d9e32
AJ
2606
2607 if (rt == 0) {
2608 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2609 return;
2610 }
2611 uimm = (uint16_t)imm;
2612 switch (opc) {
6af0bf9c 2613 case OPC_ANDI:
1f8929d2 2614 if (likely(rs != 0)) {
324d9e32 2615 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2616 } else {
324d9e32 2617 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 2618 }
6af0bf9c
FB
2619 break;
2620 case OPC_ORI:
1f8929d2 2621 if (rs != 0) {
324d9e32 2622 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2623 } else {
324d9e32 2624 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2625 }
6af0bf9c
FB
2626 break;
2627 case OPC_XORI:
1f8929d2 2628 if (likely(rs != 0)) {
324d9e32 2629 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2630 } else {
324d9e32 2631 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2632 }
6af0bf9c
FB
2633 break;
2634 case OPC_LUI:
2e211e0a 2635 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
d4ea6acd
LA
2636 /* OPC_AUI */
2637 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2638 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
2639 } else {
2640 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 2641 }
7c2c3ea3
EJ
2642 break;
2643
2644 default:
6af0bf9c 2645 break;
324d9e32 2646 }
324d9e32
AJ
2647}
2648
2649/* Set on less than with immediate operand */
d75c135e 2650static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2651 int rt, int rs, int16_t imm)
324d9e32
AJ
2652{
2653 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
2654 TCGv t0;
2655
2656 if (rt == 0) {
2657 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2658 return;
2659 }
2660 t0 = tcg_temp_new();
2661 gen_load_gpr(t0, rs);
2662 switch (opc) {
2663 case OPC_SLTI:
e68dd28f 2664 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2665 break;
2666 case OPC_SLTIU:
e68dd28f 2667 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2668 break;
2669 }
324d9e32
AJ
2670 tcg_temp_free(t0);
2671}
2672
2673/* Shifts with immediate operand */
d75c135e 2674static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
2675 int rt, int rs, int16_t imm)
2676{
2677 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
2678 TCGv t0;
2679
2680 if (rt == 0) {
2681 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2682 return;
2683 }
2684
2685 t0 = tcg_temp_new();
2686 gen_load_gpr(t0, rs);
2687 switch (opc) {
6af0bf9c 2688 case OPC_SLL:
78723684 2689 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 2690 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
2691 break;
2692 case OPC_SRA:
324d9e32 2693 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
2694 break;
2695 case OPC_SRL:
ea63e2c3
NF
2696 if (uimm != 0) {
2697 tcg_gen_ext32u_tl(t0, t0);
2698 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2699 } else {
2700 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 2701 }
ea63e2c3
NF
2702 break;
2703 case OPC_ROTR:
2704 if (uimm != 0) {
2705 TCGv_i32 t1 = tcg_temp_new_i32();
2706
2707 tcg_gen_trunc_tl_i32(t1, t0);
2708 tcg_gen_rotri_i32(t1, t1, uimm);
2709 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2710 tcg_temp_free_i32(t1);
3399e30f
NF
2711 } else {
2712 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 2713 }
7a387fff 2714 break;
d26bc211 2715#if defined(TARGET_MIPS64)
7a387fff 2716 case OPC_DSLL:
324d9e32 2717 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2718 break;
2719 case OPC_DSRA:
324d9e32 2720 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2721 break;
2722 case OPC_DSRL:
ea63e2c3 2723 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
2724 break;
2725 case OPC_DROTR:
2726 if (uimm != 0) {
2727 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2728 } else {
2729 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2730 }
7a387fff
TS
2731 break;
2732 case OPC_DSLL32:
324d9e32 2733 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2734 break;
2735 case OPC_DSRA32:
324d9e32 2736 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2737 break;
2738 case OPC_DSRL32:
ea63e2c3 2739 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
2740 break;
2741 case OPC_DROTR32:
2742 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 2743 break;
7a387fff 2744#endif
6af0bf9c 2745 }
78723684 2746 tcg_temp_free(t0);
6af0bf9c
FB
2747}
2748
2749/* Arithmetic */
d75c135e
AJ
2750static void gen_arith(DisasContext *ctx, uint32_t opc,
2751 int rd, int rs, int rt)
6af0bf9c 2752{
7a387fff
TS
2753 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2754 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
2755 /*
2756 * If no destination, treat it as a NOP.
2757 * For add & sub, we must generate the overflow exception when needed.
2758 */
460f00c4 2759 return;
185f0762 2760 }
460f00c4 2761
6af0bf9c
FB
2762 switch (opc) {
2763 case OPC_ADD:
48d38ca5 2764 {
460f00c4
AJ
2765 TCGv t0 = tcg_temp_local_new();
2766 TCGv t1 = tcg_temp_new();
2767 TCGv t2 = tcg_temp_new();
42a268c2 2768 TCGLabel *l1 = gen_new_label();
48d38ca5 2769
460f00c4
AJ
2770 gen_load_gpr(t1, rs);
2771 gen_load_gpr(t2, rt);
2772 tcg_gen_add_tl(t0, t1, t2);
2773 tcg_gen_ext32s_tl(t0, t0);
2774 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2775 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2776 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2777 tcg_temp_free(t2);
2778 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2779 tcg_temp_free(t1);
48d38ca5
TS
2780 /* operands of same sign, result different sign */
2781 generate_exception(ctx, EXCP_OVERFLOW);
2782 gen_set_label(l1);
460f00c4
AJ
2783 gen_store_gpr(t0, rd);
2784 tcg_temp_free(t0);
48d38ca5 2785 }
6af0bf9c
FB
2786 break;
2787 case OPC_ADDU:
460f00c4
AJ
2788 if (rs != 0 && rt != 0) {
2789 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2790 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2791 } else if (rs == 0 && rt != 0) {
2792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2793 } else if (rs != 0 && rt == 0) {
2794 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2795 } else {
2796 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2797 }
6af0bf9c
FB
2798 break;
2799 case OPC_SUB:
48d38ca5 2800 {
460f00c4
AJ
2801 TCGv t0 = tcg_temp_local_new();
2802 TCGv t1 = tcg_temp_new();
2803 TCGv t2 = tcg_temp_new();
42a268c2 2804 TCGLabel *l1 = gen_new_label();
48d38ca5 2805
460f00c4
AJ
2806 gen_load_gpr(t1, rs);
2807 gen_load_gpr(t2, rt);
2808 tcg_gen_sub_tl(t0, t1, t2);
2809 tcg_gen_ext32s_tl(t0, t0);
2810 tcg_gen_xor_tl(t2, t1, t2);
2811 tcg_gen_xor_tl(t1, t0, t1);
2812 tcg_gen_and_tl(t1, t1, t2);
2813 tcg_temp_free(t2);
2814 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2815 tcg_temp_free(t1);
7480515f
AM
2816 /*
2817 * operands of different sign, first operand and the result
2818 * of different sign
2819 */
48d38ca5
TS
2820 generate_exception(ctx, EXCP_OVERFLOW);
2821 gen_set_label(l1);
460f00c4
AJ
2822 gen_store_gpr(t0, rd);
2823 tcg_temp_free(t0);
48d38ca5 2824 }
6af0bf9c
FB
2825 break;
2826 case OPC_SUBU:
460f00c4
AJ
2827 if (rs != 0 && rt != 0) {
2828 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2829 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2830 } else if (rs == 0 && rt != 0) {
2831 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2832 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2833 } else if (rs != 0 && rt == 0) {
2834 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2835 } else {
2836 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2837 }
6af0bf9c 2838 break;
d26bc211 2839#if defined(TARGET_MIPS64)
7a387fff 2840 case OPC_DADD:
48d38ca5 2841 {
460f00c4
AJ
2842 TCGv t0 = tcg_temp_local_new();
2843 TCGv t1 = tcg_temp_new();
2844 TCGv t2 = tcg_temp_new();
42a268c2 2845 TCGLabel *l1 = gen_new_label();
48d38ca5 2846
460f00c4
AJ
2847 gen_load_gpr(t1, rs);
2848 gen_load_gpr(t2, rt);
2849 tcg_gen_add_tl(t0, t1, t2);
2850 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2851 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2852 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2853 tcg_temp_free(t2);
2854 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2855 tcg_temp_free(t1);
48d38ca5
TS
2856 /* operands of same sign, result different sign */
2857 generate_exception(ctx, EXCP_OVERFLOW);
2858 gen_set_label(l1);
460f00c4
AJ
2859 gen_store_gpr(t0, rd);
2860 tcg_temp_free(t0);
48d38ca5 2861 }
7a387fff
TS
2862 break;
2863 case OPC_DADDU:
460f00c4
AJ
2864 if (rs != 0 && rt != 0) {
2865 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2866 } else if (rs == 0 && rt != 0) {
2867 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2868 } else if (rs != 0 && rt == 0) {
2869 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2870 } else {
2871 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2872 }
7a387fff
TS
2873 break;
2874 case OPC_DSUB:
48d38ca5 2875 {
460f00c4
AJ
2876 TCGv t0 = tcg_temp_local_new();
2877 TCGv t1 = tcg_temp_new();
2878 TCGv t2 = tcg_temp_new();
42a268c2 2879 TCGLabel *l1 = gen_new_label();
48d38ca5 2880
460f00c4
AJ
2881 gen_load_gpr(t1, rs);
2882 gen_load_gpr(t2, rt);
2883 tcg_gen_sub_tl(t0, t1, t2);
2884 tcg_gen_xor_tl(t2, t1, t2);
2885 tcg_gen_xor_tl(t1, t0, t1);
2886 tcg_gen_and_tl(t1, t1, t2);
2887 tcg_temp_free(t2);
2888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2889 tcg_temp_free(t1);
71375b59
AM
2890 /*
2891 * Operands of different sign, first operand and result different
2892 * sign.
2893 */
48d38ca5
TS
2894 generate_exception(ctx, EXCP_OVERFLOW);
2895 gen_set_label(l1);
460f00c4
AJ
2896 gen_store_gpr(t0, rd);
2897 tcg_temp_free(t0);
48d38ca5 2898 }
7a387fff
TS
2899 break;
2900 case OPC_DSUBU:
460f00c4
AJ
2901 if (rs != 0 && rt != 0) {
2902 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2903 } else if (rs == 0 && rt != 0) {
2904 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2905 } else if (rs != 0 && rt == 0) {
2906 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2907 } else {
2908 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2909 }
7a387fff
TS
2910 break;
2911#endif
460f00c4
AJ
2912 case OPC_MUL:
2913 if (likely(rs != 0 && rt != 0)) {
2914 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2915 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2916 } else {
2917 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2918 }
6af0bf9c 2919 break;
460f00c4 2920 }
460f00c4
AJ
2921}
2922
2923/* Conditional move */
d75c135e 2924static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 2925 int rd, int rs, int rt)
460f00c4 2926{
acf12465 2927 TCGv t0, t1, t2;
460f00c4
AJ
2928
2929 if (rd == 0) {
acf12465 2930 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2931 return;
2932 }
2933
acf12465
AJ
2934 t0 = tcg_temp_new();
2935 gen_load_gpr(t0, rt);
2936 t1 = tcg_const_tl(0);
2937 t2 = tcg_temp_new();
2938 gen_load_gpr(t2, rs);
460f00c4
AJ
2939 switch (opc) {
2940 case OPC_MOVN:
acf12465 2941 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 2942 break;
460f00c4 2943 case OPC_MOVZ:
acf12465 2944 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 2945 break;
b691d9d2
LA
2946 case OPC_SELNEZ:
2947 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
2948 break;
2949 case OPC_SELEQZ:
2950 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 2951 break;
460f00c4 2952 }
acf12465
AJ
2953 tcg_temp_free(t2);
2954 tcg_temp_free(t1);
2955 tcg_temp_free(t0);
460f00c4
AJ
2956}
2957
2958/* Logic */
d75c135e 2959static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 2960 int rd, int rs, int rt)
460f00c4 2961{
460f00c4
AJ
2962 if (rd == 0) {
2963 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2964 return;
2965 }
2966
2967 switch (opc) {
6af0bf9c 2968 case OPC_AND:
460f00c4
AJ
2969 if (likely(rs != 0 && rt != 0)) {
2970 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2971 } else {
2972 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2973 }
6af0bf9c
FB
2974 break;
2975 case OPC_NOR:
460f00c4
AJ
2976 if (rs != 0 && rt != 0) {
2977 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2978 } else if (rs == 0 && rt != 0) {
2979 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2980 } else if (rs != 0 && rt == 0) {
2981 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2982 } else {
2983 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2984 }
6af0bf9c
FB
2985 break;
2986 case OPC_OR:
460f00c4
AJ
2987 if (likely(rs != 0 && rt != 0)) {
2988 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2989 } else if (rs == 0 && rt != 0) {
2990 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2991 } else if (rs != 0 && rt == 0) {
2992 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2993 } else {
2994 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2995 }
6af0bf9c
FB
2996 break;
2997 case OPC_XOR:
460f00c4
AJ
2998 if (likely(rs != 0 && rt != 0)) {
2999 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3000 } else if (rs == 0 && rt != 0) {
3001 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3002 } else if (rs != 0 && rt == 0) {
3003 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3004 } else {
3005 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3006 }
6af0bf9c 3007 break;
460f00c4 3008 }
460f00c4
AJ
3009}
3010
3011/* Set on lower than */
d75c135e 3012static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 3013 int rd, int rs, int rt)
460f00c4 3014{
460f00c4
AJ
3015 TCGv t0, t1;
3016
3017 if (rd == 0) {
3018 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3019 return;
3020 }
3021
3022 t0 = tcg_temp_new();
3023 t1 = tcg_temp_new();
3024 gen_load_gpr(t0, rs);
3025 gen_load_gpr(t1, rt);
3026 switch (opc) {
3027 case OPC_SLT:
e68dd28f 3028 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 3029 break;
460f00c4 3030 case OPC_SLTU:
e68dd28f 3031 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
3032 break;
3033 }
460f00c4
AJ
3034 tcg_temp_free(t0);
3035 tcg_temp_free(t1);
3036}
20c4c97c 3037
460f00c4 3038/* Shifts */
d75c135e
AJ
3039static void gen_shift(DisasContext *ctx, uint32_t opc,
3040 int rd, int rs, int rt)
460f00c4 3041{
460f00c4 3042 TCGv t0, t1;
20c4c97c 3043
460f00c4 3044 if (rd == 0) {
7480515f
AM
3045 /*
3046 * If no destination, treat it as a NOP.
3047 * For add & sub, we must generate the overflow exception when needed.
3048 */
460f00c4
AJ
3049 return;
3050 }
3051
3052 t0 = tcg_temp_new();
3053 t1 = tcg_temp_new();
3054 gen_load_gpr(t0, rs);
3055 gen_load_gpr(t1, rt);
3056 switch (opc) {
6af0bf9c 3057 case OPC_SLLV:
78723684
TS
3058 tcg_gen_andi_tl(t0, t0, 0x1f);
3059 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 3060 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
3061 break;
3062 case OPC_SRAV:
78723684 3063 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 3064 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
3065 break;
3066 case OPC_SRLV:
ea63e2c3
NF
3067 tcg_gen_ext32u_tl(t1, t1);
3068 tcg_gen_andi_tl(t0, t0, 0x1f);
3069 tcg_gen_shr_tl(t0, t1, t0);
3070 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
3071 break;
3072 case OPC_ROTRV:
3073 {
3074 TCGv_i32 t2 = tcg_temp_new_i32();
3075 TCGv_i32 t3 = tcg_temp_new_i32();
3076
3077 tcg_gen_trunc_tl_i32(t2, t0);
3078 tcg_gen_trunc_tl_i32(t3, t1);
3079 tcg_gen_andi_i32(t2, t2, 0x1f);
3080 tcg_gen_rotr_i32(t2, t3, t2);
3081 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3082 tcg_temp_free_i32(t2);
3083 tcg_temp_free_i32(t3);
5a63bcb2 3084 }
7a387fff 3085 break;
d26bc211 3086#if defined(TARGET_MIPS64)
7a387fff 3087 case OPC_DSLLV:
78723684 3088 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3089 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3090 break;
3091 case OPC_DSRAV:
78723684 3092 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3093 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3094 break;
3095 case OPC_DSRLV:
ea63e2c3
NF
3096 tcg_gen_andi_tl(t0, t0, 0x3f);
3097 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
3098 break;
3099 case OPC_DROTRV:
3100 tcg_gen_andi_tl(t0, t0, 0x3f);
3101 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 3102 break;
7a387fff 3103#endif
6af0bf9c 3104 }
78723684
TS
3105 tcg_temp_free(t0);
3106 tcg_temp_free(t1);
6af0bf9c
FB
3107}
3108
3109/* Arithmetic on HI/LO registers */
26135ead 3110static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 3111{
86efbfb6 3112 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 3113 /* Treat as NOP. */
a1f6684d 3114 return;
6af0bf9c 3115 }
4133498f 3116
4133498f 3117 if (acc != 0) {
86efbfb6 3118 check_dsp(ctx);
4133498f
JL
3119 }
3120
6af0bf9c
FB
3121 switch (opc) {
3122 case OPC_MFHI:
4133498f
JL
3123#if defined(TARGET_MIPS64)
3124 if (acc != 0) {
3125 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3126 } else
3127#endif
3128 {
3129 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3130 }
6af0bf9c
FB
3131 break;
3132 case OPC_MFLO:
4133498f
JL
3133#if defined(TARGET_MIPS64)
3134 if (acc != 0) {
3135 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3136 } else
3137#endif
3138 {
3139 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3140 }
6af0bf9c
FB
3141 break;
3142 case OPC_MTHI:
4133498f
JL
3143 if (reg != 0) {
3144#if defined(TARGET_MIPS64)
3145 if (acc != 0) {
3146 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3147 } else
3148#endif
3149 {
3150 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3151 }
3152 } else {
3153 tcg_gen_movi_tl(cpu_HI[acc], 0);
3154 }
6af0bf9c
FB
3155 break;
3156 case OPC_MTLO:
4133498f
JL
3157 if (reg != 0) {
3158#if defined(TARGET_MIPS64)
3159 if (acc != 0) {
3160 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3161 } else
3162#endif
3163 {
3164 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3165 }
3166 } else {
3167 tcg_gen_movi_tl(cpu_LO[acc], 0);
3168 }
6af0bf9c 3169 break;
6af0bf9c 3170 }
6af0bf9c
FB
3171}
3172
d4ea6acd 3173static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 3174 MemOp memop)
d4ea6acd
LA
3175{
3176 TCGv t0 = tcg_const_tl(addr);
3177 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3178 gen_store_gpr(t0, reg);
3179 tcg_temp_free(t0);
3180}
3181
ab39ee45
YK
3182static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3183 int rs)
d4ea6acd
LA
3184{
3185 target_long offset;
3186 target_long addr;
3187
ab39ee45 3188 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
3189 case OPC_ADDIUPC:
3190 if (rs != 0) {
3191 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3192 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3193 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3194 }
3195 break;
3196 case R6_OPC_LWPC:
3197 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3198 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3199 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3200 break;
3201#if defined(TARGET_MIPS64)
3202 case OPC_LWUPC:
3203 check_mips_64(ctx);
3204 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3205 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3206 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3207 break;
3208#endif
3209 default:
ab39ee45 3210 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
3211 case OPC_AUIPC:
3212 if (rs != 0) {
ab39ee45
YK
3213 offset = sextract32(ctx->opcode, 0, 16) << 16;
3214 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3215 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3216 }
3217 break;
3218 case OPC_ALUIPC:
3219 if (rs != 0) {
ab39ee45
YK
3220 offset = sextract32(ctx->opcode, 0, 16) << 16;
3221 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
3222 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3223 }
3224 break;
3225#if defined(TARGET_MIPS64)
3226 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3227 case R6_OPC_LDPC + (1 << 16):
3228 case R6_OPC_LDPC + (2 << 16):
3229 case R6_OPC_LDPC + (3 << 16):
3230 check_mips_64(ctx);
3231 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 3232 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
3233 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3234 break;
3235#endif
3236 default:
3237 MIPS_INVAL("OPC_PCREL");
3a4ef3b7 3238 gen_reserved_instruction(ctx);
d4ea6acd
LA
3239 break;
3240 }
3241 break;
3242 }
3243}
3244
b42ee5e1
LA
3245static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3246{
b42ee5e1
LA
3247 TCGv t0, t1;
3248
3249 if (rd == 0) {
3250 /* Treat as NOP. */
b42ee5e1
LA
3251 return;
3252 }
3253
3254 t0 = tcg_temp_new();
3255 t1 = tcg_temp_new();
3256
3257 gen_load_gpr(t0, rs);
3258 gen_load_gpr(t1, rt);
3259
3260 switch (opc) {
3261 case R6_OPC_DIV:
3262 {
3263 TCGv t2 = tcg_temp_new();
3264 TCGv t3 = tcg_temp_new();
3265 tcg_gen_ext32s_tl(t0, t0);
3266 tcg_gen_ext32s_tl(t1, t1);
3267 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3268 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3269 tcg_gen_and_tl(t2, t2, t3);
3270 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3271 tcg_gen_or_tl(t2, t2, t3);
3272 tcg_gen_movi_tl(t3, 0);
3273 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3274 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3275 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3276 tcg_temp_free(t3);
3277 tcg_temp_free(t2);
3278 }
b42ee5e1
LA
3279 break;
3280 case R6_OPC_MOD:
3281 {
3282 TCGv t2 = tcg_temp_new();
3283 TCGv t3 = tcg_temp_new();
3284 tcg_gen_ext32s_tl(t0, t0);
3285 tcg_gen_ext32s_tl(t1, t1);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3287 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3288 tcg_gen_and_tl(t2, t2, t3);
3289 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3290 tcg_gen_or_tl(t2, t2, t3);
3291 tcg_gen_movi_tl(t3, 0);
3292 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3293 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3294 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3295 tcg_temp_free(t3);
3296 tcg_temp_free(t2);
3297 }
b42ee5e1
LA
3298 break;
3299 case R6_OPC_DIVU:
3300 {
3301 TCGv t2 = tcg_const_tl(0);
3302 TCGv t3 = tcg_const_tl(1);
3303 tcg_gen_ext32u_tl(t0, t0);
3304 tcg_gen_ext32u_tl(t1, t1);
3305 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3306 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3307 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3308 tcg_temp_free(t3);
3309 tcg_temp_free(t2);
3310 }
b42ee5e1
LA
3311 break;
3312 case R6_OPC_MODU:
3313 {
3314 TCGv t2 = tcg_const_tl(0);
3315 TCGv t3 = tcg_const_tl(1);
3316 tcg_gen_ext32u_tl(t0, t0);
3317 tcg_gen_ext32u_tl(t1, t1);
3318 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3319 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3320 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3321 tcg_temp_free(t3);
3322 tcg_temp_free(t2);
3323 }
b42ee5e1
LA
3324 break;
3325 case R6_OPC_MUL:
3326 {
3327 TCGv_i32 t2 = tcg_temp_new_i32();
3328 TCGv_i32 t3 = tcg_temp_new_i32();
3329 tcg_gen_trunc_tl_i32(t2, t0);
3330 tcg_gen_trunc_tl_i32(t3, t1);
3331 tcg_gen_mul_i32(t2, t2, t3);
3332 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3333 tcg_temp_free_i32(t2);
3334 tcg_temp_free_i32(t3);
3335 }
b42ee5e1
LA
3336 break;
3337 case R6_OPC_MUH:
3338 {
3339 TCGv_i32 t2 = tcg_temp_new_i32();
3340 TCGv_i32 t3 = tcg_temp_new_i32();
3341 tcg_gen_trunc_tl_i32(t2, t0);
3342 tcg_gen_trunc_tl_i32(t3, t1);
3343 tcg_gen_muls2_i32(t2, t3, t2, t3);
3344 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3345 tcg_temp_free_i32(t2);
3346 tcg_temp_free_i32(t3);
3347 }
b42ee5e1
LA
3348 break;
3349 case R6_OPC_MULU:
3350 {
3351 TCGv_i32 t2 = tcg_temp_new_i32();
3352 TCGv_i32 t3 = tcg_temp_new_i32();
3353 tcg_gen_trunc_tl_i32(t2, t0);
3354 tcg_gen_trunc_tl_i32(t3, t1);
3355 tcg_gen_mul_i32(t2, t2, t3);
3356 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3357 tcg_temp_free_i32(t2);
3358 tcg_temp_free_i32(t3);
3359 }
b42ee5e1
LA
3360 break;
3361 case R6_OPC_MUHU:
3362 {
3363 TCGv_i32 t2 = tcg_temp_new_i32();
3364 TCGv_i32 t3 = tcg_temp_new_i32();
3365 tcg_gen_trunc_tl_i32(t2, t0);
3366 tcg_gen_trunc_tl_i32(t3, t1);
3367 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3368 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3369 tcg_temp_free_i32(t2);
3370 tcg_temp_free_i32(t3);
3371 }
b42ee5e1
LA
3372 break;
3373#if defined(TARGET_MIPS64)
3374 case R6_OPC_DDIV:
3375 {
3376 TCGv t2 = tcg_temp_new();
3377 TCGv t3 = tcg_temp_new();
3378 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3380 tcg_gen_and_tl(t2, t2, t3);
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3382 tcg_gen_or_tl(t2, t2, t3);
3383 tcg_gen_movi_tl(t3, 0);
3384 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3385 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3386 tcg_temp_free(t3);
3387 tcg_temp_free(t2);
3388 }
b42ee5e1
LA
3389 break;
3390 case R6_OPC_DMOD:
3391 {
3392 TCGv t2 = tcg_temp_new();
3393 TCGv t3 = tcg_temp_new();
3394 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3395 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3396 tcg_gen_and_tl(t2, t2, t3);
3397 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3398 tcg_gen_or_tl(t2, t2, t3);
3399 tcg_gen_movi_tl(t3, 0);
3400 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3401 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3402 tcg_temp_free(t3);
3403 tcg_temp_free(t2);
3404 }
b42ee5e1
LA
3405 break;
3406 case R6_OPC_DDIVU:
3407 {
3408 TCGv t2 = tcg_const_tl(0);
3409 TCGv t3 = tcg_const_tl(1);
3410 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3411 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3412 tcg_temp_free(t3);
3413 tcg_temp_free(t2);
3414 }
b42ee5e1
LA
3415 break;
3416 case R6_OPC_DMODU:
3417 {
3418 TCGv t2 = tcg_const_tl(0);
3419 TCGv t3 = tcg_const_tl(1);
3420 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3421 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3422 tcg_temp_free(t3);
3423 tcg_temp_free(t2);
3424 }
b42ee5e1
LA
3425 break;
3426 case R6_OPC_DMUL:
3427 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3428 break;
3429 case R6_OPC_DMUH:
3430 {
3431 TCGv t2 = tcg_temp_new();
3432 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3433 tcg_temp_free(t2);
3434 }
b42ee5e1
LA
3435 break;
3436 case R6_OPC_DMULU:
3437 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3438 break;
3439 case R6_OPC_DMUHU:
3440 {
3441 TCGv t2 = tcg_temp_new();
3442 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3443 tcg_temp_free(t2);
3444 }
b42ee5e1
LA
3445 break;
3446#endif
3447 default:
9d68ac14 3448 MIPS_INVAL("r6 mul/div");
3a4ef3b7 3449 gen_reserved_instruction(ctx);
b42ee5e1
LA
3450 goto out;
3451 }
b42ee5e1
LA
3452 out:
3453 tcg_temp_free(t0);
3454 tcg_temp_free(t1);
3455}
3456
37b9aae2 3457#if defined(TARGET_MIPS64)
c42171c3
FN
3458static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3459{
3460 TCGv t0, t1;
3461
3462 t0 = tcg_temp_new();
3463 t1 = tcg_temp_new();
3464
3465 gen_load_gpr(t0, rs);
3466 gen_load_gpr(t1, rt);
3467
3468 switch (opc) {
baa609db 3469 case MMI_OPC_DIV1:
c42171c3
FN
3470 {
3471 TCGv t2 = tcg_temp_new();
3472 TCGv t3 = tcg_temp_new();
3473 tcg_gen_ext32s_tl(t0, t0);
3474 tcg_gen_ext32s_tl(t1, t1);
3475 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3477 tcg_gen_and_tl(t2, t2, t3);
3478 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3479 tcg_gen_or_tl(t2, t2, t3);
3480 tcg_gen_movi_tl(t3, 0);
3481 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3482 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3483 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3484 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3485 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3486 tcg_temp_free(t3);
3487 tcg_temp_free(t2);
3488 }
3489 break;
baa609db 3490 case MMI_OPC_DIVU1:
c42171c3
FN
3491 {
3492 TCGv t2 = tcg_const_tl(0);
3493 TCGv t3 = tcg_const_tl(1);
3494 tcg_gen_ext32u_tl(t0, t0);
3495 tcg_gen_ext32u_tl(t1, t1);
3496 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3497 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3498 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3499 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3500 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3501 tcg_temp_free(t3);
3502 tcg_temp_free(t2);
3503 }
3504 break;
3505 default:
3506 MIPS_INVAL("div1 TX79");
3a4ef3b7 3507 gen_reserved_instruction(ctx);
c42171c3
FN
3508 goto out;
3509 }
3510 out:
3511 tcg_temp_free(t0);
3512 tcg_temp_free(t1);
3513}
37b9aae2 3514#endif
c42171c3 3515
26135ead
RS
3516static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3517 int acc, int rs, int rt)
6af0bf9c 3518{
d45f89f4
AJ
3519 TCGv t0, t1;
3520
51127181
AJ
3521 t0 = tcg_temp_new();
3522 t1 = tcg_temp_new();
6af0bf9c 3523
78723684
TS
3524 gen_load_gpr(t0, rs);
3525 gen_load_gpr(t1, rt);
51127181 3526
26135ead 3527 if (acc != 0) {
c42171c3 3528 check_dsp(ctx);
26135ead
RS
3529 }
3530
6af0bf9c
FB
3531 switch (opc) {
3532 case OPC_DIV:
48d38ca5 3533 {
51127181
AJ
3534 TCGv t2 = tcg_temp_new();
3535 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3536 tcg_gen_ext32s_tl(t0, t0);
3537 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3538 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3539 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3540 tcg_gen_and_tl(t2, t2, t3);
3541 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3542 tcg_gen_or_tl(t2, t2, t3);
3543 tcg_gen_movi_tl(t3, 0);
3544 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3545 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3546 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3547 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3548 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3549 tcg_temp_free(t3);
3550 tcg_temp_free(t2);
48d38ca5 3551 }
6af0bf9c
FB
3552 break;
3553 case OPC_DIVU:
48d38ca5 3554 {
51127181
AJ
3555 TCGv t2 = tcg_const_tl(0);
3556 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
3557 tcg_gen_ext32u_tl(t0, t0);
3558 tcg_gen_ext32u_tl(t1, t1);
51127181 3559 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3560 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3561 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3562 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3563 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3564 tcg_temp_free(t3);
3565 tcg_temp_free(t2);
48d38ca5 3566 }
6af0bf9c
FB
3567 break;
3568 case OPC_MULT:
214c465f 3569 {
ce1dd5d1
RH
3570 TCGv_i32 t2 = tcg_temp_new_i32();
3571 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3572 tcg_gen_trunc_tl_i32(t2, t0);
3573 tcg_gen_trunc_tl_i32(t3, t1);
3574 tcg_gen_muls2_i32(t2, t3, t2, t3);
3575 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3576 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3577 tcg_temp_free_i32(t2);
3578 tcg_temp_free_i32(t3);
214c465f 3579 }
6af0bf9c
FB
3580 break;
3581 case OPC_MULTU:
214c465f 3582 {
ce1dd5d1
RH
3583 TCGv_i32 t2 = tcg_temp_new_i32();
3584 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3585 tcg_gen_trunc_tl_i32(t2, t0);
3586 tcg_gen_trunc_tl_i32(t3, t1);
3587 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3588 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3589 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3590 tcg_temp_free_i32(t2);
3591 tcg_temp_free_i32(t3);
214c465f 3592 }
6af0bf9c 3593 break;
d26bc211 3594#if defined(TARGET_MIPS64)
7a387fff 3595 case OPC_DDIV:
48d38ca5 3596 {
51127181
AJ
3597 TCGv t2 = tcg_temp_new();
3598 TCGv t3 = tcg_temp_new();
3599 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3600 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3601 tcg_gen_and_tl(t2, t2, t3);
3602 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3603 tcg_gen_or_tl(t2, t2, t3);
3604 tcg_gen_movi_tl(t3, 0);
3605 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3606 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3607 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
3608 tcg_temp_free(t3);
3609 tcg_temp_free(t2);
48d38ca5 3610 }
7a387fff
TS
3611 break;
3612 case OPC_DDIVU:
48d38ca5 3613 {
51127181
AJ
3614 TCGv t2 = tcg_const_tl(0);
3615 TCGv t3 = tcg_const_tl(1);
3616 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3617 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3618 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
3619 tcg_temp_free(t3);
3620 tcg_temp_free(t2);
48d38ca5 3621 }
7a387fff
TS
3622 break;
3623 case OPC_DMULT:
26135ead 3624 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3625 break;
3626 case OPC_DMULTU:
26135ead 3627 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3628 break;
3629#endif
6af0bf9c 3630 case OPC_MADD:
214c465f 3631 {
d45f89f4
AJ
3632 TCGv_i64 t2 = tcg_temp_new_i64();
3633 TCGv_i64 t3 = tcg_temp_new_i64();
3634
3635 tcg_gen_ext_tl_i64(t2, t0);
3636 tcg_gen_ext_tl_i64(t3, t1);
3637 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3638 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3639 tcg_gen_add_i64(t2, t2, t3);
3640 tcg_temp_free_i64(t3);
71f303cd
RH
3641 gen_move_low32(cpu_LO[acc], t2);
3642 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3643 tcg_temp_free_i64(t2);
214c465f 3644 }
6af0bf9c
FB
3645 break;
3646 case OPC_MADDU:
4133498f 3647 {
d45f89f4
AJ
3648 TCGv_i64 t2 = tcg_temp_new_i64();
3649 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3650
78723684
TS
3651 tcg_gen_ext32u_tl(t0, t0);
3652 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3653 tcg_gen_extu_tl_i64(t2, t0);
3654 tcg_gen_extu_tl_i64(t3, t1);
3655 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3656 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3657 tcg_gen_add_i64(t2, t2, t3);
3658 tcg_temp_free_i64(t3);
71f303cd
RH
3659 gen_move_low32(cpu_LO[acc], t2);
3660 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3661 tcg_temp_free_i64(t2);
214c465f 3662 }
6af0bf9c
FB
3663 break;
3664 case OPC_MSUB:
214c465f 3665 {
d45f89f4
AJ
3666 TCGv_i64 t2 = tcg_temp_new_i64();
3667 TCGv_i64 t3 = tcg_temp_new_i64();
3668
3669 tcg_gen_ext_tl_i64(t2, t0);
3670 tcg_gen_ext_tl_i64(t3, t1);
3671 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3672 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3673 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3674 tcg_temp_free_i64(t3);
71f303cd
RH
3675 gen_move_low32(cpu_LO[acc], t2);
3676 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3677 tcg_temp_free_i64(t2);
214c465f 3678 }
6af0bf9c
FB
3679 break;
3680 case OPC_MSUBU:
214c465f 3681 {
d45f89f4
AJ
3682 TCGv_i64 t2 = tcg_temp_new_i64();
3683 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3684
78723684
TS
3685 tcg_gen_ext32u_tl(t0, t0);
3686 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3687 tcg_gen_extu_tl_i64(t2, t0);
3688 tcg_gen_extu_tl_i64(t3, t1);
3689 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3690 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3691 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3692 tcg_temp_free_i64(t3);
71f303cd
RH
3693 gen_move_low32(cpu_LO[acc], t2);
3694 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3695 tcg_temp_free_i64(t2);
214c465f 3696 }
6af0bf9c
FB
3697 break;
3698 default:
9d68ac14 3699 MIPS_INVAL("mul/div");
3a4ef3b7 3700 gen_reserved_instruction(ctx);
78723684 3701 goto out;
6af0bf9c 3702 }
78723684
TS
3703 out:
3704 tcg_temp_free(t0);
3705 tcg_temp_free(t1);
6af0bf9c
FB
3706}
3707
21e8e8b2 3708/*
3b948f05
PMD
3709 * These MULT[U] and MADD[U] instructions implemented in for example
3710 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
3711 * architectures are special three-operand variants with the syntax
3712 *
06de726b 3713 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
3714 *
3715 * such that
3716 *
3717 * (rd, LO, HI) <- rs * rt
3718 *
3b948f05
PMD
3719 * and
3720 *
a95c4c26 3721 * MADD[U][1] rd, rs, rt
3b948f05
PMD
3722 *
3723 * such that
3724 *
3725 * (rd, LO, HI) <- (LO, HI) + rs * rt
3726 *
21e8e8b2
FN
3727 * where the low-order 32-bits of the result is placed into both the
3728 * GPR rd and the special register LO. The high-order 32-bits of the
3729 * result is placed into the special register HI.
3730 *
3731 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3732 * which is the zero register that always reads as 0.
3733 */
3734static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3735 int rd, int rs, int rt)
3736{
3737 TCGv t0 = tcg_temp_new();
3738 TCGv t1 = tcg_temp_new();
3739 int acc = 0;
3740
3741 gen_load_gpr(t0, rs);
3742 gen_load_gpr(t1, rt);
3743
3744 switch (opc) {
baa609db 3745 case MMI_OPC_MULT1:
06de726b
FN
3746 acc = 1;
3747 /* Fall through */
21e8e8b2
FN
3748 case OPC_MULT:
3749 {
3750 TCGv_i32 t2 = tcg_temp_new_i32();
3751 TCGv_i32 t3 = tcg_temp_new_i32();
3752 tcg_gen_trunc_tl_i32(t2, t0);
3753 tcg_gen_trunc_tl_i32(t3, t1);
3754 tcg_gen_muls2_i32(t2, t3, t2, t3);
3755 if (rd) {
3756 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3757 }
3758 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3759 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3760 tcg_temp_free_i32(t2);
3761 tcg_temp_free_i32(t3);
3762 }
3763 break;
baa609db 3764 case MMI_OPC_MULTU1:
06de726b
FN
3765 acc = 1;
3766 /* Fall through */
21e8e8b2
FN
3767 case OPC_MULTU:
3768 {
3769 TCGv_i32 t2 = tcg_temp_new_i32();
3770 TCGv_i32 t3 = tcg_temp_new_i32();
3771 tcg_gen_trunc_tl_i32(t2, t0);
3772 tcg_gen_trunc_tl_i32(t3, t1);
3773 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3774 if (rd) {
3775 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3776 }
3777 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3778 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3779 tcg_temp_free_i32(t2);
3780 tcg_temp_free_i32(t3);
3781 }
3782 break;
a95c4c26
FN
3783 case MMI_OPC_MADD1:
3784 acc = 1;
3785 /* Fall through */
3b948f05
PMD
3786 case MMI_OPC_MADD:
3787 {
3788 TCGv_i64 t2 = tcg_temp_new_i64();
3789 TCGv_i64 t3 = tcg_temp_new_i64();
3790
3791 tcg_gen_ext_tl_i64(t2, t0);
3792 tcg_gen_ext_tl_i64(t3, t1);
3793 tcg_gen_mul_i64(t2, t2, t3);
3794 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3795 tcg_gen_add_i64(t2, t2, t3);
3796 tcg_temp_free_i64(t3);
3797 gen_move_low32(cpu_LO[acc], t2);
3798 gen_move_high32(cpu_HI[acc], t2);
3799 if (rd) {
3800 gen_move_low32(cpu_gpr[rd], t2);
3801 }
3802 tcg_temp_free_i64(t2);
3803 }
3804 break;
a95c4c26
FN
3805 case MMI_OPC_MADDU1:
3806 acc = 1;
3807 /* Fall through */
3b948f05
PMD
3808 case MMI_OPC_MADDU:
3809 {
3810 TCGv_i64 t2 = tcg_temp_new_i64();
3811 TCGv_i64 t3 = tcg_temp_new_i64();
3812
3813 tcg_gen_ext32u_tl(t0, t0);
3814 tcg_gen_ext32u_tl(t1, t1);
3815 tcg_gen_extu_tl_i64(t2, t0);
3816 tcg_gen_extu_tl_i64(t3, t1);
3817 tcg_gen_mul_i64(t2, t2, t3);
3818 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3819 tcg_gen_add_i64(t2, t2, t3);
3820 tcg_temp_free_i64(t3);
3821 gen_move_low32(cpu_LO[acc], t2);
3822 gen_move_high32(cpu_HI[acc], t2);
3823 if (rd) {
3824 gen_move_low32(cpu_gpr[rd], t2);
3825 }
3826 tcg_temp_free_i64(t2);
3827 }
3828 break;
21e8e8b2 3829 default:
3b948f05 3830 MIPS_INVAL("mul/madd TXx9");
3a4ef3b7 3831 gen_reserved_instruction(ctx);
21e8e8b2
FN
3832 goto out;
3833 }
3834
3835 out:
3836 tcg_temp_free(t0);
3837 tcg_temp_free(t1);
3838}
3839
235785e8
AM
3840static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3841 int rd, int rs, int rt)
e9c71dd1 3842{
f157bfe1
AJ
3843 TCGv t0 = tcg_temp_new();
3844 TCGv t1 = tcg_temp_new();
e9c71dd1 3845
6c5c1e20
TS
3846 gen_load_gpr(t0, rs);
3847 gen_load_gpr(t1, rt);
e9c71dd1
TS
3848
3849 switch (opc) {
3850 case OPC_VR54XX_MULS:
895c2d04 3851 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 3852 break;
e9c71dd1 3853 case OPC_VR54XX_MULSU:
895c2d04 3854 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 3855 break;
e9c71dd1 3856 case OPC_VR54XX_MACC:
895c2d04 3857 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 3858 break;
e9c71dd1 3859 case OPC_VR54XX_MACCU:
895c2d04 3860 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 3861 break;
e9c71dd1 3862 case OPC_VR54XX_MSAC:
895c2d04 3863 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 3864 break;
e9c71dd1 3865 case OPC_VR54XX_MSACU:
895c2d04 3866 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 3867 break;
e9c71dd1 3868 case OPC_VR54XX_MULHI:
895c2d04 3869 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 3870 break;
e9c71dd1 3871 case OPC_VR54XX_MULHIU:
895c2d04 3872 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 3873 break;
e9c71dd1 3874 case OPC_VR54XX_MULSHI:
895c2d04 3875 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 3876 break;
e9c71dd1 3877 case OPC_VR54XX_MULSHIU:
895c2d04 3878 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 3879 break;
e9c71dd1 3880 case OPC_VR54XX_MACCHI:
895c2d04 3881 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 3882 break;
e9c71dd1 3883 case OPC_VR54XX_MACCHIU:
895c2d04 3884 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 3885 break;
e9c71dd1 3886 case OPC_VR54XX_MSACHI:
895c2d04 3887 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 3888 break;
e9c71dd1 3889 case OPC_VR54XX_MSACHIU:
895c2d04 3890 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 3891 break;
e9c71dd1
TS
3892 default:
3893 MIPS_INVAL("mul vr54xx");
3a4ef3b7 3894 gen_reserved_instruction(ctx);
6c5c1e20 3895 goto out;
e9c71dd1 3896 }
6c5c1e20 3897 gen_store_gpr(t0, rd);
6c5c1e20
TS
3898
3899 out:
3900 tcg_temp_free(t0);
3901 tcg_temp_free(t1);
e9c71dd1
TS
3902}
3903
235785e8
AM
3904static void gen_cl(DisasContext *ctx, uint32_t opc,
3905 int rd, int rs)
6af0bf9c 3906{
20e1fb52 3907 TCGv t0;
6c5c1e20 3908
6af0bf9c 3909 if (rd == 0) {
ead9360e 3910 /* Treat as NOP. */
20e1fb52 3911 return;
6af0bf9c 3912 }
1a0196c5 3913 t0 = cpu_gpr[rd];
6c5c1e20 3914 gen_load_gpr(t0, rs);
1a0196c5 3915
6af0bf9c
FB
3916 switch (opc) {
3917 case OPC_CLO:
4267d3e6 3918 case R6_OPC_CLO:
1a0196c5
RH
3919#if defined(TARGET_MIPS64)
3920 case OPC_DCLO:
3921 case R6_OPC_DCLO:
3922#endif
3923 tcg_gen_not_tl(t0, t0);
6af0bf9c 3924 break;
1a0196c5
RH
3925 }
3926
3927 switch (opc) {
3928 case OPC_CLO:
3929 case R6_OPC_CLO:
6af0bf9c 3930 case OPC_CLZ:
4267d3e6 3931 case R6_OPC_CLZ:
1a0196c5
RH
3932 tcg_gen_ext32u_tl(t0, t0);
3933 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3934 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 3935 break;
d26bc211 3936#if defined(TARGET_MIPS64)
7a387fff 3937 case OPC_DCLO:
4267d3e6 3938 case R6_OPC_DCLO:
7a387fff 3939 case OPC_DCLZ:
4267d3e6 3940 case R6_OPC_DCLZ:
1a0196c5 3941 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
3942 break;
3943#endif
6af0bf9c 3944 }
6af0bf9c
FB
3945}
3946
161f85e6 3947/* Godson integer instructions */
bd277fa1
RH
3948static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3949 int rd, int rs, int rt)
161f85e6 3950{
161f85e6
AJ
3951 TCGv t0, t1;
3952
3953 if (rd == 0) {
3954 /* Treat as NOP. */
161f85e6
AJ
3955 return;
3956 }
3957
3958 switch (opc) {
3959 case OPC_MULT_G_2E:
3960 case OPC_MULT_G_2F:
3961 case OPC_MULTU_G_2E:
3962 case OPC_MULTU_G_2F:
3963#if defined(TARGET_MIPS64)
3964 case OPC_DMULT_G_2E:
3965 case OPC_DMULT_G_2F:
3966 case OPC_DMULTU_G_2E:
3967 case OPC_DMULTU_G_2F:
3968#endif
3969 t0 = tcg_temp_new();
3970 t1 = tcg_temp_new();
3971 break;
3972 default:
3973 t0 = tcg_temp_local_new();
3974 t1 = tcg_temp_local_new();
3975 break;
3976 }
3977
3978 gen_load_gpr(t0, rs);
3979 gen_load_gpr(t1, rt);
3980
3981 switch (opc) {
3982 case OPC_MULT_G_2E:
3983 case OPC_MULT_G_2F:
3984 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3985 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3986 break;
3987 case OPC_MULTU_G_2E:
3988 case OPC_MULTU_G_2F:
3989 tcg_gen_ext32u_tl(t0, t0);
3990 tcg_gen_ext32u_tl(t1, t1);
3991 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3992 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3993 break;
3994 case OPC_DIV_G_2E:
3995 case OPC_DIV_G_2F:
3996 {
42a268c2
RH
3997 TCGLabel *l1 = gen_new_label();
3998 TCGLabel *l2 = gen_new_label();
3999 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4000 tcg_gen_ext32s_tl(t0, t0);
4001 tcg_gen_ext32s_tl(t1, t1);
4002 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4003 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4004 tcg_gen_br(l3);
4005 gen_set_label(l1);
4006 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4008 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4009 tcg_gen_br(l3);
4010 gen_set_label(l2);
4011 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4012 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4013 gen_set_label(l3);
4014 }
161f85e6
AJ
4015 break;
4016 case OPC_DIVU_G_2E:
4017 case OPC_DIVU_G_2F:
4018 {
42a268c2
RH
4019 TCGLabel *l1 = gen_new_label();
4020 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4021 tcg_gen_ext32u_tl(t0, t0);
4022 tcg_gen_ext32u_tl(t1, t1);
4023 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4024 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4025 tcg_gen_br(l2);
4026 gen_set_label(l1);
4027 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4028 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4029 gen_set_label(l2);
4030 }
161f85e6
AJ
4031 break;
4032 case OPC_MOD_G_2E:
4033 case OPC_MOD_G_2F:
4034 {
42a268c2
RH
4035 TCGLabel *l1 = gen_new_label();
4036 TCGLabel *l2 = gen_new_label();
4037 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4038 tcg_gen_ext32u_tl(t0, t0);
4039 tcg_gen_ext32u_tl(t1, t1);
4040 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4041 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4042 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4043 gen_set_label(l1);
4044 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4045 tcg_gen_br(l3);
4046 gen_set_label(l2);
4047 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4048 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4049 gen_set_label(l3);
4050 }
161f85e6
AJ
4051 break;
4052 case OPC_MODU_G_2E:
4053 case OPC_MODU_G_2F:
4054 {
42a268c2
RH
4055 TCGLabel *l1 = gen_new_label();
4056 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4057 tcg_gen_ext32u_tl(t0, t0);
4058 tcg_gen_ext32u_tl(t1, t1);
4059 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4061 tcg_gen_br(l2);
4062 gen_set_label(l1);
4063 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4064 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4065 gen_set_label(l2);
4066 }
161f85e6
AJ
4067 break;
4068#if defined(TARGET_MIPS64)
4069 case OPC_DMULT_G_2E:
4070 case OPC_DMULT_G_2F:
4071 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4072 break;
4073 case OPC_DMULTU_G_2E:
4074 case OPC_DMULTU_G_2F:
4075 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4076 break;
4077 case OPC_DDIV_G_2E:
4078 case OPC_DDIV_G_2F:
4079 {
42a268c2
RH
4080 TCGLabel *l1 = gen_new_label();
4081 TCGLabel *l2 = gen_new_label();
4082 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4083 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4084 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4085 tcg_gen_br(l3);
4086 gen_set_label(l1);
4087 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4088 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4089 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4090 tcg_gen_br(l3);
4091 gen_set_label(l2);
4092 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4093 gen_set_label(l3);
4094 }
161f85e6
AJ
4095 break;
4096 case OPC_DDIVU_G_2E:
4097 case OPC_DDIVU_G_2F:
4098 {
42a268c2
RH
4099 TCGLabel *l1 = gen_new_label();
4100 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4101 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4102 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4103 tcg_gen_br(l2);
4104 gen_set_label(l1);
4105 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4106 gen_set_label(l2);
4107 }
161f85e6
AJ
4108 break;
4109 case OPC_DMOD_G_2E:
4110 case OPC_DMOD_G_2F:
4111 {
42a268c2
RH
4112 TCGLabel *l1 = gen_new_label();
4113 TCGLabel *l2 = gen_new_label();
4114 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4115 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4116 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4117 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4118 gen_set_label(l1);
4119 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4120 tcg_gen_br(l3);
4121 gen_set_label(l2);
4122 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4123 gen_set_label(l3);
4124 }
161f85e6
AJ
4125 break;
4126 case OPC_DMODU_G_2E:
4127 case OPC_DMODU_G_2F:
4128 {
42a268c2
RH
4129 TCGLabel *l1 = gen_new_label();
4130 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4131 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4132 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4133 tcg_gen_br(l2);
4134 gen_set_label(l1);
4135 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4136 gen_set_label(l2);
4137 }
161f85e6
AJ
4138 break;
4139#endif
4140 }
4141
161f85e6
AJ
4142 tcg_temp_free(t0);
4143 tcg_temp_free(t1);
4144}
4145
bd277fa1
RH
4146/* Loongson multimedia instructions */
4147static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4148{
bd277fa1
RH
4149 uint32_t opc, shift_max;
4150 TCGv_i64 t0, t1;
84878f4c 4151 TCGCond cond;
bd277fa1 4152
8e2d5831 4153 opc = MASK_LMMI(ctx->opcode);
bd277fa1
RH
4154 switch (opc) {
4155 case OPC_ADD_CP2:
4156 case OPC_SUB_CP2:
4157 case OPC_DADD_CP2:
4158 case OPC_DSUB_CP2:
4159 t0 = tcg_temp_local_new_i64();
4160 t1 = tcg_temp_local_new_i64();
4161 break;
4162 default:
4163 t0 = tcg_temp_new_i64();
4164 t1 = tcg_temp_new_i64();
4165 break;
4166 }
4167
b5a587b6 4168 check_cp1_enabled(ctx);
bd277fa1
RH
4169 gen_load_fpr64(ctx, t0, rs);
4170 gen_load_fpr64(ctx, t1, rt);
4171
bd277fa1 4172 switch (opc) {
b1cf82f0
AM
4173 case OPC_PADDSH:
4174 gen_helper_paddsh(t0, t0, t1);
4175 break;
4176 case OPC_PADDUSH:
4177 gen_helper_paddush(t0, t0, t1);
4178 break;
4179 case OPC_PADDH:
4180 gen_helper_paddh(t0, t0, t1);
4181 break;
4182 case OPC_PADDW:
4183 gen_helper_paddw(t0, t0, t1);
4184 break;
4185 case OPC_PADDSB:
4186 gen_helper_paddsb(t0, t0, t1);
4187 break;
4188 case OPC_PADDUSB:
4189 gen_helper_paddusb(t0, t0, t1);
4190 break;
4191 case OPC_PADDB:
4192 gen_helper_paddb(t0, t0, t1);
4193 break;
4194
4195 case OPC_PSUBSH:
4196 gen_helper_psubsh(t0, t0, t1);
4197 break;
4198 case OPC_PSUBUSH:
4199 gen_helper_psubush(t0, t0, t1);
4200 break;
4201 case OPC_PSUBH:
4202 gen_helper_psubh(t0, t0, t1);
4203 break;
4204 case OPC_PSUBW:
4205 gen_helper_psubw(t0, t0, t1);
4206 break;
4207 case OPC_PSUBSB:
4208 gen_helper_psubsb(t0, t0, t1);
4209 break;
4210 case OPC_PSUBUSB:
4211 gen_helper_psubusb(t0, t0, t1);
4212 break;
4213 case OPC_PSUBB:
4214 gen_helper_psubb(t0, t0, t1);
4215 break;
4216
4217 case OPC_PSHUFH:
4218 gen_helper_pshufh(t0, t0, t1);
4219 break;
4220 case OPC_PACKSSWH:
4221 gen_helper_packsswh(t0, t0, t1);
4222 break;
4223 case OPC_PACKSSHB:
4224 gen_helper_packsshb(t0, t0, t1);
4225 break;
4226 case OPC_PACKUSHB:
4227 gen_helper_packushb(t0, t0, t1);
4228 break;
4229
4230 case OPC_PUNPCKLHW:
4231 gen_helper_punpcklhw(t0, t0, t1);
4232 break;
4233 case OPC_PUNPCKHHW:
4234 gen_helper_punpckhhw(t0, t0, t1);
4235 break;
4236 case OPC_PUNPCKLBH:
4237 gen_helper_punpcklbh(t0, t0, t1);
4238 break;
4239 case OPC_PUNPCKHBH:
4240 gen_helper_punpckhbh(t0, t0, t1);
4241 break;
4242 case OPC_PUNPCKLWD:
4243 gen_helper_punpcklwd(t0, t0, t1);
4244 break;
4245 case OPC_PUNPCKHWD:
4246 gen_helper_punpckhwd(t0, t0, t1);
4247 break;
4248
4249 case OPC_PAVGH:
4250 gen_helper_pavgh(t0, t0, t1);
4251 break;
4252 case OPC_PAVGB:
4253 gen_helper_pavgb(t0, t0, t1);
4254 break;
4255 case OPC_PMAXSH:
4256 gen_helper_pmaxsh(t0, t0, t1);
4257 break;
4258 case OPC_PMINSH:
4259 gen_helper_pminsh(t0, t0, t1);
4260 break;
4261 case OPC_PMAXUB:
4262 gen_helper_pmaxub(t0, t0, t1);
4263 break;
4264 case OPC_PMINUB:
4265 gen_helper_pminub(t0, t0, t1);
4266 break;
4267
4268 case OPC_PCMPEQW:
4269 gen_helper_pcmpeqw(t0, t0, t1);
4270 break;
4271 case OPC_PCMPGTW:
4272 gen_helper_pcmpgtw(t0, t0, t1);
4273 break;
4274 case OPC_PCMPEQH:
4275 gen_helper_pcmpeqh(t0, t0, t1);
4276 break;
4277 case OPC_PCMPGTH:
4278 gen_helper_pcmpgth(t0, t0, t1);
4279 break;
4280 case OPC_PCMPEQB:
4281 gen_helper_pcmpeqb(t0, t0, t1);
4282 break;
4283 case OPC_PCMPGTB:
4284 gen_helper_pcmpgtb(t0, t0, t1);
4285 break;
4286
4287 case OPC_PSLLW:
4288 gen_helper_psllw(t0, t0, t1);
4289 break;
4290 case OPC_PSLLH:
4291 gen_helper_psllh(t0, t0, t1);
4292 break;
4293 case OPC_PSRLW:
4294 gen_helper_psrlw(t0, t0, t1);
4295 break;
4296 case OPC_PSRLH:
4297 gen_helper_psrlh(t0, t0, t1);
4298 break;
4299 case OPC_PSRAW:
4300 gen_helper_psraw(t0, t0, t1);
4301 break;
4302 case OPC_PSRAH:
4303 gen_helper_psrah(t0, t0, t1);
4304 break;
4305
4306 case OPC_PMULLH:
4307 gen_helper_pmullh(t0, t0, t1);
4308 break;
4309 case OPC_PMULHH:
4310 gen_helper_pmulhh(t0, t0, t1);
4311 break;
4312 case OPC_PMULHUH:
4313 gen_helper_pmulhuh(t0, t0, t1);
4314 break;
4315 case OPC_PMADDHW:
4316 gen_helper_pmaddhw(t0, t0, t1);
4317 break;
4318
4319 case OPC_PASUBUB:
4320 gen_helper_pasubub(t0, t0, t1);
4321 break;
4322 case OPC_BIADD:
4323 gen_helper_biadd(t0, t0);
4324 break;
4325 case OPC_PMOVMSKB:
4326 gen_helper_pmovmskb(t0, t0);
4327 break;
4328
4329 case OPC_PADDD:
4330 tcg_gen_add_i64(t0, t0, t1);
4331 break;
4332 case OPC_PSUBD:
4333 tcg_gen_sub_i64(t0, t0, t1);
4334 break;
4335 case OPC_XOR_CP2:
4336 tcg_gen_xor_i64(t0, t0, t1);
4337 break;
4338 case OPC_NOR_CP2:
4339 tcg_gen_nor_i64(t0, t0, t1);
4340 break;
4341 case OPC_AND_CP2:
4342 tcg_gen_and_i64(t0, t0, t1);
4343 break;
4344 case OPC_OR_CP2:
4345 tcg_gen_or_i64(t0, t0, t1);
4346 break;
bd277fa1 4347
9099a36b
H
4348 case OPC_PANDN:
4349 tcg_gen_andc_i64(t0, t1, t0);
4350 break;
4351
bd277fa1
RH
4352 case OPC_PINSRH_0:
4353 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
4354 break;
4355 case OPC_PINSRH_1:
4356 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
4357 break;
4358 case OPC_PINSRH_2:
4359 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
4360 break;
4361 case OPC_PINSRH_3:
4362 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
4363 break;
4364
4365 case OPC_PEXTRH:
4366 tcg_gen_andi_i64(t1, t1, 3);
4367 tcg_gen_shli_i64(t1, t1, 4);
4368 tcg_gen_shr_i64(t0, t0, t1);
4369 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
4370 break;
4371
4372 case OPC_ADDU_CP2:
4373 tcg_gen_add_i64(t0, t0, t1);
4374 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4375 break;
4376 case OPC_SUBU_CP2:
4377 tcg_gen_sub_i64(t0, t0, t1);
4378 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4379 break;
4380
4381 case OPC_SLL_CP2:
bd277fa1
RH
4382 shift_max = 32;
4383 goto do_shift;
4384 case OPC_SRL_CP2:
bd277fa1
RH
4385 shift_max = 32;
4386 goto do_shift;
4387 case OPC_SRA_CP2:
bd277fa1
RH
4388 shift_max = 32;
4389 goto do_shift;
4390 case OPC_DSLL_CP2:
bd277fa1
RH
4391 shift_max = 64;
4392 goto do_shift;
4393 case OPC_DSRL_CP2:
bd277fa1
RH
4394 shift_max = 64;
4395 goto do_shift;
4396 case OPC_DSRA_CP2:
bd277fa1
RH
4397 shift_max = 64;
4398 goto do_shift;
4399 do_shift:
4400 /* Make sure shift count isn't TCG undefined behaviour. */
4401 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4402
4403 switch (opc) {
4404 case OPC_SLL_CP2:
4405 case OPC_DSLL_CP2:
4406 tcg_gen_shl_i64(t0, t0, t1);
4407 break;
4408 case OPC_SRA_CP2:
4409 case OPC_DSRA_CP2:
7480515f
AM
4410 /*
4411 * Since SRA is UndefinedResult without sign-extended inputs,
4412 * we can treat SRA and DSRA the same.
4413 */
bd277fa1
RH
4414 tcg_gen_sar_i64(t0, t0, t1);
4415 break;
4416 case OPC_SRL_CP2:
4417 /* We want to shift in zeros for SRL; zero-extend first. */
4418 tcg_gen_ext32u_i64(t0, t0);
4419 /* FALLTHRU */
4420 case OPC_DSRL_CP2:
4421 tcg_gen_shr_i64(t0, t0, t1);
4422 break;
4423 }
4424
4425 if (shift_max == 32) {
4426 tcg_gen_ext32s_i64(t0, t0);
4427 }
4428
4429 /* Shifts larger than MAX produce zero. */
4430 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4431 tcg_gen_neg_i64(t1, t1);
4432 tcg_gen_and_i64(t0, t0, t1);
4433 break;
4434
4435 case OPC_ADD_CP2:
4436 case OPC_DADD_CP2:
4437 {
4438 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4439 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4440
4441 tcg_gen_mov_i64(t2, t0);
4442 tcg_gen_add_i64(t0, t1, t2);
4443 if (opc == OPC_ADD_CP2) {
4444 tcg_gen_ext32s_i64(t0, t0);
4445 }
4446 tcg_gen_xor_i64(t1, t1, t2);
4447 tcg_gen_xor_i64(t2, t2, t0);
4448 tcg_gen_andc_i64(t1, t2, t1);
4449 tcg_temp_free_i64(t2);
4450 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4451 generate_exception(ctx, EXCP_OVERFLOW);
4452 gen_set_label(lab);
bd277fa1
RH
4453 break;
4454 }
4455
4456 case OPC_SUB_CP2:
4457 case OPC_DSUB_CP2:
4458 {
4459 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4460 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4461
4462 tcg_gen_mov_i64(t2, t0);
4463 tcg_gen_sub_i64(t0, t1, t2);
4464 if (opc == OPC_SUB_CP2) {
4465 tcg_gen_ext32s_i64(t0, t0);
4466 }
4467 tcg_gen_xor_i64(t1, t1, t2);
4468 tcg_gen_xor_i64(t2, t2, t0);
4469 tcg_gen_and_i64(t1, t1, t2);
4470 tcg_temp_free_i64(t2);
4471 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4472 generate_exception(ctx, EXCP_OVERFLOW);
4473 gen_set_label(lab);
bd277fa1
RH
4474 break;
4475 }
4476
4477 case OPC_PMULUW:
4478 tcg_gen_ext32u_i64(t0, t0);
4479 tcg_gen_ext32u_i64(t1, t1);
4480 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
4481 break;
4482
4483 case OPC_SEQU_CP2:
4484 case OPC_SEQ_CP2:
84878f4c
JY
4485 cond = TCG_COND_EQ;
4486 goto do_cc_cond;
4487 break;
bd277fa1 4488 case OPC_SLTU_CP2:
84878f4c
JY
4489 cond = TCG_COND_LTU;
4490 goto do_cc_cond;
4491 break;
bd277fa1 4492 case OPC_SLT_CP2:
84878f4c
JY
4493 cond = TCG_COND_LT;
4494 goto do_cc_cond;
4495 break;
bd277fa1 4496 case OPC_SLEU_CP2:
84878f4c
JY
4497 cond = TCG_COND_LEU;
4498 goto do_cc_cond;
4499 break;
bd277fa1 4500 case OPC_SLE_CP2:
84878f4c
JY
4501 cond = TCG_COND_LE;
4502 do_cc_cond:
4503 {
4504 int cc = (ctx->opcode >> 8) & 0x7;
4505 TCGv_i64 t64 = tcg_temp_new_i64();
4506 TCGv_i32 t32 = tcg_temp_new_i32();
4507
4508 tcg_gen_setcond_i64(cond, t64, t0, t1);
4509 tcg_gen_extrl_i64_i32(t32, t64);
4510 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4511 get_fp_bit(cc), 1);
4512
4513 tcg_temp_free_i32(t32);
4514 tcg_temp_free_i64(t64);
4515 }
4516 goto no_rd;
4517 break;
bd277fa1 4518 default:
9d68ac14 4519 MIPS_INVAL("loongson_cp2");
3a4ef3b7 4520 gen_reserved_instruction(ctx);
bd277fa1
RH
4521 return;
4522 }
4523
bd277fa1
RH
4524 gen_store_fpr64(ctx, t0, rd);
4525
84878f4c 4526no_rd:
bd277fa1
RH
4527 tcg_temp_free_i64(t0);
4528 tcg_temp_free_i64(t1);
4529}
4530
e10a0ca1
JY
4531static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4532 int rs, int rd)
4533{
fd723105
JY
4534 TCGv t0, t1, t2;
4535 TCGv_i32 fp0;
e10a0ca1 4536#if defined(TARGET_MIPS64)
e10a0ca1
JY
4537 int lsq_rt1 = ctx->opcode & 0x1f;
4538 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4539#endif
fd723105 4540 int shf_offset = sextract32(ctx->opcode, 6, 8);
e10a0ca1
JY
4541
4542 t0 = tcg_temp_new();
4543
4544 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4545#if defined(TARGET_MIPS64)
4546 case OPC_GSLQ:
4547 t1 = tcg_temp_new();
4548 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4549 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4550 ctx->default_tcg_memop_mask);
4551 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4552 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4553 ctx->default_tcg_memop_mask);
4554 gen_store_gpr(t1, rt);
4555 gen_store_gpr(t0, lsq_rt1);
4556 tcg_temp_free(t1);
4557 break;
4558 case OPC_GSLQC1:
4559 check_cp1_enabled(ctx);
4560 t1 = tcg_temp_new();
4561 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4562 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4563 ctx->default_tcg_memop_mask);
4564 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4565 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4566 ctx->default_tcg_memop_mask);
4567 gen_store_fpr64(ctx, t1, rt);
4568 gen_store_fpr64(ctx, t0, lsq_rt1);
4569 tcg_temp_free(t1);
4570 break;
4571 case OPC_GSSQ:
4572 t1 = tcg_temp_new();
4573 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4574 gen_load_gpr(t1, rt);
4575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4576 ctx->default_tcg_memop_mask);
4577 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4578 gen_load_gpr(t1, lsq_rt1);
4579 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4580 ctx->default_tcg_memop_mask);
4581 tcg_temp_free(t1);
4582 break;
4583 case OPC_GSSQC1:
4584 check_cp1_enabled(ctx);
4585 t1 = tcg_temp_new();
4586 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4587 gen_load_fpr64(ctx, t1, rt);
4588 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4589 ctx->default_tcg_memop_mask);
4590 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4591 gen_load_fpr64(ctx, t1, lsq_rt1);
4592 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4593 ctx->default_tcg_memop_mask);
4594 tcg_temp_free(t1);
4595 break;
4596#endif
fd723105
JY
4597 case OPC_GSSHFL:
4598 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4599 case OPC_GSLWLC1:
4600 check_cp1_enabled(ctx);
4601 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4602 t1 = tcg_temp_new();
4603 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4604 tcg_gen_andi_tl(t1, t0, 3);
4605#ifndef TARGET_WORDS_BIGENDIAN
4606 tcg_gen_xori_tl(t1, t1, 3);
4607#endif
4608 tcg_gen_shli_tl(t1, t1, 3);
4609 tcg_gen_andi_tl(t0, t0, ~3);
4610 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4611 tcg_gen_shl_tl(t0, t0, t1);
4612 t2 = tcg_const_tl(-1);
4613 tcg_gen_shl_tl(t2, t2, t1);
4614 fp0 = tcg_temp_new_i32();
4615 gen_load_fpr32(ctx, fp0, rt);
4616 tcg_gen_ext_i32_tl(t1, fp0);
4617 tcg_gen_andc_tl(t1, t1, t2);
4618 tcg_temp_free(t2);
4619 tcg_gen_or_tl(t0, t0, t1);
4620 tcg_temp_free(t1);
4621#if defined(TARGET_MIPS64)
4622 tcg_gen_extrl_i64_i32(fp0, t0);
4623#else
4624 tcg_gen_ext32s_tl(fp0, t0);
4625#endif
4626 gen_store_fpr32(ctx, fp0, rt);
4627 tcg_temp_free_i32(fp0);
4628 break;
4629 case OPC_GSLWRC1:
4630 check_cp1_enabled(ctx);
4631 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4632 t1 = tcg_temp_new();
4633 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4634 tcg_gen_andi_tl(t1, t0, 3);
4635#ifdef TARGET_WORDS_BIGENDIAN
4636 tcg_gen_xori_tl(t1, t1, 3);
4637#endif
4638 tcg_gen_shli_tl(t1, t1, 3);
4639 tcg_gen_andi_tl(t0, t0, ~3);
4640 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4641 tcg_gen_shr_tl(t0, t0, t1);
4642 tcg_gen_xori_tl(t1, t1, 31);
4643 t2 = tcg_const_tl(0xfffffffeull);
4644 tcg_gen_shl_tl(t2, t2, t1);
4645 fp0 = tcg_temp_new_i32();
4646 gen_load_fpr32(ctx, fp0, rt);
4647 tcg_gen_ext_i32_tl(t1, fp0);
4648 tcg_gen_and_tl(t1, t1, t2);
4649 tcg_temp_free(t2);
4650 tcg_gen_or_tl(t0, t0, t1);
4651 tcg_temp_free(t1);
4652#if defined(TARGET_MIPS64)
4653 tcg_gen_extrl_i64_i32(fp0, t0);
4654#else
4655 tcg_gen_ext32s_tl(fp0, t0);
4656#endif
4657 gen_store_fpr32(ctx, fp0, rt);
4658 tcg_temp_free_i32(fp0);
4659 break;
4660#if defined(TARGET_MIPS64)
4661 case OPC_GSLDLC1:
4662 check_cp1_enabled(ctx);
4663 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4664 t1 = tcg_temp_new();
4665 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4666 tcg_gen_andi_tl(t1, t0, 7);
4667#ifndef TARGET_WORDS_BIGENDIAN
4668 tcg_gen_xori_tl(t1, t1, 7);
4669#endif
4670 tcg_gen_shli_tl(t1, t1, 3);
4671 tcg_gen_andi_tl(t0, t0, ~7);
4672 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4673 tcg_gen_shl_tl(t0, t0, t1);
4674 t2 = tcg_const_tl(-1);
4675 tcg_gen_shl_tl(t2, t2, t1);
4676 gen_load_fpr64(ctx, t1, rt);
4677 tcg_gen_andc_tl(t1, t1, t2);
4678 tcg_temp_free(t2);
4679 tcg_gen_or_tl(t0, t0, t1);
4680 tcg_temp_free(t1);
4681 gen_store_fpr64(ctx, t0, rt);
4682 break;
4683 case OPC_GSLDRC1:
4684 check_cp1_enabled(ctx);
4685 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4686 t1 = tcg_temp_new();
4687 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4688 tcg_gen_andi_tl(t1, t0, 7);
4689#ifdef TARGET_WORDS_BIGENDIAN
4690 tcg_gen_xori_tl(t1, t1, 7);
4691#endif
4692 tcg_gen_shli_tl(t1, t1, 3);
4693 tcg_gen_andi_tl(t0, t0, ~7);
4694 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4695 tcg_gen_shr_tl(t0, t0, t1);
4696 tcg_gen_xori_tl(t1, t1, 63);
4697 t2 = tcg_const_tl(0xfffffffffffffffeull);
4698 tcg_gen_shl_tl(t2, t2, t1);
4699 gen_load_fpr64(ctx, t1, rt);
4700 tcg_gen_and_tl(t1, t1, t2);
4701 tcg_temp_free(t2);
4702 tcg_gen_or_tl(t0, t0, t1);
4703 tcg_temp_free(t1);
4704 gen_store_fpr64(ctx, t0, rt);
4705 break;
4706#endif
4707 default:
4708 MIPS_INVAL("loongson_gsshfl");
3a4ef3b7 4709 gen_reserved_instruction(ctx);
fd723105
JY
4710 break;
4711 }
4712 break;
4713 case OPC_GSSHFS:
4714 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4715 case OPC_GSSWLC1:
4716 check_cp1_enabled(ctx);
4717 t1 = tcg_temp_new();
4718 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4719 fp0 = tcg_temp_new_i32();
4720 gen_load_fpr32(ctx, fp0, rt);
4721 tcg_gen_ext_i32_tl(t1, fp0);
4722 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4723 tcg_temp_free_i32(fp0);
4724 tcg_temp_free(t1);
4725 break;
4726 case OPC_GSSWRC1:
4727 check_cp1_enabled(ctx);
4728 t1 = tcg_temp_new();
4729 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4730 fp0 = tcg_temp_new_i32();
4731 gen_load_fpr32(ctx, fp0, rt);
4732 tcg_gen_ext_i32_tl(t1, fp0);
4733 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4734 tcg_temp_free_i32(fp0);
4735 tcg_temp_free(t1);
4736 break;
4737#if defined(TARGET_MIPS64)
4738 case OPC_GSSDLC1:
4739 check_cp1_enabled(ctx);
4740 t1 = tcg_temp_new();
4741 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4742 gen_load_fpr64(ctx, t1, rt);
4743 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4744 tcg_temp_free(t1);
4745 break;
4746 case OPC_GSSDRC1:
4747 check_cp1_enabled(ctx);
4748 t1 = tcg_temp_new();
4749 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4750 gen_load_fpr64(ctx, t1, rt);
4751 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4752 tcg_temp_free(t1);
4753 break;
4754#endif
4755 default:
4756 MIPS_INVAL("loongson_gsshfs");
3a4ef3b7 4757 gen_reserved_instruction(ctx);
fd723105
JY
4758 break;
4759 }
4760 break;
e10a0ca1
JY
4761 default:
4762 MIPS_INVAL("loongson_gslsq");
3a4ef3b7 4763 gen_reserved_instruction(ctx);
e10a0ca1
JY
4764 break;
4765 }
4766 tcg_temp_free(t0);
4767}
4768
90e22a57
JY
4769/* Loongson EXT LDC2/SDC2 */
4770static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4771 int rs, int rd)
4772{
4773 int offset = sextract32(ctx->opcode, 3, 8);
4774 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4775 TCGv t0, t1;
4776 TCGv_i32 fp0;
4777
4778 /* Pre-conditions */
4779 switch (opc) {
4780 case OPC_GSLBX:
4781 case OPC_GSLHX:
4782 case OPC_GSLWX:
4783 case OPC_GSLDX:
4784 /* prefetch, implement as NOP */
4785 if (rt == 0) {
4786 return;
4787 }
4788 break;
4789 case OPC_GSSBX:
4790 case OPC_GSSHX:
4791 case OPC_GSSWX:
4792 case OPC_GSSDX:
4793 break;
4794 case OPC_GSLWXC1:
4795#if defined(TARGET_MIPS64)
4796 case OPC_GSLDXC1:
4797#endif
4798 check_cp1_enabled(ctx);
4799 /* prefetch, implement as NOP */
4800 if (rt == 0) {
4801 return;
4802 }
4803 break;
4804 case OPC_GSSWXC1:
4805#if defined(TARGET_MIPS64)
4806 case OPC_GSSDXC1:
4807#endif
4808 check_cp1_enabled(ctx);
4809 break;
4810 default:
4811 MIPS_INVAL("loongson_lsdc2");
3a4ef3b7 4812 gen_reserved_instruction(ctx);
90e22a57
JY
4813 return;
4814 break;
4815 }
4816
4817 t0 = tcg_temp_new();
4818
4819 gen_base_offset_addr(ctx, t0, rs, offset);
4820 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4821
4822 switch (opc) {
4823 case OPC_GSLBX:
4824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4825 gen_store_gpr(t0, rt);
4826 break;
4827 case OPC_GSLHX:
4828 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4829 ctx->default_tcg_memop_mask);
4830 gen_store_gpr(t0, rt);
4831 break;
4832 case OPC_GSLWX:
4833 gen_base_offset_addr(ctx, t0, rs, offset);
4834 if (rd) {
4835 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4836 }
4837 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4838 ctx->default_tcg_memop_mask);
4839 gen_store_gpr(t0, rt);
4840 break;
4841#if defined(TARGET_MIPS64)
4842 case OPC_GSLDX:
4843 gen_base_offset_addr(ctx, t0, rs, offset);
4844 if (rd) {
4845 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4846 }
4847 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4848 ctx->default_tcg_memop_mask);
4849 gen_store_gpr(t0, rt);
4850 break;
4851#endif
4852 case OPC_GSLWXC1:
4853 check_cp1_enabled(ctx);
4854 gen_base_offset_addr(ctx, t0, rs, offset);
4855 if (rd) {
4856 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4857 }
4858 fp0 = tcg_temp_new_i32();
4859 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4860 ctx->default_tcg_memop_mask);
4861 gen_store_fpr32(ctx, fp0, rt);
4862 tcg_temp_free_i32(fp0);
4863 break;
4864#if defined(TARGET_MIPS64)
4865 case OPC_GSLDXC1:
4866 check_cp1_enabled(ctx);
4867 gen_base_offset_addr(ctx, t0, rs, offset);
4868 if (rd) {
4869 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4870 }
4871 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4872 ctx->default_tcg_memop_mask);
4873 gen_store_fpr64(ctx, t0, rt);
4874 break;
4875#endif
4876 case OPC_GSSBX:
4877 t1 = tcg_temp_new();
4878 gen_load_gpr(t1, rt);
4879 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4880 tcg_temp_free(t1);
4881 break;
4882 case OPC_GSSHX:
4883 t1 = tcg_temp_new();
4884 gen_load_gpr(t1, rt);
4885 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4886 ctx->default_tcg_memop_mask);
4887 tcg_temp_free(t1);
4888 break;
4889 case OPC_GSSWX:
4890 t1 = tcg_temp_new();
4891 gen_load_gpr(t1, rt);
4892 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4893 ctx->default_tcg_memop_mask);
4894 tcg_temp_free(t1);
4895 break;
4896#if defined(TARGET_MIPS64)
4897 case OPC_GSSDX:
4898 t1 = tcg_temp_new();
4899 gen_load_gpr(t1, rt);
4900 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4901 ctx->default_tcg_memop_mask);
4902 tcg_temp_free(t1);
4903 break;
4904#endif
4905 case OPC_GSSWXC1:
4906 fp0 = tcg_temp_new_i32();
4907 gen_load_fpr32(ctx, fp0, rt);
4908 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4909 ctx->default_tcg_memop_mask);
4910 tcg_temp_free_i32(fp0);
4911 break;
4912#if defined(TARGET_MIPS64)
4913 case OPC_GSSDXC1:
4914 t1 = tcg_temp_new();
4915 gen_load_fpr64(ctx, t1, rt);
4916 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4917 ctx->default_tcg_memop_mask);
4918 tcg_temp_free(t1);
4919 break;
4920#endif
4921 default:
4922 break;
4923 }
4924
4925 tcg_temp_free(t0);
4926}
4927
6af0bf9c 4928/* Traps */
71375b59
AM
4929static void gen_trap(DisasContext *ctx, uint32_t opc,
4930 int rs, int rt, int16_t imm)
6af0bf9c
FB
4931{
4932 int cond;
cdc0faa6 4933 TCGv t0 = tcg_temp_new();
1ba74fb8 4934 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4935
4936 cond = 0;
4937 /* Load needed operands */
4938 switch (opc) {
4939 case OPC_TEQ:
4940 case OPC_TGE:
4941 case OPC_TGEU:
4942 case OPC_TLT:
4943 case OPC_TLTU:
4944 case OPC_TNE:
4945 /* Compare two registers */
4946 if (rs != rt) {
be24bb4f
TS
4947 gen_load_gpr(t0, rs);
4948 gen_load_gpr(t1, rt);
6af0bf9c
FB
4949 cond = 1;
4950 }
179e32bb 4951 break;
6af0bf9c
FB
4952 case OPC_TEQI:
4953 case OPC_TGEI:
4954 case OPC_TGEIU:
4955 case OPC_TLTI:
4956 case OPC_TLTIU:
4957 case OPC_TNEI:
4958 /* Compare register to immediate */
4959 if (rs != 0 || imm != 0) {
be24bb4f
TS
4960 gen_load_gpr(t0, rs);
4961 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4962 cond = 1;
4963 }
4964 break;
4965 }
4966 if (cond == 0) {
4967 switch (opc) {
4968 case OPC_TEQ: /* rs == rs */
4969 case OPC_TEQI: /* r0 == 0 */
4970 case OPC_TGE: /* rs >= rs */
4971 case OPC_TGEI: /* r0 >= 0 */
4972 case OPC_TGEU: /* rs >= rs unsigned */
4973 case OPC_TGEIU: /* r0 >= 0 unsigned */
4974 /* Always trap */
9c708c7f 4975 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
4976 break;
4977 case OPC_TLT: /* rs < rs */
4978 case OPC_TLTI: /* r0 < 0 */
4979 case OPC_TLTU: /* rs < rs unsigned */
4980 case OPC_TLTIU: /* r0 < 0 unsigned */
4981 case OPC_TNE: /* rs != rs */
4982 case OPC_TNEI: /* r0 != 0 */
ead9360e 4983 /* Never trap: treat as NOP. */
cdc0faa6 4984 break;
6af0bf9c
FB
4985 }
4986 } else {
42a268c2 4987 TCGLabel *l1 = gen_new_label();
cdc0faa6 4988
6af0bf9c
FB
4989 switch (opc) {
4990 case OPC_TEQ:
4991 case OPC_TEQI:
cdc0faa6 4992 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4993 break;
4994 case OPC_TGE:
4995 case OPC_TGEI:
cdc0faa6 4996 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4997 break;
4998 case OPC_TGEU:
4999 case OPC_TGEIU:
cdc0faa6 5000 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5001 break;
5002 case OPC_TLT:
5003 case OPC_TLTI:
cdc0faa6 5004 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5005 break;
5006 case OPC_TLTU:
5007 case OPC_TLTIU:
cdc0faa6 5008 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5009 break;
5010 case OPC_TNE:
5011 case OPC_TNEI:
cdc0faa6 5012 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5013 break;
6af0bf9c 5014 }
cdc0faa6 5015 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5016 gen_set_label(l1);
5017 }
be24bb4f
TS
5018 tcg_temp_free(t0);
5019 tcg_temp_free(t1);
6af0bf9c
FB
5020}
5021
90aa39a1
SF
5022static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5023{
eeb3bba8 5024 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5025 return false;
5026 }
5027
5028#ifndef CONFIG_USER_ONLY
eeb3bba8 5029 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5030#else
5031 return true;
5032#endif
5033}
5034
356265ae 5035static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5036{
90aa39a1 5037 if (use_goto_tb(ctx, dest)) {
57fec1fe 5038 tcg_gen_goto_tb(n);
9b9e4393 5039 gen_save_pc(dest);
07ea28b4 5040 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5041 } else {
9b9e4393 5042 gen_save_pc(dest);
eeb3bba8 5043 if (ctx->base.singlestep_enabled) {
7b270ef2 5044 save_cpu_state(ctx, 0);
9c708c7f 5045 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5046 }
7f11636d 5047 tcg_gen_lookup_and_goto_ptr();
6e256c93 5048 }
c53be334
FB
5049}
5050
6af0bf9c 5051/* Branches (before delay slot) */
71375b59
AM
5052static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5053 int insn_bytes,
5054 int rs, int rt, int32_t offset,
5055 int delayslot_size)
6af0bf9c 5056{
d077b6f7 5057 target_ulong btgt = -1;
3ad4bb2d 5058 int blink = 0;
2fdbad25 5059 int bcond_compute = 0;
1ba74fb8
AJ
5060 TCGv t0 = tcg_temp_new();
5061 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5062
5063 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5064#ifdef MIPS_DEBUG_DISAS
339cd2a8 5065 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5066 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5067#endif
3a4ef3b7 5068 gen_reserved_instruction(ctx);
6c5c1e20 5069 goto out;
3ad4bb2d 5070 }
6af0bf9c 5071
6af0bf9c
FB
5072 /* Load needed operands */
5073 switch (opc) {
5074 case OPC_BEQ:
5075 case OPC_BEQL:
5076 case OPC_BNE:
5077 case OPC_BNEL:
5078 /* Compare two registers */
5079 if (rs != rt) {
6c5c1e20
TS
5080 gen_load_gpr(t0, rs);
5081 gen_load_gpr(t1, rt);
2fdbad25 5082 bcond_compute = 1;
6af0bf9c 5083 }
eeb3bba8 5084 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5085 break;
5086 case OPC_BGEZ:
5087 case OPC_BGEZAL:
5088 case OPC_BGEZALL:
5089 case OPC_BGEZL:
5090 case OPC_BGTZ:
5091 case OPC_BGTZL:
5092 case OPC_BLEZ:
5093 case OPC_BLEZL:
5094 case OPC_BLTZ:
5095 case OPC_BLTZAL:
5096 case OPC_BLTZALL:
5097 case OPC_BLTZL:
5098 /* Compare to zero */
5099 if (rs != 0) {
6c5c1e20 5100 gen_load_gpr(t0, rs);
2fdbad25 5101 bcond_compute = 1;
6af0bf9c 5102 }
eeb3bba8 5103 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5104 break;
e45a93e2
JL
5105 case OPC_BPOSGE32:
5106#if defined(TARGET_MIPS64)
5107 case OPC_BPOSGE64:
5108 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5109#else
5110 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5111#endif
5112 bcond_compute = 1;
eeb3bba8 5113 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5114 break;
6af0bf9c
FB
5115 case OPC_J:
5116 case OPC_JAL:
364d4831 5117 case OPC_JALX:
6af0bf9c 5118 /* Jump to immediate */
eeb3bba8
EC
5119 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5120 (uint32_t)offset;
6af0bf9c
FB
5121 break;
5122 case OPC_JR:
5123 case OPC_JALR:
5124 /* Jump to register */
7a387fff 5125 if (offset != 0 && offset != 16) {
7480515f
AM
5126 /*
5127 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5128 * others are reserved.
5129 */
923617a3 5130 MIPS_INVAL("jump hint");
3a4ef3b7 5131 gen_reserved_instruction(ctx);
6c5c1e20 5132 goto out;
6af0bf9c 5133 }
d077b6f7 5134 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5135 break;
5136 default:
5137 MIPS_INVAL("branch/jump");
3a4ef3b7 5138 gen_reserved_instruction(ctx);
6c5c1e20 5139 goto out;
6af0bf9c 5140 }
2fdbad25 5141 if (bcond_compute == 0) {
6af0bf9c
FB
5142 /* No condition to be computed */
5143 switch (opc) {
5144 case OPC_BEQ: /* rx == rx */
5145 case OPC_BEQL: /* rx == rx likely */
5146 case OPC_BGEZ: /* 0 >= 0 */
5147 case OPC_BGEZL: /* 0 >= 0 likely */
5148 case OPC_BLEZ: /* 0 <= 0 */
5149 case OPC_BLEZL: /* 0 <= 0 likely */
5150 /* Always take */
4ad40f36 5151 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5152 break;
5153 case OPC_BGEZAL: /* 0 >= 0 */
5154 case OPC_BGEZALL: /* 0 >= 0 likely */
5155 /* Always take and link */
5156 blink = 31;
4ad40f36 5157 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5158 break;
5159 case OPC_BNE: /* rx != rx */
5160 case OPC_BGTZ: /* 0 > 0 */
5161 case OPC_BLTZ: /* 0 < 0 */
ead9360e 5162 /* Treat as NOP. */
6c5c1e20 5163 goto out;
eeef26cd 5164 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
5165 /*
5166 * Handle as an unconditional branch to get correct delay
5167 * slot checking.
5168 */
3c824109 5169 blink = 31;
eeb3bba8 5170 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 5171 ctx->hflags |= MIPS_HFLAG_B;
3c824109 5172 break;
eeef26cd 5173 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 5174 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 5175 /* Skip the instruction in the delay slot */
eeb3bba8 5176 ctx->base.pc_next += 4;
6c5c1e20 5177 goto out;
6af0bf9c
FB
5178 case OPC_BNEL: /* rx != rx likely */
5179 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
5180 case OPC_BLTZL: /* 0 < 0 likely */
5181 /* Skip the instruction in the delay slot */
eeb3bba8 5182 ctx->base.pc_next += 4;
6c5c1e20 5183 goto out;
6af0bf9c 5184 case OPC_J:
4ad40f36 5185 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 5186 break;
364d4831
NF
5187 case OPC_JALX:
5188 ctx->hflags |= MIPS_HFLAG_BX;
5189 /* Fallthrough */
6af0bf9c
FB
5190 case OPC_JAL:
5191 blink = 31;
4ad40f36 5192 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5193 break;
5194 case OPC_JR:
4ad40f36 5195 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5196 break;
5197 case OPC_JALR:
5198 blink = rt;
4ad40f36 5199 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5200 break;
5201 default:
5202 MIPS_INVAL("branch/jump");
3a4ef3b7 5203 gen_reserved_instruction(ctx);
6c5c1e20 5204 goto out;
6af0bf9c
FB
5205 }
5206 } else {
5207 switch (opc) {
5208 case OPC_BEQ:
e68dd28f 5209 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5210 goto not_likely;
5211 case OPC_BEQL:
e68dd28f 5212 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5213 goto likely;
5214 case OPC_BNE:
e68dd28f 5215 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5216 goto not_likely;
5217 case OPC_BNEL:
e68dd28f 5218 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5219 goto likely;
5220 case OPC_BGEZ:
e68dd28f 5221 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5222 goto not_likely;
5223 case OPC_BGEZL:
e68dd28f 5224 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5225 goto likely;
5226 case OPC_BGEZAL:
e68dd28f 5227 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5228 blink = 31;
5229 goto not_likely;
5230 case OPC_BGEZALL:
e68dd28f 5231 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 5232 blink = 31;
6af0bf9c
FB
5233 goto likely;
5234 case OPC_BGTZ:
e68dd28f 5235 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5236 goto not_likely;
5237 case OPC_BGTZL:
e68dd28f 5238 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5239 goto likely;
5240 case OPC_BLEZ:
e68dd28f 5241 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5242 goto not_likely;
5243 case OPC_BLEZL:
e68dd28f 5244 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5245 goto likely;
5246 case OPC_BLTZ:
e68dd28f 5247 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
5248 goto not_likely;
5249 case OPC_BLTZL:
e68dd28f 5250 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5251 goto likely;
e45a93e2
JL
5252 case OPC_BPOSGE32:
5253 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
5254 goto not_likely;
5255#if defined(TARGET_MIPS64)
5256 case OPC_BPOSGE64:
5257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
5258 goto not_likely;
5259#endif
6af0bf9c 5260 case OPC_BLTZAL:
e68dd28f 5261 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5262 blink = 31;
6af0bf9c 5263 not_likely:
4ad40f36 5264 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
5265 break;
5266 case OPC_BLTZALL:
e68dd28f 5267 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5268 blink = 31;
6af0bf9c 5269 likely:
4ad40f36 5270 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 5271 break;
c53f4a62
TS
5272 default:
5273 MIPS_INVAL("conditional branch/jump");
3a4ef3b7 5274 gen_reserved_instruction(ctx);
6c5c1e20 5275 goto out;
6af0bf9c 5276 }
6af0bf9c 5277 }
9b9e4393 5278
d077b6f7 5279 ctx->btarget = btgt;
b231c103
YK
5280
5281 switch (delayslot_size) {
5282 case 2:
5283 ctx->hflags |= MIPS_HFLAG_BDS16;
5284 break;
5285 case 4:
5286 ctx->hflags |= MIPS_HFLAG_BDS32;
5287 break;
5288 }
5289
6af0bf9c 5290 if (blink > 0) {
b231c103 5291 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
5292 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5293
eeb3bba8
EC
5294 tcg_gen_movi_tl(cpu_gpr[blink],
5295 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 5296 }
6c5c1e20
TS
5297
5298 out:
1f8929d2 5299 if (insn_bytes == 2) {
364d4831 5300 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 5301 }
6c5c1e20
TS
5302 tcg_temp_free(t0);
5303 tcg_temp_free(t1);
6af0bf9c
FB
5304}
5305
764371d2
SM
5306
5307/* nanoMIPS Branches */
5308static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5309 int insn_bytes,
5310 int rs, int rt, int32_t offset)
5311{
5312 target_ulong btgt = -1;
5313 int bcond_compute = 0;
5314 TCGv t0 = tcg_temp_new();
5315 TCGv t1 = tcg_temp_new();
5316
5317 /* Load needed operands */
5318 switch (opc) {
5319 case OPC_BEQ:
5320 case OPC_BNE:
5321 /* Compare two registers */
5322 if (rs != rt) {
5323 gen_load_gpr(t0, rs);
5324 gen_load_gpr(t1, rt);
5325 bcond_compute = 1;
5326 }
5327 btgt = ctx->base.pc_next + insn_bytes + offset;
5328 break;
5329 case OPC_BGEZAL:
5330 /* Compare to zero */
5331 if (rs != 0) {
5332 gen_load_gpr(t0, rs);
5333 bcond_compute = 1;
5334 }
5335 btgt = ctx->base.pc_next + insn_bytes + offset;
5336 break;
5337 case OPC_BPOSGE32:
5338 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5339 bcond_compute = 1;
5340 btgt = ctx->base.pc_next + insn_bytes + offset;
5341 break;
5342 case OPC_JR:
5343 case OPC_JALR:
5344 /* Jump to register */
5345 if (offset != 0 && offset != 16) {
7480515f
AM
5346 /*
5347 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5348 * others are reserved.
5349 */
764371d2 5350 MIPS_INVAL("jump hint");
3a4ef3b7 5351 gen_reserved_instruction(ctx);
764371d2
SM
5352 goto out;
5353 }
5354 gen_load_gpr(btarget, rs);
5355 break;
5356 default:
5357 MIPS_INVAL("branch/jump");
3a4ef3b7 5358 gen_reserved_instruction(ctx);
764371d2
SM
5359 goto out;
5360 }
5361 if (bcond_compute == 0) {
5362 /* No condition to be computed */
5363 switch (opc) {
5364 case OPC_BEQ: /* rx == rx */
5365 /* Always take */
5366 ctx->hflags |= MIPS_HFLAG_B;
5367 break;
5368 case OPC_BGEZAL: /* 0 >= 0 */
5369 /* Always take and link */
5370 tcg_gen_movi_tl(cpu_gpr[31],
5371 ctx->base.pc_next + insn_bytes);
5372 ctx->hflags |= MIPS_HFLAG_B;
5373 break;
5374 case OPC_BNE: /* rx != rx */
5375 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5376 /* Skip the instruction in the delay slot */
5377 ctx->base.pc_next += 4;
5378 goto out;
5379 case OPC_JR:
5380 ctx->hflags |= MIPS_HFLAG_BR;
5381 break;
5382 case OPC_JALR:
5383 if (rt > 0) {
5384 tcg_gen_movi_tl(cpu_gpr[rt],
5385 ctx->base.pc_next + insn_bytes);
5386 }
5387 ctx->hflags |= MIPS_HFLAG_BR;
5388 break;
5389 default:
5390 MIPS_INVAL("branch/jump");
3a4ef3b7 5391 gen_reserved_instruction(ctx);
764371d2
SM
5392 goto out;
5393 }
5394 } else {
5395 switch (opc) {
5396 case OPC_BEQ:
5397 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5398 goto not_likely;
5399 case OPC_BNE:
5400 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5401 goto not_likely;
5402 case OPC_BGEZAL:
5403 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5404 tcg_gen_movi_tl(cpu_gpr[31],
5405 ctx->base.pc_next + insn_bytes);
5406 goto not_likely;
5407 case OPC_BPOSGE32:
5408 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5409 not_likely:
5410 ctx->hflags |= MIPS_HFLAG_BC;
5411 break;
5412 default:
5413 MIPS_INVAL("conditional branch/jump");
3a4ef3b7 5414 gen_reserved_instruction(ctx);
764371d2
SM
5415 goto out;
5416 }
5417 }
5418
5419 ctx->btarget = btgt;
5420
5421 out:
5422 if (insn_bytes == 2) {
5423 ctx->hflags |= MIPS_HFLAG_B16;
5424 }
5425 tcg_temp_free(t0);
5426 tcg_temp_free(t1);
5427}
5428
5429
7a387fff 5430/* special3 bitfield operations */
235785e8
AM
5431static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5432 int rs, int lsb, int msb)
7a387fff 5433{
a7812ae4
PB
5434 TCGv t0 = tcg_temp_new();
5435 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
5436
5437 gen_load_gpr(t1, rs);
7a387fff
TS
5438 switch (opc) {
5439 case OPC_EXT:
b7f26e52 5440 if (lsb + msb > 31) {
7a387fff 5441 goto fail;
b7f26e52 5442 }
505ad7c2 5443 if (msb != 31) {
6eebb7a4 5444 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 5445 } else {
7480515f
AM
5446 /*
5447 * The two checks together imply that lsb == 0,
5448 * so this is a simple sign-extension.
5449 */
6eebb7a4 5450 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 5451 }
7a387fff 5452 break;
c6d6dd7c 5453#if defined(TARGET_MIPS64)
7a387fff 5454 case OPC_DEXTU:
b7f26e52
RH
5455 lsb += 32;
5456 goto do_dext;
5457 case OPC_DEXTM:
5458 msb += 32;
5459 goto do_dext;
7a387fff 5460 case OPC_DEXT:
b7f26e52
RH
5461 do_dext:
5462 if (lsb + msb > 63) {
5463 goto fail;
5464 }
6eebb7a4 5465 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 5466 break;
c6d6dd7c 5467#endif
7a387fff 5468 case OPC_INS:
b7f26e52 5469 if (lsb > msb) {
7a387fff 5470 goto fail;
b7f26e52 5471 }
6c5c1e20 5472 gen_load_gpr(t0, rt);
e0d002f1 5473 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 5474 tcg_gen_ext32s_tl(t0, t0);
7a387fff 5475 break;
c6d6dd7c 5476#if defined(TARGET_MIPS64)
7a387fff 5477 case OPC_DINSU:
b7f26e52
RH
5478 lsb += 32;
5479 /* FALLTHRU */
5480 case OPC_DINSM:
5481 msb += 32;
5482 /* FALLTHRU */
7a387fff 5483 case OPC_DINS:
b7f26e52
RH
5484 if (lsb > msb) {
5485 goto fail;
5486 }
6c5c1e20 5487 gen_load_gpr(t0, rt);
e0d002f1 5488 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 5489 break;
c6d6dd7c 5490#endif
7a387fff
TS
5491 default:
5492fail:
5493 MIPS_INVAL("bitops");
3a4ef3b7 5494 gen_reserved_instruction(ctx);
6c5c1e20
TS
5495 tcg_temp_free(t0);
5496 tcg_temp_free(t1);
7a387fff
TS
5497 return;
5498 }
6c5c1e20
TS
5499 gen_store_gpr(t0, rt);
5500 tcg_temp_free(t0);
5501 tcg_temp_free(t1);
7a387fff
TS
5502}
5503
235785e8 5504static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 5505{
3a55fa47 5506 TCGv t0;
49bcf33c 5507
3a55fa47
AJ
5508 if (rd == 0) {
5509 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
5510 return;
5511 }
5512
5513 t0 = tcg_temp_new();
5514 gen_load_gpr(t0, rt);
49bcf33c
AJ
5515 switch (op2) {
5516 case OPC_WSBH:
3a55fa47
AJ
5517 {
5518 TCGv t1 = tcg_temp_new();
06a57e5c 5519 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
5520
5521 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5522 tcg_gen_and_tl(t1, t1, t2);
5523 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5524 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5525 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 5526 tcg_temp_free(t2);
3a55fa47
AJ
5527 tcg_temp_free(t1);
5528 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5529 }
49bcf33c
AJ
5530 break;
5531 case OPC_SEB:
3a55fa47 5532 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5533 break;
5534 case OPC_SEH:
3a55fa47 5535 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5536 break;
5537#if defined(TARGET_MIPS64)
5538 case OPC_DSBH:
3a55fa47
AJ
5539 {
5540 TCGv t1 = tcg_temp_new();
06a57e5c 5541 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
5542
5543 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5544 tcg_gen_and_tl(t1, t1, t2);
5545 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5546 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5547 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5548 tcg_temp_free(t2);
3a55fa47
AJ
5549 tcg_temp_free(t1);
5550 }
49bcf33c
AJ
5551 break;
5552 case OPC_DSHD:
3a55fa47
AJ
5553 {
5554 TCGv t1 = tcg_temp_new();
06a57e5c 5555 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
5556
5557 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
5558 tcg_gen_and_tl(t1, t1, t2);
5559 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5560 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
5561 tcg_gen_or_tl(t0, t0, t1);
5562 tcg_gen_shri_tl(t1, t0, 32);
5563 tcg_gen_shli_tl(t0, t0, 32);
5564 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5565 tcg_temp_free(t2);
3a55fa47
AJ
5566 tcg_temp_free(t1);
5567 }
49bcf33c
AJ
5568 break;
5569#endif
5570 default:
5571 MIPS_INVAL("bsfhl");
3a4ef3b7 5572 gen_reserved_instruction(ctx);
49bcf33c 5573 tcg_temp_free(t0);
49bcf33c
AJ
5574 return;
5575 }
49bcf33c 5576 tcg_temp_free(t0);
49bcf33c
AJ
5577}
5578
821f2008
JH
5579static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5580 int rt, int bits)
284b731a 5581{
1f1b4c00
YK
5582 TCGv t0;
5583 if (rd == 0) {
5584 /* Treat as NOP. */
5585 return;
5586 }
5587 t0 = tcg_temp_new();
821f2008
JH
5588 if (bits == 0 || bits == wordsz) {
5589 if (bits == 0) {
5590 gen_load_gpr(t0, rt);
5591 } else {
5592 gen_load_gpr(t0, rs);
5593 }
5594 switch (wordsz) {
5595 case 32:
51243852
MD
5596 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5597 break;
5598#if defined(TARGET_MIPS64)
821f2008 5599 case 64:
51243852
MD
5600 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5601 break;
5602#endif
5603 }
1f1b4c00
YK
5604 } else {
5605 TCGv t1 = tcg_temp_new();
821f2008 5606 gen_load_gpr(t0, rt);
1f1b4c00 5607 gen_load_gpr(t1, rs);
821f2008
JH
5608 switch (wordsz) {
5609 case 32:
1f1b4c00
YK
5610 {
5611 TCGv_i64 t2 = tcg_temp_new_i64();
5612 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 5613 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
5614 gen_move_low32(cpu_gpr[rd], t2);
5615 tcg_temp_free_i64(t2);
5616 }
5617 break;
284b731a 5618#if defined(TARGET_MIPS64)
821f2008
JH
5619 case 64:
5620 tcg_gen_shli_tl(t0, t0, bits);
5621 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
5622 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5623 break;
284b731a 5624#endif
1f1b4c00
YK
5625 }
5626 tcg_temp_free(t1);
5627 }
5628
5629 tcg_temp_free(t0);
5630}
5631
d5076631 5632void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
821f2008
JH
5633{
5634 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5635}
5636
5637static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5638 int shift)
5639{
5640 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5641}
5642
1f1b4c00
YK
5643static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5644{
5645 TCGv t0;
5646 if (rd == 0) {
5647 /* Treat as NOP. */
5648 return;
5649 }
5650 t0 = tcg_temp_new();
5651 gen_load_gpr(t0, rt);
5652 switch (opc) {
5653 case OPC_BITSWAP:
5654 gen_helper_bitswap(cpu_gpr[rd], t0);
5655 break;
5656#if defined(TARGET_MIPS64)
5657 case OPC_DBITSWAP:
5658 gen_helper_dbitswap(cpu_gpr[rd], t0);
5659 break;
5660#endif
5661 }
5662 tcg_temp_free(t0);
284b731a
LA
5663}
5664
1f1b4c00
YK
5665#ifndef CONFIG_USER_ONLY
5666/* CP0 (MMU and control) */
5204ea79
LA
5667static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5668{
5669 TCGv_i64 t0 = tcg_temp_new_i64();
5670 TCGv_i64 t1 = tcg_temp_new_i64();
5671
5672 tcg_gen_ext_tl_i64(t0, arg);
5673 tcg_gen_ld_i64(t1, cpu_env, off);
5674#if defined(TARGET_MIPS64)
5675 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5676#else
5677 tcg_gen_concat32_i64(t1, t1, t0);
5678#endif
5679 tcg_gen_st_i64(t1, cpu_env, off);
5680 tcg_temp_free_i64(t1);
5681 tcg_temp_free_i64(t0);
5682}
5683
5684static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5685{
5686 TCGv_i64 t0 = tcg_temp_new_i64();
5687 TCGv_i64 t1 = tcg_temp_new_i64();
5688
5689 tcg_gen_ext_tl_i64(t0, arg);
5690 tcg_gen_ld_i64(t1, cpu_env, off);
5691 tcg_gen_concat32_i64(t1, t1, t0);
5692 tcg_gen_st_i64(t1, cpu_env, off);
5693 tcg_temp_free_i64(t1);
5694 tcg_temp_free_i64(t0);
5695}
5696
5697static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5698{
5699 TCGv_i64 t0 = tcg_temp_new_i64();
5700
5701 tcg_gen_ld_i64(t0, cpu_env, off);
5702#if defined(TARGET_MIPS64)
5703 tcg_gen_shri_i64(t0, t0, 30);
5704#else
5705 tcg_gen_shri_i64(t0, t0, 32);
5706#endif
5707 gen_move_low32(arg, t0);
5708 tcg_temp_free_i64(t0);
5709}
5710
5711static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5712{
5713 TCGv_i64 t0 = tcg_temp_new_i64();
5714
5715 tcg_gen_ld_i64(t0, cpu_env, off);
5716 tcg_gen_shri_i64(t0, t0, 32 + shift);
5717 gen_move_low32(arg, t0);
5718 tcg_temp_free_i64(t0);
5719}
5720
235785e8 5721static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 5722{
d9bea114 5723 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 5724
d9bea114
AJ
5725 tcg_gen_ld_i32(t0, cpu_env, off);
5726 tcg_gen_ext_i32_tl(arg, t0);
5727 tcg_temp_free_i32(t0);
4f57689a
TS
5728}
5729
235785e8 5730static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 5731{
d9bea114
AJ
5732 tcg_gen_ld_tl(arg, cpu_env, off);
5733 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
5734}
5735
235785e8 5736static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 5737{
d9bea114 5738 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 5739
d9bea114
AJ
5740 tcg_gen_trunc_tl_i32(t0, arg);
5741 tcg_gen_st_i32(t0, cpu_env, off);
5742 tcg_temp_free_i32(t0);
f1aa6320
TS
5743}
5744
c98d3d79
YK
5745#define CP0_CHECK(c) \
5746 do { \
5747 if (!(c)) { \
5748 goto cp0_unimplemented; \
5749 } \
5750 } while (0)
5751
5204ea79
LA
5752static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5753{
294fc2ea 5754 const char *register_name = "invalid";
5204ea79 5755
5204ea79 5756 switch (reg) {
04992c8c 5757 case CP0_REGISTER_02:
5204ea79
LA
5758 switch (sel) {
5759 case 0:
59488dda 5760 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5761 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5762 register_name = "EntryLo0";
5204ea79
LA
5763 break;
5764 default:
c98d3d79 5765 goto cp0_unimplemented;
5204ea79
LA
5766 }
5767 break;
04992c8c 5768 case CP0_REGISTER_03:
5204ea79 5769 switch (sel) {
acd37316 5770 case CP0_REG03__ENTRYLO1:
59488dda 5771 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5772 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5773 register_name = "EntryLo1";
5204ea79
LA
5774 break;
5775 default:
c98d3d79 5776 goto cp0_unimplemented;
5204ea79
LA
5777 }
5778 break;
04992c8c 5779 case CP0_REGISTER_09:
5fb2dcd1 5780 switch (sel) {
e5a98a72 5781 case CP0_REG09__SAAR:
5fb2dcd1
YK
5782 CP0_CHECK(ctx->saar);
5783 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 5784 register_name = "SAAR";
5fb2dcd1
YK
5785 break;
5786 default:
5787 goto cp0_unimplemented;
5788 }
5789 break;
04992c8c 5790 case CP0_REGISTER_17:
5204ea79 5791 switch (sel) {
706ce142 5792 case CP0_REG17__LLADDR:
c7c7e1e9 5793 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 5794 ctx->CP0_LLAddr_shift);
294fc2ea 5795 register_name = "LLAddr";
5204ea79 5796 break;
706ce142 5797 case CP0_REG17__MAAR:
f6d4dd81
YK
5798 CP0_CHECK(ctx->mrp);
5799 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 5800 register_name = "MAAR";
f6d4dd81 5801 break;
5204ea79 5802 default:
c98d3d79 5803 goto cp0_unimplemented;
5204ea79
LA
5804 }
5805 break;
feafe82c
YK
5806 case CP0_REGISTER_19:
5807 switch (sel) {
5808 case CP0_REG19__WATCHHI0:
5809 case CP0_REG19__WATCHHI1:
5810 case CP0_REG19__WATCHHI2:
5811 case CP0_REG19__WATCHHI3:
5812 case CP0_REG19__WATCHHI4:
5813 case CP0_REG19__WATCHHI5:
5814 case CP0_REG19__WATCHHI6:
5815 case CP0_REG19__WATCHHI7:
5816 /* upper 32 bits are only available when Config5MI != 0 */
5817 CP0_CHECK(ctx->mi);
5818 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5819 register_name = "WatchHi";
5820 break;
5821 default:
5822 goto cp0_unimplemented;
5823 }
5824 break;
04992c8c 5825 case CP0_REGISTER_28:
5204ea79
LA
5826 switch (sel) {
5827 case 0:
5828 case 2:
5829 case 4:
5830 case 6:
5831 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 5832 register_name = "TagLo";
5204ea79
LA
5833 break;
5834 default:
c98d3d79 5835 goto cp0_unimplemented;
5204ea79
LA
5836 }
5837 break;
5838 default:
c98d3d79 5839 goto cp0_unimplemented;
5204ea79 5840 }
294fc2ea 5841 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
5842 return;
5843
c98d3d79 5844cp0_unimplemented:
294fc2ea
AM
5845 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5846 register_name, reg, sel);
5204ea79
LA
5847 tcg_gen_movi_tl(arg, 0);
5848}
5849
5850static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5851{
294fc2ea 5852 const char *register_name = "invalid";
5204ea79
LA
5853 uint64_t mask = ctx->PAMask >> 36;
5854
5204ea79 5855 switch (reg) {
04992c8c 5856 case CP0_REGISTER_02:
5204ea79
LA
5857 switch (sel) {
5858 case 0:
59488dda 5859 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5860 tcg_gen_andi_tl(arg, arg, mask);
5861 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5862 register_name = "EntryLo0";
5204ea79
LA
5863 break;
5864 default:
c98d3d79 5865 goto cp0_unimplemented;
5204ea79
LA
5866 }
5867 break;
04992c8c 5868 case CP0_REGISTER_03:
5204ea79 5869 switch (sel) {
acd37316 5870 case CP0_REG03__ENTRYLO1:
59488dda 5871 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5872 tcg_gen_andi_tl(arg, arg, mask);
5873 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5874 register_name = "EntryLo1";
5204ea79
LA
5875 break;
5876 default:
c98d3d79 5877 goto cp0_unimplemented;
5204ea79
LA
5878 }
5879 break;
04992c8c 5880 case CP0_REGISTER_09:
5fb2dcd1 5881 switch (sel) {
e5a98a72 5882 case CP0_REG09__SAAR:
5fb2dcd1
YK
5883 CP0_CHECK(ctx->saar);
5884 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 5885 register_name = "SAAR";
5fb2dcd1
YK
5886 break;
5887 default:
5888 goto cp0_unimplemented;
5889 }
ab8c3410 5890 break;
04992c8c 5891 case CP0_REGISTER_17:
5204ea79 5892 switch (sel) {
706ce142 5893 case CP0_REG17__LLADDR:
7480515f
AM
5894 /*
5895 * LLAddr is read-only (the only exception is bit 0 if LLB is
5896 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5897 * relevant for modern MIPS cores supporting MTHC0, therefore
5898 * treating MTHC0 to LLAddr as NOP.
5899 */
294fc2ea 5900 register_name = "LLAddr";
5204ea79 5901 break;
706ce142 5902 case CP0_REG17__MAAR:
f6d4dd81
YK
5903 CP0_CHECK(ctx->mrp);
5904 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 5905 register_name = "MAAR";
f6d4dd81 5906 break;
5204ea79 5907 default:
c98d3d79 5908 goto cp0_unimplemented;
5204ea79
LA
5909 }
5910 break;
feafe82c
YK
5911 case CP0_REGISTER_19:
5912 switch (sel) {
5913 case CP0_REG19__WATCHHI0:
5914 case CP0_REG19__WATCHHI1:
5915 case CP0_REG19__WATCHHI2:
5916 case CP0_REG19__WATCHHI3:
5917 case CP0_REG19__WATCHHI4:
5918 case CP0_REG19__WATCHHI5:
5919 case CP0_REG19__WATCHHI6:
5920 case CP0_REG19__WATCHHI7:
5921 /* upper 32 bits are only available when Config5MI != 0 */
5922 CP0_CHECK(ctx->mi);
5923 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5924 register_name = "WatchHi";
5925 break;
5926 default:
5927 goto cp0_unimplemented;
5928 }
5929 break;
04992c8c 5930 case CP0_REGISTER_28:
5204ea79
LA
5931 switch (sel) {
5932 case 0:
5933 case 2:
5934 case 4:
5935 case 6:
5936 tcg_gen_andi_tl(arg, arg, mask);
5937 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 5938 register_name = "TagLo";
5204ea79
LA
5939 break;
5940 default:
c98d3d79 5941 goto cp0_unimplemented;
5204ea79
LA
5942 }
5943 break;
5944 default:
c98d3d79 5945 goto cp0_unimplemented;
5204ea79 5946 }
294fc2ea 5947 trace_mips_translate_c0("mthc0", register_name, reg, sel);
bc2eb5ea 5948 return;
5204ea79 5949
c98d3d79 5950cp0_unimplemented:
294fc2ea
AM
5951 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5952 register_name, reg, sel);
5204ea79
LA
5953}
5954
e98c0d17
LA
5955static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5956{
2e211e0a 5957 if (ctx->insn_flags & ISA_MIPS_R6) {
e98c0d17
LA
5958 tcg_gen_movi_tl(arg, 0);
5959 } else {
5960 tcg_gen_movi_tl(arg, ~0);
5961 }
5962}
5963
d75c135e 5964static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 5965{
294fc2ea 5966 const char *register_name = "invalid";
873eb012 5967
1f8929d2 5968 if (sel != 0) {
bbd5e4a2 5969 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 5970 }
e189e748 5971
873eb012 5972 switch (reg) {
04992c8c 5973 case CP0_REGISTER_00:
7a387fff 5974 switch (sel) {
1b142da5 5975 case CP0_REG00__INDEX:
7db13fae 5976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 5977 register_name = "Index";
7a387fff 5978 break;
1b142da5 5979 case CP0_REG00__MVPCONTROL:
f31b035a 5980 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5981 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 5982 register_name = "MVPControl";
ead9360e 5983 break;
1b142da5 5984 case CP0_REG00__MVPCONF0:
f31b035a 5985 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5986 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 5987 register_name = "MVPConf0";
ead9360e 5988 break;
1b142da5 5989 case CP0_REG00__MVPCONF1:
f31b035a 5990 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5991 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 5992 register_name = "MVPConf1";
ead9360e 5993 break;
1b142da5 5994 case CP0_REG00__VPCONTROL:
01bc435b
YK
5995 CP0_CHECK(ctx->vp);
5996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 5997 register_name = "VPControl";
01bc435b 5998 break;
7a387fff 5999 default:
f31b035a 6000 goto cp0_unimplemented;
7a387fff 6001 }
873eb012 6002 break;
04992c8c 6003 case CP0_REGISTER_01:
7a387fff 6004 switch (sel) {
30deb460 6005 case CP0_REG01__RANDOM:
2e211e0a 6006 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 6007 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6008 register_name = "Random";
2423f660 6009 break;
30deb460 6010 case CP0_REG01__VPECONTROL:
f31b035a 6011 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6013 register_name = "VPEControl";
ead9360e 6014 break;
30deb460 6015 case CP0_REG01__VPECONF0:
f31b035a 6016 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6018 register_name = "VPEConf0";
ead9360e 6019 break;
30deb460 6020 case CP0_REG01__VPECONF1:
f31b035a 6021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6023 register_name = "VPEConf1";
ead9360e 6024 break;
30deb460 6025 case CP0_REG01__YQMASK:
f31b035a 6026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6027 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6028 register_name = "YQMask";
ead9360e 6029 break;
30deb460 6030 case CP0_REG01__VPESCHEDULE:
f31b035a 6031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6032 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6033 register_name = "VPESchedule";
ead9360e 6034 break;
30deb460 6035 case CP0_REG01__VPESCHEFBACK:
f31b035a 6036 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6037 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6038 register_name = "VPEScheFBack";
ead9360e 6039 break;
30deb460 6040 case CP0_REG01__VPEOPT:
f31b035a 6041 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6042 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6043 register_name = "VPEOpt";
ead9360e 6044 break;
7a387fff 6045 default:
f31b035a 6046 goto cp0_unimplemented;
7a387fff 6047 }
873eb012 6048 break;
04992c8c 6049 case CP0_REGISTER_02:
7a387fff 6050 switch (sel) {
6d27d5bd 6051 case CP0_REG02__ENTRYLO0:
284b731a
LA
6052 {
6053 TCGv_i64 tmp = tcg_temp_new_i64();
6054 tcg_gen_ld_i64(tmp, cpu_env,
6055 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6056#if defined(TARGET_MIPS64)
284b731a
LA
6057 if (ctx->rxi) {
6058 /* Move RI/XI fields to bits 31:30 */
6059 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6060 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6061 }
7207c7f9 6062#endif
284b731a
LA
6063 gen_move_low32(arg, tmp);
6064 tcg_temp_free_i64(tmp);
6065 }
294fc2ea 6066 register_name = "EntryLo0";
2423f660 6067 break;
6d27d5bd 6068 case CP0_REG02__TCSTATUS:
f31b035a 6069 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6070 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 6071 register_name = "TCStatus";
ead9360e 6072 break;
6d27d5bd 6073 case CP0_REG02__TCBIND:
f31b035a 6074 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6075 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 6076 register_name = "TCBind";
ead9360e 6077 break;
6d27d5bd 6078 case CP0_REG02__TCRESTART:
f31b035a 6079 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6080 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 6081 register_name = "TCRestart";
ead9360e 6082 break;
6d27d5bd 6083 case CP0_REG02__TCHALT:
f31b035a 6084 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6085 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 6086 register_name = "TCHalt";
ead9360e 6087 break;
6d27d5bd 6088 case CP0_REG02__TCCONTEXT:
f31b035a 6089 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6090 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 6091 register_name = "TCContext";
ead9360e 6092 break;
6d27d5bd 6093 case CP0_REG02__TCSCHEDULE:
f31b035a 6094 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6095 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 6096 register_name = "TCSchedule";
ead9360e 6097 break;
6d27d5bd 6098 case CP0_REG02__TCSCHEFBACK:
f31b035a 6099 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6100 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 6101 register_name = "TCScheFBack";
ead9360e 6102 break;
7a387fff 6103 default:
f31b035a 6104 goto cp0_unimplemented;
7a387fff 6105 }
873eb012 6106 break;
04992c8c 6107 case CP0_REGISTER_03:
7a387fff 6108 switch (sel) {
acd37316 6109 case CP0_REG03__ENTRYLO1:
284b731a
LA
6110 {
6111 TCGv_i64 tmp = tcg_temp_new_i64();
6112 tcg_gen_ld_i64(tmp, cpu_env,
6113 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6114#if defined(TARGET_MIPS64)
284b731a
LA
6115 if (ctx->rxi) {
6116 /* Move RI/XI fields to bits 31:30 */
6117 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6118 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6119 }
7207c7f9 6120#endif
284b731a
LA
6121 gen_move_low32(arg, tmp);
6122 tcg_temp_free_i64(tmp);
6123 }
294fc2ea 6124 register_name = "EntryLo1";
2423f660 6125 break;
acd37316 6126 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6127 CP0_CHECK(ctx->vp);
6128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 6129 register_name = "GlobalNumber";
01bc435b 6130 break;
7a387fff 6131 default:
f31b035a 6132 goto cp0_unimplemented;
1579a72e 6133 }
873eb012 6134 break;
04992c8c 6135 case CP0_REGISTER_04:
7a387fff 6136 switch (sel) {
020fe379 6137 case CP0_REG04__CONTEXT:
7db13fae 6138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6139 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6140 register_name = "Context";
2423f660 6141 break;
020fe379
AM
6142 case CP0_REG04__CONTEXTCONFIG:
6143 /* SmartMIPS ASE */
6144 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 6145 register_name = "ContextConfig";
f31b035a 6146 goto cp0_unimplemented;
020fe379 6147 case CP0_REG04__USERLOCAL:
f31b035a 6148 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6149 tcg_gen_ld_tl(arg, cpu_env,
6150 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6151 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6152 register_name = "UserLocal";
d279279e 6153 break;
99029be1
YK
6154 case CP0_REG04__MMID:
6155 CP0_CHECK(ctx->mi);
6156 gen_helper_mtc0_memorymapid(cpu_env, arg);
6157 register_name = "MMID";
6158 break;
7a387fff 6159 default:
f31b035a 6160 goto cp0_unimplemented;
1579a72e 6161 }
873eb012 6162 break;
04992c8c 6163 case CP0_REGISTER_05:
7a387fff 6164 switch (sel) {
a1e76353 6165 case CP0_REG05__PAGEMASK:
7db13fae 6166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 6167 register_name = "PageMask";
2423f660 6168 break;
a1e76353 6169 case CP0_REG05__PAGEGRAIN:
7a47bae5 6170 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 6172 register_name = "PageGrain";
2423f660 6173 break;
a1e76353 6174 case CP0_REG05__SEGCTL0:
cec56a73
JH
6175 CP0_CHECK(ctx->sc);
6176 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6177 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6178 register_name = "SegCtl0";
cec56a73 6179 break;
a1e76353 6180 case CP0_REG05__SEGCTL1:
cec56a73
JH
6181 CP0_CHECK(ctx->sc);
6182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6183 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6184 register_name = "SegCtl1";
cec56a73 6185 break;
a1e76353 6186 case CP0_REG05__SEGCTL2:
cec56a73
JH
6187 CP0_CHECK(ctx->sc);
6188 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6189 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6190 register_name = "SegCtl2";
cec56a73 6191 break;
a1e76353 6192 case CP0_REG05__PWBASE:
5e31fdd5
YK
6193 check_pw(ctx);
6194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6195 register_name = "PWBase";
5e31fdd5 6196 break;
a1e76353 6197 case CP0_REG05__PWFIELD:
fa75ad14
YK
6198 check_pw(ctx);
6199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 6200 register_name = "PWField";
fa75ad14 6201 break;
a1e76353 6202 case CP0_REG05__PWSIZE:
20b28ebc
YK
6203 check_pw(ctx);
6204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 6205 register_name = "PWSize";
20b28ebc 6206 break;
7a387fff 6207 default:
f31b035a 6208 goto cp0_unimplemented;
1579a72e 6209 }
873eb012 6210 break;
04992c8c 6211 case CP0_REGISTER_06:
7a387fff 6212 switch (sel) {
9023594b 6213 case CP0_REG06__WIRED:
7db13fae 6214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 6215 register_name = "Wired";
2423f660 6216 break;
9023594b 6217 case CP0_REG06__SRSCONF0:
7a47bae5 6218 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 6220 register_name = "SRSConf0";
ead9360e 6221 break;
9023594b 6222 case CP0_REG06__SRSCONF1:
7a47bae5 6223 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 6225 register_name = "SRSConf1";
ead9360e 6226 break;
9023594b 6227 case CP0_REG06__SRSCONF2:
7a47bae5 6228 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 6230 register_name = "SRSConf2";
ead9360e 6231 break;
9023594b 6232 case CP0_REG06__SRSCONF3:
7a47bae5 6233 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 6235 register_name = "SRSConf3";
ead9360e 6236 break;
9023594b 6237 case CP0_REG06__SRSCONF4:
7a47bae5 6238 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 6240 register_name = "SRSConf4";
ead9360e 6241 break;
9023594b 6242 case CP0_REG06__PWCTL:
103be64c
YK
6243 check_pw(ctx);
6244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 6245 register_name = "PWCtl";
103be64c 6246 break;
7a387fff 6247 default:
f31b035a 6248 goto cp0_unimplemented;
1579a72e 6249 }
873eb012 6250 break;
04992c8c 6251 case CP0_REGISTER_07:
7a387fff 6252 switch (sel) {
143a9875 6253 case CP0_REG07__HWRENA:
7a47bae5 6254 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 6256 register_name = "HWREna";
2423f660 6257 break;
7a387fff 6258 default:
f31b035a 6259 goto cp0_unimplemented;
1579a72e 6260 }
8c0fdd85 6261 break;
04992c8c 6262 case CP0_REGISTER_08:
7a387fff 6263 switch (sel) {
67d167d2 6264 case CP0_REG08__BADVADDR:
7db13fae 6265 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 6266 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6267 register_name = "BadVAddr";
2423f660 6268 break;
67d167d2 6269 case CP0_REG08__BADINSTR:
f31b035a
LA
6270 CP0_CHECK(ctx->bi);
6271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 6272 register_name = "BadInstr";
aea14095 6273 break;
67d167d2 6274 case CP0_REG08__BADINSTRP:
f31b035a
LA
6275 CP0_CHECK(ctx->bp);
6276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 6277 register_name = "BadInstrP";
aea14095 6278 break;
67d167d2 6279 case CP0_REG08__BADINSTRX:
25beba9b
SM
6280 CP0_CHECK(ctx->bi);
6281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6282 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 6283 register_name = "BadInstrX";
25beba9b 6284 break;
05aa7e93 6285 default:
f31b035a 6286 goto cp0_unimplemented;
aea14095 6287 }
873eb012 6288 break;
04992c8c 6289 case CP0_REGISTER_09:
7a387fff 6290 switch (sel) {
e5a98a72 6291 case CP0_REG09__COUNT:
2e70f6ef 6292 /* Mark as an IO operation because we read the time. */
eeb3bba8 6293 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6294 gen_io_start();
7d37435b 6295 }
895c2d04 6296 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
6297 /*
6298 * Break the TB to be able to take timer interrupts immediately
6299 * after reading count. DISAS_STOP isn't sufficient, we need to
6300 * ensure we break completely out of translated code.
6301 */
eeb3bba8
EC
6302 gen_save_pc(ctx->base.pc_next + 4);
6303 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 6304 register_name = "Count";
2423f660 6305 break;
e5a98a72 6306 case CP0_REG09__SAARI:
5fb2dcd1
YK
6307 CP0_CHECK(ctx->saar);
6308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 6309 register_name = "SAARI";
5fb2dcd1 6310 break;
e5a98a72 6311 case CP0_REG09__SAAR:
5fb2dcd1
YK
6312 CP0_CHECK(ctx->saar);
6313 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 6314 register_name = "SAAR";
5fb2dcd1 6315 break;
7a387fff 6316 default:
f31b035a 6317 goto cp0_unimplemented;
2423f660 6318 }
873eb012 6319 break;
04992c8c 6320 case CP0_REGISTER_10:
7a387fff 6321 switch (sel) {
860ffef0 6322 case CP0_REG10__ENTRYHI:
7db13fae 6323 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 6324 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6325 register_name = "EntryHi";
2423f660 6326 break;
7a387fff 6327 default:
f31b035a 6328 goto cp0_unimplemented;
1579a72e 6329 }
873eb012 6330 break;
04992c8c 6331 case CP0_REGISTER_11:
7a387fff 6332 switch (sel) {
f5f3834f 6333 case CP0_REG11__COMPARE:
7db13fae 6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 6335 register_name = "Compare";
2423f660
TS
6336 break;
6337 /* 6,7 are implementation dependent */
7a387fff 6338 default:
f31b035a 6339 goto cp0_unimplemented;
2423f660 6340 }
873eb012 6341 break;
04992c8c 6342 case CP0_REGISTER_12:
7a387fff 6343 switch (sel) {
2b084867 6344 case CP0_REG12__STATUS:
7db13fae 6345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 6346 register_name = "Status";
2423f660 6347 break;
2b084867 6348 case CP0_REG12__INTCTL:
7a47bae5 6349 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 6351 register_name = "IntCtl";
2423f660 6352 break;
2b084867 6353 case CP0_REG12__SRSCTL:
7a47bae5 6354 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 6356 register_name = "SRSCtl";
2423f660 6357 break;
2b084867 6358 case CP0_REG12__SRSMAP:
7a47bae5 6359 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 6361 register_name = "SRSMap";
fd88b6ab 6362 break;
7a387fff 6363 default:
f31b035a 6364 goto cp0_unimplemented;
7a387fff 6365 }
873eb012 6366 break;
04992c8c 6367 case CP0_REGISTER_13:
7a387fff 6368 switch (sel) {
e3c7559d 6369 case CP0_REG13__CAUSE:
7db13fae 6370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 6371 register_name = "Cause";
2423f660 6372 break;
7a387fff 6373 default:
f31b035a 6374 goto cp0_unimplemented;
7a387fff 6375 }
873eb012 6376 break;
04992c8c 6377 case CP0_REGISTER_14:
7a387fff 6378 switch (sel) {
35e4b54d 6379 case CP0_REG14__EPC:
7db13fae 6380 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 6381 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6382 register_name = "EPC";
2423f660 6383 break;
7a387fff 6384 default:
f31b035a 6385 goto cp0_unimplemented;
1579a72e 6386 }
873eb012 6387 break;
04992c8c 6388 case CP0_REGISTER_15:
7a387fff 6389 switch (sel) {
4466cd49 6390 case CP0_REG15__PRID:
7db13fae 6391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 6392 register_name = "PRid";
2423f660 6393 break;
4466cd49 6394 case CP0_REG15__EBASE:
7a47bae5 6395 check_insn(ctx, ISA_MIPS_R2);
74dbf824
JH
6396 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6397 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6398 register_name = "EBase";
2423f660 6399 break;
4466cd49 6400 case CP0_REG15__CMGCRBASE:
7a47bae5 6401 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
6402 CP0_CHECK(ctx->cmgcr);
6403 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6404 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6405 register_name = "CMGCRBase";
c870e3f5 6406 break;
7a387fff 6407 default:
f31b035a 6408 goto cp0_unimplemented;
7a387fff 6409 }
873eb012 6410 break;
04992c8c 6411 case CP0_REGISTER_16:
873eb012 6412 switch (sel) {
433efb4c 6413 case CP0_REG16__CONFIG:
7db13fae 6414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 6415 register_name = "Config";
873eb012 6416 break;
433efb4c 6417 case CP0_REG16__CONFIG1:
7db13fae 6418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 6419 register_name = "Config1";
873eb012 6420 break;
433efb4c 6421 case CP0_REG16__CONFIG2:
7db13fae 6422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 6423 register_name = "Config2";
7a387fff 6424 break;
433efb4c 6425 case CP0_REG16__CONFIG3:
7db13fae 6426 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 6427 register_name = "Config3";
7a387fff 6428 break;
433efb4c 6429 case CP0_REG16__CONFIG4:
b4160af1 6430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 6431 register_name = "Config4";
b4160af1 6432 break;
433efb4c 6433 case CP0_REG16__CONFIG5:
b4dd99a3 6434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 6435 register_name = "Config5";
b4dd99a3 6436 break;
e397ee33 6437 /* 6,7 are implementation dependent */
433efb4c 6438 case CP0_REG16__CONFIG6:
7db13fae 6439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 6440 register_name = "Config6";
e397ee33 6441 break;
433efb4c 6442 case CP0_REG16__CONFIG7:
7db13fae 6443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 6444 register_name = "Config7";
e397ee33 6445 break;
873eb012 6446 default:
f31b035a 6447 goto cp0_unimplemented;
873eb012
TS
6448 }
6449 break;
04992c8c 6450 case CP0_REGISTER_17:
7a387fff 6451 switch (sel) {
706ce142 6452 case CP0_REG17__LLADDR:
895c2d04 6453 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 6454 register_name = "LLAddr";
2423f660 6455 break;
706ce142 6456 case CP0_REG17__MAAR:
f6d4dd81
YK
6457 CP0_CHECK(ctx->mrp);
6458 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 6459 register_name = "MAAR";
f6d4dd81 6460 break;
706ce142 6461 case CP0_REG17__MAARI:
f6d4dd81
YK
6462 CP0_CHECK(ctx->mrp);
6463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 6464 register_name = "MAARI";
f6d4dd81 6465 break;
7a387fff 6466 default:
f31b035a 6467 goto cp0_unimplemented;
7a387fff 6468 }
873eb012 6469 break;
04992c8c 6470 case CP0_REGISTER_18:
7a387fff 6471 switch (sel) {
e8dcfe82
AM
6472 case CP0_REG18__WATCHLO0:
6473 case CP0_REG18__WATCHLO1:
6474 case CP0_REG18__WATCHLO2:
6475 case CP0_REG18__WATCHLO3:
6476 case CP0_REG18__WATCHLO4:
6477 case CP0_REG18__WATCHLO5:
6478 case CP0_REG18__WATCHLO6:
6479 case CP0_REG18__WATCHLO7:
fa192d49 6480 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6481 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 6482 register_name = "WatchLo";
2423f660 6483 break;
7a387fff 6484 default:
f31b035a 6485 goto cp0_unimplemented;
7a387fff 6486 }
873eb012 6487 break;
04992c8c 6488 case CP0_REGISTER_19:
7a387fff 6489 switch (sel) {
be274dc1
AM
6490 case CP0_REG19__WATCHHI0:
6491 case CP0_REG19__WATCHHI1:
6492 case CP0_REG19__WATCHHI2:
6493 case CP0_REG19__WATCHHI3:
6494 case CP0_REG19__WATCHHI4:
6495 case CP0_REG19__WATCHHI5:
6496 case CP0_REG19__WATCHHI6:
6497 case CP0_REG19__WATCHHI7:
fa192d49 6498 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6499 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 6500 register_name = "WatchHi";
2423f660 6501 break;
7a387fff 6502 default:
f31b035a 6503 goto cp0_unimplemented;
7a387fff 6504 }
873eb012 6505 break;
04992c8c 6506 case CP0_REGISTER_20:
7a387fff 6507 switch (sel) {
14f92b0b 6508 case CP0_REG20__XCONTEXT:
d26bc211 6509#if defined(TARGET_MIPS64)
d75c135e 6510 check_insn(ctx, ISA_MIPS3);
7db13fae 6511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 6512 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6513 register_name = "XContext";
2423f660 6514 break;
703eaf37 6515#endif
7a387fff 6516 default:
f31b035a 6517 goto cp0_unimplemented;
7a387fff 6518 }
8c0fdd85 6519 break;
04992c8c 6520 case CP0_REGISTER_21:
7a387fff 6521 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 6522 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
6523 switch (sel) {
6524 case 0:
7db13fae 6525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 6526 register_name = "Framemask";
2423f660 6527 break;
7a387fff 6528 default:
f31b035a 6529 goto cp0_unimplemented;
7a387fff 6530 }
8c0fdd85 6531 break;
04992c8c 6532 case CP0_REGISTER_22:
d9bea114 6533 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 6534 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 6535 break;
04992c8c 6536 case CP0_REGISTER_23:
7a387fff 6537 switch (sel) {
4cbf4b6d 6538 case CP0_REG23__DEBUG:
895c2d04 6539 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 6540 register_name = "Debug";
2423f660 6541 break;
4cbf4b6d
AM
6542 case CP0_REG23__TRACECONTROL:
6543 /* PDtrace support */
6544 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 6545 register_name = "TraceControl";
3570d7f6 6546 goto cp0_unimplemented;
4cbf4b6d
AM
6547 case CP0_REG23__TRACECONTROL2:
6548 /* PDtrace support */
6549 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 6550 register_name = "TraceControl2";
3570d7f6 6551 goto cp0_unimplemented;
4cbf4b6d
AM
6552 case CP0_REG23__USERTRACEDATA1:
6553 /* PDtrace support */
6554 /* gen_helper_mfc0_usertracedata1(arg);*/
6555 register_name = "UserTraceData1";
3570d7f6 6556 goto cp0_unimplemented;
4cbf4b6d
AM
6557 case CP0_REG23__TRACEIBPC:
6558 /* PDtrace support */
6559 /* gen_helper_mfc0_traceibpc(arg); */
6560 register_name = "TraceIBPC";
6561 goto cp0_unimplemented;
6562 case CP0_REG23__TRACEDBPC:
6563 /* PDtrace support */
6564 /* gen_helper_mfc0_tracedbpc(arg); */
6565 register_name = "TraceDBPC";
3570d7f6 6566 goto cp0_unimplemented;
7a387fff 6567 default:
f31b035a 6568 goto cp0_unimplemented;
7a387fff 6569 }
873eb012 6570 break;
04992c8c 6571 case CP0_REGISTER_24:
7a387fff 6572 switch (sel) {
8d7b4b6e 6573 case CP0_REG24__DEPC:
f0b3f3ae 6574 /* EJTAG support */
7db13fae 6575 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 6576 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6577 register_name = "DEPC";
2423f660 6578 break;
7a387fff 6579 default:
f31b035a 6580 goto cp0_unimplemented;
7a387fff 6581 }
873eb012 6582 break;
04992c8c 6583 case CP0_REGISTER_25:
7a387fff 6584 switch (sel) {
1176b328 6585 case CP0_REG25__PERFCTL0:
7db13fae 6586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 6587 register_name = "Performance0";
7a387fff 6588 break;
1176b328 6589 case CP0_REG25__PERFCNT0:
7480515f 6590 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 6591 register_name = "Performance1";
3570d7f6 6592 goto cp0_unimplemented;
1176b328 6593 case CP0_REG25__PERFCTL1:
7480515f 6594 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 6595 register_name = "Performance2";
3570d7f6 6596 goto cp0_unimplemented;
1176b328 6597 case CP0_REG25__PERFCNT1:
7480515f 6598 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 6599 register_name = "Performance3";
3570d7f6 6600 goto cp0_unimplemented;
1176b328 6601 case CP0_REG25__PERFCTL2:
7480515f 6602 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 6603 register_name = "Performance4";
3570d7f6 6604 goto cp0_unimplemented;
1176b328 6605 case CP0_REG25__PERFCNT2:
7480515f 6606 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 6607 register_name = "Performance5";
3570d7f6 6608 goto cp0_unimplemented;
1176b328 6609 case CP0_REG25__PERFCTL3:
7480515f 6610 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 6611 register_name = "Performance6";
3570d7f6 6612 goto cp0_unimplemented;
1176b328 6613 case CP0_REG25__PERFCNT3:
7480515f 6614 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 6615 register_name = "Performance7";
3570d7f6 6616 goto cp0_unimplemented;
7a387fff 6617 default:
f31b035a 6618 goto cp0_unimplemented;
7a387fff 6619 }
8c0fdd85 6620 break;
04992c8c 6621 case CP0_REGISTER_26:
0d74a222 6622 switch (sel) {
dbbf08b2 6623 case CP0_REG26__ERRCTL:
0d74a222 6624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 6625 register_name = "ErrCtl";
0d74a222
LA
6626 break;
6627 default:
6628 goto cp0_unimplemented;
6629 }
da80682b 6630 break;
04992c8c 6631 case CP0_REGISTER_27:
7a387fff 6632 switch (sel) {
5a10873d 6633 case CP0_REG27__CACHERR:
d9bea114 6634 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 6635 register_name = "CacheErr";
2423f660 6636 break;
7a387fff 6637 default:
f31b035a 6638 goto cp0_unimplemented;
7a387fff 6639 }
8c0fdd85 6640 break;
04992c8c 6641 case CP0_REGISTER_28:
873eb012 6642 switch (sel) {
a30e2f21
AM
6643 case CP0_REG28__TAGLO:
6644 case CP0_REG28__TAGLO1:
6645 case CP0_REG28__TAGLO2:
6646 case CP0_REG28__TAGLO3:
284b731a
LA
6647 {
6648 TCGv_i64 tmp = tcg_temp_new_i64();
6649 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6650 gen_move_low32(arg, tmp);
6651 tcg_temp_free_i64(tmp);
6652 }
294fc2ea 6653 register_name = "TagLo";
873eb012 6654 break;
a30e2f21
AM
6655 case CP0_REG28__DATALO:
6656 case CP0_REG28__DATALO1:
6657 case CP0_REG28__DATALO2:
6658 case CP0_REG28__DATALO3:
7db13fae 6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 6660 register_name = "DataLo";
873eb012
TS
6661 break;
6662 default:
f31b035a 6663 goto cp0_unimplemented;
873eb012
TS
6664 }
6665 break;
04992c8c 6666 case CP0_REGISTER_29:
7a387fff 6667 switch (sel) {
af4bb6da
AM
6668 case CP0_REG29__TAGHI:
6669 case CP0_REG29__TAGHI1:
6670 case CP0_REG29__TAGHI2:
6671 case CP0_REG29__TAGHI3:
7db13fae 6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 6673 register_name = "TagHi";
7a387fff 6674 break;
af4bb6da
AM
6675 case CP0_REG29__DATAHI:
6676 case CP0_REG29__DATAHI1:
6677 case CP0_REG29__DATAHI2:
6678 case CP0_REG29__DATAHI3:
7db13fae 6679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 6680 register_name = "DataHi";
7a387fff
TS
6681 break;
6682 default:
f31b035a 6683 goto cp0_unimplemented;
7a387fff 6684 }
8c0fdd85 6685 break;
04992c8c 6686 case CP0_REGISTER_30:
7a387fff 6687 switch (sel) {
4bcf121e 6688 case CP0_REG30__ERROREPC:
7db13fae 6689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 6690 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6691 register_name = "ErrorEPC";
2423f660 6692 break;
7a387fff 6693 default:
f31b035a 6694 goto cp0_unimplemented;
7a387fff 6695 }
873eb012 6696 break;
04992c8c 6697 case CP0_REGISTER_31:
7a387fff 6698 switch (sel) {
14d92efd 6699 case CP0_REG31__DESAVE:
f0b3f3ae 6700 /* EJTAG support */
7db13fae 6701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 6702 register_name = "DESAVE";
2423f660 6703 break;
14d92efd
AM
6704 case CP0_REG31__KSCRATCH1:
6705 case CP0_REG31__KSCRATCH2:
6706 case CP0_REG31__KSCRATCH3:
6707 case CP0_REG31__KSCRATCH4:
6708 case CP0_REG31__KSCRATCH5:
6709 case CP0_REG31__KSCRATCH6:
f31b035a
LA
6710 CP0_CHECK(ctx->kscrexist & (1 << sel));
6711 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 6712 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 6713 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6714 register_name = "KScratch";
e98c0d17 6715 break;
7a387fff 6716 default:
f31b035a 6717 goto cp0_unimplemented;
7a387fff 6718 }
873eb012
TS
6719 break;
6720 default:
f31b035a 6721 goto cp0_unimplemented;
873eb012 6722 }
294fc2ea 6723 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
6724 return;
6725
f31b035a 6726cp0_unimplemented:
294fc2ea
AM
6727 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6728 register_name, reg, sel);
f31b035a 6729 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
6730}
6731
d75c135e 6732static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 6733{
294fc2ea 6734 const char *register_name = "invalid";
7a387fff 6735
1f8929d2 6736 if (sel != 0) {
bbd5e4a2 6737 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 6738 }
e189e748 6739
eeb3bba8 6740 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6741 gen_io_start();
bd79255d 6742 }
2e70f6ef 6743
8c0fdd85 6744 switch (reg) {
04992c8c 6745 case CP0_REGISTER_00:
7a387fff 6746 switch (sel) {
1b142da5 6747 case CP0_REG00__INDEX:
895c2d04 6748 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 6749 register_name = "Index";
7a387fff 6750 break;
1b142da5 6751 case CP0_REG00__MVPCONTROL:
f31b035a 6752 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6753 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 6754 register_name = "MVPControl";
ead9360e 6755 break;
1b142da5 6756 case CP0_REG00__MVPCONF0:
f31b035a 6757 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6758 /* ignored */
294fc2ea 6759 register_name = "MVPConf0";
ead9360e 6760 break;
1b142da5 6761 case CP0_REG00__MVPCONF1:
f31b035a 6762 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6763 /* ignored */
294fc2ea 6764 register_name = "MVPConf1";
ead9360e 6765 break;
1b142da5 6766 case CP0_REG00__VPCONTROL:
01bc435b
YK
6767 CP0_CHECK(ctx->vp);
6768 /* ignored */
294fc2ea 6769 register_name = "VPControl";
01bc435b 6770 break;
7a387fff 6771 default:
f31b035a 6772 goto cp0_unimplemented;
7a387fff 6773 }
8c0fdd85 6774 break;
04992c8c 6775 case CP0_REGISTER_01:
7a387fff 6776 switch (sel) {
30deb460 6777 case CP0_REG01__RANDOM:
2423f660 6778 /* ignored */
294fc2ea 6779 register_name = "Random";
2423f660 6780 break;
30deb460 6781 case CP0_REG01__VPECONTROL:
f31b035a 6782 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6783 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 6784 register_name = "VPEControl";
ead9360e 6785 break;
30deb460 6786 case CP0_REG01__VPECONF0:
f31b035a 6787 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6788 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 6789 register_name = "VPEConf0";
ead9360e 6790 break;
30deb460 6791 case CP0_REG01__VPECONF1:
f31b035a 6792 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6793 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 6794 register_name = "VPEConf1";
ead9360e 6795 break;
30deb460 6796 case CP0_REG01__YQMASK:
f31b035a 6797 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6798 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 6799 register_name = "YQMask";
ead9360e 6800 break;
30deb460 6801 case CP0_REG01__VPESCHEDULE:
f31b035a 6802 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6803 tcg_gen_st_tl(arg, cpu_env,
6804 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6805 register_name = "VPESchedule";
ead9360e 6806 break;
30deb460 6807 case CP0_REG01__VPESCHEFBACK:
f31b035a 6808 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6809 tcg_gen_st_tl(arg, cpu_env,
6810 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6811 register_name = "VPEScheFBack";
ead9360e 6812 break;
30deb460 6813 case CP0_REG01__VPEOPT:
f31b035a 6814 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6815 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 6816 register_name = "VPEOpt";
ead9360e 6817 break;
7a387fff 6818 default:
f31b035a 6819 goto cp0_unimplemented;
7a387fff 6820 }
8c0fdd85 6821 break;
04992c8c 6822 case CP0_REGISTER_02:
7a387fff 6823 switch (sel) {
6d27d5bd 6824 case CP0_REG02__ENTRYLO0:
895c2d04 6825 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 6826 register_name = "EntryLo0";
2423f660 6827 break;
6d27d5bd 6828 case CP0_REG02__TCSTATUS:
f31b035a 6829 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6830 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 6831 register_name = "TCStatus";
ead9360e 6832 break;
6d27d5bd 6833 case CP0_REG02__TCBIND:
f31b035a 6834 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6835 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 6836 register_name = "TCBind";
ead9360e 6837 break;
6d27d5bd 6838 case CP0_REG02__TCRESTART:
f31b035a 6839 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6840 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 6841 register_name = "TCRestart";
ead9360e 6842 break;
6d27d5bd 6843 case CP0_REG02__TCHALT:
f31b035a 6844 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6845 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 6846 register_name = "TCHalt";
ead9360e 6847 break;
6d27d5bd 6848 case CP0_REG02__TCCONTEXT:
f31b035a 6849 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6850 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 6851 register_name = "TCContext";
ead9360e 6852 break;
6d27d5bd 6853 case CP0_REG02__TCSCHEDULE:
f31b035a 6854 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6855 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 6856 register_name = "TCSchedule";
ead9360e 6857 break;
6d27d5bd 6858 case CP0_REG02__TCSCHEFBACK:
f31b035a 6859 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6860 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 6861 register_name = "TCScheFBack";
ead9360e 6862 break;
7a387fff 6863 default:
f31b035a 6864 goto cp0_unimplemented;
7a387fff 6865 }
8c0fdd85 6866 break;
04992c8c 6867 case CP0_REGISTER_03:
7a387fff 6868 switch (sel) {
acd37316 6869 case CP0_REG03__ENTRYLO1:
895c2d04 6870 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 6871 register_name = "EntryLo1";
2423f660 6872 break;
acd37316 6873 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6874 CP0_CHECK(ctx->vp);
6875 /* ignored */
294fc2ea 6876 register_name = "GlobalNumber";
01bc435b 6877 break;
7a387fff 6878 default:
f31b035a 6879 goto cp0_unimplemented;
876d4b07 6880 }
8c0fdd85 6881 break;
04992c8c 6882 case CP0_REGISTER_04:
7a387fff 6883 switch (sel) {
020fe379 6884 case CP0_REG04__CONTEXT:
895c2d04 6885 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 6886 register_name = "Context";
2423f660 6887 break;
020fe379
AM
6888 case CP0_REG04__CONTEXTCONFIG:
6889 /* SmartMIPS ASE */
6890 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 6891 register_name = "ContextConfig";
f31b035a 6892 goto cp0_unimplemented;
020fe379 6893 case CP0_REG04__USERLOCAL:
f31b035a
LA
6894 CP0_CHECK(ctx->ulri);
6895 tcg_gen_st_tl(arg, cpu_env,
6896 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 6897 register_name = "UserLocal";
d279279e 6898 break;
99029be1
YK
6899 case CP0_REG04__MMID:
6900 CP0_CHECK(ctx->mi);
6901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6902 register_name = "MMID";
6903 break;
7a387fff 6904 default:
f31b035a 6905 goto cp0_unimplemented;
876d4b07 6906 }
8c0fdd85 6907 break;
04992c8c 6908 case CP0_REGISTER_05:
7a387fff 6909 switch (sel) {
a1e76353 6910 case CP0_REG05__PAGEMASK:
895c2d04 6911 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 6912 register_name = "PageMask";
2423f660 6913 break;
a1e76353 6914 case CP0_REG05__PAGEGRAIN:
7a47bae5 6915 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6916 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 6917 register_name = "PageGrain";
eeb3bba8 6918 ctx->base.is_jmp = DISAS_STOP;
2423f660 6919 break;
a1e76353 6920 case CP0_REG05__SEGCTL0:
cec56a73
JH
6921 CP0_CHECK(ctx->sc);
6922 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 6923 register_name = "SegCtl0";
cec56a73 6924 break;
a1e76353 6925 case CP0_REG05__SEGCTL1:
cec56a73
JH
6926 CP0_CHECK(ctx->sc);
6927 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 6928 register_name = "SegCtl1";
cec56a73 6929 break;
a1e76353 6930 case CP0_REG05__SEGCTL2:
cec56a73
JH
6931 CP0_CHECK(ctx->sc);
6932 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 6933 register_name = "SegCtl2";
cec56a73 6934 break;
a1e76353 6935 case CP0_REG05__PWBASE:
5e31fdd5
YK
6936 check_pw(ctx);
6937 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6938 register_name = "PWBase";
5e31fdd5 6939 break;
a1e76353 6940 case CP0_REG05__PWFIELD:
fa75ad14
YK
6941 check_pw(ctx);
6942 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 6943 register_name = "PWField";
fa75ad14 6944 break;
a1e76353 6945 case CP0_REG05__PWSIZE:
20b28ebc
YK
6946 check_pw(ctx);
6947 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 6948 register_name = "PWSize";
20b28ebc 6949 break;
7a387fff 6950 default:
f31b035a 6951 goto cp0_unimplemented;
876d4b07 6952 }
8c0fdd85 6953 break;
04992c8c 6954 case CP0_REGISTER_06:
7a387fff 6955 switch (sel) {
9023594b 6956 case CP0_REG06__WIRED:
895c2d04 6957 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 6958 register_name = "Wired";
2423f660 6959 break;
9023594b 6960 case CP0_REG06__SRSCONF0:
7a47bae5 6961 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6962 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 6963 register_name = "SRSConf0";
ead9360e 6964 break;
9023594b 6965 case CP0_REG06__SRSCONF1:
7a47bae5 6966 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6967 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 6968 register_name = "SRSConf1";
ead9360e 6969 break;
9023594b 6970 case CP0_REG06__SRSCONF2:
7a47bae5 6971 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6972 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 6973 register_name = "SRSConf2";
ead9360e 6974 break;
9023594b 6975 case CP0_REG06__SRSCONF3:
7a47bae5 6976 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6977 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 6978 register_name = "SRSConf3";
ead9360e 6979 break;
9023594b 6980 case CP0_REG06__SRSCONF4:
7a47bae5 6981 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6982 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 6983 register_name = "SRSConf4";
ead9360e 6984 break;
9023594b 6985 case CP0_REG06__PWCTL:
103be64c
YK
6986 check_pw(ctx);
6987 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 6988 register_name = "PWCtl";
103be64c 6989 break;
7a387fff 6990 default:
f31b035a 6991 goto cp0_unimplemented;
876d4b07 6992 }
8c0fdd85 6993 break;
04992c8c 6994 case CP0_REGISTER_07:
7a387fff 6995 switch (sel) {
143a9875 6996 case CP0_REG07__HWRENA:
7a47bae5 6997 check_insn(ctx, ISA_MIPS_R2);
895c2d04 6998 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 6999 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7000 register_name = "HWREna";
2423f660 7001 break;
7a387fff 7002 default:
f31b035a 7003 goto cp0_unimplemented;
876d4b07 7004 }
8c0fdd85 7005 break;
04992c8c 7006 case CP0_REGISTER_08:
aea14095 7007 switch (sel) {
67d167d2 7008 case CP0_REG08__BADVADDR:
aea14095 7009 /* ignored */
294fc2ea 7010 register_name = "BadVAddr";
aea14095 7011 break;
67d167d2 7012 case CP0_REG08__BADINSTR:
aea14095 7013 /* ignored */
294fc2ea 7014 register_name = "BadInstr";
aea14095 7015 break;
67d167d2 7016 case CP0_REG08__BADINSTRP:
aea14095 7017 /* ignored */
294fc2ea 7018 register_name = "BadInstrP";
aea14095 7019 break;
67d167d2 7020 case CP0_REG08__BADINSTRX:
25beba9b 7021 /* ignored */
294fc2ea 7022 register_name = "BadInstrX";
25beba9b 7023 break;
aea14095 7024 default:
f31b035a 7025 goto cp0_unimplemented;
aea14095 7026 }
8c0fdd85 7027 break;
04992c8c 7028 case CP0_REGISTER_09:
7a387fff 7029 switch (sel) {
e5a98a72 7030 case CP0_REG09__COUNT:
895c2d04 7031 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 7032 register_name = "Count";
2423f660 7033 break;
e5a98a72 7034 case CP0_REG09__SAARI:
5fb2dcd1
YK
7035 CP0_CHECK(ctx->saar);
7036 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 7037 register_name = "SAARI";
5fb2dcd1 7038 break;
e5a98a72 7039 case CP0_REG09__SAAR:
5fb2dcd1
YK
7040 CP0_CHECK(ctx->saar);
7041 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 7042 register_name = "SAAR";
5fb2dcd1 7043 break;
7a387fff 7044 default:
f31b035a 7045 goto cp0_unimplemented;
876d4b07 7046 }
8c0fdd85 7047 break;
04992c8c 7048 case CP0_REGISTER_10:
7a387fff 7049 switch (sel) {
860ffef0 7050 case CP0_REG10__ENTRYHI:
895c2d04 7051 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 7052 register_name = "EntryHi";
2423f660 7053 break;
7a387fff 7054 default:
f31b035a 7055 goto cp0_unimplemented;
876d4b07 7056 }
8c0fdd85 7057 break;
04992c8c 7058 case CP0_REGISTER_11:
7a387fff 7059 switch (sel) {
f5f3834f 7060 case CP0_REG11__COMPARE:
895c2d04 7061 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 7062 register_name = "Compare";
2423f660
TS
7063 break;
7064 /* 6,7 are implementation dependent */
7a387fff 7065 default:
f31b035a 7066 goto cp0_unimplemented;
876d4b07 7067 }
8c0fdd85 7068 break;
04992c8c 7069 case CP0_REGISTER_12:
7a387fff 7070 switch (sel) {
2b084867 7071 case CP0_REG12__STATUS:
867abc7e 7072 save_cpu_state(ctx, 1);
895c2d04 7073 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7074 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7075 gen_save_pc(ctx->base.pc_next + 4);
7076 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7077 register_name = "Status";
2423f660 7078 break;
2b084867 7079 case CP0_REG12__INTCTL:
7a47bae5 7080 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7081 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7082 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7083 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7084 register_name = "IntCtl";
2423f660 7085 break;
2b084867 7086 case CP0_REG12__SRSCTL:
7a47bae5 7087 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7088 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7089 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7090 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7091 register_name = "SRSCtl";
2423f660 7092 break;
2b084867 7093 case CP0_REG12__SRSMAP:
7a47bae5 7094 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7095 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7096 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7097 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7098 register_name = "SRSMap";
fd88b6ab 7099 break;
7a387fff 7100 default:
f31b035a 7101 goto cp0_unimplemented;
876d4b07 7102 }
8c0fdd85 7103 break;
04992c8c 7104 case CP0_REGISTER_13:
7a387fff 7105 switch (sel) {
e3c7559d 7106 case CP0_REG13__CAUSE:
867abc7e 7107 save_cpu_state(ctx, 1);
895c2d04 7108 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
7109 /*
7110 * Stop translation as we may have triggered an interrupt.
b28425ba 7111 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
7112 * translated code to check for pending interrupts.
7113 */
eeb3bba8
EC
7114 gen_save_pc(ctx->base.pc_next + 4);
7115 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7116 register_name = "Cause";
2423f660 7117 break;
7a387fff 7118 default:
f31b035a 7119 goto cp0_unimplemented;
876d4b07 7120 }
8c0fdd85 7121 break;
04992c8c 7122 case CP0_REGISTER_14:
7a387fff 7123 switch (sel) {
35e4b54d 7124 case CP0_REG14__EPC:
d54a299b 7125 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7126 register_name = "EPC";
2423f660 7127 break;
7a387fff 7128 default:
f31b035a 7129 goto cp0_unimplemented;
876d4b07 7130 }
8c0fdd85 7131 break;
04992c8c 7132 case CP0_REGISTER_15:
7a387fff 7133 switch (sel) {
4466cd49 7134 case CP0_REG15__PRID:
2423f660 7135 /* ignored */
294fc2ea 7136 register_name = "PRid";
2423f660 7137 break;
4466cd49 7138 case CP0_REG15__EBASE:
7a47bae5 7139 check_insn(ctx, ISA_MIPS_R2);
895c2d04 7140 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 7141 register_name = "EBase";
2423f660 7142 break;
7a387fff 7143 default:
f31b035a 7144 goto cp0_unimplemented;
1579a72e 7145 }
8c0fdd85 7146 break;
04992c8c 7147 case CP0_REGISTER_16:
8c0fdd85 7148 switch (sel) {
433efb4c 7149 case CP0_REG16__CONFIG:
895c2d04 7150 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 7151 register_name = "Config";
2423f660 7152 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7153 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7154 break;
433efb4c 7155 case CP0_REG16__CONFIG1:
e397ee33 7156 /* ignored, read only */
294fc2ea 7157 register_name = "Config1";
7a387fff 7158 break;
433efb4c 7159 case CP0_REG16__CONFIG2:
895c2d04 7160 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 7161 register_name = "Config2";
2423f660 7162 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7163 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7164 break;
433efb4c 7165 case CP0_REG16__CONFIG3:
90f12d73 7166 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 7167 register_name = "Config3";
90f12d73 7168 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7169 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7170 break;
433efb4c 7171 case CP0_REG16__CONFIG4:
b4160af1 7172 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 7173 register_name = "Config4";
eeb3bba8 7174 ctx->base.is_jmp = DISAS_STOP;
b4160af1 7175 break;
433efb4c 7176 case CP0_REG16__CONFIG5:
b4dd99a3 7177 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 7178 register_name = "Config5";
b4dd99a3 7179 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7180 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 7181 break;
e397ee33 7182 /* 6,7 are implementation dependent */
433efb4c 7183 case CP0_REG16__CONFIG6:
e397ee33 7184 /* ignored */
294fc2ea 7185 register_name = "Config6";
e397ee33 7186 break;
433efb4c 7187 case CP0_REG16__CONFIG7:
e397ee33 7188 /* ignored */
294fc2ea 7189 register_name = "Config7";
e397ee33 7190 break;
8c0fdd85 7191 default:
294fc2ea 7192 register_name = "Invalid config selector";
f31b035a 7193 goto cp0_unimplemented;
8c0fdd85
TS
7194 }
7195 break;
04992c8c 7196 case CP0_REGISTER_17:
7a387fff 7197 switch (sel) {
706ce142 7198 case CP0_REG17__LLADDR:
895c2d04 7199 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 7200 register_name = "LLAddr";
2423f660 7201 break;
706ce142 7202 case CP0_REG17__MAAR:
f6d4dd81
YK
7203 CP0_CHECK(ctx->mrp);
7204 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 7205 register_name = "MAAR";
f6d4dd81 7206 break;
706ce142 7207 case CP0_REG17__MAARI:
f6d4dd81
YK
7208 CP0_CHECK(ctx->mrp);
7209 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 7210 register_name = "MAARI";
f6d4dd81 7211 break;
7a387fff 7212 default:
f31b035a 7213 goto cp0_unimplemented;
7a387fff 7214 }
8c0fdd85 7215 break;
04992c8c 7216 case CP0_REGISTER_18:
7a387fff 7217 switch (sel) {
e8dcfe82
AM
7218 case CP0_REG18__WATCHLO0:
7219 case CP0_REG18__WATCHLO1:
7220 case CP0_REG18__WATCHLO2:
7221 case CP0_REG18__WATCHLO3:
7222 case CP0_REG18__WATCHLO4:
7223 case CP0_REG18__WATCHLO5:
7224 case CP0_REG18__WATCHLO6:
7225 case CP0_REG18__WATCHLO7:
fa192d49 7226 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7227 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 7228 register_name = "WatchLo";
2423f660 7229 break;
7a387fff 7230 default:
f31b035a 7231 goto cp0_unimplemented;
7a387fff 7232 }
8c0fdd85 7233 break;
04992c8c 7234 case CP0_REGISTER_19:
7a387fff 7235 switch (sel) {
be274dc1
AM
7236 case CP0_REG19__WATCHHI0:
7237 case CP0_REG19__WATCHHI1:
7238 case CP0_REG19__WATCHHI2:
7239 case CP0_REG19__WATCHHI3:
7240 case CP0_REG19__WATCHHI4:
7241 case CP0_REG19__WATCHHI5:
7242 case CP0_REG19__WATCHHI6:
7243 case CP0_REG19__WATCHHI7:
fa192d49 7244 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7245 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 7246 register_name = "WatchHi";
2423f660 7247 break;
7a387fff 7248 default:
f31b035a 7249 goto cp0_unimplemented;
7a387fff 7250 }
8c0fdd85 7251 break;
04992c8c 7252 case CP0_REGISTER_20:
7a387fff 7253 switch (sel) {
14f92b0b 7254 case CP0_REG20__XCONTEXT:
d26bc211 7255#if defined(TARGET_MIPS64)
d75c135e 7256 check_insn(ctx, ISA_MIPS3);
895c2d04 7257 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 7258 register_name = "XContext";
2423f660 7259 break;
703eaf37 7260#endif
7a387fff 7261 default:
f31b035a 7262 goto cp0_unimplemented;
7a387fff 7263 }
8c0fdd85 7264 break;
04992c8c 7265 case CP0_REGISTER_21:
7a387fff 7266 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 7267 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
7268 switch (sel) {
7269 case 0:
895c2d04 7270 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 7271 register_name = "Framemask";
2423f660 7272 break;
7a387fff 7273 default:
f31b035a 7274 goto cp0_unimplemented;
7a387fff
TS
7275 }
7276 break;
04992c8c 7277 case CP0_REGISTER_22:
7a387fff 7278 /* ignored */
294fc2ea 7279 register_name = "Diagnostic"; /* implementation dependent */
2423f660 7280 break;
04992c8c 7281 case CP0_REGISTER_23:
7a387fff 7282 switch (sel) {
4cbf4b6d 7283 case CP0_REG23__DEBUG:
895c2d04 7284 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 7285 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7286 gen_save_pc(ctx->base.pc_next + 4);
7287 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7288 register_name = "Debug";
2423f660 7289 break;
4cbf4b6d
AM
7290 case CP0_REG23__TRACECONTROL:
7291 /* PDtrace support */
7292 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
294fc2ea 7293 register_name = "TraceControl";
8487327a 7294 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7295 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7296 goto cp0_unimplemented;
4cbf4b6d
AM
7297 case CP0_REG23__TRACECONTROL2:
7298 /* PDtrace support */
7299 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
294fc2ea 7300 register_name = "TraceControl2";
8487327a 7301 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7302 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7303 goto cp0_unimplemented;
4cbf4b6d 7304 case CP0_REG23__USERTRACEDATA1:
8487327a 7305 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7306 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
7307 /* PDtrace support */
7308 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
294fc2ea 7309 register_name = "UserTraceData";
8487327a 7310 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7311 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7312 goto cp0_unimplemented;
4cbf4b6d
AM
7313 case CP0_REG23__TRACEIBPC:
7314 /* PDtrace support */
7315 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8487327a 7316 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7317 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
7318 register_name = "TraceIBPC";
7319 goto cp0_unimplemented;
7320 case CP0_REG23__TRACEDBPC:
7321 /* PDtrace support */
7322 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7323 /* Stop translation as we may have switched the execution mode */
7324 ctx->base.is_jmp = DISAS_STOP;
7325 register_name = "TraceDBPC";
3570d7f6 7326 goto cp0_unimplemented;
7a387fff 7327 default:
f31b035a 7328 goto cp0_unimplemented;
7a387fff 7329 }
8c0fdd85 7330 break;
04992c8c 7331 case CP0_REGISTER_24:
7a387fff 7332 switch (sel) {
8d7b4b6e 7333 case CP0_REG24__DEPC:
f1aa6320 7334 /* EJTAG support */
d54a299b 7335 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 7336 register_name = "DEPC";
2423f660 7337 break;
7a387fff 7338 default:
f31b035a 7339 goto cp0_unimplemented;
7a387fff 7340 }
8c0fdd85 7341 break;
04992c8c 7342 case CP0_REGISTER_25:
7a387fff 7343 switch (sel) {
1176b328 7344 case CP0_REG25__PERFCTL0:
895c2d04 7345 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 7346 register_name = "Performance0";
2423f660 7347 break;
1176b328 7348 case CP0_REG25__PERFCNT0:
7480515f 7349 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 7350 register_name = "Performance1";
3570d7f6 7351 goto cp0_unimplemented;
1176b328 7352 case CP0_REG25__PERFCTL1:
7480515f 7353 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 7354 register_name = "Performance2";
3570d7f6 7355 goto cp0_unimplemented;
1176b328 7356 case CP0_REG25__PERFCNT1:
7480515f 7357 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 7358 register_name = "Performance3";
3570d7f6 7359 goto cp0_unimplemented;
1176b328 7360 case CP0_REG25__PERFCTL2:
7480515f 7361 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 7362 register_name = "Performance4";
3570d7f6 7363 goto cp0_unimplemented;
1176b328 7364 case CP0_REG25__PERFCNT2:
7480515f 7365 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 7366 register_name = "Performance5";
3570d7f6 7367 goto cp0_unimplemented;
1176b328 7368 case CP0_REG25__PERFCTL3:
7480515f 7369 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 7370 register_name = "Performance6";
3570d7f6 7371 goto cp0_unimplemented;
1176b328 7372 case CP0_REG25__PERFCNT3:
7480515f 7373 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 7374 register_name = "Performance7";
3570d7f6 7375 goto cp0_unimplemented;
7a387fff 7376 default:
f31b035a 7377 goto cp0_unimplemented;
7a387fff 7378 }
8c0fdd85 7379 break;
04992c8c 7380 case CP0_REGISTER_26:
0d74a222 7381 switch (sel) {
dbbf08b2 7382 case CP0_REG26__ERRCTL:
0d74a222 7383 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 7384 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7385 register_name = "ErrCtl";
0d74a222
LA
7386 break;
7387 default:
7388 goto cp0_unimplemented;
7389 }
2423f660 7390 break;
04992c8c 7391 case CP0_REGISTER_27:
7a387fff 7392 switch (sel) {
5a10873d 7393 case CP0_REG27__CACHERR:
2423f660 7394 /* ignored */
294fc2ea 7395 register_name = "CacheErr";
2423f660 7396 break;
7a387fff 7397 default:
f31b035a 7398 goto cp0_unimplemented;
7a387fff 7399 }
8c0fdd85 7400 break;
04992c8c 7401 case CP0_REGISTER_28:
8c0fdd85 7402 switch (sel) {
a30e2f21
AM
7403 case CP0_REG28__TAGLO:
7404 case CP0_REG28__TAGLO1:
7405 case CP0_REG28__TAGLO2:
7406 case CP0_REG28__TAGLO3:
895c2d04 7407 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 7408 register_name = "TagLo";
8c0fdd85 7409 break;
a30e2f21
AM
7410 case CP0_REG28__DATALO:
7411 case CP0_REG28__DATALO1:
7412 case CP0_REG28__DATALO2:
7413 case CP0_REG28__DATALO3:
895c2d04 7414 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 7415 register_name = "DataLo";
7a387fff 7416 break;
8c0fdd85 7417 default:
f31b035a 7418 goto cp0_unimplemented;
8c0fdd85
TS
7419 }
7420 break;
04992c8c 7421 case CP0_REGISTER_29:
7a387fff 7422 switch (sel) {
af4bb6da
AM
7423 case CP0_REG29__TAGHI:
7424 case CP0_REG29__TAGHI1:
7425 case CP0_REG29__TAGHI2:
7426 case CP0_REG29__TAGHI3:
895c2d04 7427 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 7428 register_name = "TagHi";
7a387fff 7429 break;
af4bb6da
AM
7430 case CP0_REG29__DATAHI:
7431 case CP0_REG29__DATAHI1:
7432 case CP0_REG29__DATAHI2:
7433 case CP0_REG29__DATAHI3:
895c2d04 7434 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 7435 register_name = "DataHi";
7a387fff
TS
7436 break;
7437 default:
294fc2ea 7438 register_name = "invalid sel";
f31b035a 7439 goto cp0_unimplemented;
7a387fff 7440 }
8c0fdd85 7441 break;
04992c8c 7442 case CP0_REGISTER_30:
7a387fff 7443 switch (sel) {
4bcf121e 7444 case CP0_REG30__ERROREPC:
d54a299b 7445 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 7446 register_name = "ErrorEPC";
2423f660 7447 break;
7a387fff 7448 default:
f31b035a 7449 goto cp0_unimplemented;
7a387fff 7450 }
8c0fdd85 7451 break;
04992c8c 7452 case CP0_REGISTER_31:
7a387fff 7453 switch (sel) {
14d92efd 7454 case CP0_REG31__DESAVE:
f1aa6320 7455 /* EJTAG support */
7db13fae 7456 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7457 register_name = "DESAVE";
2423f660 7458 break;
14d92efd
AM
7459 case CP0_REG31__KSCRATCH1:
7460 case CP0_REG31__KSCRATCH2:
7461 case CP0_REG31__KSCRATCH3:
7462 case CP0_REG31__KSCRATCH4:
7463 case CP0_REG31__KSCRATCH5:
7464 case CP0_REG31__KSCRATCH6:
f31b035a
LA
7465 CP0_CHECK(ctx->kscrexist & (1 << sel));
7466 tcg_gen_st_tl(arg, cpu_env,
05aa7e93 7467 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 7468 register_name = "KScratch";
e98c0d17 7469 break;
7a387fff 7470 default:
f31b035a 7471 goto cp0_unimplemented;
7a387fff 7472 }
8c0fdd85
TS
7473 break;
7474 default:
f31b035a 7475 goto cp0_unimplemented;
8c0fdd85 7476 }
294fc2ea 7477 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 7478
bf20dc07 7479 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 7480 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
7481 /*
7482 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7483 * translated code to check for pending interrupts.
7484 */
eeb3bba8
EC
7485 gen_save_pc(ctx->base.pc_next + 4);
7486 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 7487 }
8c0fdd85
TS
7488 return;
7489
f31b035a 7490cp0_unimplemented:
294fc2ea
AM
7491 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7492 register_name, reg, sel);
8c0fdd85
TS
7493}
7494
d26bc211 7495#if defined(TARGET_MIPS64)
d75c135e 7496static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 7497{
294fc2ea 7498 const char *register_name = "invalid";
9c2149c8 7499
1f8929d2 7500 if (sel != 0) {
bbd5e4a2 7501 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 7502 }
e189e748 7503
9c2149c8 7504 switch (reg) {
04992c8c 7505 case CP0_REGISTER_00:
9c2149c8 7506 switch (sel) {
1b142da5 7507 case CP0_REG00__INDEX:
7db13fae 7508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 7509 register_name = "Index";
9c2149c8 7510 break;
1b142da5 7511 case CP0_REG00__MVPCONTROL:
f31b035a 7512 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7513 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 7514 register_name = "MVPControl";
ead9360e 7515 break;
1b142da5 7516 case CP0_REG00__MVPCONF0:
f31b035a 7517 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7518 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 7519 register_name = "MVPConf0";
ead9360e 7520 break;
1b142da5 7521 case CP0_REG00__MVPCONF1:
f31b035a 7522 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7523 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 7524 register_name = "MVPConf1";
ead9360e 7525 break;
1b142da5 7526 case CP0_REG00__VPCONTROL:
01bc435b
YK
7527 CP0_CHECK(ctx->vp);
7528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 7529 register_name = "VPControl";
01bc435b 7530 break;
9c2149c8 7531 default:
f31b035a 7532 goto cp0_unimplemented;
9c2149c8
TS
7533 }
7534 break;
04992c8c 7535 case CP0_REGISTER_01:
9c2149c8 7536 switch (sel) {
30deb460 7537 case CP0_REG01__RANDOM:
2e211e0a 7538 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
895c2d04 7539 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 7540 register_name = "Random";
2423f660 7541 break;
30deb460 7542 case CP0_REG01__VPECONTROL:
f31b035a 7543 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 7545 register_name = "VPEControl";
ead9360e 7546 break;
30deb460 7547 case CP0_REG01__VPECONF0:
f31b035a 7548 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 7550 register_name = "VPEConf0";
ead9360e 7551 break;
30deb460 7552 case CP0_REG01__VPECONF1:
f31b035a 7553 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 7555 register_name = "VPEConf1";
ead9360e 7556 break;
30deb460 7557 case CP0_REG01__YQMASK:
f31b035a 7558 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7559 tcg_gen_ld_tl(arg, cpu_env,
7560 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 7561 register_name = "YQMask";
ead9360e 7562 break;
30deb460 7563 case CP0_REG01__VPESCHEDULE:
f31b035a 7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7565 tcg_gen_ld_tl(arg, cpu_env,
7566 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7567 register_name = "VPESchedule";
ead9360e 7568 break;
30deb460 7569 case CP0_REG01__VPESCHEFBACK:
f31b035a 7570 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
7571 tcg_gen_ld_tl(arg, cpu_env,
7572 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7573 register_name = "VPEScheFBack";
ead9360e 7574 break;
30deb460 7575 case CP0_REG01__VPEOPT:
f31b035a 7576 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 7578 register_name = "VPEOpt";
ead9360e 7579 break;
9c2149c8 7580 default:
f31b035a 7581 goto cp0_unimplemented;
9c2149c8
TS
7582 }
7583 break;
04992c8c 7584 case CP0_REGISTER_02:
9c2149c8 7585 switch (sel) {
6d27d5bd 7586 case CP0_REG02__ENTRYLO0:
05aa7e93
AM
7587 tcg_gen_ld_tl(arg, cpu_env,
7588 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 7589 register_name = "EntryLo0";
2423f660 7590 break;
6d27d5bd 7591 case CP0_REG02__TCSTATUS:
f31b035a 7592 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7593 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 7594 register_name = "TCStatus";
ead9360e 7595 break;
6d27d5bd 7596 case CP0_REG02__TCBIND:
f31b035a 7597 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7598 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 7599 register_name = "TCBind";
ead9360e 7600 break;
6d27d5bd 7601 case CP0_REG02__TCRESTART:
f31b035a 7602 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7603 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 7604 register_name = "TCRestart";
ead9360e 7605 break;
6d27d5bd 7606 case CP0_REG02__TCHALT:
f31b035a 7607 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7608 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 7609 register_name = "TCHalt";
ead9360e 7610 break;
6d27d5bd 7611 case CP0_REG02__TCCONTEXT:
f31b035a 7612 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7613 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 7614 register_name = "TCContext";
ead9360e 7615 break;
6d27d5bd 7616 case CP0_REG02__TCSCHEDULE:
f31b035a 7617 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7618 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 7619 register_name = "TCSchedule";
ead9360e 7620 break;
6d27d5bd 7621 case CP0_REG02__TCSCHEFBACK:
f31b035a 7622 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7623 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 7624 register_name = "TCScheFBack";
ead9360e 7625 break;
9c2149c8 7626 default:
f31b035a 7627 goto cp0_unimplemented;
9c2149c8
TS
7628 }
7629 break;
04992c8c 7630 case CP0_REGISTER_03:
9c2149c8 7631 switch (sel) {
acd37316 7632 case CP0_REG03__ENTRYLO1:
7db13fae 7633 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 7634 register_name = "EntryLo1";
2423f660 7635 break;
acd37316 7636 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7637 CP0_CHECK(ctx->vp);
7638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7639 register_name = "GlobalNumber";
01bc435b 7640 break;
9c2149c8 7641 default:
f31b035a 7642 goto cp0_unimplemented;
1579a72e 7643 }
9c2149c8 7644 break;
04992c8c 7645 case CP0_REGISTER_04:
9c2149c8 7646 switch (sel) {
020fe379 7647 case CP0_REG04__CONTEXT:
7db13fae 7648 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 7649 register_name = "Context";
2423f660 7650 break;
020fe379
AM
7651 case CP0_REG04__CONTEXTCONFIG:
7652 /* SmartMIPS ASE */
7653 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 7654 register_name = "ContextConfig";
f31b035a 7655 goto cp0_unimplemented;
020fe379 7656 case CP0_REG04__USERLOCAL:
f31b035a
LA
7657 CP0_CHECK(ctx->ulri);
7658 tcg_gen_ld_tl(arg, cpu_env,
7659 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7660 register_name = "UserLocal";
d279279e 7661 break;
99029be1
YK
7662 case CP0_REG04__MMID:
7663 CP0_CHECK(ctx->mi);
7664 gen_helper_mtc0_memorymapid(cpu_env, arg);
7665 register_name = "MMID";
7666 break;
9c2149c8 7667 default:
f31b035a 7668 goto cp0_unimplemented;
876d4b07 7669 }
9c2149c8 7670 break;
04992c8c 7671 case CP0_REGISTER_05:
9c2149c8 7672 switch (sel) {
a1e76353 7673 case CP0_REG05__PAGEMASK:
7db13fae 7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7675 register_name = "PageMask";
2423f660 7676 break;
a1e76353 7677 case CP0_REG05__PAGEGRAIN:
7a47bae5 7678 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7680 register_name = "PageGrain";
2423f660 7681 break;
a1e76353 7682 case CP0_REG05__SEGCTL0:
cec56a73
JH
7683 CP0_CHECK(ctx->sc);
7684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 7685 register_name = "SegCtl0";
cec56a73 7686 break;
a1e76353 7687 case CP0_REG05__SEGCTL1:
cec56a73
JH
7688 CP0_CHECK(ctx->sc);
7689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 7690 register_name = "SegCtl1";
cec56a73 7691 break;
a1e76353 7692 case CP0_REG05__SEGCTL2:
cec56a73
JH
7693 CP0_CHECK(ctx->sc);
7694 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 7695 register_name = "SegCtl2";
cec56a73 7696 break;
a1e76353 7697 case CP0_REG05__PWBASE:
5e31fdd5
YK
7698 check_pw(ctx);
7699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7700 register_name = "PWBase";
5e31fdd5 7701 break;
a1e76353 7702 case CP0_REG05__PWFIELD:
fa75ad14
YK
7703 check_pw(ctx);
7704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7705 register_name = "PWField";
fa75ad14 7706 break;
a1e76353 7707 case CP0_REG05__PWSIZE:
20b28ebc
YK
7708 check_pw(ctx);
7709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7710 register_name = "PWSize";
20b28ebc 7711 break;
9c2149c8 7712 default:
f31b035a 7713 goto cp0_unimplemented;
876d4b07 7714 }
9c2149c8 7715 break;
04992c8c 7716 case CP0_REGISTER_06:
9c2149c8 7717 switch (sel) {
9023594b 7718 case CP0_REG06__WIRED:
7db13fae 7719 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7720 register_name = "Wired";
2423f660 7721 break;
9023594b 7722 case CP0_REG06__SRSCONF0:
7a47bae5 7723 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7725 register_name = "SRSConf0";
ead9360e 7726 break;
9023594b 7727 case CP0_REG06__SRSCONF1:
7a47bae5 7728 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7730 register_name = "SRSConf1";
ead9360e 7731 break;
9023594b 7732 case CP0_REG06__SRSCONF2:
7a47bae5 7733 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7735 register_name = "SRSConf2";
ead9360e 7736 break;
9023594b 7737 case CP0_REG06__SRSCONF3:
7a47bae5 7738 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7740 register_name = "SRSConf3";
ead9360e 7741 break;
9023594b 7742 case CP0_REG06__SRSCONF4:
7a47bae5 7743 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7745 register_name = "SRSConf4";
ead9360e 7746 break;
9023594b 7747 case CP0_REG06__PWCTL:
103be64c
YK
7748 check_pw(ctx);
7749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7750 register_name = "PWCtl";
103be64c 7751 break;
9c2149c8 7752 default:
f31b035a 7753 goto cp0_unimplemented;
876d4b07 7754 }
9c2149c8 7755 break;
04992c8c 7756 case CP0_REGISTER_07:
9c2149c8 7757 switch (sel) {
143a9875 7758 case CP0_REG07__HWRENA:
7a47bae5 7759 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7761 register_name = "HWREna";
2423f660 7762 break;
9c2149c8 7763 default:
f31b035a 7764 goto cp0_unimplemented;
876d4b07 7765 }
9c2149c8 7766 break;
04992c8c 7767 case CP0_REGISTER_08:
9c2149c8 7768 switch (sel) {
67d167d2 7769 case CP0_REG08__BADVADDR:
7db13fae 7770 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 7771 register_name = "BadVAddr";
2423f660 7772 break;
67d167d2 7773 case CP0_REG08__BADINSTR:
f31b035a
LA
7774 CP0_CHECK(ctx->bi);
7775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7776 register_name = "BadInstr";
aea14095 7777 break;
67d167d2 7778 case CP0_REG08__BADINSTRP:
f31b035a
LA
7779 CP0_CHECK(ctx->bp);
7780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7781 register_name = "BadInstrP";
aea14095 7782 break;
67d167d2 7783 case CP0_REG08__BADINSTRX:
25beba9b
SM
7784 CP0_CHECK(ctx->bi);
7785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7786 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7787 register_name = "BadInstrX";
25beba9b 7788 break;
9c2149c8 7789 default:
f31b035a 7790 goto cp0_unimplemented;
876d4b07 7791 }
9c2149c8 7792 break;
04992c8c 7793 case CP0_REGISTER_09:
9c2149c8 7794 switch (sel) {
e5a98a72 7795 case CP0_REG09__COUNT:
2e70f6ef 7796 /* Mark as an IO operation because we read the time. */
eeb3bba8 7797 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7798 gen_io_start();
bd79255d 7799 }
895c2d04 7800 gen_helper_mfc0_count(arg, cpu_env);
7480515f
AM
7801 /*
7802 * Break the TB to be able to take timer interrupts immediately
7803 * after reading count. DISAS_STOP isn't sufficient, we need to
7804 * ensure we break completely out of translated code.
7805 */
eeb3bba8
EC
7806 gen_save_pc(ctx->base.pc_next + 4);
7807 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7808 register_name = "Count";
2423f660 7809 break;
e5a98a72 7810 case CP0_REG09__SAARI:
5fb2dcd1
YK
7811 CP0_CHECK(ctx->saar);
7812 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7813 register_name = "SAARI";
5fb2dcd1 7814 break;
e5a98a72 7815 case CP0_REG09__SAAR:
5fb2dcd1
YK
7816 CP0_CHECK(ctx->saar);
7817 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 7818 register_name = "SAAR";
5fb2dcd1 7819 break;
9c2149c8 7820 default:
f31b035a 7821 goto cp0_unimplemented;
876d4b07 7822 }
9c2149c8 7823 break;
04992c8c 7824 case CP0_REGISTER_10:
9c2149c8 7825 switch (sel) {
860ffef0 7826 case CP0_REG10__ENTRYHI:
7db13fae 7827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 7828 register_name = "EntryHi";
2423f660 7829 break;
9c2149c8 7830 default:
f31b035a 7831 goto cp0_unimplemented;
876d4b07 7832 }
9c2149c8 7833 break;
04992c8c 7834 case CP0_REGISTER_11:
9c2149c8 7835 switch (sel) {
f5f3834f 7836 case CP0_REG11__COMPARE:
7db13fae 7837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7838 register_name = "Compare";
2423f660 7839 break;
876d4b07 7840 /* 6,7 are implementation dependent */
9c2149c8 7841 default:
f31b035a 7842 goto cp0_unimplemented;
876d4b07 7843 }
9c2149c8 7844 break;
04992c8c 7845 case CP0_REGISTER_12:
9c2149c8 7846 switch (sel) {
2b084867 7847 case CP0_REG12__STATUS:
7db13fae 7848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7849 register_name = "Status";
2423f660 7850 break;
2b084867 7851 case CP0_REG12__INTCTL:
7a47bae5 7852 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7854 register_name = "IntCtl";
2423f660 7855 break;
2b084867 7856 case CP0_REG12__SRSCTL:
7a47bae5 7857 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7859 register_name = "SRSCtl";
2423f660 7860 break;
2b084867 7861 case CP0_REG12__SRSMAP:
7a47bae5 7862 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7864 register_name = "SRSMap";
2423f660 7865 break;
9c2149c8 7866 default:
f31b035a 7867 goto cp0_unimplemented;
876d4b07 7868 }
9c2149c8 7869 break;
04992c8c 7870 case CP0_REGISTER_13:
9c2149c8 7871 switch (sel) {
e3c7559d 7872 case CP0_REG13__CAUSE:
7db13fae 7873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7874 register_name = "Cause";
2423f660 7875 break;
9c2149c8 7876 default:
f31b035a 7877 goto cp0_unimplemented;
876d4b07 7878 }
9c2149c8 7879 break;
04992c8c 7880 case CP0_REGISTER_14:
9c2149c8 7881 switch (sel) {
35e4b54d 7882 case CP0_REG14__EPC:
7db13fae 7883 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7884 register_name = "EPC";
2423f660 7885 break;
9c2149c8 7886 default:
f31b035a 7887 goto cp0_unimplemented;
876d4b07 7888 }
9c2149c8 7889 break;
04992c8c 7890 case CP0_REGISTER_15:
9c2149c8 7891 switch (sel) {
4466cd49 7892 case CP0_REG15__PRID:
7db13fae 7893 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7894 register_name = "PRid";
2423f660 7895 break;
4466cd49 7896 case CP0_REG15__EBASE:
7a47bae5 7897 check_insn(ctx, ISA_MIPS_R2);
74dbf824 7898 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 7899 register_name = "EBase";
2423f660 7900 break;
4466cd49 7901 case CP0_REG15__CMGCRBASE:
7a47bae5 7902 check_insn(ctx, ISA_MIPS_R2);
c870e3f5
YK
7903 CP0_CHECK(ctx->cmgcr);
7904 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 7905 register_name = "CMGCRBase";
c870e3f5 7906 break;
9c2149c8 7907 default:
f31b035a 7908 goto cp0_unimplemented;
876d4b07 7909 }
9c2149c8 7910 break;
04992c8c 7911 case CP0_REGISTER_16:
9c2149c8 7912 switch (sel) {
433efb4c 7913 case CP0_REG16__CONFIG:
7db13fae 7914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7915 register_name = "Config";
9c2149c8 7916 break;
433efb4c 7917 case CP0_REG16__CONFIG1:
7db13fae 7918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7919 register_name = "Config1";
9c2149c8 7920 break;
433efb4c 7921 case CP0_REG16__CONFIG2:
7db13fae 7922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7923 register_name = "Config2";
9c2149c8 7924 break;
433efb4c 7925 case CP0_REG16__CONFIG3:
7db13fae 7926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7927 register_name = "Config3";
9c2149c8 7928 break;
433efb4c 7929 case CP0_REG16__CONFIG4:
faf1f68b 7930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7931 register_name = "Config4";
faf1f68b 7932 break;
433efb4c 7933 case CP0_REG16__CONFIG5:
faf1f68b 7934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7935 register_name = "Config5";
faf1f68b 7936 break;
05aa7e93 7937 /* 6,7 are implementation dependent */
433efb4c 7938 case CP0_REG16__CONFIG6:
7db13fae 7939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7940 register_name = "Config6";
f0b3f3ae 7941 break;
433efb4c 7942 case CP0_REG16__CONFIG7:
7db13fae 7943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7944 register_name = "Config7";
f0b3f3ae 7945 break;
9c2149c8 7946 default:
f31b035a 7947 goto cp0_unimplemented;
9c2149c8
TS
7948 }
7949 break;
04992c8c 7950 case CP0_REGISTER_17:
9c2149c8 7951 switch (sel) {
706ce142 7952 case CP0_REG17__LLADDR:
895c2d04 7953 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 7954 register_name = "LLAddr";
2423f660 7955 break;
706ce142 7956 case CP0_REG17__MAAR:
f6d4dd81
YK
7957 CP0_CHECK(ctx->mrp);
7958 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 7959 register_name = "MAAR";
f6d4dd81 7960 break;
706ce142 7961 case CP0_REG17__MAARI:
f6d4dd81
YK
7962 CP0_CHECK(ctx->mrp);
7963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7964 register_name = "MAARI";
f6d4dd81 7965 break;
9c2149c8 7966 default:
f31b035a 7967 goto cp0_unimplemented;
9c2149c8
TS
7968 }
7969 break;
04992c8c 7970 case CP0_REGISTER_18:
9c2149c8 7971 switch (sel) {
e8dcfe82
AM
7972 case CP0_REG18__WATCHLO0:
7973 case CP0_REG18__WATCHLO1:
7974 case CP0_REG18__WATCHLO2:
7975 case CP0_REG18__WATCHLO3:
7976 case CP0_REG18__WATCHLO4:
7977 case CP0_REG18__WATCHLO5:
7978 case CP0_REG18__WATCHLO6:
7979 case CP0_REG18__WATCHLO7:
fa192d49 7980 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7981 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 7982 register_name = "WatchLo";
2423f660 7983 break;
9c2149c8 7984 default:
f31b035a 7985 goto cp0_unimplemented;
9c2149c8
TS
7986 }
7987 break;
04992c8c 7988 case CP0_REGISTER_19:
9c2149c8 7989 switch (sel) {
be274dc1
AM
7990 case CP0_REG19__WATCHHI0:
7991 case CP0_REG19__WATCHHI1:
7992 case CP0_REG19__WATCHHI2:
7993 case CP0_REG19__WATCHHI3:
7994 case CP0_REG19__WATCHHI4:
7995 case CP0_REG19__WATCHHI5:
7996 case CP0_REG19__WATCHHI6:
7997 case CP0_REG19__WATCHHI7:
fa192d49 7998 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 7999 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 8000 register_name = "WatchHi";
2423f660 8001 break;
9c2149c8 8002 default:
f31b035a 8003 goto cp0_unimplemented;
9c2149c8
TS
8004 }
8005 break;
04992c8c 8006 case CP0_REGISTER_20:
9c2149c8 8007 switch (sel) {
14f92b0b 8008 case CP0_REG20__XCONTEXT:
d75c135e 8009 check_insn(ctx, ISA_MIPS3);
7db13fae 8010 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8011 register_name = "XContext";
2423f660 8012 break;
9c2149c8 8013 default:
f31b035a 8014 goto cp0_unimplemented;
9c2149c8
TS
8015 }
8016 break;
04992c8c 8017 case CP0_REGISTER_21:
05aa7e93 8018 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8019 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
8020 switch (sel) {
8021 case 0:
7db13fae 8022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8023 register_name = "Framemask";
2423f660 8024 break;
9c2149c8 8025 default:
f31b035a 8026 goto cp0_unimplemented;
9c2149c8
TS
8027 }
8028 break;
04992c8c 8029 case CP0_REGISTER_22:
d9bea114 8030 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8031 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8032 break;
04992c8c 8033 case CP0_REGISTER_23:
9c2149c8 8034 switch (sel) {
4cbf4b6d 8035 case CP0_REG23__DEBUG:
895c2d04 8036 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 8037 register_name = "Debug";
2423f660 8038 break;
4cbf4b6d
AM
8039 case CP0_REG23__TRACECONTROL:
8040 /* PDtrace support */
8041 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
294fc2ea 8042 register_name = "TraceControl";
3570d7f6 8043 goto cp0_unimplemented;
4cbf4b6d
AM
8044 case CP0_REG23__TRACECONTROL2:
8045 /* PDtrace support */
8046 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
294fc2ea 8047 register_name = "TraceControl2";
3570d7f6 8048 goto cp0_unimplemented;
4cbf4b6d
AM
8049 case CP0_REG23__USERTRACEDATA1:
8050 /* PDtrace support */
8051 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8052 register_name = "UserTraceData1";
3570d7f6 8053 goto cp0_unimplemented;
4cbf4b6d
AM
8054 case CP0_REG23__TRACEIBPC:
8055 /* PDtrace support */
8056 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8057 register_name = "TraceIBPC";
8058 goto cp0_unimplemented;
8059 case CP0_REG23__TRACEDBPC:
8060 /* PDtrace support */
8061 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8062 register_name = "TraceDBPC";
3570d7f6 8063 goto cp0_unimplemented;
9c2149c8 8064 default:
f31b035a 8065 goto cp0_unimplemented;
9c2149c8
TS
8066 }
8067 break;
04992c8c 8068 case CP0_REGISTER_24:
9c2149c8 8069 switch (sel) {
8d7b4b6e 8070 case CP0_REG24__DEPC:
f0b3f3ae 8071 /* EJTAG support */
7db13fae 8072 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8073 register_name = "DEPC";
2423f660 8074 break;
9c2149c8 8075 default:
f31b035a 8076 goto cp0_unimplemented;
9c2149c8
TS
8077 }
8078 break;
04992c8c 8079 case CP0_REGISTER_25:
9c2149c8 8080 switch (sel) {
1176b328 8081 case CP0_REG25__PERFCTL0:
7db13fae 8082 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8083 register_name = "Performance0";
9c2149c8 8084 break;
1176b328 8085 case CP0_REG25__PERFCNT0:
7480515f 8086 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 8087 register_name = "Performance1";
3570d7f6 8088 goto cp0_unimplemented;
1176b328 8089 case CP0_REG25__PERFCTL1:
7480515f 8090 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 8091 register_name = "Performance2";
3570d7f6 8092 goto cp0_unimplemented;
1176b328 8093 case CP0_REG25__PERFCNT1:
7480515f 8094 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 8095 register_name = "Performance3";
3570d7f6 8096 goto cp0_unimplemented;
1176b328 8097 case CP0_REG25__PERFCTL2:
7480515f 8098 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 8099 register_name = "Performance4";
3570d7f6 8100 goto cp0_unimplemented;
1176b328 8101 case CP0_REG25__PERFCNT2:
7480515f 8102 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 8103 register_name = "Performance5";
3570d7f6 8104 goto cp0_unimplemented;
1176b328 8105 case CP0_REG25__PERFCTL3:
7480515f 8106 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 8107 register_name = "Performance6";
3570d7f6 8108 goto cp0_unimplemented;
1176b328 8109 case CP0_REG25__PERFCNT3:
7480515f 8110 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 8111 register_name = "Performance7";
3570d7f6 8112 goto cp0_unimplemented;
9c2149c8 8113 default:
f31b035a 8114 goto cp0_unimplemented;
9c2149c8
TS
8115 }
8116 break;
04992c8c 8117 case CP0_REGISTER_26:
0d74a222 8118 switch (sel) {
dbbf08b2 8119 case CP0_REG26__ERRCTL:
0d74a222 8120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8121 register_name = "ErrCtl";
0d74a222
LA
8122 break;
8123 default:
8124 goto cp0_unimplemented;
8125 }
da80682b 8126 break;
04992c8c 8127 case CP0_REGISTER_27:
9c2149c8
TS
8128 switch (sel) {
8129 /* ignored */
5a10873d 8130 case CP0_REG27__CACHERR:
d9bea114 8131 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8132 register_name = "CacheErr";
2423f660 8133 break;
9c2149c8 8134 default:
f31b035a 8135 goto cp0_unimplemented;
9c2149c8
TS
8136 }
8137 break;
04992c8c 8138 case CP0_REGISTER_28:
9c2149c8 8139 switch (sel) {
a30e2f21
AM
8140 case CP0_REG28__TAGLO:
8141 case CP0_REG28__TAGLO1:
8142 case CP0_REG28__TAGLO2:
8143 case CP0_REG28__TAGLO3:
7db13fae 8144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 8145 register_name = "TagLo";
9c2149c8 8146 break;
a30e2f21
AM
8147 case CP0_REG28__DATALO:
8148 case CP0_REG28__DATALO1:
8149 case CP0_REG28__DATALO2:
8150 case CP0_REG28__DATALO3:
7db13fae 8151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8152 register_name = "DataLo";
9c2149c8
TS
8153 break;
8154 default:
f31b035a 8155 goto cp0_unimplemented;
9c2149c8
TS
8156 }
8157 break;
04992c8c 8158 case CP0_REGISTER_29:
9c2149c8 8159 switch (sel) {
af4bb6da
AM
8160 case CP0_REG29__TAGHI:
8161 case CP0_REG29__TAGHI1:
8162 case CP0_REG29__TAGHI2:
8163 case CP0_REG29__TAGHI3:
7db13fae 8164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8165 register_name = "TagHi";
9c2149c8 8166 break;
af4bb6da
AM
8167 case CP0_REG29__DATAHI:
8168 case CP0_REG29__DATAHI1:
8169 case CP0_REG29__DATAHI2:
8170 case CP0_REG29__DATAHI3:
7db13fae 8171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8172 register_name = "DataHi";
9c2149c8
TS
8173 break;
8174 default:
f31b035a 8175 goto cp0_unimplemented;
9c2149c8
TS
8176 }
8177 break;
04992c8c 8178 case CP0_REGISTER_30:
9c2149c8 8179 switch (sel) {
4bcf121e 8180 case CP0_REG30__ERROREPC:
7db13fae 8181 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8182 register_name = "ErrorEPC";
2423f660 8183 break;
9c2149c8 8184 default:
f31b035a 8185 goto cp0_unimplemented;
9c2149c8
TS
8186 }
8187 break;
04992c8c 8188 case CP0_REGISTER_31:
9c2149c8 8189 switch (sel) {
14d92efd 8190 case CP0_REG31__DESAVE:
f0b3f3ae 8191 /* EJTAG support */
7db13fae 8192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8193 register_name = "DESAVE";
2423f660 8194 break;
14d92efd
AM
8195 case CP0_REG31__KSCRATCH1:
8196 case CP0_REG31__KSCRATCH2:
8197 case CP0_REG31__KSCRATCH3:
8198 case CP0_REG31__KSCRATCH4:
8199 case CP0_REG31__KSCRATCH5:
8200 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8201 CP0_CHECK(ctx->kscrexist & (1 << sel));
8202 tcg_gen_ld_tl(arg, cpu_env,
05aa7e93 8203 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8204 register_name = "KScratch";
e98c0d17 8205 break;
9c2149c8 8206 default:
f31b035a 8207 goto cp0_unimplemented;
9c2149c8
TS
8208 }
8209 break;
8210 default:
f31b035a 8211 goto cp0_unimplemented;
9c2149c8 8212 }
294fc2ea 8213 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
8214 return;
8215
f31b035a 8216cp0_unimplemented:
294fc2ea
AM
8217 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8218 register_name, reg, sel);
f31b035a 8219 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
8220}
8221
d75c135e 8222static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8223{
294fc2ea 8224 const char *register_name = "invalid";
9c2149c8 8225
1f8929d2 8226 if (sel != 0) {
bbd5e4a2 8227 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 8228 }
e189e748 8229
eeb3bba8 8230 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8231 gen_io_start();
bd79255d 8232 }
2e70f6ef 8233
9c2149c8 8234 switch (reg) {
04992c8c 8235 case CP0_REGISTER_00:
9c2149c8 8236 switch (sel) {
1b142da5 8237 case CP0_REG00__INDEX:
895c2d04 8238 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 8239 register_name = "Index";
9c2149c8 8240 break;
1b142da5 8241 case CP0_REG00__MVPCONTROL:
f31b035a 8242 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8243 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 8244 register_name = "MVPControl";
ead9360e 8245 break;
1b142da5 8246 case CP0_REG00__MVPCONF0:
f31b035a 8247 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8248 /* ignored */
294fc2ea 8249 register_name = "MVPConf0";
ead9360e 8250 break;
1b142da5 8251 case CP0_REG00__MVPCONF1:
f31b035a 8252 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8253 /* ignored */
294fc2ea 8254 register_name = "MVPConf1";
ead9360e 8255 break;
1b142da5 8256 case CP0_REG00__VPCONTROL:
01bc435b
YK
8257 CP0_CHECK(ctx->vp);
8258 /* ignored */
294fc2ea 8259 register_name = "VPControl";
01bc435b 8260 break;
9c2149c8 8261 default:
f31b035a 8262 goto cp0_unimplemented;
9c2149c8
TS
8263 }
8264 break;
04992c8c 8265 case CP0_REGISTER_01:
9c2149c8 8266 switch (sel) {
30deb460 8267 case CP0_REG01__RANDOM:
2423f660 8268 /* ignored */
294fc2ea 8269 register_name = "Random";
2423f660 8270 break;
30deb460 8271 case CP0_REG01__VPECONTROL:
f31b035a 8272 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8273 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 8274 register_name = "VPEControl";
ead9360e 8275 break;
30deb460 8276 case CP0_REG01__VPECONF0:
f31b035a 8277 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8278 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 8279 register_name = "VPEConf0";
ead9360e 8280 break;
30deb460 8281 case CP0_REG01__VPECONF1:
f31b035a 8282 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8283 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 8284 register_name = "VPEConf1";
ead9360e 8285 break;
30deb460 8286 case CP0_REG01__YQMASK:
f31b035a 8287 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8288 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 8289 register_name = "YQMask";
ead9360e 8290 break;
30deb460 8291 case CP0_REG01__VPESCHEDULE:
f31b035a 8292 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8293 tcg_gen_st_tl(arg, cpu_env,
8294 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8295 register_name = "VPESchedule";
ead9360e 8296 break;
30deb460 8297 case CP0_REG01__VPESCHEFBACK:
f31b035a 8298 CP0_CHECK(ctx->insn_flags & ASE_MT);
05aa7e93
AM
8299 tcg_gen_st_tl(arg, cpu_env,
8300 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8301 register_name = "VPEScheFBack";
ead9360e 8302 break;
30deb460 8303 case CP0_REG01__VPEOPT:
f31b035a 8304 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8305 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 8306 register_name = "VPEOpt";
ead9360e 8307 break;
9c2149c8 8308 default:
f31b035a 8309 goto cp0_unimplemented;
9c2149c8
TS
8310 }
8311 break;
04992c8c 8312 case CP0_REGISTER_02:
9c2149c8 8313 switch (sel) {
6d27d5bd 8314 case CP0_REG02__ENTRYLO0:
7207c7f9 8315 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 8316 register_name = "EntryLo0";
2423f660 8317 break;
6d27d5bd 8318 case CP0_REG02__TCSTATUS:
f31b035a 8319 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8320 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 8321 register_name = "TCStatus";
ead9360e 8322 break;
6d27d5bd 8323 case CP0_REG02__TCBIND:
f31b035a 8324 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8325 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 8326 register_name = "TCBind";
ead9360e 8327 break;
6d27d5bd 8328 case CP0_REG02__TCRESTART:
f31b035a 8329 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8330 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 8331 register_name = "TCRestart";
ead9360e 8332 break;
6d27d5bd 8333 case CP0_REG02__TCHALT:
f31b035a 8334 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8335 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 8336 register_name = "TCHalt";
ead9360e 8337 break;
6d27d5bd 8338 case CP0_REG02__TCCONTEXT:
f31b035a 8339 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8340 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 8341 register_name = "TCContext";
ead9360e 8342 break;
6d27d5bd 8343 case CP0_REG02__TCSCHEDULE:
f31b035a 8344 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8345 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 8346 register_name = "TCSchedule";
ead9360e 8347 break;
6d27d5bd 8348 case CP0_REG02__TCSCHEFBACK:
f31b035a 8349 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8350 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 8351 register_name = "TCScheFBack";
ead9360e 8352 break;
9c2149c8 8353 default:
f31b035a 8354 goto cp0_unimplemented;
9c2149c8
TS
8355 }
8356 break;
04992c8c 8357 case CP0_REGISTER_03:
9c2149c8 8358 switch (sel) {
acd37316 8359 case CP0_REG03__ENTRYLO1:
7207c7f9 8360 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 8361 register_name = "EntryLo1";
2423f660 8362 break;
acd37316 8363 case CP0_REG03__GLOBALNUM:
01bc435b
YK
8364 CP0_CHECK(ctx->vp);
8365 /* ignored */
294fc2ea 8366 register_name = "GlobalNumber";
01bc435b 8367 break;
9c2149c8 8368 default:
f31b035a 8369 goto cp0_unimplemented;
876d4b07 8370 }
9c2149c8 8371 break;
04992c8c 8372 case CP0_REGISTER_04:
9c2149c8 8373 switch (sel) {
020fe379 8374 case CP0_REG04__CONTEXT:
895c2d04 8375 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 8376 register_name = "Context";
2423f660 8377 break;
020fe379
AM
8378 case CP0_REG04__CONTEXTCONFIG:
8379 /* SmartMIPS ASE */
8380 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 8381 register_name = "ContextConfig";
f31b035a 8382 goto cp0_unimplemented;
020fe379 8383 case CP0_REG04__USERLOCAL:
f31b035a
LA
8384 CP0_CHECK(ctx->ulri);
8385 tcg_gen_st_tl(arg, cpu_env,
8386 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8387 register_name = "UserLocal";
d279279e 8388 break;
99029be1
YK
8389 case CP0_REG04__MMID:
8390 CP0_CHECK(ctx->mi);
8391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8392 register_name = "MMID";
8393 break;
9c2149c8 8394 default:
f31b035a 8395 goto cp0_unimplemented;
876d4b07 8396 }
9c2149c8 8397 break;
04992c8c 8398 case CP0_REGISTER_05:
9c2149c8 8399 switch (sel) {
a1e76353 8400 case CP0_REG05__PAGEMASK:
895c2d04 8401 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 8402 register_name = "PageMask";
2423f660 8403 break;
a1e76353 8404 case CP0_REG05__PAGEGRAIN:
7a47bae5 8405 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8406 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 8407 register_name = "PageGrain";
2423f660 8408 break;
a1e76353 8409 case CP0_REG05__SEGCTL0:
cec56a73
JH
8410 CP0_CHECK(ctx->sc);
8411 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 8412 register_name = "SegCtl0";
cec56a73 8413 break;
a1e76353 8414 case CP0_REG05__SEGCTL1:
cec56a73
JH
8415 CP0_CHECK(ctx->sc);
8416 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 8417 register_name = "SegCtl1";
cec56a73 8418 break;
a1e76353 8419 case CP0_REG05__SEGCTL2:
cec56a73
JH
8420 CP0_CHECK(ctx->sc);
8421 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 8422 register_name = "SegCtl2";
cec56a73 8423 break;
a1e76353 8424 case CP0_REG05__PWBASE:
5e31fdd5
YK
8425 check_pw(ctx);
8426 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8427 register_name = "PWBase";
5e31fdd5 8428 break;
a1e76353 8429 case CP0_REG05__PWFIELD:
fa75ad14
YK
8430 check_pw(ctx);
8431 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 8432 register_name = "PWField";
fa75ad14 8433 break;
a1e76353 8434 case CP0_REG05__PWSIZE:
20b28ebc
YK
8435 check_pw(ctx);
8436 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 8437 register_name = "PWSize";
20b28ebc 8438 break;
9c2149c8 8439 default:
f31b035a 8440 goto cp0_unimplemented;
876d4b07 8441 }
9c2149c8 8442 break;
04992c8c 8443 case CP0_REGISTER_06:
9c2149c8 8444 switch (sel) {
9023594b 8445 case CP0_REG06__WIRED:
895c2d04 8446 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 8447 register_name = "Wired";
2423f660 8448 break;
9023594b 8449 case CP0_REG06__SRSCONF0:
7a47bae5 8450 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8451 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 8452 register_name = "SRSConf0";
ead9360e 8453 break;
9023594b 8454 case CP0_REG06__SRSCONF1:
7a47bae5 8455 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8456 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 8457 register_name = "SRSConf1";
ead9360e 8458 break;
9023594b 8459 case CP0_REG06__SRSCONF2:
7a47bae5 8460 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8461 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 8462 register_name = "SRSConf2";
ead9360e 8463 break;
9023594b 8464 case CP0_REG06__SRSCONF3:
7a47bae5 8465 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8466 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 8467 register_name = "SRSConf3";
ead9360e 8468 break;
9023594b 8469 case CP0_REG06__SRSCONF4:
7a47bae5 8470 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8471 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 8472 register_name = "SRSConf4";
ead9360e 8473 break;
9023594b 8474 case CP0_REG06__PWCTL:
103be64c
YK
8475 check_pw(ctx);
8476 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 8477 register_name = "PWCtl";
103be64c 8478 break;
9c2149c8 8479 default:
f31b035a 8480 goto cp0_unimplemented;
876d4b07 8481 }
9c2149c8 8482 break;
04992c8c 8483 case CP0_REGISTER_07:
9c2149c8 8484 switch (sel) {
143a9875 8485 case CP0_REG07__HWRENA:
7a47bae5 8486 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8487 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 8488 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8489 register_name = "HWREna";
2423f660 8490 break;
9c2149c8 8491 default:
f31b035a 8492 goto cp0_unimplemented;
876d4b07 8493 }
9c2149c8 8494 break;
04992c8c 8495 case CP0_REGISTER_08:
aea14095 8496 switch (sel) {
67d167d2 8497 case CP0_REG08__BADVADDR:
aea14095 8498 /* ignored */
294fc2ea 8499 register_name = "BadVAddr";
aea14095 8500 break;
67d167d2 8501 case CP0_REG08__BADINSTR:
aea14095 8502 /* ignored */
294fc2ea 8503 register_name = "BadInstr";
aea14095 8504 break;
67d167d2 8505 case CP0_REG08__BADINSTRP:
aea14095 8506 /* ignored */
294fc2ea 8507 register_name = "BadInstrP";
aea14095 8508 break;
67d167d2 8509 case CP0_REG08__BADINSTRX:
25beba9b 8510 /* ignored */
294fc2ea 8511 register_name = "BadInstrX";
25beba9b 8512 break;
aea14095 8513 default:
f31b035a 8514 goto cp0_unimplemented;
aea14095 8515 }
9c2149c8 8516 break;
04992c8c 8517 case CP0_REGISTER_09:
9c2149c8 8518 switch (sel) {
e5a98a72 8519 case CP0_REG09__COUNT:
895c2d04 8520 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 8521 register_name = "Count";
2423f660 8522 break;
e5a98a72 8523 case CP0_REG09__SAARI:
5fb2dcd1
YK
8524 CP0_CHECK(ctx->saar);
8525 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 8526 register_name = "SAARI";
5fb2dcd1 8527 break;
e5a98a72 8528 case CP0_REG09__SAAR:
5fb2dcd1
YK
8529 CP0_CHECK(ctx->saar);
8530 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 8531 register_name = "SAAR";
5fb2dcd1 8532 break;
9c2149c8 8533 default:
f31b035a 8534 goto cp0_unimplemented;
876d4b07
TS
8535 }
8536 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8537 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8538 break;
04992c8c 8539 case CP0_REGISTER_10:
9c2149c8 8540 switch (sel) {
860ffef0 8541 case CP0_REG10__ENTRYHI:
895c2d04 8542 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 8543 register_name = "EntryHi";
2423f660 8544 break;
9c2149c8 8545 default:
f31b035a 8546 goto cp0_unimplemented;
876d4b07 8547 }
9c2149c8 8548 break;
04992c8c 8549 case CP0_REGISTER_11:
9c2149c8 8550 switch (sel) {
f5f3834f 8551 case CP0_REG11__COMPARE:
895c2d04 8552 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 8553 register_name = "Compare";
2423f660 8554 break;
876d4b07 8555 /* 6,7 are implementation dependent */
9c2149c8 8556 default:
f31b035a 8557 goto cp0_unimplemented;
876d4b07 8558 }
de9a95f0 8559 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8560 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8561 break;
04992c8c 8562 case CP0_REGISTER_12:
9c2149c8 8563 switch (sel) {
2b084867 8564 case CP0_REG12__STATUS:
867abc7e 8565 save_cpu_state(ctx, 1);
895c2d04 8566 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8567 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8568 gen_save_pc(ctx->base.pc_next + 4);
8569 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8570 register_name = "Status";
2423f660 8571 break;
2b084867 8572 case CP0_REG12__INTCTL:
7a47bae5 8573 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8574 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8575 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8576 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8577 register_name = "IntCtl";
2423f660 8578 break;
2b084867 8579 case CP0_REG12__SRSCTL:
7a47bae5 8580 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8581 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8582 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8583 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8584 register_name = "SRSCtl";
2423f660 8585 break;
2b084867 8586 case CP0_REG12__SRSMAP:
7a47bae5 8587 check_insn(ctx, ISA_MIPS_R2);
7db13fae 8588 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8589 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8590 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8591 register_name = "SRSMap";
2423f660
TS
8592 break;
8593 default:
f31b035a 8594 goto cp0_unimplemented;
876d4b07 8595 }
9c2149c8 8596 break;
04992c8c 8597 case CP0_REGISTER_13:
9c2149c8 8598 switch (sel) {
e3c7559d 8599 case CP0_REG13__CAUSE:
867abc7e 8600 save_cpu_state(ctx, 1);
895c2d04 8601 gen_helper_mtc0_cause(cpu_env, arg);
7480515f
AM
8602 /*
8603 * Stop translation as we may have triggered an interrupt.
b28425ba 8604 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
8605 * translated code to check for pending interrupts.
8606 */
eeb3bba8
EC
8607 gen_save_pc(ctx->base.pc_next + 4);
8608 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8609 register_name = "Cause";
2423f660 8610 break;
9c2149c8 8611 default:
f31b035a 8612 goto cp0_unimplemented;
876d4b07 8613 }
9c2149c8 8614 break;
04992c8c 8615 case CP0_REGISTER_14:
9c2149c8 8616 switch (sel) {
35e4b54d 8617 case CP0_REG14__EPC:
7db13fae 8618 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8619 register_name = "EPC";
2423f660 8620 break;
9c2149c8 8621 default:
f31b035a 8622 goto cp0_unimplemented;
876d4b07 8623 }
9c2149c8 8624 break;
04992c8c 8625 case CP0_REGISTER_15:
9c2149c8 8626 switch (sel) {
4466cd49 8627 case CP0_REG15__PRID:
2423f660 8628 /* ignored */
294fc2ea 8629 register_name = "PRid";
2423f660 8630 break;
4466cd49 8631 case CP0_REG15__EBASE:
7a47bae5 8632 check_insn(ctx, ISA_MIPS_R2);
895c2d04 8633 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 8634 register_name = "EBase";
2423f660 8635 break;
9c2149c8 8636 default:
f31b035a 8637 goto cp0_unimplemented;
876d4b07 8638 }
9c2149c8 8639 break;
04992c8c 8640 case CP0_REGISTER_16:
9c2149c8 8641 switch (sel) {
433efb4c 8642 case CP0_REG16__CONFIG:
895c2d04 8643 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 8644 register_name = "Config";
2423f660 8645 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8646 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8647 break;
433efb4c 8648 case CP0_REG16__CONFIG1:
1fc7bf6e 8649 /* ignored, read only */
294fc2ea 8650 register_name = "Config1";
9c2149c8 8651 break;
433efb4c 8652 case CP0_REG16__CONFIG2:
895c2d04 8653 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 8654 register_name = "Config2";
2423f660 8655 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8656 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8657 break;
433efb4c 8658 case CP0_REG16__CONFIG3:
90f12d73 8659 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 8660 register_name = "Config3";
90f12d73 8661 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8662 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8663 break;
433efb4c 8664 case CP0_REG16__CONFIG4:
faf1f68b 8665 /* currently ignored */
294fc2ea 8666 register_name = "Config4";
faf1f68b 8667 break;
433efb4c 8668 case CP0_REG16__CONFIG5:
faf1f68b 8669 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 8670 register_name = "Config5";
faf1f68b 8671 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8672 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 8673 break;
9c2149c8
TS
8674 /* 6,7 are implementation dependent */
8675 default:
294fc2ea 8676 register_name = "Invalid config selector";
f31b035a 8677 goto cp0_unimplemented;
9c2149c8 8678 }
9c2149c8 8679 break;
04992c8c 8680 case CP0_REGISTER_17:
9c2149c8 8681 switch (sel) {
706ce142 8682 case CP0_REG17__LLADDR:
895c2d04 8683 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 8684 register_name = "LLAddr";
2423f660 8685 break;
706ce142 8686 case CP0_REG17__MAAR:
f6d4dd81
YK
8687 CP0_CHECK(ctx->mrp);
8688 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 8689 register_name = "MAAR";
f6d4dd81 8690 break;
706ce142 8691 case CP0_REG17__MAARI:
f6d4dd81
YK
8692 CP0_CHECK(ctx->mrp);
8693 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 8694 register_name = "MAARI";
f6d4dd81 8695 break;
9c2149c8 8696 default:
f31b035a 8697 goto cp0_unimplemented;
9c2149c8
TS
8698 }
8699 break;
04992c8c 8700 case CP0_REGISTER_18:
9c2149c8 8701 switch (sel) {
e8dcfe82
AM
8702 case CP0_REG18__WATCHLO0:
8703 case CP0_REG18__WATCHLO1:
8704 case CP0_REG18__WATCHLO2:
8705 case CP0_REG18__WATCHLO3:
8706 case CP0_REG18__WATCHLO4:
8707 case CP0_REG18__WATCHLO5:
8708 case CP0_REG18__WATCHLO6:
8709 case CP0_REG18__WATCHLO7:
fa192d49 8710 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8711 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8712 register_name = "WatchLo";
2423f660 8713 break;
9c2149c8 8714 default:
f31b035a 8715 goto cp0_unimplemented;
9c2149c8
TS
8716 }
8717 break;
04992c8c 8718 case CP0_REGISTER_19:
9c2149c8 8719 switch (sel) {
be274dc1
AM
8720 case CP0_REG19__WATCHHI0:
8721 case CP0_REG19__WATCHHI1:
8722 case CP0_REG19__WATCHHI2:
8723 case CP0_REG19__WATCHHI3:
8724 case CP0_REG19__WATCHHI4:
8725 case CP0_REG19__WATCHHI5:
8726 case CP0_REG19__WATCHHI6:
8727 case CP0_REG19__WATCHHI7:
fa192d49 8728 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8729 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8730 register_name = "WatchHi";
2423f660 8731 break;
9c2149c8 8732 default:
f31b035a 8733 goto cp0_unimplemented;
9c2149c8
TS
8734 }
8735 break;
04992c8c 8736 case CP0_REGISTER_20:
9c2149c8 8737 switch (sel) {
14f92b0b 8738 case CP0_REG20__XCONTEXT:
d75c135e 8739 check_insn(ctx, ISA_MIPS3);
895c2d04 8740 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8741 register_name = "XContext";
2423f660 8742 break;
9c2149c8 8743 default:
f31b035a 8744 goto cp0_unimplemented;
9c2149c8
TS
8745 }
8746 break;
04992c8c 8747 case CP0_REGISTER_21:
9c2149c8 8748 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8749 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
8750 switch (sel) {
8751 case 0:
895c2d04 8752 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8753 register_name = "Framemask";
2423f660 8754 break;
9c2149c8 8755 default:
f31b035a 8756 goto cp0_unimplemented;
9c2149c8
TS
8757 }
8758 break;
04992c8c 8759 case CP0_REGISTER_22:
9c2149c8 8760 /* ignored */
294fc2ea 8761 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 8762 break;
04992c8c 8763 case CP0_REGISTER_23:
9c2149c8 8764 switch (sel) {
4cbf4b6d 8765 case CP0_REG23__DEBUG:
895c2d04 8766 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8767 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8768 gen_save_pc(ctx->base.pc_next + 4);
8769 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8770 register_name = "Debug";
2423f660 8771 break;
4cbf4b6d
AM
8772 case CP0_REG23__TRACECONTROL:
8773 /* PDtrace support */
8774 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8487327a 8775 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8776 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8777 register_name = "TraceControl";
3570d7f6 8778 goto cp0_unimplemented;
4cbf4b6d
AM
8779 case CP0_REG23__TRACECONTROL2:
8780 /* PDtrace support */
8781 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8487327a 8782 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8783 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8784 register_name = "TraceControl2";
3570d7f6 8785 goto cp0_unimplemented;
4cbf4b6d
AM
8786 case CP0_REG23__USERTRACEDATA1:
8787 /* PDtrace support */
8788 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8487327a 8789 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8790 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8791 register_name = "UserTraceData1";
3570d7f6 8792 goto cp0_unimplemented;
4cbf4b6d
AM
8793 case CP0_REG23__TRACEIBPC:
8794 /* PDtrace support */
8795 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8796 /* Stop translation as we may have switched the execution mode */
8797 ctx->base.is_jmp = DISAS_STOP;
8798 register_name = "TraceIBPC";
8799 goto cp0_unimplemented;
8800 case CP0_REG23__TRACEDBPC:
8801 /* PDtrace support */
8802 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8487327a 8803 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8804 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8805 register_name = "TraceDBPC";
3570d7f6 8806 goto cp0_unimplemented;
9c2149c8 8807 default:
f31b035a 8808 goto cp0_unimplemented;
9c2149c8 8809 }
9c2149c8 8810 break;
04992c8c 8811 case CP0_REGISTER_24:
9c2149c8 8812 switch (sel) {
8d7b4b6e 8813 case CP0_REG24__DEPC:
f1aa6320 8814 /* EJTAG support */
7db13fae 8815 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8816 register_name = "DEPC";
2423f660 8817 break;
9c2149c8 8818 default:
f31b035a 8819 goto cp0_unimplemented;
9c2149c8
TS
8820 }
8821 break;
04992c8c 8822 case CP0_REGISTER_25:
9c2149c8 8823 switch (sel) {
1176b328 8824 case CP0_REG25__PERFCTL0:
895c2d04 8825 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8826 register_name = "Performance0";
2423f660 8827 break;
1176b328 8828 case CP0_REG25__PERFCNT0:
7480515f 8829 /* gen_helper_mtc0_performance1(cpu_env, arg); */
294fc2ea 8830 register_name = "Performance1";
3570d7f6 8831 goto cp0_unimplemented;
1176b328 8832 case CP0_REG25__PERFCTL1:
7480515f 8833 /* gen_helper_mtc0_performance2(cpu_env, arg); */
294fc2ea 8834 register_name = "Performance2";
3570d7f6 8835 goto cp0_unimplemented;
1176b328 8836 case CP0_REG25__PERFCNT1:
7480515f 8837 /* gen_helper_mtc0_performance3(cpu_env, arg); */
294fc2ea 8838 register_name = "Performance3";
3570d7f6 8839 goto cp0_unimplemented;
1176b328 8840 case CP0_REG25__PERFCTL2:
7480515f 8841 /* gen_helper_mtc0_performance4(cpu_env, arg); */
294fc2ea 8842 register_name = "Performance4";
3570d7f6 8843 goto cp0_unimplemented;
1176b328 8844 case CP0_REG25__PERFCNT2:
7480515f 8845 /* gen_helper_mtc0_performance5(cpu_env, arg); */
294fc2ea 8846 register_name = "Performance5";
3570d7f6 8847 goto cp0_unimplemented;
1176b328 8848 case CP0_REG25__PERFCTL3:
7480515f 8849 /* gen_helper_mtc0_performance6(cpu_env, arg); */
294fc2ea 8850 register_name = "Performance6";
3570d7f6 8851 goto cp0_unimplemented;
1176b328 8852 case CP0_REG25__PERFCNT3:
7480515f 8853 /* gen_helper_mtc0_performance7(cpu_env, arg); */
294fc2ea 8854 register_name = "Performance7";
3570d7f6 8855 goto cp0_unimplemented;
9c2149c8 8856 default:
f31b035a 8857 goto cp0_unimplemented;
9c2149c8 8858 }
876d4b07 8859 break;
04992c8c 8860 case CP0_REGISTER_26:
0d74a222 8861 switch (sel) {
dbbf08b2 8862 case CP0_REG26__ERRCTL:
0d74a222 8863 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8864 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8865 register_name = "ErrCtl";
0d74a222
LA
8866 break;
8867 default:
8868 goto cp0_unimplemented;
8869 }
876d4b07 8870 break;
04992c8c 8871 case CP0_REGISTER_27:
9c2149c8 8872 switch (sel) {
5a10873d 8873 case CP0_REG27__CACHERR:
2423f660 8874 /* ignored */
294fc2ea 8875 register_name = "CacheErr";
2423f660 8876 break;
9c2149c8 8877 default:
f31b035a 8878 goto cp0_unimplemented;
9c2149c8 8879 }
876d4b07 8880 break;
04992c8c 8881 case CP0_REGISTER_28:
9c2149c8 8882 switch (sel) {
a30e2f21
AM
8883 case CP0_REG28__TAGLO:
8884 case CP0_REG28__TAGLO1:
8885 case CP0_REG28__TAGLO2:
8886 case CP0_REG28__TAGLO3:
895c2d04 8887 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8888 register_name = "TagLo";
9c2149c8 8889 break;
a30e2f21
AM
8890 case CP0_REG28__DATALO:
8891 case CP0_REG28__DATALO1:
8892 case CP0_REG28__DATALO2:
8893 case CP0_REG28__DATALO3:
895c2d04 8894 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8895 register_name = "DataLo";
9c2149c8
TS
8896 break;
8897 default:
f31b035a 8898 goto cp0_unimplemented;
9c2149c8
TS
8899 }
8900 break;
04992c8c 8901 case CP0_REGISTER_29:
9c2149c8 8902 switch (sel) {
af4bb6da
AM
8903 case CP0_REG29__TAGHI:
8904 case CP0_REG29__TAGHI1:
8905 case CP0_REG29__TAGHI2:
8906 case CP0_REG29__TAGHI3:
895c2d04 8907 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8908 register_name = "TagHi";
9c2149c8 8909 break;
af4bb6da
AM
8910 case CP0_REG29__DATAHI:
8911 case CP0_REG29__DATAHI1:
8912 case CP0_REG29__DATAHI2:
8913 case CP0_REG29__DATAHI3:
895c2d04 8914 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8915 register_name = "DataHi";
9c2149c8
TS
8916 break;
8917 default:
294fc2ea 8918 register_name = "invalid sel";
f31b035a 8919 goto cp0_unimplemented;
9c2149c8 8920 }
876d4b07 8921 break;
04992c8c 8922 case CP0_REGISTER_30:
9c2149c8 8923 switch (sel) {
4bcf121e 8924 case CP0_REG30__ERROREPC:
7db13fae 8925 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8926 register_name = "ErrorEPC";
2423f660 8927 break;
9c2149c8 8928 default:
f31b035a 8929 goto cp0_unimplemented;
9c2149c8
TS
8930 }
8931 break;
04992c8c 8932 case CP0_REGISTER_31:
9c2149c8 8933 switch (sel) {
14d92efd 8934 case CP0_REG31__DESAVE:
f1aa6320 8935 /* EJTAG support */
7db13fae 8936 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8937 register_name = "DESAVE";
2423f660 8938 break;
14d92efd
AM
8939 case CP0_REG31__KSCRATCH1:
8940 case CP0_REG31__KSCRATCH2:
8941 case CP0_REG31__KSCRATCH3:
8942 case CP0_REG31__KSCRATCH4:
8943 case CP0_REG31__KSCRATCH5:
8944 case CP0_REG31__KSCRATCH6:
f31b035a
LA
8945 CP0_CHECK(ctx->kscrexist & (1 << sel));
8946 tcg_gen_st_tl(arg, cpu_env,
71375b59 8947 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8948 register_name = "KScratch";
e98c0d17 8949 break;
9c2149c8 8950 default:
f31b035a 8951 goto cp0_unimplemented;
9c2149c8 8952 }
9c2149c8
TS
8953 break;
8954 default:
f31b035a 8955 goto cp0_unimplemented;
9c2149c8 8956 }
294fc2ea 8957 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 8958
bf20dc07 8959 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8960 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7480515f
AM
8961 /*
8962 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8963 * translated code to check for pending interrupts.
8964 */
eeb3bba8
EC
8965 gen_save_pc(ctx->base.pc_next + 4);
8966 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8967 }
9c2149c8
TS
8968 return;
8969
f31b035a 8970cp0_unimplemented:
294fc2ea
AM
8971 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8972 register_name, reg, sel);
9c2149c8 8973}
d26bc211 8974#endif /* TARGET_MIPS64 */
9c2149c8 8975
7db13fae 8976static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
8977 int u, int sel, int h)
8978{
8979 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8980 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
8981
8982 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 8983 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 8984 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 8985 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
8986 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8987 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 8988 tcg_gen_movi_tl(t0, -1);
1f8929d2 8989 } else if (u == 0) {
ead9360e 8990 switch (rt) {
5a25ce94
EI
8991 case 1:
8992 switch (sel) {
8993 case 1:
895c2d04 8994 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
8995 break;
8996 case 2:
895c2d04 8997 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
8998 break;
8999 default:
9000 goto die;
9001 break;
9002 }
9003 break;
ead9360e
TS
9004 case 2:
9005 switch (sel) {
9006 case 1:
895c2d04 9007 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9008 break;
9009 case 2:
895c2d04 9010 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9011 break;
9012 case 3:
895c2d04 9013 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9014 break;
9015 case 4:
895c2d04 9016 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9017 break;
9018 case 5:
895c2d04 9019 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9020 break;
9021 case 6:
895c2d04 9022 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9023 break;
9024 case 7:
895c2d04 9025 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9026 break;
9027 default:
d75c135e 9028 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9029 break;
9030 }
9031 break;
9032 case 10:
9033 switch (sel) {
9034 case 0:
895c2d04 9035 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9036 break;
9037 default:
d75c135e 9038 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9039 break;
9040 }
f1fadbb2 9041 break;
ead9360e
TS
9042 case 12:
9043 switch (sel) {
9044 case 0:
895c2d04 9045 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9046 break;
9047 default:
d75c135e 9048 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9049 break;
9050 }
f1fadbb2 9051 break;
5a25ce94
EI
9052 case 13:
9053 switch (sel) {
9054 case 0:
895c2d04 9055 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9056 break;
9057 default:
9058 goto die;
9059 break;
9060 }
9061 break;
9062 case 14:
9063 switch (sel) {
9064 case 0:
895c2d04 9065 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9066 break;
9067 default:
9068 goto die;
9069 break;
9070 }
9071 break;
9072 case 15:
9073 switch (sel) {
9074 case 1:
895c2d04 9075 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9076 break;
9077 default:
9078 goto die;
9079 break;
9080 }
9081 break;
9082 case 16:
9083 switch (sel) {
c2e19f3c
AM
9084 case 0:
9085 case 1:
9086 case 2:
9087 case 3:
9088 case 4:
9089 case 5:
9090 case 6:
9091 case 7:
895c2d04 9092 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9093 break;
9094 default:
9095 goto die;
9096 break;
9097 }
9098 break;
ead9360e
TS
9099 case 23:
9100 switch (sel) {
9101 case 0:
895c2d04 9102 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9103 break;
9104 default:
d75c135e 9105 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9106 break;
9107 }
9108 break;
9109 default:
d75c135e 9110 gen_mfc0(ctx, t0, rt, sel);
ead9360e 9111 }
71375b59
AM
9112 } else {
9113 switch (sel) {
9114 /* GPR registers. */
ead9360e 9115 case 0:
71375b59 9116 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 9117 break;
71375b59 9118 /* Auxiliary CPU registers */
ead9360e 9119 case 1:
71375b59
AM
9120 switch (rt) {
9121 case 0:
9122 gen_helper_1e0i(mftlo, t0, 0);
9123 break;
9124 case 1:
9125 gen_helper_1e0i(mfthi, t0, 0);
9126 break;
9127 case 2:
9128 gen_helper_1e0i(mftacx, t0, 0);
9129 break;
9130 case 4:
9131 gen_helper_1e0i(mftlo, t0, 1);
9132 break;
9133 case 5:
9134 gen_helper_1e0i(mfthi, t0, 1);
9135 break;
9136 case 6:
9137 gen_helper_1e0i(mftacx, t0, 1);
9138 break;
9139 case 8:
9140 gen_helper_1e0i(mftlo, t0, 2);
9141 break;
9142 case 9:
9143 gen_helper_1e0i(mfthi, t0, 2);
9144 break;
9145 case 10:
9146 gen_helper_1e0i(mftacx, t0, 2);
9147 break;
9148 case 12:
9149 gen_helper_1e0i(mftlo, t0, 3);
9150 break;
9151 case 13:
9152 gen_helper_1e0i(mfthi, t0, 3);
9153 break;
9154 case 14:
9155 gen_helper_1e0i(mftacx, t0, 3);
9156 break;
9157 case 16:
9158 gen_helper_mftdsp(t0, cpu_env);
9159 break;
9160 default:
9161 goto die;
9162 }
ead9360e 9163 break;
71375b59 9164 /* Floating point (COP1). */
ead9360e 9165 case 2:
71375b59
AM
9166 /* XXX: For now we support only a single FPU context. */
9167 if (h == 0) {
9168 TCGv_i32 fp0 = tcg_temp_new_i32();
9169
9170 gen_load_fpr32(ctx, fp0, rt);
9171 tcg_gen_ext_i32_tl(t0, fp0);
9172 tcg_temp_free_i32(fp0);
9173 } else {
9174 TCGv_i32 fp0 = tcg_temp_new_i32();
9175
9176 gen_load_fpr32h(ctx, fp0, rt);
9177 tcg_gen_ext_i32_tl(t0, fp0);
9178 tcg_temp_free_i32(fp0);
9179 }
ead9360e 9180 break;
71375b59
AM
9181 case 3:
9182 /* XXX: For now we support only a single FPU context. */
9183 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 9184 break;
71375b59
AM
9185 /* COP2: Not implemented. */
9186 case 4:
ead9360e 9187 case 5:
71375b59 9188 /* fall through */
ead9360e
TS
9189 default:
9190 goto die;
9191 }
ead9360e 9192 }
b44a7fb1 9193 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
9194 gen_store_gpr(t0, rd);
9195 tcg_temp_free(t0);
ead9360e
TS
9196 return;
9197
9198die:
1a3fd9c3 9199 tcg_temp_free(t0);
d12d51d5 9200 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
3a4ef3b7 9201 gen_reserved_instruction(ctx);
ead9360e
TS
9202}
9203
7db13fae 9204static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
9205 int u, int sel, int h)
9206{
9207 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9208 TCGv t0 = tcg_temp_local_new();
ead9360e 9209
1a3fd9c3 9210 gen_load_gpr(t0, rt);
ead9360e 9211 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 9212 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 9213 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
9214 /* NOP */
9215 ;
1f8929d2
AM
9216 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9217 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
9218 /* NOP */
9219 ;
1f8929d2 9220 } else if (u == 0) {
ead9360e 9221 switch (rd) {
5a25ce94
EI
9222 case 1:
9223 switch (sel) {
9224 case 1:
895c2d04 9225 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
9226 break;
9227 case 2:
895c2d04 9228 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
9229 break;
9230 default:
9231 goto die;
9232 break;
9233 }
9234 break;
ead9360e
TS
9235 case 2:
9236 switch (sel) {
9237 case 1:
895c2d04 9238 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
9239 break;
9240 case 2:
895c2d04 9241 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
9242 break;
9243 case 3:
895c2d04 9244 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
9245 break;
9246 case 4:
895c2d04 9247 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
9248 break;
9249 case 5:
895c2d04 9250 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
9251 break;
9252 case 6:
895c2d04 9253 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
9254 break;
9255 case 7:
895c2d04 9256 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
9257 break;
9258 default:
d75c135e 9259 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9260 break;
9261 }
9262 break;
9263 case 10:
9264 switch (sel) {
9265 case 0:
895c2d04 9266 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
9267 break;
9268 default:
d75c135e 9269 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9270 break;
9271 }
0d0304f2 9272 break;
ead9360e
TS
9273 case 12:
9274 switch (sel) {
9275 case 0:
895c2d04 9276 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
9277 break;
9278 default:
d75c135e 9279 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9280 break;
9281 }
0d0304f2 9282 break;
5a25ce94
EI
9283 case 13:
9284 switch (sel) {
9285 case 0:
895c2d04 9286 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
9287 break;
9288 default:
9289 goto die;
9290 break;
9291 }
9292 break;
9293 case 15:
9294 switch (sel) {
9295 case 1:
895c2d04 9296 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
9297 break;
9298 default:
9299 goto die;
9300 break;
9301 }
9302 break;
ead9360e
TS
9303 case 23:
9304 switch (sel) {
9305 case 0:
895c2d04 9306 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
9307 break;
9308 default:
d75c135e 9309 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9310 break;
9311 }
9312 break;
9313 default:
d75c135e 9314 gen_mtc0(ctx, t0, rd, sel);
ead9360e 9315 }
71375b59
AM
9316 } else {
9317 switch (sel) {
9318 /* GPR registers. */
ead9360e 9319 case 0:
71375b59 9320 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 9321 break;
71375b59 9322 /* Auxiliary CPU registers */
ead9360e 9323 case 1:
71375b59
AM
9324 switch (rd) {
9325 case 0:
9326 gen_helper_0e1i(mttlo, t0, 0);
9327 break;
9328 case 1:
9329 gen_helper_0e1i(mtthi, t0, 0);
9330 break;
9331 case 2:
9332 gen_helper_0e1i(mttacx, t0, 0);
9333 break;
9334 case 4:
9335 gen_helper_0e1i(mttlo, t0, 1);
9336 break;
9337 case 5:
9338 gen_helper_0e1i(mtthi, t0, 1);
9339 break;
9340 case 6:
9341 gen_helper_0e1i(mttacx, t0, 1);
9342 break;
9343 case 8:
9344 gen_helper_0e1i(mttlo, t0, 2);
9345 break;
9346 case 9:
9347 gen_helper_0e1i(mtthi, t0, 2);
9348 break;
9349 case 10:
9350 gen_helper_0e1i(mttacx, t0, 2);
9351 break;
9352 case 12:
9353 gen_helper_0e1i(mttlo, t0, 3);
9354 break;
9355 case 13:
9356 gen_helper_0e1i(mtthi, t0, 3);
9357 break;
9358 case 14:
9359 gen_helper_0e1i(mttacx, t0, 3);
9360 break;
9361 case 16:
9362 gen_helper_mttdsp(cpu_env, t0);
9363 break;
9364 default:
9365 goto die;
9366 }
ead9360e 9367 break;
71375b59 9368 /* Floating point (COP1). */
ead9360e 9369 case 2:
71375b59
AM
9370 /* XXX: For now we support only a single FPU context. */
9371 if (h == 0) {
9372 TCGv_i32 fp0 = tcg_temp_new_i32();
9373
9374 tcg_gen_trunc_tl_i32(fp0, t0);
9375 gen_store_fpr32(ctx, fp0, rd);
9376 tcg_temp_free_i32(fp0);
9377 } else {
9378 TCGv_i32 fp0 = tcg_temp_new_i32();
9379
9380 tcg_gen_trunc_tl_i32(fp0, t0);
9381 gen_store_fpr32h(ctx, fp0, rd);
9382 tcg_temp_free_i32(fp0);
9383 }
ead9360e 9384 break;
71375b59
AM
9385 case 3:
9386 /* XXX: For now we support only a single FPU context. */
9387 {
9388 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9389
9390 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9391 tcg_temp_free_i32(fs_tmp);
9392 }
9393 /* Stop translation as we may have changed hflags */
9394 ctx->base.is_jmp = DISAS_STOP;
ead9360e 9395 break;
71375b59
AM
9396 /* COP2: Not implemented. */
9397 case 4:
ead9360e 9398 case 5:
71375b59 9399 /* fall through */
ead9360e
TS
9400 default:
9401 goto die;
9402 }
ead9360e 9403 }
b44a7fb1 9404 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 9405 tcg_temp_free(t0);
ead9360e
TS
9406 return;
9407
9408die:
1a3fd9c3 9409 tcg_temp_free(t0);
d12d51d5 9410 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
3a4ef3b7 9411 gen_reserved_instruction(ctx);
ead9360e
TS
9412}
9413
235785e8
AM
9414static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9415 int rt, int rd)
6af0bf9c 9416{
287c4b84 9417 const char *opn = "ldst";
6af0bf9c 9418
2e15497c 9419 check_cp0_enabled(ctx);
6af0bf9c
FB
9420 switch (opc) {
9421 case OPC_MFC0:
9422 if (rt == 0) {
ead9360e 9423 /* Treat as NOP. */
6af0bf9c
FB
9424 return;
9425 }
d75c135e 9426 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
9427 opn = "mfc0";
9428 break;
9429 case OPC_MTC0:
1a3fd9c3 9430 {
1fc7bf6e 9431 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9432
9433 gen_load_gpr(t0, rt);
d75c135e 9434 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9435 tcg_temp_free(t0);
9436 }
6af0bf9c
FB
9437 opn = "mtc0";
9438 break;
d26bc211 9439#if defined(TARGET_MIPS64)
9c2149c8 9440 case OPC_DMFC0:
d75c135e 9441 check_insn(ctx, ISA_MIPS3);
9c2149c8 9442 if (rt == 0) {
ead9360e 9443 /* Treat as NOP. */
9c2149c8
TS
9444 return;
9445 }
d75c135e 9446 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
9447 opn = "dmfc0";
9448 break;
9449 case OPC_DMTC0:
d75c135e 9450 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 9451 {
1fc7bf6e 9452 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9453
9454 gen_load_gpr(t0, rt);
d75c135e 9455 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9456 tcg_temp_free(t0);
9457 }
9c2149c8
TS
9458 opn = "dmtc0";
9459 break;
534ce69f 9460#endif
5204ea79
LA
9461 case OPC_MFHC0:
9462 check_mvh(ctx);
9463 if (rt == 0) {
9464 /* Treat as NOP. */
9465 return;
9466 }
9467 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9468 opn = "mfhc0";
9469 break;
9470 case OPC_MTHC0:
9471 check_mvh(ctx);
9472 {
9473 TCGv t0 = tcg_temp_new();
9474 gen_load_gpr(t0, rt);
9475 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9476 tcg_temp_free(t0);
9477 }
9478 opn = "mthc0";
9479 break;
ead9360e 9480 case OPC_MFTR:
9affc1c5 9481 check_cp0_enabled(ctx);
ead9360e
TS
9482 if (rd == 0) {
9483 /* Treat as NOP. */
9484 return;
9485 }
6c5c1e20 9486 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 9487 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
9488 opn = "mftr";
9489 break;
9490 case OPC_MTTR:
9affc1c5 9491 check_cp0_enabled(ctx);
6c5c1e20 9492 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
9493 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9494 opn = "mttr";
9495 break;
6af0bf9c 9496 case OPC_TLBWI:
6af0bf9c 9497 opn = "tlbwi";
1f8929d2 9498 if (!env->tlb->helper_tlbwi) {
29929e34 9499 goto die;
1f8929d2 9500 }
895c2d04 9501 gen_helper_tlbwi(cpu_env);
6af0bf9c 9502 break;
9456c2fb
LA
9503 case OPC_TLBINV:
9504 opn = "tlbinv";
9505 if (ctx->ie >= 2) {
9506 if (!env->tlb->helper_tlbinv) {
9507 goto die;
9508 }
9509 gen_helper_tlbinv(cpu_env);
9510 } /* treat as nop if TLBINV not supported */
9511 break;
9512 case OPC_TLBINVF:
9513 opn = "tlbinvf";
9514 if (ctx->ie >= 2) {
9515 if (!env->tlb->helper_tlbinvf) {
9516 goto die;
9517 }
9518 gen_helper_tlbinvf(cpu_env);
9519 } /* treat as nop if TLBINV not supported */
9520 break;
6af0bf9c 9521 case OPC_TLBWR:
6af0bf9c 9522 opn = "tlbwr";
1f8929d2 9523 if (!env->tlb->helper_tlbwr) {
29929e34 9524 goto die;
1f8929d2 9525 }
895c2d04 9526 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
9527 break;
9528 case OPC_TLBP:
6af0bf9c 9529 opn = "tlbp";
1f8929d2 9530 if (!env->tlb->helper_tlbp) {
29929e34 9531 goto die;
1f8929d2 9532 }
895c2d04 9533 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
9534 break;
9535 case OPC_TLBR:
6af0bf9c 9536 opn = "tlbr";
1f8929d2 9537 if (!env->tlb->helper_tlbr) {
29929e34 9538 goto die;
1f8929d2 9539 }
895c2d04 9540 gen_helper_tlbr(cpu_env);
6af0bf9c 9541 break;
ce9782f4 9542 case OPC_ERET: /* OPC_ERETNC */
2e211e0a 9543 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9544 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 9545 goto die;
ce9782f4
LA
9546 } else {
9547 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9548 if (ctx->opcode & (1 << bit_shift)) {
9549 /* OPC_ERETNC */
9550 opn = "eretnc";
5f89ce4f 9551 check_insn(ctx, ISA_MIPS_R5);
ce9782f4
LA
9552 gen_helper_eretnc(cpu_env);
9553 } else {
9554 /* OPC_ERET */
9555 opn = "eret";
9556 check_insn(ctx, ISA_MIPS2);
9557 gen_helper_eret(cpu_env);
9558 }
eeb3bba8 9559 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 9560 }
6af0bf9c
FB
9561 break;
9562 case OPC_DERET:
9563 opn = "deret";
bbd5e4a2 9564 check_insn(ctx, ISA_MIPS_R1);
2e211e0a 9565 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9566 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9567 goto die;
9568 }
6af0bf9c 9569 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 9570 MIPS_INVAL(opn);
3a4ef3b7 9571 gen_reserved_instruction(ctx);
6af0bf9c 9572 } else {
895c2d04 9573 gen_helper_deret(cpu_env);
eeb3bba8 9574 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
9575 }
9576 break;
4ad40f36
FB
9577 case OPC_WAIT:
9578 opn = "wait";
bbd5e4a2 9579 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
2e211e0a 9580 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 9581 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9582 goto die;
9583 }
4ad40f36 9584 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 9585 ctx->base.pc_next += 4;
4ad40f36 9586 save_cpu_state(ctx, 1);
eeb3bba8 9587 ctx->base.pc_next -= 4;
895c2d04 9588 gen_helper_wait(cpu_env);
eeb3bba8 9589 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 9590 break;
6af0bf9c 9591 default:
29929e34 9592 die:
923617a3 9593 MIPS_INVAL(opn);
3a4ef3b7 9594 gen_reserved_instruction(ctx);
6af0bf9c
FB
9595 return;
9596 }
2abf314d 9597 (void)opn; /* avoid a compiler warning */
6af0bf9c 9598}
f1aa6320 9599#endif /* !CONFIG_USER_ONLY */
6af0bf9c 9600
6ea83fed 9601/* CP1 Branches (before delay slot) */
d75c135e
AJ
9602static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9603 int32_t cc, int32_t offset)
6ea83fed
FB
9604{
9605 target_ulong btarget;
a7812ae4 9606 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 9607
2e211e0a 9608 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 9609 gen_reserved_instruction(ctx);
339cd2a8
LA
9610 goto out;
9611 }
9612
1f8929d2 9613 if (cc != 0) {
bbd5e4a2 9614 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
1f8929d2 9615 }
e189e748 9616
eeb3bba8 9617 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 9618
7a387fff
TS
9619 switch (op) {
9620 case OPC_BC1F:
d94536f4
AJ
9621 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9622 tcg_gen_not_i32(t0, t0);
9623 tcg_gen_andi_i32(t0, t0, 1);
9624 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9625 goto not_likely;
7a387fff 9626 case OPC_BC1FL:
d94536f4
AJ
9627 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9628 tcg_gen_not_i32(t0, t0);
9629 tcg_gen_andi_i32(t0, t0, 1);
9630 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9631 goto likely;
7a387fff 9632 case OPC_BC1T:
d94536f4
AJ
9633 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9634 tcg_gen_andi_i32(t0, t0, 1);
9635 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 9636 goto not_likely;
7a387fff 9637 case OPC_BC1TL:
d94536f4
AJ
9638 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9639 tcg_gen_andi_i32(t0, t0, 1);
9640 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
9641 likely:
9642 ctx->hflags |= MIPS_HFLAG_BL;
9643 break;
5a5012ec 9644 case OPC_BC1FANY2:
a16336e4 9645 {
d94536f4
AJ
9646 TCGv_i32 t1 = tcg_temp_new_i32();
9647 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9648 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9649 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9650 tcg_temp_free_i32(t1);
d94536f4
AJ
9651 tcg_gen_andi_i32(t0, t0, 1);
9652 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9653 }
5a5012ec
TS
9654 goto not_likely;
9655 case OPC_BC1TANY2:
a16336e4 9656 {
d94536f4
AJ
9657 TCGv_i32 t1 = tcg_temp_new_i32();
9658 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9659 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4
AJ
9660 tcg_gen_or_i32(t0, t0, t1);
9661 tcg_temp_free_i32(t1);
9662 tcg_gen_andi_i32(t0, t0, 1);
9663 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9664 }
5a5012ec
TS
9665 goto not_likely;
9666 case OPC_BC1FANY4:
a16336e4 9667 {
d94536f4
AJ
9668 TCGv_i32 t1 = tcg_temp_new_i32();
9669 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9670 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9671 tcg_gen_and_i32(t0, t0, t1);
71375b59 9672 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 9673 tcg_gen_and_i32(t0, t0, t1);
71375b59 9674 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 9675 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9676 tcg_temp_free_i32(t1);
d94536f4
AJ
9677 tcg_gen_andi_i32(t0, t0, 1);
9678 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9679 }
5a5012ec
TS
9680 goto not_likely;
9681 case OPC_BC1TANY4:
a16336e4 9682 {
d94536f4
AJ
9683 TCGv_i32 t1 = tcg_temp_new_i32();
9684 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9685 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 9686 tcg_gen_or_i32(t0, t0, t1);
71375b59 9687 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 9688 tcg_gen_or_i32(t0, t0, t1);
71375b59 9689 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4
AJ
9690 tcg_gen_or_i32(t0, t0, t1);
9691 tcg_temp_free_i32(t1);
9692 tcg_gen_andi_i32(t0, t0, 1);
9693 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9694 }
5a5012ec
TS
9695 not_likely:
9696 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
9697 break;
9698 default:
9d68ac14 9699 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9700 gen_reserved_instruction(ctx);
6c5c1e20 9701 goto out;
6ea83fed 9702 }
6ea83fed 9703 ctx->btarget = btarget;
b231c103 9704 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 9705 out:
a7812ae4 9706 tcg_temp_free_i32(t0);
6ea83fed
FB
9707}
9708
31837be3
YK
9709/* R6 CP1 Branches */
9710static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
9711 int32_t ft, int32_t offset,
9712 int delayslot_size)
31837be3
YK
9713{
9714 target_ulong btarget;
31837be3
YK
9715 TCGv_i64 t0 = tcg_temp_new_i64();
9716
9717 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9718#ifdef MIPS_DEBUG_DISAS
339cd2a8 9719 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 9720 "\n", ctx->base.pc_next);
31837be3 9721#endif
3a4ef3b7 9722 gen_reserved_instruction(ctx);
31837be3
YK
9723 goto out;
9724 }
9725
9726 gen_load_fpr64(ctx, t0, ft);
9727 tcg_gen_andi_i64(t0, t0, 1);
9728
eeb3bba8 9729 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
9730
9731 switch (op) {
9732 case OPC_BC1EQZ:
9733 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
9734 ctx->hflags |= MIPS_HFLAG_BC;
9735 break;
9736 case OPC_BC1NEZ:
9737 /* t0 already set */
31837be3
YK
9738 ctx->hflags |= MIPS_HFLAG_BC;
9739 break;
9740 default:
9d68ac14 9741 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9742 gen_reserved_instruction(ctx);
31837be3
YK
9743 goto out;
9744 }
9745
9746 tcg_gen_trunc_i64_tl(bcond, t0);
9747
31837be3 9748 ctx->btarget = btarget;
65935f07
YK
9749
9750 switch (delayslot_size) {
9751 case 2:
9752 ctx->hflags |= MIPS_HFLAG_BDS16;
9753 break;
9754 case 4:
9755 ctx->hflags |= MIPS_HFLAG_BDS32;
9756 break;
9757 }
31837be3
YK
9758
9759out:
9760 tcg_temp_free_i64(t0);
9761}
9762
6af0bf9c 9763/* Coprocessor 1 (FPU) */
5a5012ec 9764
5a5012ec
TS
9765#define FOP(func, fmt) (((fmt) << 21) | (func))
9766
bf4120ad
NF
9767enum fopcode {
9768 OPC_ADD_S = FOP(0, FMT_S),
9769 OPC_SUB_S = FOP(1, FMT_S),
9770 OPC_MUL_S = FOP(2, FMT_S),
9771 OPC_DIV_S = FOP(3, FMT_S),
9772 OPC_SQRT_S = FOP(4, FMT_S),
9773 OPC_ABS_S = FOP(5, FMT_S),
9774 OPC_MOV_S = FOP(6, FMT_S),
9775 OPC_NEG_S = FOP(7, FMT_S),
9776 OPC_ROUND_L_S = FOP(8, FMT_S),
9777 OPC_TRUNC_L_S = FOP(9, FMT_S),
9778 OPC_CEIL_L_S = FOP(10, FMT_S),
9779 OPC_FLOOR_L_S = FOP(11, FMT_S),
9780 OPC_ROUND_W_S = FOP(12, FMT_S),
9781 OPC_TRUNC_W_S = FOP(13, FMT_S),
9782 OPC_CEIL_W_S = FOP(14, FMT_S),
9783 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 9784 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
9785 OPC_MOVCF_S = FOP(17, FMT_S),
9786 OPC_MOVZ_S = FOP(18, FMT_S),
9787 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 9788 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
9789 OPC_RECIP_S = FOP(21, FMT_S),
9790 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
9791 OPC_SELNEZ_S = FOP(23, FMT_S),
9792 OPC_MADDF_S = FOP(24, FMT_S),
9793 OPC_MSUBF_S = FOP(25, FMT_S),
9794 OPC_RINT_S = FOP(26, FMT_S),
9795 OPC_CLASS_S = FOP(27, FMT_S),
9796 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 9797 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 9798 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 9799 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 9800 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 9801 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 9802 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
9803 OPC_RSQRT2_S = FOP(31, FMT_S),
9804 OPC_CVT_D_S = FOP(33, FMT_S),
9805 OPC_CVT_W_S = FOP(36, FMT_S),
9806 OPC_CVT_L_S = FOP(37, FMT_S),
9807 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
9808 OPC_CMP_F_S = FOP(48, FMT_S),
9809 OPC_CMP_UN_S = FOP(49, FMT_S),
9810 OPC_CMP_EQ_S = FOP(50, FMT_S),
9811 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9812 OPC_CMP_OLT_S = FOP(52, FMT_S),
9813 OPC_CMP_ULT_S = FOP(53, FMT_S),
9814 OPC_CMP_OLE_S = FOP(54, FMT_S),
9815 OPC_CMP_ULE_S = FOP(55, FMT_S),
9816 OPC_CMP_SF_S = FOP(56, FMT_S),
9817 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9818 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9819 OPC_CMP_NGL_S = FOP(59, FMT_S),
9820 OPC_CMP_LT_S = FOP(60, FMT_S),
9821 OPC_CMP_NGE_S = FOP(61, FMT_S),
9822 OPC_CMP_LE_S = FOP(62, FMT_S),
9823 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
9824
9825 OPC_ADD_D = FOP(0, FMT_D),
9826 OPC_SUB_D = FOP(1, FMT_D),
9827 OPC_MUL_D = FOP(2, FMT_D),
9828 OPC_DIV_D = FOP(3, FMT_D),
9829 OPC_SQRT_D = FOP(4, FMT_D),
9830 OPC_ABS_D = FOP(5, FMT_D),
9831 OPC_MOV_D = FOP(6, FMT_D),
9832 OPC_NEG_D = FOP(7, FMT_D),
9833 OPC_ROUND_L_D = FOP(8, FMT_D),
9834 OPC_TRUNC_L_D = FOP(9, FMT_D),
9835 OPC_CEIL_L_D = FOP(10, FMT_D),
9836 OPC_FLOOR_L_D = FOP(11, FMT_D),
9837 OPC_ROUND_W_D = FOP(12, FMT_D),
9838 OPC_TRUNC_W_D = FOP(13, FMT_D),
9839 OPC_CEIL_W_D = FOP(14, FMT_D),
9840 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 9841 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
9842 OPC_MOVCF_D = FOP(17, FMT_D),
9843 OPC_MOVZ_D = FOP(18, FMT_D),
9844 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 9845 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
9846 OPC_RECIP_D = FOP(21, FMT_D),
9847 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
9848 OPC_SELNEZ_D = FOP(23, FMT_D),
9849 OPC_MADDF_D = FOP(24, FMT_D),
9850 OPC_MSUBF_D = FOP(25, FMT_D),
9851 OPC_RINT_D = FOP(26, FMT_D),
9852 OPC_CLASS_D = FOP(27, FMT_D),
9853 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 9854 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 9855 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 9856 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 9857 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 9858 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 9859 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
9860 OPC_RSQRT2_D = FOP(31, FMT_D),
9861 OPC_CVT_S_D = FOP(32, FMT_D),
9862 OPC_CVT_W_D = FOP(36, FMT_D),
9863 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
9864 OPC_CMP_F_D = FOP(48, FMT_D),
9865 OPC_CMP_UN_D = FOP(49, FMT_D),
9866 OPC_CMP_EQ_D = FOP(50, FMT_D),
9867 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9868 OPC_CMP_OLT_D = FOP(52, FMT_D),
9869 OPC_CMP_ULT_D = FOP(53, FMT_D),
9870 OPC_CMP_OLE_D = FOP(54, FMT_D),
9871 OPC_CMP_ULE_D = FOP(55, FMT_D),
9872 OPC_CMP_SF_D = FOP(56, FMT_D),
9873 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9874 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9875 OPC_CMP_NGL_D = FOP(59, FMT_D),
9876 OPC_CMP_LT_D = FOP(60, FMT_D),
9877 OPC_CMP_NGE_D = FOP(61, FMT_D),
9878 OPC_CMP_LE_D = FOP(62, FMT_D),
9879 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
9880
9881 OPC_CVT_S_W = FOP(32, FMT_W),
9882 OPC_CVT_D_W = FOP(33, FMT_W),
9883 OPC_CVT_S_L = FOP(32, FMT_L),
9884 OPC_CVT_D_L = FOP(33, FMT_L),
9885 OPC_CVT_PS_PW = FOP(38, FMT_W),
9886
9887 OPC_ADD_PS = FOP(0, FMT_PS),
9888 OPC_SUB_PS = FOP(1, FMT_PS),
9889 OPC_MUL_PS = FOP(2, FMT_PS),
9890 OPC_DIV_PS = FOP(3, FMT_PS),
9891 OPC_ABS_PS = FOP(5, FMT_PS),
9892 OPC_MOV_PS = FOP(6, FMT_PS),
9893 OPC_NEG_PS = FOP(7, FMT_PS),
9894 OPC_MOVCF_PS = FOP(17, FMT_PS),
9895 OPC_MOVZ_PS = FOP(18, FMT_PS),
9896 OPC_MOVN_PS = FOP(19, FMT_PS),
9897 OPC_ADDR_PS = FOP(24, FMT_PS),
9898 OPC_MULR_PS = FOP(26, FMT_PS),
9899 OPC_RECIP2_PS = FOP(28, FMT_PS),
9900 OPC_RECIP1_PS = FOP(29, FMT_PS),
9901 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9902 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9903
9904 OPC_CVT_S_PU = FOP(32, FMT_PS),
9905 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9906 OPC_CVT_S_PL = FOP(40, FMT_PS),
9907 OPC_PLL_PS = FOP(44, FMT_PS),
9908 OPC_PLU_PS = FOP(45, FMT_PS),
9909 OPC_PUL_PS = FOP(46, FMT_PS),
9910 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
9911 OPC_CMP_F_PS = FOP(48, FMT_PS),
9912 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9913 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9914 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9915 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9916 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9917 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9918 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9919 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9920 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9921 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9922 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9923 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9924 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9925 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9926 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
9927};
9928
3f493883
YK
9929enum r6_f_cmp_op {
9930 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9931 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9932 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9933 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9934 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9935 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9936 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9937 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9938 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9939 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9940 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9941 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9942 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9943 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9944 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9945 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9946 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9947 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9948 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9949 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9950 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9951 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9952
9953 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9954 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9955 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9956 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9957 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9958 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9959 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9960 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9961 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9962 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9963 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9964 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9965 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9966 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9967 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9968 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9969 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9970 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9971 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9972 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9973 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9974 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9975};
235785e8
AM
9976
9977static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 9978{
72c3a3ee 9979 TCGv t0 = tcg_temp_new();
6ea83fed
FB
9980
9981 switch (opc) {
9982 case OPC_MFC1:
b6d96bed 9983 {
a7812ae4 9984 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9985
7c979afd 9986 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 9987 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9988 tcg_temp_free_i32(fp0);
6958549d 9989 }
6c5c1e20 9990 gen_store_gpr(t0, rt);
6ea83fed
FB
9991 break;
9992 case OPC_MTC1:
6c5c1e20 9993 gen_load_gpr(t0, rt);
b6d96bed 9994 {
a7812ae4 9995 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9996
9997 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 9998 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 9999 tcg_temp_free_i32(fp0);
6958549d 10000 }
6ea83fed
FB
10001 break;
10002 case OPC_CFC1:
895c2d04 10003 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10004 gen_store_gpr(t0, rt);
6ea83fed
FB
10005 break;
10006 case OPC_CTC1:
6c5c1e20 10007 gen_load_gpr(t0, rt);
9c708c7f 10008 save_cpu_state(ctx, 0);
736d120a
PJ
10009 {
10010 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10011
10012 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10013 tcg_temp_free_i32(fs_tmp);
10014 }
4cf8a45f 10015 /* Stop translation as we may have changed hflags */
eeb3bba8 10016 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10017 break;
72c3a3ee 10018#if defined(TARGET_MIPS64)
9c2149c8 10019 case OPC_DMFC1:
72c3a3ee 10020 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10021 gen_store_gpr(t0, rt);
5a5012ec 10022 break;
9c2149c8 10023 case OPC_DMTC1:
6c5c1e20 10024 gen_load_gpr(t0, rt);
72c3a3ee 10025 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10026 break;
72c3a3ee 10027#endif
5a5012ec 10028 case OPC_MFHC1:
b6d96bed 10029 {
a7812ae4 10030 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10031
7f6613ce 10032 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10033 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10034 tcg_temp_free_i32(fp0);
6958549d 10035 }
6c5c1e20 10036 gen_store_gpr(t0, rt);
5a5012ec
TS
10037 break;
10038 case OPC_MTHC1:
6c5c1e20 10039 gen_load_gpr(t0, rt);
b6d96bed 10040 {
a7812ae4 10041 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10042
10043 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10044 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10045 tcg_temp_free_i32(fp0);
6958549d 10046 }
5a5012ec 10047 break;
6ea83fed 10048 default:
9d68ac14 10049 MIPS_INVAL("cp1 move");
3a4ef3b7 10050 gen_reserved_instruction(ctx);
6c5c1e20 10051 goto out;
6ea83fed 10052 }
6c5c1e20
TS
10053
10054 out:
10055 tcg_temp_free(t0);
6ea83fed
FB
10056}
10057
235785e8 10058static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 10059{
42a268c2 10060 TCGLabel *l1;
e214b9bb 10061 TCGCond cond;
af58f9ca
AJ
10062 TCGv_i32 t0;
10063
10064 if (rd == 0) {
10065 /* Treat as NOP. */
10066 return;
10067 }
6ea83fed 10068
1f8929d2 10069 if (tf) {
e214b9bb 10070 cond = TCG_COND_EQ;
1f8929d2 10071 } else {
27848470 10072 cond = TCG_COND_NE;
1f8929d2 10073 }
27848470 10074
af58f9ca
AJ
10075 l1 = gen_new_label();
10076 t0 = tcg_temp_new_i32();
fa31af0e 10077 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10078 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10079 tcg_temp_free_i32(t0);
c27b4579 10080 gen_load_gpr(cpu_gpr[rd], rs);
e214b9bb 10081 gen_set_label(l1);
5a5012ec
TS
10082}
10083
7c979afd
LA
10084static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10085 int tf)
a16336e4 10086{
a16336e4 10087 int cond;
cbc37b28 10088 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10089 TCGLabel *l1 = gen_new_label();
a16336e4 10090
1f8929d2 10091 if (tf) {
a16336e4 10092 cond = TCG_COND_EQ;
1f8929d2 10093 } else {
a16336e4 10094 cond = TCG_COND_NE;
1f8929d2 10095 }
a16336e4 10096
fa31af0e 10097 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10098 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10099 gen_load_fpr32(ctx, t0, fs);
10100 gen_store_fpr32(ctx, t0, fd);
a16336e4 10101 gen_set_label(l1);
cbc37b28 10102 tcg_temp_free_i32(t0);
5a5012ec 10103}
a16336e4 10104
235785e8
AM
10105static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10106 int tf)
a16336e4 10107{
a16336e4 10108 int cond;
cbc37b28
AJ
10109 TCGv_i32 t0 = tcg_temp_new_i32();
10110 TCGv_i64 fp0;
42a268c2 10111 TCGLabel *l1 = gen_new_label();
a16336e4 10112
1f8929d2 10113 if (tf) {
a16336e4 10114 cond = TCG_COND_EQ;
1f8929d2 10115 } else {
a16336e4 10116 cond = TCG_COND_NE;
1f8929d2 10117 }
a16336e4 10118
fa31af0e 10119 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10120 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10121 tcg_temp_free_i32(t0);
11f94258 10122 fp0 = tcg_temp_new_i64();
9bf3eb2c 10123 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10124 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10125 tcg_temp_free_i64(fp0);
cbc37b28 10126 gen_set_label(l1);
a16336e4
TS
10127}
10128
7f6613ce
PJ
10129static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10130 int cc, int tf)
a16336e4
TS
10131{
10132 int cond;
cbc37b28 10133 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10134 TCGLabel *l1 = gen_new_label();
10135 TCGLabel *l2 = gen_new_label();
a16336e4 10136
1f8929d2 10137 if (tf) {
a16336e4 10138 cond = TCG_COND_EQ;
1f8929d2 10139 } else {
a16336e4 10140 cond = TCG_COND_NE;
1f8929d2 10141 }
a16336e4 10142
fa31af0e 10143 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10144 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10145 gen_load_fpr32(ctx, t0, fs);
10146 gen_store_fpr32(ctx, t0, fd);
a16336e4 10147 gen_set_label(l1);
9bf3eb2c 10148
71375b59 10149 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 10150 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10151 gen_load_fpr32h(ctx, t0, fs);
10152 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10153 tcg_temp_free_i32(t0);
a16336e4 10154 gen_set_label(l2);
a16336e4
TS
10155}
10156
e7f16abb
LA
10157static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10158 int fs)
10159{
10160 TCGv_i32 t1 = tcg_const_i32(0);
10161 TCGv_i32 fp0 = tcg_temp_new_i32();
10162 TCGv_i32 fp1 = tcg_temp_new_i32();
10163 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10164 gen_load_fpr32(ctx, fp0, fd);
10165 gen_load_fpr32(ctx, fp1, ft);
10166 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10167
10168 switch (op1) {
10169 case OPC_SEL_S:
10170 tcg_gen_andi_i32(fp0, fp0, 1);
10171 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10172 break;
10173 case OPC_SELEQZ_S:
10174 tcg_gen_andi_i32(fp1, fp1, 1);
10175 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10176 break;
10177 case OPC_SELNEZ_S:
10178 tcg_gen_andi_i32(fp1, fp1, 1);
10179 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10180 break;
10181 default:
10182 MIPS_INVAL("gen_sel_s");
3a4ef3b7 10183 gen_reserved_instruction(ctx);
e7f16abb
LA
10184 break;
10185 }
10186
7c979afd 10187 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10188 tcg_temp_free_i32(fp2);
10189 tcg_temp_free_i32(fp1);
10190 tcg_temp_free_i32(fp0);
10191 tcg_temp_free_i32(t1);
10192}
10193
10194static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10195 int fs)
10196{
10197 TCGv_i64 t1 = tcg_const_i64(0);
10198 TCGv_i64 fp0 = tcg_temp_new_i64();
10199 TCGv_i64 fp1 = tcg_temp_new_i64();
10200 TCGv_i64 fp2 = tcg_temp_new_i64();
10201 gen_load_fpr64(ctx, fp0, fd);
10202 gen_load_fpr64(ctx, fp1, ft);
10203 gen_load_fpr64(ctx, fp2, fs);
10204
10205 switch (op1) {
10206 case OPC_SEL_D:
10207 tcg_gen_andi_i64(fp0, fp0, 1);
10208 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10209 break;
10210 case OPC_SELEQZ_D:
10211 tcg_gen_andi_i64(fp1, fp1, 1);
10212 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10213 break;
10214 case OPC_SELNEZ_D:
10215 tcg_gen_andi_i64(fp1, fp1, 1);
10216 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10217 break;
10218 default:
10219 MIPS_INVAL("gen_sel_d");
3a4ef3b7 10220 gen_reserved_instruction(ctx);
e7f16abb
LA
10221 break;
10222 }
10223
10224 gen_store_fpr64(ctx, fp0, fd);
10225 tcg_temp_free_i64(fp2);
10226 tcg_temp_free_i64(fp1);
10227 tcg_temp_free_i64(fp0);
10228 tcg_temp_free_i64(t1);
10229}
6ea83fed 10230
235785e8
AM
10231static void gen_farith(DisasContext *ctx, enum fopcode op1,
10232 int ft, int fs, int fd, int cc)
6ea83fed 10233{
7a387fff 10234 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
10235 switch (op1) {
10236 case OPC_ADD_S:
b6d96bed 10237 {
a7812ae4
PB
10238 TCGv_i32 fp0 = tcg_temp_new_i32();
10239 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10240
7c979afd
LA
10241 gen_load_fpr32(ctx, fp0, fs);
10242 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10243 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10244 tcg_temp_free_i32(fp1);
7c979afd 10245 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10246 tcg_temp_free_i32(fp0);
b6d96bed 10247 }
5a5012ec 10248 break;
bf4120ad 10249 case OPC_SUB_S:
b6d96bed 10250 {
a7812ae4
PB
10251 TCGv_i32 fp0 = tcg_temp_new_i32();
10252 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10253
7c979afd
LA
10254 gen_load_fpr32(ctx, fp0, fs);
10255 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10256 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10257 tcg_temp_free_i32(fp1);
7c979afd 10258 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10259 tcg_temp_free_i32(fp0);
b6d96bed 10260 }
5a5012ec 10261 break;
bf4120ad 10262 case OPC_MUL_S:
b6d96bed 10263 {
a7812ae4
PB
10264 TCGv_i32 fp0 = tcg_temp_new_i32();
10265 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10266
7c979afd
LA
10267 gen_load_fpr32(ctx, fp0, fs);
10268 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10269 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10270 tcg_temp_free_i32(fp1);
7c979afd 10271 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10272 tcg_temp_free_i32(fp0);
b6d96bed 10273 }
5a5012ec 10274 break;
bf4120ad 10275 case OPC_DIV_S:
b6d96bed 10276 {
a7812ae4
PB
10277 TCGv_i32 fp0 = tcg_temp_new_i32();
10278 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10279
7c979afd
LA
10280 gen_load_fpr32(ctx, fp0, fs);
10281 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10282 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10283 tcg_temp_free_i32(fp1);
7c979afd 10284 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10285 tcg_temp_free_i32(fp0);
b6d96bed 10286 }
5a5012ec 10287 break;
bf4120ad 10288 case OPC_SQRT_S:
b6d96bed 10289 {
a7812ae4 10290 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10291
7c979afd 10292 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10293 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 10294 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10295 tcg_temp_free_i32(fp0);
b6d96bed 10296 }
5a5012ec 10297 break;
bf4120ad 10298 case OPC_ABS_S:
b6d96bed 10299 {
a7812ae4 10300 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10301
7c979afd 10302 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10303 if (ctx->abs2008) {
10304 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10305 } else {
10306 gen_helper_float_abs_s(fp0, fp0);
10307 }
7c979afd 10308 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10309 tcg_temp_free_i32(fp0);
b6d96bed 10310 }
5a5012ec 10311 break;
bf4120ad 10312 case OPC_MOV_S:
b6d96bed 10313 {
a7812ae4 10314 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10315
7c979afd
LA
10316 gen_load_fpr32(ctx, fp0, fs);
10317 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10318 tcg_temp_free_i32(fp0);
b6d96bed 10319 }
5a5012ec 10320 break;
bf4120ad 10321 case OPC_NEG_S:
b6d96bed 10322 {
a7812ae4 10323 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10324
7c979afd 10325 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10326 if (ctx->abs2008) {
10327 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10328 } else {
10329 gen_helper_float_chs_s(fp0, fp0);
10330 }
7c979afd 10331 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10332 tcg_temp_free_i32(fp0);
b6d96bed 10333 }
5a5012ec 10334 break;
bf4120ad 10335 case OPC_ROUND_L_S:
5e755519 10336 check_cp1_64bitmode(ctx);
b6d96bed 10337 {
a7812ae4
PB
10338 TCGv_i32 fp32 = tcg_temp_new_i32();
10339 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10340
7c979afd 10341 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10342 if (ctx->nan2008) {
10343 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10344 } else {
10345 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10346 }
a7812ae4 10347 tcg_temp_free_i32(fp32);
b6d96bed 10348 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10349 tcg_temp_free_i64(fp64);
b6d96bed 10350 }
5a5012ec 10351 break;
bf4120ad 10352 case OPC_TRUNC_L_S:
5e755519 10353 check_cp1_64bitmode(ctx);
b6d96bed 10354 {
a7812ae4
PB
10355 TCGv_i32 fp32 = tcg_temp_new_i32();
10356 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10357
7c979afd 10358 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10359 if (ctx->nan2008) {
10360 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10361 } else {
10362 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10363 }
a7812ae4 10364 tcg_temp_free_i32(fp32);
b6d96bed 10365 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10366 tcg_temp_free_i64(fp64);
b6d96bed 10367 }
5a5012ec 10368 break;
bf4120ad 10369 case OPC_CEIL_L_S:
5e755519 10370 check_cp1_64bitmode(ctx);
b6d96bed 10371 {
a7812ae4
PB
10372 TCGv_i32 fp32 = tcg_temp_new_i32();
10373 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10374
7c979afd 10375 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10376 if (ctx->nan2008) {
10377 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10378 } else {
10379 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10380 }
a7812ae4 10381 tcg_temp_free_i32(fp32);
b6d96bed 10382 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10383 tcg_temp_free_i64(fp64);
b6d96bed 10384 }
5a5012ec 10385 break;
bf4120ad 10386 case OPC_FLOOR_L_S:
5e755519 10387 check_cp1_64bitmode(ctx);
b6d96bed 10388 {
a7812ae4
PB
10389 TCGv_i32 fp32 = tcg_temp_new_i32();
10390 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10391
7c979afd 10392 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10393 if (ctx->nan2008) {
10394 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10395 } else {
10396 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10397 }
a7812ae4 10398 tcg_temp_free_i32(fp32);
b6d96bed 10399 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10400 tcg_temp_free_i64(fp64);
b6d96bed 10401 }
5a5012ec 10402 break;
bf4120ad 10403 case OPC_ROUND_W_S:
b6d96bed 10404 {
a7812ae4 10405 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10406
7c979afd 10407 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10408 if (ctx->nan2008) {
10409 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10410 } else {
10411 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10412 }
7c979afd 10413 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10414 tcg_temp_free_i32(fp0);
b6d96bed 10415 }
5a5012ec 10416 break;
bf4120ad 10417 case OPC_TRUNC_W_S:
b6d96bed 10418 {
a7812ae4 10419 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10420
7c979afd 10421 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10422 if (ctx->nan2008) {
10423 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10424 } else {
10425 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10426 }
7c979afd 10427 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10428 tcg_temp_free_i32(fp0);
b6d96bed 10429 }
5a5012ec 10430 break;
bf4120ad 10431 case OPC_CEIL_W_S:
b6d96bed 10432 {
a7812ae4 10433 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10434
7c979afd 10435 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10436 if (ctx->nan2008) {
10437 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10438 } else {
10439 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10440 }
7c979afd 10441 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10442 tcg_temp_free_i32(fp0);
b6d96bed 10443 }
5a5012ec 10444 break;
bf4120ad 10445 case OPC_FLOOR_W_S:
b6d96bed 10446 {
a7812ae4 10447 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10448
7c979afd 10449 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10450 if (ctx->nan2008) {
10451 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10452 } else {
10453 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10454 }
7c979afd 10455 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10456 tcg_temp_free_i32(fp0);
b6d96bed 10457 }
5a5012ec 10458 break;
e7f16abb 10459 case OPC_SEL_S:
2e211e0a 10460 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10461 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10462 break;
10463 case OPC_SELEQZ_S:
2e211e0a 10464 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10465 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10466 break;
10467 case OPC_SELNEZ_S:
2e211e0a 10468 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10469 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 10470 break;
bf4120ad 10471 case OPC_MOVCF_S:
2e211e0a 10472 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7c979afd 10473 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 10474 break;
bf4120ad 10475 case OPC_MOVZ_S:
2e211e0a 10476 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10477 {
42a268c2 10478 TCGLabel *l1 = gen_new_label();
c9297f4d 10479 TCGv_i32 fp0;
a16336e4 10480
c9297f4d
AJ
10481 if (ft != 0) {
10482 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10483 }
10484 fp0 = tcg_temp_new_i32();
7c979afd
LA
10485 gen_load_fpr32(ctx, fp0, fs);
10486 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10487 tcg_temp_free_i32(fp0);
a16336e4
TS
10488 gen_set_label(l1);
10489 }
5a5012ec 10490 break;
bf4120ad 10491 case OPC_MOVN_S:
2e211e0a 10492 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10493 {
42a268c2 10494 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10495 TCGv_i32 fp0;
10496
10497 if (ft != 0) {
10498 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10499 fp0 = tcg_temp_new_i32();
7c979afd
LA
10500 gen_load_fpr32(ctx, fp0, fs);
10501 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
10502 tcg_temp_free_i32(fp0);
10503 gen_set_label(l1);
10504 }
a16336e4 10505 }
5a5012ec 10506 break;
bf4120ad 10507 case OPC_RECIP_S:
b6d96bed 10508 {
a7812ae4 10509 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10510
7c979afd 10511 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10512 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 10513 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10514 tcg_temp_free_i32(fp0);
b6d96bed 10515 }
57fa1fb3 10516 break;
bf4120ad 10517 case OPC_RSQRT_S:
b6d96bed 10518 {
a7812ae4 10519 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10520
7c979afd 10521 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10522 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 10523 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10524 tcg_temp_free_i32(fp0);
b6d96bed 10525 }
57fa1fb3 10526 break;
e7f16abb 10527 case OPC_MADDF_S:
2e211e0a 10528 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10529 {
a7812ae4
PB
10530 TCGv_i32 fp0 = tcg_temp_new_i32();
10531 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10532 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10533 gen_load_fpr32(ctx, fp0, fs);
10534 gen_load_fpr32(ctx, fp1, ft);
10535 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10536 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10537 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 10538 tcg_temp_free_i32(fp2);
a7812ae4 10539 tcg_temp_free_i32(fp1);
a7812ae4 10540 tcg_temp_free_i32(fp0);
b6d96bed 10541 }
57fa1fb3 10542 break;
e7f16abb 10543 case OPC_MSUBF_S:
2e211e0a 10544 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10545 {
a7812ae4 10546 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
10547 TCGv_i32 fp1 = tcg_temp_new_i32();
10548 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10549 gen_load_fpr32(ctx, fp0, fs);
10550 gen_load_fpr32(ctx, fp1, ft);
10551 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10552 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10553 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10554 tcg_temp_free_i32(fp2);
10555 tcg_temp_free_i32(fp1);
a7812ae4 10556 tcg_temp_free_i32(fp0);
b6d96bed 10557 }
57fa1fb3 10558 break;
e7f16abb 10559 case OPC_RINT_S:
2e211e0a 10560 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10561 {
a7812ae4 10562 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10563 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10564 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 10565 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10566 tcg_temp_free_i32(fp0);
b6d96bed 10567 }
57fa1fb3 10568 break;
e7f16abb 10569 case OPC_CLASS_S:
2e211e0a 10570 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10571 {
e7f16abb 10572 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10573 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 10574 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 10575 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 10576 tcg_temp_free_i32(fp0);
e7f16abb
LA
10577 }
10578 break;
10579 case OPC_MIN_S: /* OPC_RECIP2_S */
2e211e0a 10580 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 10581 /* OPC_MIN_S */
a7812ae4
PB
10582 TCGv_i32 fp0 = tcg_temp_new_i32();
10583 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10584 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10585 gen_load_fpr32(ctx, fp0, fs);
10586 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10587 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 10588 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10589 tcg_temp_free_i32(fp2);
10590 tcg_temp_free_i32(fp1);
10591 tcg_temp_free_i32(fp0);
e7f16abb
LA
10592 } else {
10593 /* OPC_RECIP2_S */
10594 check_cp1_64bitmode(ctx);
10595 {
10596 TCGv_i32 fp0 = tcg_temp_new_i32();
10597 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10598
7c979afd
LA
10599 gen_load_fpr32(ctx, fp0, fs);
10600 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10601 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10602 tcg_temp_free_i32(fp1);
7c979afd 10603 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10604 tcg_temp_free_i32(fp0);
10605 }
e7f16abb
LA
10606 }
10607 break;
10608 case OPC_MINA_S: /* OPC_RECIP1_S */
2e211e0a 10609 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10610 /* OPC_MINA_S */
10611 TCGv_i32 fp0 = tcg_temp_new_i32();
10612 TCGv_i32 fp1 = tcg_temp_new_i32();
10613 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10614 gen_load_fpr32(ctx, fp0, fs);
10615 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10616 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 10617 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10618 tcg_temp_free_i32(fp2);
10619 tcg_temp_free_i32(fp1);
10620 tcg_temp_free_i32(fp0);
e7f16abb
LA
10621 } else {
10622 /* OPC_RECIP1_S */
10623 check_cp1_64bitmode(ctx);
10624 {
10625 TCGv_i32 fp0 = tcg_temp_new_i32();
10626
7c979afd 10627 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10628 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 10629 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10630 tcg_temp_free_i32(fp0);
10631 }
e7f16abb
LA
10632 }
10633 break;
10634 case OPC_MAX_S: /* OPC_RSQRT1_S */
2e211e0a 10635 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10636 /* OPC_MAX_S */
10637 TCGv_i32 fp0 = tcg_temp_new_i32();
10638 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10639 gen_load_fpr32(ctx, fp0, fs);
10640 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10641 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 10642 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
10643 tcg_temp_free_i32(fp1);
10644 tcg_temp_free_i32(fp0);
e7f16abb
LA
10645 } else {
10646 /* OPC_RSQRT1_S */
10647 check_cp1_64bitmode(ctx);
10648 {
10649 TCGv_i32 fp0 = tcg_temp_new_i32();
10650
7c979afd 10651 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10652 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 10653 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10654 tcg_temp_free_i32(fp0);
10655 }
e7f16abb
LA
10656 }
10657 break;
10658 case OPC_MAXA_S: /* OPC_RSQRT2_S */
2e211e0a 10659 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10660 /* OPC_MAXA_S */
10661 TCGv_i32 fp0 = tcg_temp_new_i32();
10662 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10663 gen_load_fpr32(ctx, fp0, fs);
10664 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10665 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 10666 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 10667 tcg_temp_free_i32(fp1);
a7812ae4 10668 tcg_temp_free_i32(fp0);
e7f16abb
LA
10669 } else {
10670 /* OPC_RSQRT2_S */
10671 check_cp1_64bitmode(ctx);
10672 {
10673 TCGv_i32 fp0 = tcg_temp_new_i32();
10674 TCGv_i32 fp1 = tcg_temp_new_i32();
10675
7c979afd
LA
10676 gen_load_fpr32(ctx, fp0, fs);
10677 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10678 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10679 tcg_temp_free_i32(fp1);
7c979afd 10680 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10681 tcg_temp_free_i32(fp0);
10682 }
b6d96bed 10683 }
57fa1fb3 10684 break;
bf4120ad 10685 case OPC_CVT_D_S:
5e755519 10686 check_cp1_registers(ctx, fd);
b6d96bed 10687 {
a7812ae4
PB
10688 TCGv_i32 fp32 = tcg_temp_new_i32();
10689 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10690
7c979afd 10691 gen_load_fpr32(ctx, fp32, fs);
895c2d04 10692 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 10693 tcg_temp_free_i32(fp32);
b6d96bed 10694 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10695 tcg_temp_free_i64(fp64);
b6d96bed 10696 }
5a5012ec 10697 break;
bf4120ad 10698 case OPC_CVT_W_S:
b6d96bed 10699 {
a7812ae4 10700 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10701
7c979afd 10702 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10703 if (ctx->nan2008) {
10704 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10705 } else {
10706 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10707 }
7c979afd 10708 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10709 tcg_temp_free_i32(fp0);
b6d96bed 10710 }
5a5012ec 10711 break;
bf4120ad 10712 case OPC_CVT_L_S:
5e755519 10713 check_cp1_64bitmode(ctx);
b6d96bed 10714 {
a7812ae4
PB
10715 TCGv_i32 fp32 = tcg_temp_new_i32();
10716 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10717
7c979afd 10718 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10719 if (ctx->nan2008) {
10720 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10721 } else {
10722 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10723 }
a7812ae4 10724 tcg_temp_free_i32(fp32);
b6d96bed 10725 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10726 tcg_temp_free_i64(fp64);
b6d96bed 10727 }
5a5012ec 10728 break;
bf4120ad 10729 case OPC_CVT_PS_S:
e29c9628 10730 check_ps(ctx);
b6d96bed 10731 {
a7812ae4
PB
10732 TCGv_i64 fp64 = tcg_temp_new_i64();
10733 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10734 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 10735
7c979afd
LA
10736 gen_load_fpr32(ctx, fp32_0, fs);
10737 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 10738 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
10739 tcg_temp_free_i32(fp32_1);
10740 tcg_temp_free_i32(fp32_0);
36aa55dc 10741 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10742 tcg_temp_free_i64(fp64);
b6d96bed 10743 }
5a5012ec 10744 break;
bf4120ad
NF
10745 case OPC_CMP_F_S:
10746 case OPC_CMP_UN_S:
10747 case OPC_CMP_EQ_S:
10748 case OPC_CMP_UEQ_S:
10749 case OPC_CMP_OLT_S:
10750 case OPC_CMP_ULT_S:
10751 case OPC_CMP_OLE_S:
10752 case OPC_CMP_ULE_S:
10753 case OPC_CMP_SF_S:
10754 case OPC_CMP_NGLE_S:
10755 case OPC_CMP_SEQ_S:
10756 case OPC_CMP_NGL_S:
10757 case OPC_CMP_LT_S:
10758 case OPC_CMP_NGE_S:
10759 case OPC_CMP_LE_S:
10760 case OPC_CMP_NGT_S:
2e211e0a 10761 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 10762 if (ctx->opcode & (1 << 6)) {
71375b59 10763 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 10764 } else {
71375b59 10765 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 10766 }
5a5012ec 10767 break;
bf4120ad 10768 case OPC_ADD_D:
5e755519 10769 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10770 {
a7812ae4
PB
10771 TCGv_i64 fp0 = tcg_temp_new_i64();
10772 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10773
10774 gen_load_fpr64(ctx, fp0, fs);
10775 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10776 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10777 tcg_temp_free_i64(fp1);
b6d96bed 10778 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10779 tcg_temp_free_i64(fp0);
b6d96bed 10780 }
6ea83fed 10781 break;
bf4120ad 10782 case OPC_SUB_D:
5e755519 10783 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10784 {
a7812ae4
PB
10785 TCGv_i64 fp0 = tcg_temp_new_i64();
10786 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10787
10788 gen_load_fpr64(ctx, fp0, fs);
10789 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10790 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10791 tcg_temp_free_i64(fp1);
b6d96bed 10792 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10793 tcg_temp_free_i64(fp0);
b6d96bed 10794 }
6ea83fed 10795 break;
bf4120ad 10796 case OPC_MUL_D:
5e755519 10797 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10798 {
a7812ae4
PB
10799 TCGv_i64 fp0 = tcg_temp_new_i64();
10800 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10801
10802 gen_load_fpr64(ctx, fp0, fs);
10803 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10804 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10805 tcg_temp_free_i64(fp1);
b6d96bed 10806 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10807 tcg_temp_free_i64(fp0);
b6d96bed 10808 }
6ea83fed 10809 break;
bf4120ad 10810 case OPC_DIV_D:
5e755519 10811 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10812 {
a7812ae4
PB
10813 TCGv_i64 fp0 = tcg_temp_new_i64();
10814 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10815
10816 gen_load_fpr64(ctx, fp0, fs);
10817 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10818 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10819 tcg_temp_free_i64(fp1);
b6d96bed 10820 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10821 tcg_temp_free_i64(fp0);
b6d96bed 10822 }
6ea83fed 10823 break;
bf4120ad 10824 case OPC_SQRT_D:
5e755519 10825 check_cp1_registers(ctx, fs | fd);
b6d96bed 10826 {
a7812ae4 10827 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10828
10829 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10830 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 10831 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10832 tcg_temp_free_i64(fp0);
b6d96bed 10833 }
6ea83fed 10834 break;
bf4120ad 10835 case OPC_ABS_D:
5e755519 10836 check_cp1_registers(ctx, fs | fd);
b6d96bed 10837 {
a7812ae4 10838 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10839
10840 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10841 if (ctx->abs2008) {
10842 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10843 } else {
10844 gen_helper_float_abs_d(fp0, fp0);
10845 }
b6d96bed 10846 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10847 tcg_temp_free_i64(fp0);
b6d96bed 10848 }
6ea83fed 10849 break;
bf4120ad 10850 case OPC_MOV_D:
5e755519 10851 check_cp1_registers(ctx, fs | fd);
b6d96bed 10852 {
a7812ae4 10853 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10854
10855 gen_load_fpr64(ctx, fp0, fs);
10856 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10857 tcg_temp_free_i64(fp0);
b6d96bed 10858 }
6ea83fed 10859 break;
bf4120ad 10860 case OPC_NEG_D:
5e755519 10861 check_cp1_registers(ctx, fs | fd);
b6d96bed 10862 {
a7812ae4 10863 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10864
10865 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10866 if (ctx->abs2008) {
10867 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10868 } else {
10869 gen_helper_float_chs_d(fp0, fp0);
10870 }
b6d96bed 10871 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10872 tcg_temp_free_i64(fp0);
b6d96bed 10873 }
6ea83fed 10874 break;
bf4120ad 10875 case OPC_ROUND_L_D:
5e755519 10876 check_cp1_64bitmode(ctx);
b6d96bed 10877 {
a7812ae4 10878 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10879
10880 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10881 if (ctx->nan2008) {
10882 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10883 } else {
10884 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10885 }
b6d96bed 10886 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10887 tcg_temp_free_i64(fp0);
b6d96bed 10888 }
5a5012ec 10889 break;
bf4120ad 10890 case OPC_TRUNC_L_D:
5e755519 10891 check_cp1_64bitmode(ctx);
b6d96bed 10892 {
a7812ae4 10893 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10894
10895 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10896 if (ctx->nan2008) {
10897 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10898 } else {
10899 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10900 }
b6d96bed 10901 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10902 tcg_temp_free_i64(fp0);
b6d96bed 10903 }
5a5012ec 10904 break;
bf4120ad 10905 case OPC_CEIL_L_D:
5e755519 10906 check_cp1_64bitmode(ctx);
b6d96bed 10907 {
a7812ae4 10908 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10909
10910 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10911 if (ctx->nan2008) {
10912 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10913 } else {
10914 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10915 }
b6d96bed 10916 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10917 tcg_temp_free_i64(fp0);
b6d96bed 10918 }
5a5012ec 10919 break;
bf4120ad 10920 case OPC_FLOOR_L_D:
5e755519 10921 check_cp1_64bitmode(ctx);
b6d96bed 10922 {
a7812ae4 10923 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10924
10925 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10926 if (ctx->nan2008) {
10927 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10928 } else {
10929 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10930 }
b6d96bed 10931 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10932 tcg_temp_free_i64(fp0);
b6d96bed 10933 }
5a5012ec 10934 break;
bf4120ad 10935 case OPC_ROUND_W_D:
5e755519 10936 check_cp1_registers(ctx, fs);
b6d96bed 10937 {
a7812ae4
PB
10938 TCGv_i32 fp32 = tcg_temp_new_i32();
10939 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10940
10941 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10942 if (ctx->nan2008) {
10943 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10944 } else {
10945 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10946 }
a7812ae4 10947 tcg_temp_free_i64(fp64);
7c979afd 10948 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10949 tcg_temp_free_i32(fp32);
b6d96bed 10950 }
6ea83fed 10951 break;
bf4120ad 10952 case OPC_TRUNC_W_D:
5e755519 10953 check_cp1_registers(ctx, fs);
b6d96bed 10954 {
a7812ae4
PB
10955 TCGv_i32 fp32 = tcg_temp_new_i32();
10956 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10957
10958 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10959 if (ctx->nan2008) {
10960 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10961 } else {
10962 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10963 }
a7812ae4 10964 tcg_temp_free_i64(fp64);
7c979afd 10965 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10966 tcg_temp_free_i32(fp32);
b6d96bed 10967 }
6ea83fed 10968 break;
bf4120ad 10969 case OPC_CEIL_W_D:
5e755519 10970 check_cp1_registers(ctx, fs);
b6d96bed 10971 {
a7812ae4
PB
10972 TCGv_i32 fp32 = tcg_temp_new_i32();
10973 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10974
10975 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10976 if (ctx->nan2008) {
10977 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10978 } else {
10979 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10980 }
a7812ae4 10981 tcg_temp_free_i64(fp64);
7c979afd 10982 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10983 tcg_temp_free_i32(fp32);
b6d96bed 10984 }
6ea83fed 10985 break;
bf4120ad 10986 case OPC_FLOOR_W_D:
5e755519 10987 check_cp1_registers(ctx, fs);
b6d96bed 10988 {
a7812ae4
PB
10989 TCGv_i32 fp32 = tcg_temp_new_i32();
10990 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10991
10992 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10993 if (ctx->nan2008) {
10994 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10995 } else {
10996 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10997 }
a7812ae4 10998 tcg_temp_free_i64(fp64);
7c979afd 10999 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11000 tcg_temp_free_i32(fp32);
b6d96bed 11001 }
6ea83fed 11002 break;
e7f16abb 11003 case OPC_SEL_D:
2e211e0a 11004 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11005 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11006 break;
11007 case OPC_SELEQZ_D:
2e211e0a 11008 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11009 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11010 break;
11011 case OPC_SELNEZ_D:
2e211e0a 11012 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 11013 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11014 break;
bf4120ad 11015 case OPC_MOVCF_D:
2e211e0a 11016 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6d96bed 11017 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11018 break;
bf4120ad 11019 case OPC_MOVZ_D:
2e211e0a 11020 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11021 {
42a268c2 11022 TCGLabel *l1 = gen_new_label();
c9297f4d 11023 TCGv_i64 fp0;
a16336e4 11024
c9297f4d
AJ
11025 if (ft != 0) {
11026 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11027 }
11028 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11029 gen_load_fpr64(ctx, fp0, fs);
11030 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11031 tcg_temp_free_i64(fp0);
a16336e4
TS
11032 gen_set_label(l1);
11033 }
5a5012ec 11034 break;
bf4120ad 11035 case OPC_MOVN_D:
2e211e0a 11036 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 11037 {
42a268c2 11038 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11039 TCGv_i64 fp0;
11040
11041 if (ft != 0) {
11042 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11043 fp0 = tcg_temp_new_i64();
11044 gen_load_fpr64(ctx, fp0, fs);
11045 gen_store_fpr64(ctx, fp0, fd);
11046 tcg_temp_free_i64(fp0);
11047 gen_set_label(l1);
11048 }
a16336e4 11049 }
6ea83fed 11050 break;
bf4120ad 11051 case OPC_RECIP_D:
ca6c7803 11052 check_cp1_registers(ctx, fs | fd);
b6d96bed 11053 {
a7812ae4 11054 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11055
11056 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11057 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11058 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11059 tcg_temp_free_i64(fp0);
b6d96bed 11060 }
57fa1fb3 11061 break;
bf4120ad 11062 case OPC_RSQRT_D:
ca6c7803 11063 check_cp1_registers(ctx, fs | fd);
b6d96bed 11064 {
a7812ae4 11065 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11066
11067 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11068 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11069 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11070 tcg_temp_free_i64(fp0);
b6d96bed 11071 }
57fa1fb3 11072 break;
e7f16abb 11073 case OPC_MADDF_D:
2e211e0a 11074 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11075 {
a7812ae4
PB
11076 TCGv_i64 fp0 = tcg_temp_new_i64();
11077 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11078 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11079 gen_load_fpr64(ctx, fp0, fs);
11080 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11081 gen_load_fpr64(ctx, fp2, fd);
11082 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11083 gen_store_fpr64(ctx, fp2, fd);
11084 tcg_temp_free_i64(fp2);
a7812ae4 11085 tcg_temp_free_i64(fp1);
a7812ae4 11086 tcg_temp_free_i64(fp0);
b6d96bed 11087 }
57fa1fb3 11088 break;
e7f16abb 11089 case OPC_MSUBF_D:
2e211e0a 11090 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11091 {
a7812ae4 11092 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11093 TCGv_i64 fp1 = tcg_temp_new_i64();
11094 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11095 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11096 gen_load_fpr64(ctx, fp1, ft);
11097 gen_load_fpr64(ctx, fp2, fd);
11098 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11099 gen_store_fpr64(ctx, fp2, fd);
11100 tcg_temp_free_i64(fp2);
11101 tcg_temp_free_i64(fp1);
a7812ae4 11102 tcg_temp_free_i64(fp0);
b6d96bed 11103 }
57fa1fb3 11104 break;
e7f16abb 11105 case OPC_RINT_D:
2e211e0a 11106 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11107 {
a7812ae4 11108 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11109 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11110 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11111 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11112 tcg_temp_free_i64(fp0);
b6d96bed 11113 }
57fa1fb3 11114 break;
e7f16abb 11115 case OPC_CLASS_D:
2e211e0a 11116 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 11117 {
e7f16abb
LA
11118 TCGv_i64 fp0 = tcg_temp_new_i64();
11119 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11120 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11121 gen_store_fpr64(ctx, fp0, fd);
11122 tcg_temp_free_i64(fp0);
e7f16abb
LA
11123 }
11124 break;
11125 case OPC_MIN_D: /* OPC_RECIP2_D */
2e211e0a 11126 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 11127 /* OPC_MIN_D */
a7812ae4
PB
11128 TCGv_i64 fp0 = tcg_temp_new_i64();
11129 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11130 gen_load_fpr64(ctx, fp0, fs);
11131 gen_load_fpr64(ctx, fp1, ft);
11132 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11133 gen_store_fpr64(ctx, fp1, fd);
11134 tcg_temp_free_i64(fp1);
11135 tcg_temp_free_i64(fp0);
e7f16abb
LA
11136 } else {
11137 /* OPC_RECIP2_D */
11138 check_cp1_64bitmode(ctx);
11139 {
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11141 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11142
e7f16abb
LA
11143 gen_load_fpr64(ctx, fp0, fs);
11144 gen_load_fpr64(ctx, fp1, ft);
11145 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11146 tcg_temp_free_i64(fp1);
11147 gen_store_fpr64(ctx, fp0, fd);
11148 tcg_temp_free_i64(fp0);
11149 }
e7f16abb
LA
11150 }
11151 break;
11152 case OPC_MINA_D: /* OPC_RECIP1_D */
2e211e0a 11153 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11154 /* OPC_MINA_D */
11155 TCGv_i64 fp0 = tcg_temp_new_i64();
11156 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11157 gen_load_fpr64(ctx, fp0, fs);
11158 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11159 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11160 gen_store_fpr64(ctx, fp1, fd);
11161 tcg_temp_free_i64(fp1);
11162 tcg_temp_free_i64(fp0);
e7f16abb
LA
11163 } else {
11164 /* OPC_RECIP1_D */
11165 check_cp1_64bitmode(ctx);
11166 {
11167 TCGv_i64 fp0 = tcg_temp_new_i64();
11168
11169 gen_load_fpr64(ctx, fp0, fs);
11170 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11171 gen_store_fpr64(ctx, fp0, fd);
11172 tcg_temp_free_i64(fp0);
11173 }
e7f16abb
LA
11174 }
11175 break;
11176 case OPC_MAX_D: /* OPC_RSQRT1_D */
2e211e0a 11177 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11178 /* OPC_MAX_D */
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11180 TCGv_i64 fp1 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 gen_load_fpr64(ctx, fp1, ft);
11183 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11184 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 11185 tcg_temp_free_i64(fp1);
a7812ae4 11186 tcg_temp_free_i64(fp0);
e7f16abb
LA
11187 } else {
11188 /* OPC_RSQRT1_D */
11189 check_cp1_64bitmode(ctx);
11190 {
11191 TCGv_i64 fp0 = tcg_temp_new_i64();
11192
11193 gen_load_fpr64(ctx, fp0, fs);
11194 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11195 gen_store_fpr64(ctx, fp0, fd);
11196 tcg_temp_free_i64(fp0);
11197 }
e7f16abb
LA
11198 }
11199 break;
11200 case OPC_MAXA_D: /* OPC_RSQRT2_D */
2e211e0a 11201 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
11202 /* OPC_MAXA_D */
11203 TCGv_i64 fp0 = tcg_temp_new_i64();
11204 TCGv_i64 fp1 = tcg_temp_new_i64();
11205 gen_load_fpr64(ctx, fp0, fs);
11206 gen_load_fpr64(ctx, fp1, ft);
11207 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11208 gen_store_fpr64(ctx, fp1, fd);
11209 tcg_temp_free_i64(fp1);
11210 tcg_temp_free_i64(fp0);
e7f16abb
LA
11211 } else {
11212 /* OPC_RSQRT2_D */
11213 check_cp1_64bitmode(ctx);
11214 {
11215 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 TCGv_i64 fp1 = tcg_temp_new_i64();
11217
11218 gen_load_fpr64(ctx, fp0, fs);
11219 gen_load_fpr64(ctx, fp1, ft);
11220 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11221 tcg_temp_free_i64(fp1);
11222 gen_store_fpr64(ctx, fp0, fd);
11223 tcg_temp_free_i64(fp0);
11224 }
b6d96bed 11225 }
57fa1fb3 11226 break;
bf4120ad
NF
11227 case OPC_CMP_F_D:
11228 case OPC_CMP_UN_D:
11229 case OPC_CMP_EQ_D:
11230 case OPC_CMP_UEQ_D:
11231 case OPC_CMP_OLT_D:
11232 case OPC_CMP_ULT_D:
11233 case OPC_CMP_OLE_D:
11234 case OPC_CMP_ULE_D:
11235 case OPC_CMP_SF_D:
11236 case OPC_CMP_NGLE_D:
11237 case OPC_CMP_SEQ_D:
11238 case OPC_CMP_NGL_D:
11239 case OPC_CMP_LT_D:
11240 case OPC_CMP_NGE_D:
11241 case OPC_CMP_LE_D:
11242 case OPC_CMP_NGT_D:
2e211e0a 11243 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 11244 if (ctx->opcode & (1 << 6)) {
71375b59 11245 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 11246 } else {
71375b59 11247 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11248 }
6ea83fed 11249 break;
bf4120ad 11250 case OPC_CVT_S_D:
5e755519 11251 check_cp1_registers(ctx, fs);
b6d96bed 11252 {
a7812ae4
PB
11253 TCGv_i32 fp32 = tcg_temp_new_i32();
11254 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11255
11256 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11257 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 11258 tcg_temp_free_i64(fp64);
7c979afd 11259 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11260 tcg_temp_free_i32(fp32);
b6d96bed 11261 }
5a5012ec 11262 break;
bf4120ad 11263 case OPC_CVT_W_D:
5e755519 11264 check_cp1_registers(ctx, fs);
b6d96bed 11265 {
a7812ae4
PB
11266 TCGv_i32 fp32 = tcg_temp_new_i32();
11267 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11268
11269 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11270 if (ctx->nan2008) {
11271 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11272 } else {
11273 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11274 }
a7812ae4 11275 tcg_temp_free_i64(fp64);
7c979afd 11276 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11277 tcg_temp_free_i32(fp32);
b6d96bed 11278 }
5a5012ec 11279 break;
bf4120ad 11280 case OPC_CVT_L_D:
5e755519 11281 check_cp1_64bitmode(ctx);
b6d96bed 11282 {
a7812ae4 11283 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11284
11285 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11286 if (ctx->nan2008) {
11287 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11288 } else {
11289 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11290 }
b6d96bed 11291 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11292 tcg_temp_free_i64(fp0);
b6d96bed 11293 }
5a5012ec 11294 break;
bf4120ad 11295 case OPC_CVT_S_W:
b6d96bed 11296 {
a7812ae4 11297 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11298
7c979afd 11299 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11300 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 11301 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11302 tcg_temp_free_i32(fp0);
b6d96bed 11303 }
6ea83fed 11304 break;
bf4120ad 11305 case OPC_CVT_D_W:
5e755519 11306 check_cp1_registers(ctx, fd);
b6d96bed 11307 {
a7812ae4
PB
11308 TCGv_i32 fp32 = tcg_temp_new_i32();
11309 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11310
7c979afd 11311 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11312 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 11313 tcg_temp_free_i32(fp32);
b6d96bed 11314 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11315 tcg_temp_free_i64(fp64);
b6d96bed 11316 }
5a5012ec 11317 break;
bf4120ad 11318 case OPC_CVT_S_L:
5e755519 11319 check_cp1_64bitmode(ctx);
b6d96bed 11320 {
a7812ae4
PB
11321 TCGv_i32 fp32 = tcg_temp_new_i32();
11322 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11323
11324 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11325 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 11326 tcg_temp_free_i64(fp64);
7c979afd 11327 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11328 tcg_temp_free_i32(fp32);
b6d96bed 11329 }
5a5012ec 11330 break;
bf4120ad 11331 case OPC_CVT_D_L:
5e755519 11332 check_cp1_64bitmode(ctx);
b6d96bed 11333 {
a7812ae4 11334 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11335
11336 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11337 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 11338 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11339 tcg_temp_free_i64(fp0);
b6d96bed 11340 }
5a5012ec 11341 break;
bf4120ad 11342 case OPC_CVT_PS_PW:
e29c9628 11343 check_ps(ctx);
b6d96bed 11344 {
a7812ae4 11345 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11346
11347 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11348 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 11349 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11350 tcg_temp_free_i64(fp0);
b6d96bed 11351 }
5a5012ec 11352 break;
bf4120ad 11353 case OPC_ADD_PS:
e29c9628 11354 check_ps(ctx);
b6d96bed 11355 {
a7812ae4
PB
11356 TCGv_i64 fp0 = tcg_temp_new_i64();
11357 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11358
11359 gen_load_fpr64(ctx, fp0, fs);
11360 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11361 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11362 tcg_temp_free_i64(fp1);
b6d96bed 11363 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11364 tcg_temp_free_i64(fp0);
b6d96bed 11365 }
6ea83fed 11366 break;
bf4120ad 11367 case OPC_SUB_PS:
e29c9628 11368 check_ps(ctx);
b6d96bed 11369 {
a7812ae4
PB
11370 TCGv_i64 fp0 = tcg_temp_new_i64();
11371 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11372
11373 gen_load_fpr64(ctx, fp0, fs);
11374 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11375 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11376 tcg_temp_free_i64(fp1);
b6d96bed 11377 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11378 tcg_temp_free_i64(fp0);
b6d96bed 11379 }
6ea83fed 11380 break;
bf4120ad 11381 case OPC_MUL_PS:
e29c9628 11382 check_ps(ctx);
b6d96bed 11383 {
a7812ae4
PB
11384 TCGv_i64 fp0 = tcg_temp_new_i64();
11385 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11386
11387 gen_load_fpr64(ctx, fp0, fs);
11388 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11389 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11390 tcg_temp_free_i64(fp1);
b6d96bed 11391 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11392 tcg_temp_free_i64(fp0);
b6d96bed 11393 }
6ea83fed 11394 break;
bf4120ad 11395 case OPC_ABS_PS:
e29c9628 11396 check_ps(ctx);
b6d96bed 11397 {
a7812ae4 11398 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11399
11400 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11401 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 11402 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11403 tcg_temp_free_i64(fp0);
b6d96bed 11404 }
6ea83fed 11405 break;
bf4120ad 11406 case OPC_MOV_PS:
e29c9628 11407 check_ps(ctx);
b6d96bed 11408 {
a7812ae4 11409 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11410
11411 gen_load_fpr64(ctx, fp0, fs);
11412 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11413 tcg_temp_free_i64(fp0);
b6d96bed 11414 }
6ea83fed 11415 break;
bf4120ad 11416 case OPC_NEG_PS:
e29c9628 11417 check_ps(ctx);
b6d96bed 11418 {
a7812ae4 11419 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11420
11421 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11422 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 11423 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11424 tcg_temp_free_i64(fp0);
b6d96bed 11425 }
6ea83fed 11426 break;
bf4120ad 11427 case OPC_MOVCF_PS:
e29c9628 11428 check_ps(ctx);
7f6613ce 11429 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 11430 break;
bf4120ad 11431 case OPC_MOVZ_PS:
e29c9628 11432 check_ps(ctx);
a16336e4 11433 {
42a268c2 11434 TCGLabel *l1 = gen_new_label();
30a3848b 11435 TCGv_i64 fp0;
a16336e4 11436
1f8929d2 11437 if (ft != 0) {
c9297f4d 11438 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 11439 }
c9297f4d
AJ
11440 fp0 = tcg_temp_new_i64();
11441 gen_load_fpr64(ctx, fp0, fs);
11442 gen_store_fpr64(ctx, fp0, fd);
11443 tcg_temp_free_i64(fp0);
a16336e4
TS
11444 gen_set_label(l1);
11445 }
6ea83fed 11446 break;
bf4120ad 11447 case OPC_MOVN_PS:
e29c9628 11448 check_ps(ctx);
a16336e4 11449 {
42a268c2 11450 TCGLabel *l1 = gen_new_label();
30a3848b 11451 TCGv_i64 fp0;
c9297f4d
AJ
11452
11453 if (ft != 0) {
11454 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11455 fp0 = tcg_temp_new_i64();
11456 gen_load_fpr64(ctx, fp0, fs);
11457 gen_store_fpr64(ctx, fp0, fd);
11458 tcg_temp_free_i64(fp0);
11459 gen_set_label(l1);
11460 }
a16336e4 11461 }
6ea83fed 11462 break;
bf4120ad 11463 case OPC_ADDR_PS:
e29c9628 11464 check_ps(ctx);
b6d96bed 11465 {
a7812ae4
PB
11466 TCGv_i64 fp0 = tcg_temp_new_i64();
11467 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11468
11469 gen_load_fpr64(ctx, fp0, ft);
11470 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11471 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11472 tcg_temp_free_i64(fp1);
b6d96bed 11473 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11474 tcg_temp_free_i64(fp0);
b6d96bed 11475 }
fbcc6828 11476 break;
bf4120ad 11477 case OPC_MULR_PS:
e29c9628 11478 check_ps(ctx);
b6d96bed 11479 {
a7812ae4
PB
11480 TCGv_i64 fp0 = tcg_temp_new_i64();
11481 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11482
11483 gen_load_fpr64(ctx, fp0, ft);
11484 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11485 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11486 tcg_temp_free_i64(fp1);
b6d96bed 11487 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11488 tcg_temp_free_i64(fp0);
b6d96bed 11489 }
57fa1fb3 11490 break;
bf4120ad 11491 case OPC_RECIP2_PS:
e29c9628 11492 check_ps(ctx);
b6d96bed 11493 {
a7812ae4
PB
11494 TCGv_i64 fp0 = tcg_temp_new_i64();
11495 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11496
11497 gen_load_fpr64(ctx, fp0, fs);
d22d7289 11498 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11499 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11500 tcg_temp_free_i64(fp1);
b6d96bed 11501 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11502 tcg_temp_free_i64(fp0);
b6d96bed 11503 }
57fa1fb3 11504 break;
bf4120ad 11505 case OPC_RECIP1_PS:
e29c9628 11506 check_ps(ctx);
b6d96bed 11507 {
a7812ae4 11508 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11509
11510 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11511 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 11512 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11513 tcg_temp_free_i64(fp0);
b6d96bed 11514 }
57fa1fb3 11515 break;
bf4120ad 11516 case OPC_RSQRT1_PS:
e29c9628 11517 check_ps(ctx);
b6d96bed 11518 {
a7812ae4 11519 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11520
11521 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11522 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 11523 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11524 tcg_temp_free_i64(fp0);
b6d96bed 11525 }
57fa1fb3 11526 break;
bf4120ad 11527 case OPC_RSQRT2_PS:
e29c9628 11528 check_ps(ctx);
b6d96bed 11529 {
a7812ae4
PB
11530 TCGv_i64 fp0 = tcg_temp_new_i64();
11531 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11532
11533 gen_load_fpr64(ctx, fp0, fs);
11534 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11535 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11536 tcg_temp_free_i64(fp1);
b6d96bed 11537 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11538 tcg_temp_free_i64(fp0);
b6d96bed 11539 }
57fa1fb3 11540 break;
bf4120ad 11541 case OPC_CVT_S_PU:
5e755519 11542 check_cp1_64bitmode(ctx);
b6d96bed 11543 {
a7812ae4 11544 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11545
7f6613ce 11546 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 11547 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 11548 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11549 tcg_temp_free_i32(fp0);
b6d96bed 11550 }
dd016883 11551 break;
bf4120ad 11552 case OPC_CVT_PW_PS:
e29c9628 11553 check_ps(ctx);
b6d96bed 11554 {
a7812ae4 11555 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11556
11557 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11558 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 11559 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11560 tcg_temp_free_i64(fp0);
b6d96bed 11561 }
6ea83fed 11562 break;
bf4120ad 11563 case OPC_CVT_S_PL:
5e755519 11564 check_cp1_64bitmode(ctx);
b6d96bed 11565 {
a7812ae4 11566 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11567
7c979afd 11568 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11569 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 11570 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11571 tcg_temp_free_i32(fp0);
b6d96bed 11572 }
6ea83fed 11573 break;
bf4120ad 11574 case OPC_PLL_PS:
e29c9628 11575 check_ps(ctx);
b6d96bed 11576 {
a7812ae4
PB
11577 TCGv_i32 fp0 = tcg_temp_new_i32();
11578 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11579
7c979afd
LA
11580 gen_load_fpr32(ctx, fp0, fs);
11581 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 11582 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 11583 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
11584 tcg_temp_free_i32(fp0);
11585 tcg_temp_free_i32(fp1);
b6d96bed 11586 }
6ea83fed 11587 break;
bf4120ad 11588 case OPC_PLU_PS:
e29c9628 11589 check_ps(ctx);
b6d96bed 11590 {
a7812ae4
PB
11591 TCGv_i32 fp0 = tcg_temp_new_i32();
11592 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11593
7c979afd 11594 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 11595 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11596 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11597 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11598 tcg_temp_free_i32(fp0);
11599 tcg_temp_free_i32(fp1);
b6d96bed 11600 }
5a5012ec 11601 break;
bf4120ad 11602 case OPC_PUL_PS:
e29c9628 11603 check_ps(ctx);
b6d96bed 11604 {
a7812ae4
PB
11605 TCGv_i32 fp0 = tcg_temp_new_i32();
11606 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11607
7f6613ce 11608 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
11609 gen_load_fpr32(ctx, fp1, ft);
11610 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11611 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11612 tcg_temp_free_i32(fp0);
11613 tcg_temp_free_i32(fp1);
b6d96bed 11614 }
5a5012ec 11615 break;
bf4120ad 11616 case OPC_PUU_PS:
e29c9628 11617 check_ps(ctx);
b6d96bed 11618 {
a7812ae4
PB
11619 TCGv_i32 fp0 = tcg_temp_new_i32();
11620 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11621
7f6613ce
PJ
11622 gen_load_fpr32h(ctx, fp0, fs);
11623 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11624 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11625 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11626 tcg_temp_free_i32(fp0);
11627 tcg_temp_free_i32(fp1);
b6d96bed 11628 }
5a5012ec 11629 break;
bf4120ad
NF
11630 case OPC_CMP_F_PS:
11631 case OPC_CMP_UN_PS:
11632 case OPC_CMP_EQ_PS:
11633 case OPC_CMP_UEQ_PS:
11634 case OPC_CMP_OLT_PS:
11635 case OPC_CMP_ULT_PS:
11636 case OPC_CMP_OLE_PS:
11637 case OPC_CMP_ULE_PS:
11638 case OPC_CMP_SF_PS:
11639 case OPC_CMP_NGLE_PS:
11640 case OPC_CMP_SEQ_PS:
11641 case OPC_CMP_NGL_PS:
11642 case OPC_CMP_LT_PS:
11643 case OPC_CMP_NGE_PS:
11644 case OPC_CMP_LE_PS:
11645 case OPC_CMP_NGT_PS:
8153667c 11646 if (ctx->opcode & (1 << 6)) {
71375b59 11647 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 11648 } else {
71375b59 11649 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 11650 }
6ea83fed 11651 break;
5a5012ec 11652 default:
9d68ac14 11653 MIPS_INVAL("farith");
3a4ef3b7 11654 gen_reserved_instruction(ctx);
6ea83fed
FB
11655 return;
11656 }
6ea83fed 11657}
6af0bf9c 11658
5a5012ec 11659/* Coprocessor 3 (FPU) */
235785e8
AM
11660static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11661 int fd, int fs, int base, int index)
7a387fff 11662{
4e2474d6 11663 TCGv t0 = tcg_temp_new();
7a387fff 11664
93b12ccc 11665 if (base == 0) {
6c5c1e20 11666 gen_load_gpr(t0, index);
93b12ccc 11667 } else if (index == 0) {
6c5c1e20 11668 gen_load_gpr(t0, base);
93b12ccc 11669 } else {
05168674 11670 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 11671 }
7480515f
AM
11672 /*
11673 * Don't do NOP if destination is zero: we must perform the actual
11674 * memory access.
11675 */
5a5012ec
TS
11676 switch (opc) {
11677 case OPC_LWXC1:
8c0ab41f 11678 check_cop1x(ctx);
b6d96bed 11679 {
a7812ae4 11680 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11681
5f68f5ae 11682 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 11683 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 11684 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11685 tcg_temp_free_i32(fp0);
b6d96bed 11686 }
5a5012ec
TS
11687 break;
11688 case OPC_LDXC1:
8c0ab41f
AJ
11689 check_cop1x(ctx);
11690 check_cp1_registers(ctx, fd);
b6d96bed 11691 {
a7812ae4 11692 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 11693 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11694 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11695 tcg_temp_free_i64(fp0);
b6d96bed 11696 }
5a5012ec
TS
11697 break;
11698 case OPC_LUXC1:
8c0ab41f 11699 check_cp1_64bitmode(ctx);
6c5c1e20 11700 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11701 {
a7812ae4 11702 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11703
5f68f5ae 11704 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11705 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11706 tcg_temp_free_i64(fp0);
b6d96bed 11707 }
5a5012ec
TS
11708 break;
11709 case OPC_SWXC1:
8c0ab41f 11710 check_cop1x(ctx);
b6d96bed 11711 {
a7812ae4 11712 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11713 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 11714 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 11715 tcg_temp_free_i32(fp0);
b6d96bed 11716 }
5a5012ec
TS
11717 break;
11718 case OPC_SDXC1:
8c0ab41f
AJ
11719 check_cop1x(ctx);
11720 check_cp1_registers(ctx, fs);
b6d96bed 11721 {
a7812ae4 11722 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11723 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11724 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11725 tcg_temp_free_i64(fp0);
b6d96bed 11726 }
5a5012ec
TS
11727 break;
11728 case OPC_SUXC1:
8c0ab41f 11729 check_cp1_64bitmode(ctx);
6c5c1e20 11730 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11731 {
a7812ae4 11732 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11733 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11734 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11735 tcg_temp_free_i64(fp0);
b6d96bed 11736 }
5a5012ec 11737 break;
5a5012ec 11738 }
6c5c1e20 11739 tcg_temp_free(t0);
5a5012ec
TS
11740}
11741
235785e8
AM
11742static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11743 int fd, int fr, int fs, int ft)
5a5012ec 11744{
5a5012ec
TS
11745 switch (opc) {
11746 case OPC_ALNV_PS:
e29c9628 11747 check_ps(ctx);
a16336e4 11748 {
a7812ae4 11749 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
11750 TCGv_i32 fp = tcg_temp_new_i32();
11751 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
11752 TCGLabel *l1 = gen_new_label();
11753 TCGLabel *l2 = gen_new_label();
a16336e4 11754
6c5c1e20
TS
11755 gen_load_gpr(t0, fr);
11756 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
11757
11758 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 11759 gen_load_fpr32(ctx, fp, fs);
7f6613ce 11760 gen_load_fpr32h(ctx, fph, fs);
7c979afd 11761 gen_store_fpr32(ctx, fp, fd);
7f6613ce 11762 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
11763 tcg_gen_br(l2);
11764 gen_set_label(l1);
6c5c1e20
TS
11765 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11766 tcg_temp_free(t0);
a16336e4 11767#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 11768 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
11769 gen_load_fpr32h(ctx, fph, ft);
11770 gen_store_fpr32h(ctx, fp, fd);
7c979afd 11771 gen_store_fpr32(ctx, fph, fd);
a16336e4 11772#else
7f6613ce 11773 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
11774 gen_load_fpr32(ctx, fp, ft);
11775 gen_store_fpr32(ctx, fph, fd);
7f6613ce 11776 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
11777#endif
11778 gen_set_label(l2);
c905fdac
AJ
11779 tcg_temp_free_i32(fp);
11780 tcg_temp_free_i32(fph);
a16336e4 11781 }
5a5012ec
TS
11782 break;
11783 case OPC_MADD_S:
b8aa4598 11784 check_cop1x(ctx);
b6d96bed 11785 {
a7812ae4
PB
11786 TCGv_i32 fp0 = tcg_temp_new_i32();
11787 TCGv_i32 fp1 = tcg_temp_new_i32();
11788 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11789
7c979afd
LA
11790 gen_load_fpr32(ctx, fp0, fs);
11791 gen_load_fpr32(ctx, fp1, ft);
11792 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11793 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11794 tcg_temp_free_i32(fp0);
11795 tcg_temp_free_i32(fp1);
7c979afd 11796 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11797 tcg_temp_free_i32(fp2);
b6d96bed 11798 }
5a5012ec
TS
11799 break;
11800 case OPC_MADD_D:
b8aa4598
TS
11801 check_cop1x(ctx);
11802 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11803 {
a7812ae4
PB
11804 TCGv_i64 fp0 = tcg_temp_new_i64();
11805 TCGv_i64 fp1 = tcg_temp_new_i64();
11806 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11807
11808 gen_load_fpr64(ctx, fp0, fs);
11809 gen_load_fpr64(ctx, fp1, ft);
11810 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11811 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11812 tcg_temp_free_i64(fp0);
11813 tcg_temp_free_i64(fp1);
b6d96bed 11814 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11815 tcg_temp_free_i64(fp2);
b6d96bed 11816 }
5a5012ec
TS
11817 break;
11818 case OPC_MADD_PS:
e29c9628 11819 check_ps(ctx);
b6d96bed 11820 {
a7812ae4
PB
11821 TCGv_i64 fp0 = tcg_temp_new_i64();
11822 TCGv_i64 fp1 = tcg_temp_new_i64();
11823 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11824
11825 gen_load_fpr64(ctx, fp0, fs);
11826 gen_load_fpr64(ctx, fp1, ft);
11827 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11828 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11829 tcg_temp_free_i64(fp0);
11830 tcg_temp_free_i64(fp1);
b6d96bed 11831 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11832 tcg_temp_free_i64(fp2);
b6d96bed 11833 }
5a5012ec
TS
11834 break;
11835 case OPC_MSUB_S:
b8aa4598 11836 check_cop1x(ctx);
b6d96bed 11837 {
a7812ae4
PB
11838 TCGv_i32 fp0 = tcg_temp_new_i32();
11839 TCGv_i32 fp1 = tcg_temp_new_i32();
11840 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11841
7c979afd
LA
11842 gen_load_fpr32(ctx, fp0, fs);
11843 gen_load_fpr32(ctx, fp1, ft);
11844 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11845 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11846 tcg_temp_free_i32(fp0);
11847 tcg_temp_free_i32(fp1);
7c979afd 11848 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11849 tcg_temp_free_i32(fp2);
b6d96bed 11850 }
5a5012ec
TS
11851 break;
11852 case OPC_MSUB_D:
b8aa4598
TS
11853 check_cop1x(ctx);
11854 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11855 {
a7812ae4
PB
11856 TCGv_i64 fp0 = tcg_temp_new_i64();
11857 TCGv_i64 fp1 = tcg_temp_new_i64();
11858 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11859
11860 gen_load_fpr64(ctx, fp0, fs);
11861 gen_load_fpr64(ctx, fp1, ft);
11862 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11863 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11864 tcg_temp_free_i64(fp0);
11865 tcg_temp_free_i64(fp1);
b6d96bed 11866 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11867 tcg_temp_free_i64(fp2);
b6d96bed 11868 }
5a5012ec
TS
11869 break;
11870 case OPC_MSUB_PS:
e29c9628 11871 check_ps(ctx);
b6d96bed 11872 {
a7812ae4
PB
11873 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 TCGv_i64 fp1 = tcg_temp_new_i64();
11875 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11876
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_load_fpr64(ctx, fp1, ft);
11879 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11880 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11881 tcg_temp_free_i64(fp0);
11882 tcg_temp_free_i64(fp1);
b6d96bed 11883 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11884 tcg_temp_free_i64(fp2);
b6d96bed 11885 }
5a5012ec
TS
11886 break;
11887 case OPC_NMADD_S:
b8aa4598 11888 check_cop1x(ctx);
b6d96bed 11889 {
a7812ae4
PB
11890 TCGv_i32 fp0 = tcg_temp_new_i32();
11891 TCGv_i32 fp1 = tcg_temp_new_i32();
11892 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11893
7c979afd
LA
11894 gen_load_fpr32(ctx, fp0, fs);
11895 gen_load_fpr32(ctx, fp1, ft);
11896 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11897 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11898 tcg_temp_free_i32(fp0);
11899 tcg_temp_free_i32(fp1);
7c979afd 11900 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11901 tcg_temp_free_i32(fp2);
b6d96bed 11902 }
5a5012ec
TS
11903 break;
11904 case OPC_NMADD_D:
b8aa4598
TS
11905 check_cop1x(ctx);
11906 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11907 {
a7812ae4
PB
11908 TCGv_i64 fp0 = tcg_temp_new_i64();
11909 TCGv_i64 fp1 = tcg_temp_new_i64();
11910 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11911
11912 gen_load_fpr64(ctx, fp0, fs);
11913 gen_load_fpr64(ctx, fp1, ft);
11914 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11915 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11916 tcg_temp_free_i64(fp0);
11917 tcg_temp_free_i64(fp1);
b6d96bed 11918 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11919 tcg_temp_free_i64(fp2);
b6d96bed 11920 }
5a5012ec
TS
11921 break;
11922 case OPC_NMADD_PS:
e29c9628 11923 check_ps(ctx);
b6d96bed 11924 {
a7812ae4
PB
11925 TCGv_i64 fp0 = tcg_temp_new_i64();
11926 TCGv_i64 fp1 = tcg_temp_new_i64();
11927 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11928
11929 gen_load_fpr64(ctx, fp0, fs);
11930 gen_load_fpr64(ctx, fp1, ft);
11931 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11932 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11933 tcg_temp_free_i64(fp0);
11934 tcg_temp_free_i64(fp1);
b6d96bed 11935 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11936 tcg_temp_free_i64(fp2);
b6d96bed 11937 }
5a5012ec
TS
11938 break;
11939 case OPC_NMSUB_S:
b8aa4598 11940 check_cop1x(ctx);
b6d96bed 11941 {
a7812ae4
PB
11942 TCGv_i32 fp0 = tcg_temp_new_i32();
11943 TCGv_i32 fp1 = tcg_temp_new_i32();
11944 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11945
7c979afd
LA
11946 gen_load_fpr32(ctx, fp0, fs);
11947 gen_load_fpr32(ctx, fp1, ft);
11948 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11949 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11950 tcg_temp_free_i32(fp0);
11951 tcg_temp_free_i32(fp1);
7c979afd 11952 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11953 tcg_temp_free_i32(fp2);
b6d96bed 11954 }
5a5012ec
TS
11955 break;
11956 case OPC_NMSUB_D:
b8aa4598
TS
11957 check_cop1x(ctx);
11958 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11959 {
a7812ae4
PB
11960 TCGv_i64 fp0 = tcg_temp_new_i64();
11961 TCGv_i64 fp1 = tcg_temp_new_i64();
11962 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11963
11964 gen_load_fpr64(ctx, fp0, fs);
11965 gen_load_fpr64(ctx, fp1, ft);
11966 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11967 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11968 tcg_temp_free_i64(fp0);
11969 tcg_temp_free_i64(fp1);
b6d96bed 11970 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11971 tcg_temp_free_i64(fp2);
b6d96bed 11972 }
5a5012ec
TS
11973 break;
11974 case OPC_NMSUB_PS:
e29c9628 11975 check_ps(ctx);
b6d96bed 11976 {
a7812ae4
PB
11977 TCGv_i64 fp0 = tcg_temp_new_i64();
11978 TCGv_i64 fp1 = tcg_temp_new_i64();
11979 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11980
11981 gen_load_fpr64(ctx, fp0, fs);
11982 gen_load_fpr64(ctx, fp1, ft);
11983 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11984 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11985 tcg_temp_free_i64(fp0);
11986 tcg_temp_free_i64(fp1);
b6d96bed 11987 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11988 tcg_temp_free_i64(fp2);
b6d96bed 11989 }
5a5012ec 11990 break;
923617a3 11991 default:
9d68ac14 11992 MIPS_INVAL("flt3_arith");
3a4ef3b7 11993 gen_reserved_instruction(ctx);
5a5012ec
TS
11994 return;
11995 }
7a387fff
TS
11996}
11997
f9fa53f1 11998void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
11999{
12000 TCGv t0;
12001
b3167288 12002#if !defined(CONFIG_USER_ONLY)
7480515f
AM
12003 /*
12004 * The Linux kernel will emulate rdhwr if it's not supported natively.
12005 * Therefore only check the ISA in system mode.
12006 */
7a47bae5 12007 check_insn(ctx, ISA_MIPS_R2);
b3167288 12008#endif
26ebe468
NF
12009 t0 = tcg_temp_new();
12010
12011 switch (rd) {
12012 case 0:
895c2d04 12013 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12014 gen_store_gpr(t0, rt);
12015 break;
12016 case 1:
895c2d04 12017 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12018 gen_store_gpr(t0, rt);
12019 break;
12020 case 2:
eeb3bba8 12021 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12022 gen_io_start();
12023 }
895c2d04 12024 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468 12025 gen_store_gpr(t0, rt);
7480515f
AM
12026 /*
12027 * Break the TB to be able to take timer interrupts immediately
12028 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12029 * we break completely out of translated code.
12030 */
eeb3bba8
EC
12031 gen_save_pc(ctx->base.pc_next + 4);
12032 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12033 break;
12034 case 3:
895c2d04 12035 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12036 gen_store_gpr(t0, rt);
12037 break;
b00c7218 12038 case 4:
2e211e0a 12039 check_insn(ctx, ISA_MIPS_R6);
b00c7218 12040 if (sel != 0) {
7480515f
AM
12041 /*
12042 * Performance counter registers are not implemented other than
b00c7218
YK
12043 * control register 0.
12044 */
12045 generate_exception(ctx, EXCP_RI);
12046 }
12047 gen_helper_rdhwr_performance(t0, cpu_env);
12048 gen_store_gpr(t0, rt);
12049 break;
12050 case 5:
2e211e0a 12051 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
12052 gen_helper_rdhwr_xnp(t0, cpu_env);
12053 gen_store_gpr(t0, rt);
12054 break;
26ebe468
NF
12055 case 29:
12056#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12057 tcg_gen_ld_tl(t0, cpu_env,
12058 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12059 gen_store_gpr(t0, rt);
12060 break;
12061#else
d279279e
PJ
12062 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12063 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12064 tcg_gen_ld_tl(t0, cpu_env,
12065 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12066 gen_store_gpr(t0, rt);
12067 } else {
3a4ef3b7 12068 gen_reserved_instruction(ctx);
d279279e
PJ
12069 }
12070 break;
26ebe468
NF
12071#endif
12072 default: /* Invalid */
12073 MIPS_INVAL("rdhwr");
3a4ef3b7 12074 gen_reserved_instruction(ctx);
26ebe468
NF
12075 break;
12076 }
12077 tcg_temp_free(t0);
12078}
12079
a5f53390
LA
12080static inline void clear_branch_hflags(DisasContext *ctx)
12081{
12082 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12083 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12084 save_cpu_state(ctx, 0);
12085 } else {
7480515f
AM
12086 /*
12087 * It is not safe to save ctx->hflags as hflags may be changed
12088 * in execution time by the instruction in delay / forbidden slot.
12089 */
a5f53390
LA
12090 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12091 }
12092}
12093
31837be3 12094static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12095{
12096 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12097 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12098 /* Branches completion */
a5f53390 12099 clear_branch_hflags(ctx);
eeb3bba8 12100 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12101 /* FIXME: Need to clear can_do_io. */
364d4831 12102 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12103 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12104 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12105 break;
c9602061
NF
12106 case MIPS_HFLAG_B:
12107 /* unconditional branch */
364d4831
NF
12108 if (proc_hflags & MIPS_HFLAG_BX) {
12109 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12110 }
c9602061
NF
12111 gen_goto_tb(ctx, 0, ctx->btarget);
12112 break;
12113 case MIPS_HFLAG_BL:
12114 /* blikely taken case */
c9602061
NF
12115 gen_goto_tb(ctx, 0, ctx->btarget);
12116 break;
12117 case MIPS_HFLAG_BC:
12118 /* Conditional branch */
c9602061 12119 {
42a268c2 12120 TCGLabel *l1 = gen_new_label();
c9602061
NF
12121
12122 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12123 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12124 gen_set_label(l1);
12125 gen_goto_tb(ctx, 0, ctx->btarget);
12126 }
12127 break;
12128 case MIPS_HFLAG_BR:
12129 /* unconditional branch to register */
d75c135e 12130 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12131 TCGv t0 = tcg_temp_new();
12132 TCGv_i32 t1 = tcg_temp_new_i32();
12133
12134 tcg_gen_andi_tl(t0, btarget, 0x1);
12135 tcg_gen_trunc_tl_i32(t1, t0);
12136 tcg_temp_free(t0);
12137 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12138 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12139 tcg_gen_or_i32(hflags, hflags, t1);
12140 tcg_temp_free_i32(t1);
12141
12142 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12143 } else {
12144 tcg_gen_mov_tl(cpu_PC, btarget);
12145 }
eeb3bba8 12146 if (ctx->base.singlestep_enabled) {
c9602061 12147 save_cpu_state(ctx, 0);
9c708c7f 12148 gen_helper_raise_exception_debug(cpu_env);
c9602061 12149 }
7f11636d 12150 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12151 break;
12152 default:
05d9d035
PMD
12153 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
12154 gen_reserved_instruction(ctx);
c9602061
NF
12155 }
12156 }
12157}
12158
6893f074
YK
12159/* Compact Branches */
12160static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12161 int rs, int rt, int32_t offset)
12162{
12163 int bcond_compute = 0;
12164 TCGv t0 = tcg_temp_new();
12165 TCGv t1 = tcg_temp_new();
65935f07 12166 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12167
12168 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12169#ifdef MIPS_DEBUG_DISAS
12170 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12171 "\n", ctx->base.pc_next);
6893f074 12172#endif
3a4ef3b7 12173 gen_reserved_instruction(ctx);
6893f074
YK
12174 goto out;
12175 }
12176
12177 /* Load needed operands and calculate btarget */
12178 switch (opc) {
12179 /* compact branch */
12180 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12181 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12182 gen_load_gpr(t0, rs);
12183 gen_load_gpr(t1, rt);
12184 bcond_compute = 1;
eeb3bba8 12185 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12186 if (rs <= rt && rs == 0) {
12187 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 12188 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12189 }
12190 break;
12191 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12192 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12193 gen_load_gpr(t0, rs);
12194 gen_load_gpr(t1, rt);
12195 bcond_compute = 1;
eeb3bba8 12196 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12197 break;
12198 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12199 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12200 if (rs == 0 || rs == rt) {
12201 /* OPC_BLEZALC, OPC_BGEZALC */
12202 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 12203 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12204 }
12205 gen_load_gpr(t0, rs);
12206 gen_load_gpr(t1, rt);
12207 bcond_compute = 1;
eeb3bba8 12208 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12209 break;
12210 case OPC_BC:
12211 case OPC_BALC:
eeb3bba8 12212 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12213 break;
12214 case OPC_BEQZC:
12215 case OPC_BNEZC:
12216 if (rs != 0) {
12217 /* OPC_BEQZC, OPC_BNEZC */
12218 gen_load_gpr(t0, rs);
12219 bcond_compute = 1;
eeb3bba8 12220 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12221 } else {
12222 /* OPC_JIC, OPC_JIALC */
12223 TCGv tbase = tcg_temp_new();
12224 TCGv toffset = tcg_temp_new();
12225
12226 gen_load_gpr(tbase, rt);
12227 tcg_gen_movi_tl(toffset, offset);
12228 gen_op_addr_add(ctx, btarget, tbase, toffset);
12229 tcg_temp_free(tbase);
12230 tcg_temp_free(toffset);
12231 }
12232 break;
12233 default:
12234 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 12235 gen_reserved_instruction(ctx);
6893f074
YK
12236 goto out;
12237 }
12238
12239 if (bcond_compute == 0) {
63978560 12240 /* Unconditional compact branch */
6893f074
YK
12241 switch (opc) {
12242 case OPC_JIALC:
eeb3bba8 12243 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12244 /* Fallthrough */
12245 case OPC_JIC:
12246 ctx->hflags |= MIPS_HFLAG_BR;
12247 break;
12248 case OPC_BALC:
eeb3bba8 12249 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12250 /* Fallthrough */
12251 case OPC_BC:
12252 ctx->hflags |= MIPS_HFLAG_B;
12253 break;
12254 default:
12255 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 12256 gen_reserved_instruction(ctx);
6893f074
YK
12257 goto out;
12258 }
12259
12260 /* Generating branch here as compact branches don't have delay slot */
12261 gen_branch(ctx, 4);
12262 } else {
12263 /* Conditional compact branch */
12264 TCGLabel *fs = gen_new_label();
12265 save_cpu_state(ctx, 0);
12266
12267 switch (opc) {
12268 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12269 if (rs == 0 && rt != 0) {
12270 /* OPC_BLEZALC */
12271 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12272 } else if (rs != 0 && rt != 0 && rs == rt) {
12273 /* OPC_BGEZALC */
12274 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12275 } else {
12276 /* OPC_BGEUC */
12277 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12278 }
12279 break;
12280 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12281 if (rs == 0 && rt != 0) {
12282 /* OPC_BGTZALC */
12283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12284 } else if (rs != 0 && rt != 0 && rs == rt) {
12285 /* OPC_BLTZALC */
12286 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12287 } else {
12288 /* OPC_BLTUC */
12289 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12290 }
12291 break;
12292 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12293 if (rs == 0 && rt != 0) {
12294 /* OPC_BLEZC */
12295 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12296 } else if (rs != 0 && rt != 0 && rs == rt) {
12297 /* OPC_BGEZC */
12298 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12299 } else {
12300 /* OPC_BGEC */
12301 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12302 }
12303 break;
12304 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12305 if (rs == 0 && rt != 0) {
12306 /* OPC_BGTZC */
12307 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12308 } else if (rs != 0 && rt != 0 && rs == rt) {
12309 /* OPC_BLTZC */
12310 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12311 } else {
12312 /* OPC_BLTC */
12313 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12314 }
12315 break;
12316 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12317 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12318 if (rs >= rt) {
12319 /* OPC_BOVC, OPC_BNVC */
12320 TCGv t2 = tcg_temp_new();
12321 TCGv t3 = tcg_temp_new();
12322 TCGv t4 = tcg_temp_new();
12323 TCGv input_overflow = tcg_temp_new();
12324
12325 gen_load_gpr(t0, rs);
12326 gen_load_gpr(t1, rt);
12327 tcg_gen_ext32s_tl(t2, t0);
12328 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12329 tcg_gen_ext32s_tl(t3, t1);
12330 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12331 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12332
12333 tcg_gen_add_tl(t4, t2, t3);
12334 tcg_gen_ext32s_tl(t4, t4);
12335 tcg_gen_xor_tl(t2, t2, t3);
12336 tcg_gen_xor_tl(t3, t4, t3);
12337 tcg_gen_andc_tl(t2, t3, t2);
12338 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12339 tcg_gen_or_tl(t4, t4, input_overflow);
12340 if (opc == OPC_BOVC) {
12341 /* OPC_BOVC */
12342 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12343 } else {
12344 /* OPC_BNVC */
12345 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12346 }
12347 tcg_temp_free(input_overflow);
12348 tcg_temp_free(t4);
12349 tcg_temp_free(t3);
12350 tcg_temp_free(t2);
12351 } else if (rs < rt && rs == 0) {
12352 /* OPC_BEQZALC, OPC_BNEZALC */
12353 if (opc == OPC_BEQZALC) {
12354 /* OPC_BEQZALC */
12355 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12356 } else {
12357 /* OPC_BNEZALC */
12358 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12359 }
12360 } else {
12361 /* OPC_BEQC, OPC_BNEC */
12362 if (opc == OPC_BEQC) {
12363 /* OPC_BEQC */
12364 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12365 } else {
12366 /* OPC_BNEC */
12367 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12368 }
12369 }
12370 break;
12371 case OPC_BEQZC:
12372 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12373 break;
12374 case OPC_BNEZC:
12375 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12376 break;
12377 default:
12378 MIPS_INVAL("Compact conditional branch/jump");
3a4ef3b7 12379 gen_reserved_instruction(ctx);
6893f074
YK
12380 goto out;
12381 }
12382
12383 /* Generating branch here as compact branches don't have delay slot */
12384 gen_goto_tb(ctx, 1, ctx->btarget);
12385 gen_set_label(fs);
12386
12387 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
12388 }
12389
12390out:
12391 tcg_temp_free(t0);
12392 tcg_temp_free(t1);
12393}
12394
7a387fff 12395/* ISA extensions (ASEs) */
6af0bf9c 12396/* MIPS16 extension to MIPS32 */
6ea219d0
NF
12397
12398/* MIPS16 major opcodes */
12399enum {
12400 M16_OPC_ADDIUSP = 0x00,
12401 M16_OPC_ADDIUPC = 0x01,
12402 M16_OPC_B = 0x02,
12403 M16_OPC_JAL = 0x03,
12404 M16_OPC_BEQZ = 0x04,
12405 M16_OPC_BNEQZ = 0x05,
12406 M16_OPC_SHIFT = 0x06,
12407 M16_OPC_LD = 0x07,
12408 M16_OPC_RRIA = 0x08,
12409 M16_OPC_ADDIU8 = 0x09,
12410 M16_OPC_SLTI = 0x0a,
12411 M16_OPC_SLTIU = 0x0b,
12412 M16_OPC_I8 = 0x0c,
12413 M16_OPC_LI = 0x0d,
12414 M16_OPC_CMPI = 0x0e,
12415 M16_OPC_SD = 0x0f,
12416 M16_OPC_LB = 0x10,
12417 M16_OPC_LH = 0x11,
12418 M16_OPC_LWSP = 0x12,
12419 M16_OPC_LW = 0x13,
12420 M16_OPC_LBU = 0x14,
12421 M16_OPC_LHU = 0x15,
12422 M16_OPC_LWPC = 0x16,
12423 M16_OPC_LWU = 0x17,
12424 M16_OPC_SB = 0x18,
12425 M16_OPC_SH = 0x19,
12426 M16_OPC_SWSP = 0x1a,
12427 M16_OPC_SW = 0x1b,
12428 M16_OPC_RRR = 0x1c,
12429 M16_OPC_RR = 0x1d,
12430 M16_OPC_EXTEND = 0x1e,
12431 M16_OPC_I64 = 0x1f
12432};
12433
12434/* I8 funct field */
12435enum {
12436 I8_BTEQZ = 0x0,
12437 I8_BTNEZ = 0x1,
12438 I8_SWRASP = 0x2,
12439 I8_ADJSP = 0x3,
12440 I8_SVRS = 0x4,
12441 I8_MOV32R = 0x5,
12442 I8_MOVR32 = 0x7
12443};
12444
12445/* RRR f field */
12446enum {
12447 RRR_DADDU = 0x0,
12448 RRR_ADDU = 0x1,
12449 RRR_DSUBU = 0x2,
12450 RRR_SUBU = 0x3
12451};
12452
12453/* RR funct field */
12454enum {
12455 RR_JR = 0x00,
12456 RR_SDBBP = 0x01,
12457 RR_SLT = 0x02,
12458 RR_SLTU = 0x03,
12459 RR_SLLV = 0x04,
12460 RR_BREAK = 0x05,
12461 RR_SRLV = 0x06,
12462 RR_SRAV = 0x07,
12463 RR_DSRL = 0x08,
12464 RR_CMP = 0x0a,
12465 RR_NEG = 0x0b,
12466 RR_AND = 0x0c,
12467 RR_OR = 0x0d,
12468 RR_XOR = 0x0e,
12469 RR_NOT = 0x0f,
12470 RR_MFHI = 0x10,
12471 RR_CNVT = 0x11,
12472 RR_MFLO = 0x12,
12473 RR_DSRA = 0x13,
12474 RR_DSLLV = 0x14,
12475 RR_DSRLV = 0x16,
12476 RR_DSRAV = 0x17,
12477 RR_MULT = 0x18,
12478 RR_MULTU = 0x19,
12479 RR_DIV = 0x1a,
12480 RR_DIVU = 0x1b,
12481 RR_DMULT = 0x1c,
12482 RR_DMULTU = 0x1d,
12483 RR_DDIV = 0x1e,
12484 RR_DDIVU = 0x1f
12485};
12486
12487/* I64 funct field */
12488enum {
12489 I64_LDSP = 0x0,
12490 I64_SDSP = 0x1,
12491 I64_SDRASP = 0x2,
12492 I64_DADJSP = 0x3,
12493 I64_LDPC = 0x4,
364d4831 12494 I64_DADDIU5 = 0x5,
6ea219d0
NF
12495 I64_DADDIUPC = 0x6,
12496 I64_DADDIUSP = 0x7
12497};
12498
12499/* RR ry field for CNVT */
12500enum {
12501 RR_RY_CNVT_ZEB = 0x0,
12502 RR_RY_CNVT_ZEH = 0x1,
12503 RR_RY_CNVT_ZEW = 0x2,
12504 RR_RY_CNVT_SEB = 0x4,
12505 RR_RY_CNVT_SEH = 0x5,
12506 RR_RY_CNVT_SEW = 0x6,
12507};
12508
235785e8 12509static int xlat(int r)
364d4831
NF
12510{
12511 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12512
12513 return map[r];
12514}
12515
235785e8
AM
12516static void gen_mips16_save(DisasContext *ctx,
12517 int xsregs, int aregs,
12518 int do_ra, int do_s0, int do_s1,
12519 int framesize)
364d4831
NF
12520{
12521 TCGv t0 = tcg_temp_new();
12522 TCGv t1 = tcg_temp_new();
c48245f0 12523 TCGv t2 = tcg_temp_new();
364d4831
NF
12524 int args, astatic;
12525
12526 switch (aregs) {
12527 case 0:
12528 case 1:
12529 case 2:
12530 case 3:
12531 case 11:
12532 args = 0;
12533 break;
12534 case 4:
12535 case 5:
12536 case 6:
12537 case 7:
12538 args = 1;
12539 break;
12540 case 8:
12541 case 9:
12542 case 10:
12543 args = 2;
12544 break;
12545 case 12:
12546 case 13:
12547 args = 3;
12548 break;
12549 case 14:
12550 args = 4;
12551 break;
12552 default:
3a4ef3b7 12553 gen_reserved_instruction(ctx);
364d4831
NF
12554 return;
12555 }
12556
12557 switch (args) {
12558 case 4:
12559 gen_base_offset_addr(ctx, t0, 29, 12);
12560 gen_load_gpr(t1, 7);
5f68f5ae 12561 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12562 /* Fall through */
12563 case 3:
12564 gen_base_offset_addr(ctx, t0, 29, 8);
12565 gen_load_gpr(t1, 6);
5f68f5ae 12566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12567 /* Fall through */
12568 case 2:
12569 gen_base_offset_addr(ctx, t0, 29, 4);
12570 gen_load_gpr(t1, 5);
5f68f5ae 12571 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12572 /* Fall through */
12573 case 1:
12574 gen_base_offset_addr(ctx, t0, 29, 0);
12575 gen_load_gpr(t1, 4);
5f68f5ae 12576 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12577 }
12578
12579 gen_load_gpr(t0, 29);
12580
5f68f5ae 12581#define DECR_AND_STORE(reg) do { \
c48245f0
MR
12582 tcg_gen_movi_tl(t2, -4); \
12583 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12584 gen_load_gpr(t1, reg); \
12585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
12586 } while (0)
12587
12588 if (do_ra) {
12589 DECR_AND_STORE(31);
12590 }
12591
12592 switch (xsregs) {
12593 case 7:
12594 DECR_AND_STORE(30);
12595 /* Fall through */
12596 case 6:
12597 DECR_AND_STORE(23);
12598 /* Fall through */
12599 case 5:
12600 DECR_AND_STORE(22);
12601 /* Fall through */
12602 case 4:
12603 DECR_AND_STORE(21);
12604 /* Fall through */
12605 case 3:
12606 DECR_AND_STORE(20);
12607 /* Fall through */
12608 case 2:
12609 DECR_AND_STORE(19);
12610 /* Fall through */
12611 case 1:
12612 DECR_AND_STORE(18);
12613 }
12614
12615 if (do_s1) {
12616 DECR_AND_STORE(17);
12617 }
12618 if (do_s0) {
12619 DECR_AND_STORE(16);
12620 }
12621
12622 switch (aregs) {
12623 case 0:
12624 case 4:
12625 case 8:
12626 case 12:
12627 case 14:
12628 astatic = 0;
12629 break;
12630 case 1:
12631 case 5:
12632 case 9:
12633 case 13:
12634 astatic = 1;
12635 break;
12636 case 2:
12637 case 6:
12638 case 10:
12639 astatic = 2;
12640 break;
12641 case 3:
12642 case 7:
12643 astatic = 3;
12644 break;
12645 case 11:
12646 astatic = 4;
12647 break;
12648 default:
3a4ef3b7 12649 gen_reserved_instruction(ctx);
364d4831
NF
12650 return;
12651 }
12652
12653 if (astatic > 0) {
12654 DECR_AND_STORE(7);
12655 if (astatic > 1) {
12656 DECR_AND_STORE(6);
12657 if (astatic > 2) {
12658 DECR_AND_STORE(5);
12659 if (astatic > 3) {
12660 DECR_AND_STORE(4);
12661 }
12662 }
12663 }
12664 }
12665#undef DECR_AND_STORE
12666
c48245f0
MR
12667 tcg_gen_movi_tl(t2, -framesize);
12668 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12669 tcg_temp_free(t0);
12670 tcg_temp_free(t1);
c48245f0 12671 tcg_temp_free(t2);
364d4831
NF
12672}
12673
235785e8
AM
12674static void gen_mips16_restore(DisasContext *ctx,
12675 int xsregs, int aregs,
12676 int do_ra, int do_s0, int do_s1,
12677 int framesize)
364d4831
NF
12678{
12679 int astatic;
12680 TCGv t0 = tcg_temp_new();
12681 TCGv t1 = tcg_temp_new();
c48245f0 12682 TCGv t2 = tcg_temp_new();
364d4831 12683
c48245f0
MR
12684 tcg_gen_movi_tl(t2, framesize);
12685 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 12686
5f68f5ae 12687#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
12688 tcg_gen_movi_tl(t2, -4); \
12689 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12690 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12691 gen_store_gpr(t1, reg); \
364d4831
NF
12692 } while (0)
12693
12694 if (do_ra) {
12695 DECR_AND_LOAD(31);
12696 }
12697
12698 switch (xsregs) {
12699 case 7:
12700 DECR_AND_LOAD(30);
12701 /* Fall through */
12702 case 6:
12703 DECR_AND_LOAD(23);
12704 /* Fall through */
12705 case 5:
12706 DECR_AND_LOAD(22);
12707 /* Fall through */
12708 case 4:
12709 DECR_AND_LOAD(21);
12710 /* Fall through */
12711 case 3:
12712 DECR_AND_LOAD(20);
12713 /* Fall through */
12714 case 2:
12715 DECR_AND_LOAD(19);
12716 /* Fall through */
12717 case 1:
12718 DECR_AND_LOAD(18);
12719 }
12720
12721 if (do_s1) {
12722 DECR_AND_LOAD(17);
12723 }
12724 if (do_s0) {
12725 DECR_AND_LOAD(16);
12726 }
12727
12728 switch (aregs) {
12729 case 0:
12730 case 4:
12731 case 8:
12732 case 12:
12733 case 14:
12734 astatic = 0;
12735 break;
12736 case 1:
12737 case 5:
12738 case 9:
12739 case 13:
12740 astatic = 1;
12741 break;
12742 case 2:
12743 case 6:
12744 case 10:
12745 astatic = 2;
12746 break;
12747 case 3:
12748 case 7:
12749 astatic = 3;
12750 break;
12751 case 11:
12752 astatic = 4;
12753 break;
12754 default:
3a4ef3b7 12755 gen_reserved_instruction(ctx);
364d4831
NF
12756 return;
12757 }
12758
12759 if (astatic > 0) {
12760 DECR_AND_LOAD(7);
12761 if (astatic > 1) {
12762 DECR_AND_LOAD(6);
12763 if (astatic > 2) {
12764 DECR_AND_LOAD(5);
12765 if (astatic > 3) {
12766 DECR_AND_LOAD(4);
12767 }
12768 }
12769 }
12770 }
12771#undef DECR_AND_LOAD
12772
c48245f0
MR
12773 tcg_gen_movi_tl(t2, framesize);
12774 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12775 tcg_temp_free(t0);
12776 tcg_temp_free(t1);
c48245f0 12777 tcg_temp_free(t2);
364d4831
NF
12778}
12779
d5076631
PMD
12780void gen_addiupc(DisasContext *ctx, int rx, int imm,
12781 int is_64_bit, int extended)
364d4831
NF
12782{
12783 TCGv t0;
12784
12785 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 12786 gen_reserved_instruction(ctx);
364d4831
NF
12787 return;
12788 }
12789
12790 t0 = tcg_temp_new();
12791
12792 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12793 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12794 if (!is_64_bit) {
12795 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12796 }
12797
12798 tcg_temp_free(t0);
12799}
12800
0d74a222
LA
12801static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12802 int16_t offset)
12803{
12804 TCGv_i32 t0 = tcg_const_i32(op);
12805 TCGv t1 = tcg_temp_new();
12806 gen_base_offset_addr(ctx, t1, base, offset);
12807 gen_helper_cache(cpu_env, t1, t0);
f4349ba9
PMD
12808 tcg_temp_free(t1);
12809 tcg_temp_free_i32(t0);
0d74a222
LA
12810}
12811
364d4831 12812#if defined(TARGET_MIPS64)
235785e8
AM
12813static void decode_i64_mips16(DisasContext *ctx,
12814 int ry, int funct, int16_t offset,
12815 int extended)
364d4831
NF
12816{
12817 switch (funct) {
12818 case I64_LDSP:
d9224450 12819 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12820 check_mips_64(ctx);
12821 offset = extended ? offset : offset << 3;
d75c135e 12822 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
12823 break;
12824 case I64_SDSP:
d9224450 12825 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12826 check_mips_64(ctx);
12827 offset = extended ? offset : offset << 3;
5c13fdfd 12828 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
12829 break;
12830 case I64_SDRASP:
d9224450 12831 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12832 check_mips_64(ctx);
12833 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 12834 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
12835 break;
12836 case I64_DADJSP:
d9224450 12837 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12838 check_mips_64(ctx);
12839 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 12840 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
12841 break;
12842 case I64_LDPC:
d9224450
MR
12843 check_insn(ctx, ISA_MIPS3);
12844 check_mips_64(ctx);
364d4831 12845 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 12846 gen_reserved_instruction(ctx);
364d4831
NF
12847 } else {
12848 offset = extended ? offset : offset << 3;
d75c135e 12849 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
12850 }
12851 break;
12852 case I64_DADDIU5:
d9224450 12853 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12854 check_mips_64(ctx);
12855 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 12856 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
12857 break;
12858 case I64_DADDIUPC:
d9224450 12859 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12860 check_mips_64(ctx);
12861 offset = extended ? offset : offset << 2;
12862 gen_addiupc(ctx, ry, offset, 1, extended);
12863 break;
12864 case I64_DADDIUSP:
d9224450 12865 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12866 check_mips_64(ctx);
12867 offset = extended ? offset : offset << 2;
d75c135e 12868 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
12869 break;
12870 }
12871}
12872#endif
12873
235785e8 12874static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831 12875{
0ab8e33a 12876 int extend = translator_lduw(env, ctx->base.pc_next + 2);
364d4831
NF
12877 int op, rx, ry, funct, sa;
12878 int16_t imm, offset;
12879
12880 ctx->opcode = (ctx->opcode << 16) | extend;
12881 op = (ctx->opcode >> 11) & 0x1f;
12882 sa = (ctx->opcode >> 22) & 0x1f;
12883 funct = (ctx->opcode >> 8) & 0x7;
12884 rx = xlat((ctx->opcode >> 8) & 0x7);
12885 ry = xlat((ctx->opcode >> 5) & 0x7);
12886 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12887 | ((ctx->opcode >> 21) & 0x3f) << 5
12888 | (ctx->opcode & 0x1f));
12889
7480515f
AM
12890 /*
12891 * The extended opcodes cleverly reuse the opcodes from their 16-bit
12892 * counterparts.
12893 */
364d4831
NF
12894 switch (op) {
12895 case M16_OPC_ADDIUSP:
d75c135e 12896 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
12897 break;
12898 case M16_OPC_ADDIUPC:
12899 gen_addiupc(ctx, rx, imm, 0, 1);
12900 break;
12901 case M16_OPC_B:
b231c103 12902 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
12903 /* No delay slot, so just process as a normal instruction */
12904 break;
12905 case M16_OPC_BEQZ:
b231c103 12906 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
12907 /* No delay slot, so just process as a normal instruction */
12908 break;
12909 case M16_OPC_BNEQZ:
b231c103 12910 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
12911 /* No delay slot, so just process as a normal instruction */
12912 break;
12913 case M16_OPC_SHIFT:
12914 switch (ctx->opcode & 0x3) {
12915 case 0x0:
d75c135e 12916 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12917 break;
12918 case 0x1:
12919#if defined(TARGET_MIPS64)
12920 check_mips_64(ctx);
d75c135e 12921 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12922#else
3a4ef3b7 12923 gen_reserved_instruction(ctx);
364d4831
NF
12924#endif
12925 break;
12926 case 0x2:
d75c135e 12927 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12928 break;
12929 case 0x3:
d75c135e 12930 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12931 break;
12932 }
12933 break;
12934#if defined(TARGET_MIPS64)
12935 case M16_OPC_LD:
d9224450 12936 check_insn(ctx, ISA_MIPS3);
d75de749 12937 check_mips_64(ctx);
d75c135e 12938 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
12939 break;
12940#endif
12941 case M16_OPC_RRIA:
12942 imm = ctx->opcode & 0xf;
12943 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12944 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12945 imm = (int16_t) (imm << 1) >> 1;
12946 if ((ctx->opcode >> 4) & 0x1) {
12947#if defined(TARGET_MIPS64)
12948 check_mips_64(ctx);
d75c135e 12949 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12950#else
3a4ef3b7 12951 gen_reserved_instruction(ctx);
364d4831
NF
12952#endif
12953 } else {
d75c135e 12954 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12955 }
12956 break;
12957 case M16_OPC_ADDIU8:
d75c135e 12958 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12959 break;
12960 case M16_OPC_SLTI:
d75c135e 12961 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12962 break;
12963 case M16_OPC_SLTIU:
d75c135e 12964 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12965 break;
12966 case M16_OPC_I8:
12967 switch (funct) {
12968 case I8_BTEQZ:
b231c103 12969 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
12970 break;
12971 case I8_BTNEZ:
b231c103 12972 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
12973 break;
12974 case I8_SWRASP:
5c13fdfd 12975 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
12976 break;
12977 case I8_ADJSP:
d75c135e 12978 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
12979 break;
12980 case I8_SVRS:
bbd5e4a2 12981 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
12982 {
12983 int xsregs = (ctx->opcode >> 24) & 0x7;
12984 int aregs = (ctx->opcode >> 16) & 0xf;
12985 int do_ra = (ctx->opcode >> 6) & 0x1;
12986 int do_s0 = (ctx->opcode >> 5) & 0x1;
12987 int do_s1 = (ctx->opcode >> 4) & 0x1;
12988 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12989 | (ctx->opcode & 0xf)) << 3;
12990
12991 if (ctx->opcode & (1 << 7)) {
12992 gen_mips16_save(ctx, xsregs, aregs,
12993 do_ra, do_s0, do_s1,
12994 framesize);
12995 } else {
12996 gen_mips16_restore(ctx, xsregs, aregs,
12997 do_ra, do_s0, do_s1,
12998 framesize);
12999 }
13000 }
13001 break;
13002 default:
3a4ef3b7 13003 gen_reserved_instruction(ctx);
364d4831
NF
13004 break;
13005 }
13006 break;
13007 case M16_OPC_LI:
13008 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13009 break;
13010 case M16_OPC_CMPI:
13011 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13012 break;
13013#if defined(TARGET_MIPS64)
13014 case M16_OPC_SD:
d9224450
MR
13015 check_insn(ctx, ISA_MIPS3);
13016 check_mips_64(ctx);
5c13fdfd 13017 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13018 break;
13019#endif
13020 case M16_OPC_LB:
d75c135e 13021 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13022 break;
13023 case M16_OPC_LH:
d75c135e 13024 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13025 break;
13026 case M16_OPC_LWSP:
d75c135e 13027 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13028 break;
13029 case M16_OPC_LW:
d75c135e 13030 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13031 break;
13032 case M16_OPC_LBU:
d75c135e 13033 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13034 break;
13035 case M16_OPC_LHU:
d75c135e 13036 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13037 break;
13038 case M16_OPC_LWPC:
d75c135e 13039 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13040 break;
13041#if defined(TARGET_MIPS64)
13042 case M16_OPC_LWU:
d9224450
MR
13043 check_insn(ctx, ISA_MIPS3);
13044 check_mips_64(ctx);
d75c135e 13045 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13046 break;
13047#endif
13048 case M16_OPC_SB:
5c13fdfd 13049 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13050 break;
13051 case M16_OPC_SH:
5c13fdfd 13052 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13053 break;
13054 case M16_OPC_SWSP:
5c13fdfd 13055 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13056 break;
13057 case M16_OPC_SW:
5c13fdfd 13058 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13059 break;
13060#if defined(TARGET_MIPS64)
13061 case M16_OPC_I64:
d75c135e 13062 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13063 break;
13064#endif
13065 default:
3a4ef3b7 13066 gen_reserved_instruction(ctx);
364d4831
NF
13067 break;
13068 }
13069
13070 return 4;
13071}
13072
3b3c1694
LA
13073static inline bool is_uhi(int sdbbp_code)
13074{
13075#ifdef CONFIG_USER_ONLY
13076 return false;
13077#else
13078 return semihosting_enabled() && sdbbp_code == 1;
13079#endif
13080}
13081
82ba4266
AB
13082#ifdef CONFIG_USER_ONLY
13083/* The above should dead-code away any calls to this..*/
13084static inline void gen_helper_do_semihosting(void *env)
13085{
13086 g_assert_not_reached();
13087}
13088#endif
13089
235785e8 13090static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13091{
13092 int rx, ry;
13093 int sa;
13094 int op, cnvt_op, op1, offset;
13095 int funct;
13096 int n_bytes;
13097
13098 op = (ctx->opcode >> 11) & 0x1f;
13099 sa = (ctx->opcode >> 2) & 0x7;
13100 sa = sa == 0 ? 8 : sa;
13101 rx = xlat((ctx->opcode >> 8) & 0x7);
13102 cnvt_op = (ctx->opcode >> 5) & 0x7;
13103 ry = xlat((ctx->opcode >> 5) & 0x7);
13104 op1 = offset = ctx->opcode & 0x1f;
13105
13106 n_bytes = 2;
13107
13108 switch (op) {
13109 case M16_OPC_ADDIUSP:
13110 {
13111 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13112
d75c135e 13113 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13114 }
13115 break;
13116 case M16_OPC_ADDIUPC:
13117 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13118 break;
13119 case M16_OPC_B:
13120 offset = (ctx->opcode & 0x7ff) << 1;
13121 offset = (int16_t)(offset << 4) >> 4;
b231c103 13122 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13123 /* No delay slot, so just process as a normal instruction */
13124 break;
13125 case M16_OPC_JAL:
0ab8e33a 13126 offset = translator_lduw(env, ctx->base.pc_next + 2);
364d4831
NF
13127 offset = (((ctx->opcode & 0x1f) << 21)
13128 | ((ctx->opcode >> 5) & 0x1f) << 16
13129 | offset) << 2;
b231c103
YK
13130 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13131 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13132 n_bytes = 4;
364d4831
NF
13133 break;
13134 case M16_OPC_BEQZ:
b231c103
YK
13135 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13136 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13137 /* No delay slot, so just process as a normal instruction */
13138 break;
13139 case M16_OPC_BNEQZ:
b231c103
YK
13140 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13141 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13142 /* No delay slot, so just process as a normal instruction */
13143 break;
13144 case M16_OPC_SHIFT:
13145 switch (ctx->opcode & 0x3) {
13146 case 0x0:
d75c135e 13147 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13148 break;
13149 case 0x1:
13150#if defined(TARGET_MIPS64)
d9224450 13151 check_insn(ctx, ISA_MIPS3);
364d4831 13152 check_mips_64(ctx);
d75c135e 13153 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13154#else
3a4ef3b7 13155 gen_reserved_instruction(ctx);
364d4831
NF
13156#endif
13157 break;
13158 case 0x2:
d75c135e 13159 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13160 break;
13161 case 0x3:
d75c135e 13162 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13163 break;
13164 }
13165 break;
13166#if defined(TARGET_MIPS64)
13167 case M16_OPC_LD:
d9224450 13168 check_insn(ctx, ISA_MIPS3);
364d4831 13169 check_mips_64(ctx);
d75c135e 13170 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13171 break;
13172#endif
13173 case M16_OPC_RRIA:
13174 {
13175 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13176
13177 if ((ctx->opcode >> 4) & 1) {
13178#if defined(TARGET_MIPS64)
d9224450 13179 check_insn(ctx, ISA_MIPS3);
364d4831 13180 check_mips_64(ctx);
d75c135e 13181 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13182#else
3a4ef3b7 13183 gen_reserved_instruction(ctx);
364d4831
NF
13184#endif
13185 } else {
d75c135e 13186 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13187 }
13188 }
13189 break;
13190 case M16_OPC_ADDIU8:
13191 {
13192 int16_t imm = (int8_t) ctx->opcode;
13193
d75c135e 13194 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13195 }
13196 break;
13197 case M16_OPC_SLTI:
13198 {
13199 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13200 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13201 }
13202 break;
13203 case M16_OPC_SLTIU:
13204 {
13205 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13206 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13207 }
13208 break;
13209 case M16_OPC_I8:
13210 {
13211 int reg32;
13212
13213 funct = (ctx->opcode >> 8) & 0x7;
13214 switch (funct) {
13215 case I8_BTEQZ:
13216 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 13217 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13218 break;
13219 case I8_BTNEZ:
13220 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 13221 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13222 break;
13223 case I8_SWRASP:
5c13fdfd 13224 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
13225 break;
13226 case I8_ADJSP:
d75c135e 13227 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
13228 ((int8_t)ctx->opcode) << 3);
13229 break;
13230 case I8_SVRS:
bbd5e4a2 13231 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13232 {
13233 int do_ra = ctx->opcode & (1 << 6);
13234 int do_s0 = ctx->opcode & (1 << 5);
13235 int do_s1 = ctx->opcode & (1 << 4);
13236 int framesize = ctx->opcode & 0xf;
13237
13238 if (framesize == 0) {
13239 framesize = 128;
13240 } else {
13241 framesize = framesize << 3;
13242 }
13243
13244 if (ctx->opcode & (1 << 7)) {
13245 gen_mips16_save(ctx, 0, 0,
13246 do_ra, do_s0, do_s1, framesize);
13247 } else {
13248 gen_mips16_restore(ctx, 0, 0,
13249 do_ra, do_s0, do_s1, framesize);
13250 }
13251 }
13252 break;
13253 case I8_MOV32R:
13254 {
13255 int rz = xlat(ctx->opcode & 0x7);
13256
13257 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13258 ((ctx->opcode >> 5) & 0x7);
d75c135e 13259 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
13260 }
13261 break;
13262 case I8_MOVR32:
13263 reg32 = ctx->opcode & 0x1f;
d75c135e 13264 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
13265 break;
13266 default:
3a4ef3b7 13267 gen_reserved_instruction(ctx);
364d4831
NF
13268 break;
13269 }
13270 }
13271 break;
13272 case M16_OPC_LI:
13273 {
13274 int16_t imm = (uint8_t) ctx->opcode;
13275
d75c135e 13276 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
13277 }
13278 break;
13279 case M16_OPC_CMPI:
13280 {
13281 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13282 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
13283 }
13284 break;
13285#if defined(TARGET_MIPS64)
13286 case M16_OPC_SD:
d9224450 13287 check_insn(ctx, ISA_MIPS3);
364d4831 13288 check_mips_64(ctx);
5c13fdfd 13289 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
13290 break;
13291#endif
13292 case M16_OPC_LB:
d75c135e 13293 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13294 break;
13295 case M16_OPC_LH:
d75c135e 13296 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
13297 break;
13298 case M16_OPC_LWSP:
d75c135e 13299 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13300 break;
13301 case M16_OPC_LW:
d75c135e 13302 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
13303 break;
13304 case M16_OPC_LBU:
d75c135e 13305 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13306 break;
13307 case M16_OPC_LHU:
d75c135e 13308 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
13309 break;
13310 case M16_OPC_LWPC:
d75c135e 13311 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831 13312 break;
235785e8 13313#if defined(TARGET_MIPS64)
364d4831 13314 case M16_OPC_LWU:
d9224450 13315 check_insn(ctx, ISA_MIPS3);
364d4831 13316 check_mips_64(ctx);
d75c135e 13317 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
13318 break;
13319#endif
13320 case M16_OPC_SB:
5c13fdfd 13321 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13322 break;
13323 case M16_OPC_SH:
5c13fdfd 13324 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
13325 break;
13326 case M16_OPC_SWSP:
5c13fdfd 13327 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13328 break;
13329 case M16_OPC_SW:
5c13fdfd 13330 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
13331 break;
13332 case M16_OPC_RRR:
13333 {
13334 int rz = xlat((ctx->opcode >> 2) & 0x7);
13335 int mips32_op;
13336
13337 switch (ctx->opcode & 0x3) {
13338 case RRR_ADDU:
13339 mips32_op = OPC_ADDU;
13340 break;
13341 case RRR_SUBU:
13342 mips32_op = OPC_SUBU;
13343 break;
13344#if defined(TARGET_MIPS64)
13345 case RRR_DADDU:
13346 mips32_op = OPC_DADDU;
d9224450 13347 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13348 check_mips_64(ctx);
13349 break;
13350 case RRR_DSUBU:
13351 mips32_op = OPC_DSUBU;
d9224450 13352 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13353 check_mips_64(ctx);
13354 break;
13355#endif
13356 default:
3a4ef3b7 13357 gen_reserved_instruction(ctx);
364d4831
NF
13358 goto done;
13359 }
13360
d75c135e 13361 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
13362 done:
13363 ;
13364 }
13365 break;
13366 case M16_OPC_RR:
13367 switch (op1) {
13368 case RR_JR:
13369 {
13370 int nd = (ctx->opcode >> 7) & 0x1;
13371 int link = (ctx->opcode >> 6) & 0x1;
13372 int ra = (ctx->opcode >> 5) & 0x1;
13373
d9224450 13374 if (nd) {
bbd5e4a2 13375 check_insn(ctx, ISA_MIPS_R1);
d9224450
MR
13376 }
13377
364d4831 13378 if (link) {
b231c103 13379 op = OPC_JALR;
364d4831
NF
13380 } else {
13381 op = OPC_JR;
13382 }
13383
b231c103
YK
13384 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13385 (nd ? 0 : 2));
364d4831
NF
13386 }
13387 break;
13388 case RR_SDBBP:
3b3c1694
LA
13389 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13390 gen_helper_do_semihosting(cpu_env);
13391 } else {
7480515f
AM
13392 /*
13393 * XXX: not clear which exception should be raised
3b3c1694
LA
13394 * when in debug mode...
13395 */
bbd5e4a2 13396 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 13397 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13398 }
364d4831
NF
13399 break;
13400 case RR_SLT:
d75c135e 13401 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
13402 break;
13403 case RR_SLTU:
d75c135e 13404 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
13405 break;
13406 case RR_BREAK:
9c708c7f 13407 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
13408 break;
13409 case RR_SLLV:
d75c135e 13410 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
13411 break;
13412 case RR_SRLV:
d75c135e 13413 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
13414 break;
13415 case RR_SRAV:
d75c135e 13416 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831 13417 break;
235785e8 13418#if defined(TARGET_MIPS64)
364d4831 13419 case RR_DSRL:
d9224450 13420 check_insn(ctx, ISA_MIPS3);
364d4831 13421 check_mips_64(ctx);
d75c135e 13422 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
13423 break;
13424#endif
13425 case RR_CMP:
d75c135e 13426 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
13427 break;
13428 case RR_NEG:
d75c135e 13429 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
13430 break;
13431 case RR_AND:
d75c135e 13432 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
13433 break;
13434 case RR_OR:
d75c135e 13435 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
13436 break;
13437 case RR_XOR:
d75c135e 13438 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
13439 break;
13440 case RR_NOT:
d75c135e 13441 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
13442 break;
13443 case RR_MFHI:
26135ead 13444 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
13445 break;
13446 case RR_CNVT:
bbd5e4a2 13447 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13448 switch (cnvt_op) {
13449 case RR_RY_CNVT_ZEB:
13450 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13451 break;
13452 case RR_RY_CNVT_ZEH:
13453 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13454 break;
13455 case RR_RY_CNVT_SEB:
13456 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13457 break;
13458 case RR_RY_CNVT_SEH:
13459 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13460 break;
71375b59 13461#if defined(TARGET_MIPS64)
364d4831 13462 case RR_RY_CNVT_ZEW:
bbd5e4a2 13463 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13464 check_mips_64(ctx);
13465 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13466 break;
13467 case RR_RY_CNVT_SEW:
bbd5e4a2 13468 check_insn(ctx, ISA_MIPS_R1);
364d4831
NF
13469 check_mips_64(ctx);
13470 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13471 break;
13472#endif
13473 default:
3a4ef3b7 13474 gen_reserved_instruction(ctx);
364d4831
NF
13475 break;
13476 }
13477 break;
13478 case RR_MFLO:
26135ead 13479 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831 13480 break;
235785e8 13481#if defined(TARGET_MIPS64)
364d4831 13482 case RR_DSRA:
d9224450 13483 check_insn(ctx, ISA_MIPS3);
364d4831 13484 check_mips_64(ctx);
d75c135e 13485 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
13486 break;
13487 case RR_DSLLV:
d9224450 13488 check_insn(ctx, ISA_MIPS3);
364d4831 13489 check_mips_64(ctx);
d75c135e 13490 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
13491 break;
13492 case RR_DSRLV:
d9224450 13493 check_insn(ctx, ISA_MIPS3);
364d4831 13494 check_mips_64(ctx);
d75c135e 13495 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
13496 break;
13497 case RR_DSRAV:
d9224450 13498 check_insn(ctx, ISA_MIPS3);
364d4831 13499 check_mips_64(ctx);
d75c135e 13500 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
13501 break;
13502#endif
13503 case RR_MULT:
26135ead 13504 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
13505 break;
13506 case RR_MULTU:
26135ead 13507 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
13508 break;
13509 case RR_DIV:
26135ead 13510 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
13511 break;
13512 case RR_DIVU:
26135ead 13513 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831 13514 break;
235785e8 13515#if defined(TARGET_MIPS64)
364d4831 13516 case RR_DMULT:
d9224450 13517 check_insn(ctx, ISA_MIPS3);
364d4831 13518 check_mips_64(ctx);
26135ead 13519 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
13520 break;
13521 case RR_DMULTU:
d9224450 13522 check_insn(ctx, ISA_MIPS3);
364d4831 13523 check_mips_64(ctx);
26135ead 13524 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
13525 break;
13526 case RR_DDIV:
d9224450 13527 check_insn(ctx, ISA_MIPS3);
364d4831 13528 check_mips_64(ctx);
26135ead 13529 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
13530 break;
13531 case RR_DDIVU:
d9224450 13532 check_insn(ctx, ISA_MIPS3);
364d4831 13533 check_mips_64(ctx);
26135ead 13534 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
13535 break;
13536#endif
13537 default:
3a4ef3b7 13538 gen_reserved_instruction(ctx);
364d4831
NF
13539 break;
13540 }
13541 break;
13542 case M16_OPC_EXTEND:
240ce26a 13543 decode_extended_mips16_opc(env, ctx);
364d4831
NF
13544 n_bytes = 4;
13545 break;
13546#if defined(TARGET_MIPS64)
13547 case M16_OPC_I64:
13548 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 13549 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
13550 break;
13551#endif
13552 default:
3a4ef3b7 13553 gen_reserved_instruction(ctx);
364d4831
NF
13554 break;
13555 }
13556
13557 return n_bytes;
13558}
13559
211da992 13560/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 13561
211da992
CWR
13562/*
13563 * microMIPS32/microMIPS64 major opcodes
13564 *
13565 * 1. MIPS Architecture for Programmers Volume II-B:
13566 * The microMIPS32 Instruction Set (Revision 3.05)
13567 *
13568 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13569 *
13570 * 2. MIPS Architecture For Programmers Volume II-A:
13571 * The MIPS64 Instruction Set (Revision 3.51)
13572 */
6af0bf9c 13573
3c824109
NF
13574enum {
13575 POOL32A = 0x00,
13576 POOL16A = 0x01,
13577 LBU16 = 0x02,
13578 MOVE16 = 0x03,
13579 ADDI32 = 0x04,
3a1f4268
YK
13580 R6_LUI = 0x04,
13581 AUI = 0x04,
3c824109
NF
13582 LBU32 = 0x05,
13583 SB32 = 0x06,
13584 LB32 = 0x07,
13585
13586 POOL32B = 0x08,
13587 POOL16B = 0x09,
13588 LHU16 = 0x0a,
13589 ANDI16 = 0x0b,
13590 ADDIU32 = 0x0c,
13591 LHU32 = 0x0d,
13592 SH32 = 0x0e,
13593 LH32 = 0x0f,
13594
13595 POOL32I = 0x10,
13596 POOL16C = 0x11,
13597 LWSP16 = 0x12,
13598 POOL16D = 0x13,
13599 ORI32 = 0x14,
13600 POOL32F = 0x15,
211da992
CWR
13601 POOL32S = 0x16, /* MIPS64 */
13602 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
13603
13604 POOL32C = 0x18,
13605 LWGP16 = 0x19,
13606 LW16 = 0x1a,
13607 POOL16E = 0x1b,
13608 XORI32 = 0x1c,
13609 JALS32 = 0x1d,
3a1f4268
YK
13610 BOVC = 0x1d,
13611 BEQC = 0x1d,
13612 BEQZALC = 0x1d,
3c824109 13613 ADDIUPC = 0x1e,
3a1f4268
YK
13614 PCREL = 0x1e,
13615 BNVC = 0x1f,
13616 BNEC = 0x1f,
13617 BNEZALC = 0x1f,
3c824109 13618
3a1f4268
YK
13619 R6_BEQZC = 0x20,
13620 JIC = 0x20,
3c824109
NF
13621 POOL16F = 0x21,
13622 SB16 = 0x22,
13623 BEQZ16 = 0x23,
3a1f4268 13624 BEQZC16 = 0x23,
3c824109
NF
13625 SLTI32 = 0x24,
13626 BEQ32 = 0x25,
3a1f4268 13627 BC = 0x25,
3c824109
NF
13628 SWC132 = 0x26,
13629 LWC132 = 0x27,
13630
3a1f4268 13631 /* 0x29 is reserved */
3c824109 13632 RES_29 = 0x29,
3a1f4268
YK
13633 R6_BNEZC = 0x28,
13634 JIALC = 0x28,
3c824109
NF
13635 SH16 = 0x2a,
13636 BNEZ16 = 0x2b,
3a1f4268 13637 BNEZC16 = 0x2b,
3c824109
NF
13638 SLTIU32 = 0x2c,
13639 BNE32 = 0x2d,
3a1f4268 13640 BALC = 0x2d,
3c824109
NF
13641 SDC132 = 0x2e,
13642 LDC132 = 0x2f,
13643
3a1f4268 13644 /* 0x31 is reserved */
3c824109 13645 RES_31 = 0x31,
3a1f4268
YK
13646 BLEZALC = 0x30,
13647 BGEZALC = 0x30,
13648 BGEUC = 0x30,
3c824109
NF
13649 SWSP16 = 0x32,
13650 B16 = 0x33,
3a1f4268 13651 BC16 = 0x33,
3c824109
NF
13652 ANDI32 = 0x34,
13653 J32 = 0x35,
3a1f4268
YK
13654 BGTZC = 0x35,
13655 BLTZC = 0x35,
13656 BLTC = 0x35,
211da992
CWR
13657 SD32 = 0x36, /* MIPS64 */
13658 LD32 = 0x37, /* MIPS64 */
3c824109 13659
3a1f4268 13660 /* 0x39 is reserved */
3c824109 13661 RES_39 = 0x39,
3a1f4268
YK
13662 BGTZALC = 0x38,
13663 BLTZALC = 0x38,
13664 BLTUC = 0x38,
3c824109
NF
13665 SW16 = 0x3a,
13666 LI16 = 0x3b,
13667 JALX32 = 0x3c,
13668 JAL32 = 0x3d,
3a1f4268
YK
13669 BLEZC = 0x3d,
13670 BGEZC = 0x3d,
13671 BGEC = 0x3d,
3c824109
NF
13672 SW32 = 0x3e,
13673 LW32 = 0x3f
13674};
13675
3a1f4268
YK
13676/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13677enum {
13678 ADDIUPC_00 = 0x00,
c38a1d52
AR
13679 ADDIUPC_01 = 0x01,
13680 ADDIUPC_02 = 0x02,
13681 ADDIUPC_03 = 0x03,
13682 ADDIUPC_04 = 0x04,
13683 ADDIUPC_05 = 0x05,
13684 ADDIUPC_06 = 0x06,
3a1f4268
YK
13685 ADDIUPC_07 = 0x07,
13686 AUIPC = 0x1e,
13687 ALUIPC = 0x1f,
13688 LWPC_08 = 0x08,
c38a1d52
AR
13689 LWPC_09 = 0x09,
13690 LWPC_0A = 0x0A,
13691 LWPC_0B = 0x0B,
13692 LWPC_0C = 0x0C,
13693 LWPC_0D = 0x0D,
13694 LWPC_0E = 0x0E,
3a1f4268
YK
13695 LWPC_0F = 0x0F,
13696};
13697
3c824109
NF
13698/* POOL32A encoding of minor opcode field */
13699
13700enum {
7480515f
AM
13701 /*
13702 * These opcodes are distinguished only by bits 9..6; those bits are
13703 * what are recorded below.
13704 */
3c824109
NF
13705 SLL32 = 0x0,
13706 SRL32 = 0x1,
13707 SRA = 0x2,
13708 ROTR = 0x3,
3a1f4268
YK
13709 SELEQZ = 0x5,
13710 SELNEZ = 0x6,
b00c7218 13711 R6_RDHWR = 0x7,
3c824109
NF
13712
13713 SLLV = 0x0,
13714 SRLV = 0x1,
13715 SRAV = 0x2,
13716 ROTRV = 0x3,
13717 ADD = 0x4,
13718 ADDU32 = 0x5,
13719 SUB = 0x6,
13720 SUBU32 = 0x7,
13721 MUL = 0x8,
13722 AND = 0x9,
13723 OR32 = 0xa,
13724 NOR = 0xb,
13725 XOR32 = 0xc,
13726 SLT = 0xd,
13727 SLTU = 0xe,
13728
13729 MOVN = 0x0,
3a1f4268 13730 R6_MUL = 0x0,
3c824109 13731 MOVZ = 0x1,
3a1f4268
YK
13732 MUH = 0x1,
13733 MULU = 0x2,
13734 MUHU = 0x3,
3c824109 13735 LWXS = 0x4,
3a1f4268
YK
13736 R6_DIV = 0x4,
13737 MOD = 0x5,
13738 R6_DIVU = 0x6,
13739 MODU = 0x7,
3c824109
NF
13740
13741 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 13742 BREAK32 = 0x07,
3c824109 13743 INS = 0x0c,
3a1f4268
YK
13744 LSA = 0x0f,
13745 ALIGN = 0x1f,
3c824109 13746 EXT = 0x2c,
bb238210
YK
13747 POOL32AXF = 0x3c,
13748 SIGRIE = 0x3f
3c824109
NF
13749};
13750
13751/* POOL32AXF encoding of minor opcode field extension */
13752
d132c79f
CWR
13753/*
13754 * 1. MIPS Architecture for Programmers Volume II-B:
13755 * The microMIPS32 Instruction Set (Revision 3.05)
13756 *
13757 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13758 *
13759 * 2. MIPS Architecture for Programmers VolumeIV-e:
13760 * The MIPS DSP Application-Specific Extension
13761 * to the microMIPS32 Architecture (Revision 2.34)
13762 *
13763 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13764 */
13765
3c824109
NF
13766enum {
13767 /* bits 11..6 */
13768 TEQ = 0x00,
13769 TGE = 0x08,
13770 TGEU = 0x10,
13771 TLT = 0x20,
13772 TLTU = 0x28,
13773 TNE = 0x30,
13774
13775 MFC0 = 0x03,
13776 MTC0 = 0x0b,
13777
d132c79f
CWR
13778 /* begin of microMIPS32 DSP */
13779
3c824109
NF
13780 /* bits 13..12 for 0x01 */
13781 MFHI_ACC = 0x0,
13782 MFLO_ACC = 0x1,
13783 MTHI_ACC = 0x2,
13784 MTLO_ACC = 0x3,
13785
13786 /* bits 13..12 for 0x2a */
13787 MADD_ACC = 0x0,
13788 MADDU_ACC = 0x1,
13789 MSUB_ACC = 0x2,
13790 MSUBU_ACC = 0x3,
13791
13792 /* bits 13..12 for 0x32 */
13793 MULT_ACC = 0x0,
6801038b 13794 MULTU_ACC = 0x1,
3c824109 13795
d132c79f
CWR
13796 /* end of microMIPS32 DSP */
13797
3c824109 13798 /* bits 15..12 for 0x2c */
3a1f4268 13799 BITSWAP = 0x0,
3c824109
NF
13800 SEB = 0x2,
13801 SEH = 0x3,
13802 CLO = 0x4,
13803 CLZ = 0x5,
13804 RDHWR = 0x6,
13805 WSBH = 0x7,
13806 MULT = 0x8,
13807 MULTU = 0x9,
13808 DIV = 0xa,
13809 DIVU = 0xb,
13810 MADD = 0xc,
13811 MADDU = 0xd,
13812 MSUB = 0xe,
13813 MSUBU = 0xf,
13814
13815 /* bits 15..12 for 0x34 */
13816 MFC2 = 0x4,
13817 MTC2 = 0x5,
13818 MFHC2 = 0x8,
13819 MTHC2 = 0x9,
13820 CFC2 = 0xc,
13821 CTC2 = 0xd,
13822
13823 /* bits 15..12 for 0x3c */
13824 JALR = 0x0,
13825 JR = 0x0, /* alias */
3a1f4268
YK
13826 JALRC = 0x0,
13827 JRC = 0x0,
3c824109 13828 JALR_HB = 0x1,
3a1f4268 13829 JALRC_HB = 0x1,
3c824109
NF
13830 JALRS = 0x4,
13831 JALRS_HB = 0x5,
13832
13833 /* bits 15..12 for 0x05 */
13834 RDPGPR = 0xe,
13835 WRPGPR = 0xf,
13836
13837 /* bits 15..12 for 0x0d */
13838 TLBP = 0x0,
13839 TLBR = 0x1,
13840 TLBWI = 0x2,
13841 TLBWR = 0x3,
e60ec063
YK
13842 TLBINV = 0x4,
13843 TLBINVF = 0x5,
3c824109
NF
13844 WAIT = 0x9,
13845 IRET = 0xd,
13846 DERET = 0xe,
13847 ERET = 0xf,
13848
13849 /* bits 15..12 for 0x15 */
13850 DMT = 0x0,
13851 DVPE = 0x1,
13852 EMT = 0x2,
13853 EVPE = 0x3,
13854
13855 /* bits 15..12 for 0x1d */
13856 DI = 0x4,
13857 EI = 0x5,
13858
13859 /* bits 15..12 for 0x2d */
13860 SYNC = 0x6,
13861 SYSCALL = 0x8,
13862 SDBBP = 0xd,
13863
13864 /* bits 15..12 for 0x35 */
13865 MFHI32 = 0x0,
13866 MFLO32 = 0x1,
13867 MTHI32 = 0x2,
13868 MTLO32 = 0x3,
13869};
13870
13871/* POOL32B encoding of minor opcode field (bits 15..12) */
13872
13873enum {
13874 LWC2 = 0x0,
13875 LWP = 0x1,
13876 LDP = 0x4,
13877 LWM32 = 0x5,
13878 CACHE = 0x6,
13879 LDM = 0x7,
13880 SWC2 = 0x8,
13881 SWP = 0x9,
13882 SDP = 0xc,
13883 SWM32 = 0xd,
13884 SDM = 0xf
13885};
13886
13887/* POOL32C encoding of minor opcode field (bits 15..12) */
13888
13889enum {
13890 LWL = 0x0,
13891 SWL = 0x8,
13892 LWR = 0x1,
13893 SWR = 0x9,
13894 PREF = 0x2,
8fffc646 13895 ST_EVA = 0xa,
3c824109
NF
13896 LL = 0x3,
13897 SC = 0xb,
13898 LDL = 0x4,
13899 SDL = 0xc,
13900 LDR = 0x5,
13901 SDR = 0xd,
8fffc646 13902 LD_EVA = 0x6,
3c824109
NF
13903 LWU = 0xe,
13904 LLD = 0x7,
13905 SCD = 0xf
13906};
13907
8fffc646
JH
13908/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13909
13910enum {
13911 LBUE = 0x0,
13912 LHUE = 0x1,
13913 LWLE = 0x2,
13914 LWRE = 0x3,
13915 LBE = 0x4,
13916 LHE = 0x5,
13917 LLE = 0x6,
13918 LWE = 0x7,
13919};
13920
13921/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13922
13923enum {
13924 SWLE = 0x0,
13925 SWRE = 0x1,
13926 PREFE = 0x2,
13927 CACHEE = 0x3,
13928 SBE = 0x4,
13929 SHE = 0x5,
13930 SCE = 0x6,
13931 SWE = 0x7,
13932};
13933
3c824109
NF
13934/* POOL32F encoding of minor opcode field (bits 5..0) */
13935
13936enum {
13937 /* These are the bit 7..6 values */
13938 ADD_FMT = 0x0,
3c824109
NF
13939
13940 SUB_FMT = 0x1,
3c824109
NF
13941
13942 MUL_FMT = 0x2,
13943
13944 DIV_FMT = 0x3,
13945
13946 /* These are the bit 8..6 values */
3a1f4268 13947 MOVN_FMT = 0x0,
3c824109
NF
13948 RSQRT2_FMT = 0x0,
13949 MOVF_FMT = 0x0,
3a1f4268
YK
13950 RINT_FMT = 0x0,
13951 SELNEZ_FMT = 0x0,
3c824109 13952
3a1f4268 13953 MOVZ_FMT = 0x1,
3c824109
NF
13954 LWXC1 = 0x1,
13955 MOVT_FMT = 0x1,
3a1f4268
YK
13956 CLASS_FMT = 0x1,
13957 SELEQZ_FMT = 0x1,
3c824109
NF
13958
13959 PLL_PS = 0x2,
13960 SWXC1 = 0x2,
3a1f4268 13961 SEL_FMT = 0x2,
3c824109
NF
13962
13963 PLU_PS = 0x3,
13964 LDXC1 = 0x3,
13965
3a1f4268 13966 MOVN_FMT_04 = 0x4,
3c824109
NF
13967 PUL_PS = 0x4,
13968 SDXC1 = 0x4,
13969 RECIP2_FMT = 0x4,
13970
3a1f4268 13971 MOVZ_FMT_05 = 0x05,
3c824109
NF
13972 PUU_PS = 0x5,
13973 LUXC1 = 0x5,
13974
13975 CVT_PS_S = 0x6,
13976 SUXC1 = 0x6,
13977 ADDR_PS = 0x6,
13978 PREFX = 0x6,
3a1f4268 13979 MADDF_FMT = 0x6,
3c824109
NF
13980
13981 MULR_PS = 0x7,
3a1f4268 13982 MSUBF_FMT = 0x7,
3c824109
NF
13983
13984 MADD_S = 0x01,
13985 MADD_D = 0x09,
13986 MADD_PS = 0x11,
13987 ALNV_PS = 0x19,
13988 MSUB_S = 0x21,
13989 MSUB_D = 0x29,
13990 MSUB_PS = 0x31,
13991
13992 NMADD_S = 0x02,
13993 NMADD_D = 0x0a,
13994 NMADD_PS = 0x12,
13995 NMSUB_S = 0x22,
13996 NMSUB_D = 0x2a,
13997 NMSUB_PS = 0x32,
13998
3a1f4268
YK
13999 MIN_FMT = 0x3,
14000 MAX_FMT = 0xb,
14001 MINA_FMT = 0x23,
14002 MAXA_FMT = 0x2b,
3c824109
NF
14003 POOL32FXF = 0x3b,
14004
14005 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14006 C_COND_FMT = 0x3c,
14007
14008 CMP_CONDN_S = 0x5,
14009 CMP_CONDN_D = 0x15
3c824109
NF
14010};
14011
14012/* POOL32Fxf encoding of minor opcode extension field */
14013
14014enum {
14015 CVT_L = 0x04,
14016 RSQRT_FMT = 0x08,
14017 FLOOR_L = 0x0c,
14018 CVT_PW_PS = 0x1c,
14019 CVT_W = 0x24,
14020 SQRT_FMT = 0x28,
14021 FLOOR_W = 0x2c,
14022 CVT_PS_PW = 0x3c,
14023 CFC1 = 0x40,
14024 RECIP_FMT = 0x48,
14025 CEIL_L = 0x4c,
14026 CTC1 = 0x60,
14027 CEIL_W = 0x6c,
14028 MFC1 = 0x80,
14029 CVT_S_PL = 0x84,
14030 TRUNC_L = 0x8c,
14031 MTC1 = 0xa0,
14032 CVT_S_PU = 0xa4,
14033 TRUNC_W = 0xac,
14034 MFHC1 = 0xc0,
14035 ROUND_L = 0xcc,
14036 MTHC1 = 0xe0,
14037 ROUND_W = 0xec,
14038
14039 MOV_FMT = 0x01,
14040 MOVF = 0x05,
14041 ABS_FMT = 0x0d,
14042 RSQRT1_FMT = 0x1d,
14043 MOVT = 0x25,
14044 NEG_FMT = 0x2d,
14045 CVT_D = 0x4d,
14046 RECIP1_FMT = 0x5d,
14047 CVT_S = 0x6d
14048};
14049
14050/* POOL32I encoding of minor opcode field (bits 25..21) */
14051
14052enum {
14053 BLTZ = 0x00,
14054 BLTZAL = 0x01,
14055 BGEZ = 0x02,
14056 BGEZAL = 0x03,
14057 BLEZ = 0x04,
14058 BNEZC = 0x05,
14059 BGTZ = 0x06,
14060 BEQZC = 0x07,
14061 TLTI = 0x08,
3a1f4268 14062 BC1EQZC = 0x08,
3c824109 14063 TGEI = 0x09,
3a1f4268 14064 BC1NEZC = 0x09,
3c824109 14065 TLTIU = 0x0a,
3a1f4268 14066 BC2EQZC = 0x0a,
3c824109 14067 TGEIU = 0x0b,
3a1f4268 14068 BC2NEZC = 0x0a,
3c824109 14069 TNEI = 0x0c,
3a1f4268 14070 R6_SYNCI = 0x0c,
3c824109
NF
14071 LUI = 0x0d,
14072 TEQI = 0x0e,
14073 SYNCI = 0x10,
14074 BLTZALS = 0x11,
14075 BGEZALS = 0x13,
14076 BC2F = 0x14,
14077 BC2T = 0x15,
3c824109
NF
14078 /* These overlap and are distinguished by bit16 of the instruction */
14079 BC1F = 0x1c,
14080 BC1T = 0x1d,
14081 BC1ANY2F = 0x1c,
14082 BC1ANY2T = 0x1d,
14083 BC1ANY4F = 0x1e,
14084 BC1ANY4T = 0x1f
14085};
14086
14087/* POOL16A encoding of minor opcode field */
14088
14089enum {
14090 ADDU16 = 0x0,
14091 SUBU16 = 0x1
14092};
14093
14094/* POOL16B encoding of minor opcode field */
14095
14096enum {
14097 SLL16 = 0x0,
14098 SRL16 = 0x1
14099};
14100
14101/* POOL16C encoding of minor opcode field */
14102
14103enum {
14104 NOT16 = 0x00,
14105 XOR16 = 0x04,
14106 AND16 = 0x08,
14107 OR16 = 0x0c,
14108 LWM16 = 0x10,
14109 SWM16 = 0x14,
14110 JR16 = 0x18,
14111 JRC16 = 0x1a,
14112 JALR16 = 0x1c,
14113 JALR16S = 0x1e,
14114 MFHI16 = 0x20,
14115 MFLO16 = 0x24,
14116 BREAK16 = 0x28,
14117 SDBBP16 = 0x2c,
14118 JRADDIUSP = 0x30
14119};
14120
3a1f4268
YK
14121/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14122
14123enum {
14124 R6_NOT16 = 0x00,
14125 R6_AND16 = 0x01,
14126 R6_LWM16 = 0x02,
14127 R6_JRC16 = 0x03,
14128 MOVEP = 0x04,
c38a1d52
AR
14129 MOVEP_05 = 0x05,
14130 MOVEP_06 = 0x06,
3a1f4268
YK
14131 MOVEP_07 = 0x07,
14132 R6_XOR16 = 0x08,
14133 R6_OR16 = 0x09,
14134 R6_SWM16 = 0x0a,
14135 JALRC16 = 0x0b,
14136 MOVEP_0C = 0x0c,
c38a1d52
AR
14137 MOVEP_0D = 0x0d,
14138 MOVEP_0E = 0x0e,
3a1f4268
YK
14139 MOVEP_0F = 0x0f,
14140 JRCADDIUSP = 0x13,
14141 R6_BREAK16 = 0x1b,
14142 R6_SDBBP16 = 0x3b
14143};
14144
3c824109
NF
14145/* POOL16D encoding of minor opcode field */
14146
14147enum {
14148 ADDIUS5 = 0x0,
14149 ADDIUSP = 0x1
14150};
14151
14152/* POOL16E encoding of minor opcode field */
14153
14154enum {
14155 ADDIUR2 = 0x0,
14156 ADDIUR1SP = 0x1
14157};
14158
235785e8 14159static int mmreg(int r)
3c824109
NF
14160{
14161 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14162
14163 return map[r];
14164}
14165
14166/* Used for 16-bit store instructions. */
235785e8 14167static int mmreg2(int r)
3c824109
NF
14168{
14169 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14170
14171 return map[r];
14172}
14173
14174#define uMIPS_RD(op) ((op >> 7) & 0x7)
14175#define uMIPS_RS(op) ((op >> 4) & 0x7)
14176#define uMIPS_RS2(op) uMIPS_RS(op)
14177#define uMIPS_RS1(op) ((op >> 1) & 0x7)
14178#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14179#define uMIPS_RS5(op) (op & 0x1f)
14180
14181/* Signed immediate */
14182#define SIMM(op, start, width) \
71375b59
AM
14183 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14184 << (32 - width)) \
14185 >> (32 - width))
3c824109 14186/* Zero-extended immediate */
71375b59 14187#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
3c824109 14188
d75c135e 14189static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
14190{
14191 int rd = mmreg(uMIPS_RD(ctx->opcode));
14192
d75c135e 14193 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
14194}
14195
d75c135e 14196static void gen_addiur2(DisasContext *ctx)
3c824109
NF
14197{
14198 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14199 int rd = mmreg(uMIPS_RD(ctx->opcode));
14200 int rs = mmreg(uMIPS_RS(ctx->opcode));
14201
d75c135e 14202 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
14203}
14204
d75c135e 14205static void gen_addiusp(DisasContext *ctx)
3c824109
NF
14206{
14207 int encoded = ZIMM(ctx->opcode, 1, 9);
14208 int decoded;
14209
14210 if (encoded <= 1) {
14211 decoded = 256 + encoded;
14212 } else if (encoded <= 255) {
14213 decoded = encoded;
14214 } else if (encoded <= 509) {
14215 decoded = encoded - 512;
14216 } else {
14217 decoded = encoded - 768;
14218 }
14219
d75c135e 14220 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
14221}
14222
d75c135e 14223static void gen_addius5(DisasContext *ctx)
3c824109
NF
14224{
14225 int imm = SIMM(ctx->opcode, 1, 4);
14226 int rd = (ctx->opcode >> 5) & 0x1f;
14227
d75c135e 14228 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
14229}
14230
d75c135e 14231static void gen_andi16(DisasContext *ctx)
3c824109
NF
14232{
14233 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14234 31, 32, 63, 64, 255, 32768, 65535 };
14235 int rd = mmreg(uMIPS_RD(ctx->opcode));
14236 int rs = mmreg(uMIPS_RS(ctx->opcode));
14237 int encoded = ZIMM(ctx->opcode, 0, 4);
14238
d75c135e 14239 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
14240}
14241
235785e8
AM
14242static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14243 int base, int16_t offset)
3c824109
NF
14244{
14245 TCGv t0, t1;
14246 TCGv_i32 t2;
14247
14248 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3a4ef3b7 14249 gen_reserved_instruction(ctx);
3c824109
NF
14250 return;
14251 }
14252
14253 t0 = tcg_temp_new();
14254
14255 gen_base_offset_addr(ctx, t0, base, offset);
14256
14257 t1 = tcg_const_tl(reglist);
14258 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 14259
3c824109
NF
14260 save_cpu_state(ctx, 1);
14261 switch (opc) {
14262 case LWM32:
895c2d04 14263 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
14264 break;
14265 case SWM32:
895c2d04 14266 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
14267 break;
14268#ifdef TARGET_MIPS64
14269 case LDM:
895c2d04 14270 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
14271 break;
14272 case SDM:
895c2d04 14273 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 14274 break;
6af0bf9c 14275#endif
3c824109 14276 }
3c824109 14277 tcg_temp_free(t0);
33087598 14278 tcg_temp_free(t1);
3c824109
NF
14279 tcg_temp_free_i32(t2);
14280}
6af0bf9c 14281
3c824109 14282
240ce26a 14283static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 14284{
3c824109
NF
14285 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14286 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 14287
3c824109
NF
14288 switch (((ctx->opcode) >> 4) & 0x3f) {
14289 case NOT16 + 0:
14290 case NOT16 + 1:
14291 case NOT16 + 2:
14292 case NOT16 + 3:
d75c135e 14293 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
14294 break;
14295 case XOR16 + 0:
14296 case XOR16 + 1:
14297 case XOR16 + 2:
14298 case XOR16 + 3:
d75c135e 14299 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
14300 break;
14301 case AND16 + 0:
14302 case AND16 + 1:
14303 case AND16 + 2:
14304 case AND16 + 3:
d75c135e 14305 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
14306 break;
14307 case OR16 + 0:
14308 case OR16 + 1:
14309 case OR16 + 2:
14310 case OR16 + 3:
d75c135e 14311 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
14312 break;
14313 case LWM16 + 0:
14314 case LWM16 + 1:
14315 case LWM16 + 2:
14316 case LWM16 + 3:
14317 {
14318 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14319 int offset = ZIMM(ctx->opcode, 0, 4);
14320
14321 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14322 29, offset << 2);
14323 }
14324 break;
14325 case SWM16 + 0:
14326 case SWM16 + 1:
14327 case SWM16 + 2:
14328 case SWM16 + 3:
14329 {
14330 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14331 int offset = ZIMM(ctx->opcode, 0, 4);
14332
14333 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14334 29, offset << 2);
14335 }
14336 break;
14337 case JR16 + 0:
14338 case JR16 + 1:
14339 {
14340 int reg = ctx->opcode & 0x1f;
14341
b231c103 14342 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 14343 }
3c824109
NF
14344 break;
14345 case JRC16 + 0:
14346 case JRC16 + 1:
14347 {
14348 int reg = ctx->opcode & 0x1f;
b231c103 14349 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
7480515f
AM
14350 /*
14351 * Let normal delay slot handling in our caller take us
14352 * to the branch target.
14353 */
3c824109
NF
14354 }
14355 break;
14356 case JALR16 + 0:
14357 case JALR16 + 1:
b231c103
YK
14358 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14359 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14360 break;
3c824109
NF
14361 case JALR16S + 0:
14362 case JALR16S + 1:
b231c103
YK
14363 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14364 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14365 break;
14366 case MFHI16 + 0:
14367 case MFHI16 + 1:
26135ead 14368 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14369 break;
14370 case MFLO16 + 0:
14371 case MFLO16 + 1:
26135ead 14372 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14373 break;
14374 case BREAK16:
9c708c7f 14375 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
14376 break;
14377 case SDBBP16:
3b3c1694
LA
14378 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14379 gen_helper_do_semihosting(cpu_env);
14380 } else {
7480515f
AM
14381 /*
14382 * XXX: not clear which exception should be raised
3b3c1694
LA
14383 * when in debug mode...
14384 */
bbd5e4a2 14385 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 14386 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14387 }
3c824109
NF
14388 break;
14389 case JRADDIUSP + 0:
14390 case JRADDIUSP + 1:
14391 {
14392 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 14393 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 14394 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
7480515f
AM
14395 /*
14396 * Let normal delay slot handling in our caller take us
14397 * to the branch target.
14398 */
3c824109
NF
14399 }
14400 break;
14401 default:
3a4ef3b7 14402 gen_reserved_instruction(ctx);
3c824109
NF
14403 break;
14404 }
14405}
14406
ed7ce6c0
YK
14407static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14408 int enc_rs)
14409{
c27b4579 14410 int rd, re;
ed7ce6c0
YK
14411 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14412 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14413 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
c27b4579 14414
ed7ce6c0
YK
14415 rd = rd_enc[enc_dest];
14416 re = re_enc[enc_dest];
c27b4579
PMD
14417 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14418 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
ed7ce6c0
YK
14419}
14420
14421static void gen_pool16c_r6_insn(DisasContext *ctx)
14422{
14423 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14424 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14425
14426 switch (ctx->opcode & 0xf) {
14427 case R6_NOT16:
14428 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14429 break;
14430 case R6_AND16:
14431 gen_logic(ctx, OPC_AND, rt, rt, rs);
14432 break;
14433 case R6_LWM16:
14434 {
14435 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14436 int offset = extract32(ctx->opcode, 4, 4);
14437 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14438 }
14439 break;
14440 case R6_JRC16: /* JRCADDIUSP */
14441 if ((ctx->opcode >> 4) & 1) {
14442 /* JRCADDIUSP */
14443 int imm = extract32(ctx->opcode, 5, 5);
14444 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14445 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14446 } else {
14447 /* JRC16 */
e1555d7d 14448 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
14449 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14450 }
14451 break;
c38a1d52
AR
14452 case MOVEP:
14453 case MOVEP_05:
14454 case MOVEP_06:
14455 case MOVEP_07:
14456 case MOVEP_0C:
14457 case MOVEP_0D:
14458 case MOVEP_0E:
14459 case MOVEP_0F:
ed7ce6c0
YK
14460 {
14461 int enc_dest = uMIPS_RD(ctx->opcode);
14462 int enc_rt = uMIPS_RS2(ctx->opcode);
14463 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14464 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14465 }
14466 break;
14467 case R6_XOR16:
14468 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14469 break;
14470 case R6_OR16:
14471 gen_logic(ctx, OPC_OR, rt, rt, rs);
14472 break;
14473 case R6_SWM16:
14474 {
14475 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14476 int offset = extract32(ctx->opcode, 4, 4);
14477 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14478 }
14479 break;
14480 case JALRC16: /* BREAK16, SDBBP16 */
14481 switch (ctx->opcode & 0x3f) {
14482 case JALRC16:
14483 case JALRC16 + 0x20:
14484 /* JALRC16 */
14485 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14486 31, 0, 0);
14487 break;
14488 case R6_BREAK16:
14489 /* BREAK16 */
14490 generate_exception(ctx, EXCP_BREAK);
14491 break;
14492 case R6_SDBBP16:
14493 /* SDBBP16 */
060ebfef
LA
14494 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14495 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 14496 } else {
060ebfef
LA
14497 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14498 generate_exception(ctx, EXCP_RI);
14499 } else {
14500 generate_exception(ctx, EXCP_DBp);
14501 }
ed7ce6c0
YK
14502 }
14503 break;
14504 }
14505 break;
14506 default:
14507 generate_exception(ctx, EXCP_RI);
14508 break;
14509 }
14510}
14511
d5076631 14512void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
14513{
14514 TCGv t0 = tcg_temp_new();
14515 TCGv t1 = tcg_temp_new();
14516
14517 gen_load_gpr(t0, base);
14518
14519 if (index != 0) {
14520 gen_load_gpr(t1, index);
14521 tcg_gen_shli_tl(t1, t1, 2);
14522 gen_op_addr_add(ctx, t0, t1, t0);
14523 }
14524
5f68f5ae 14525 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14526 gen_store_gpr(t1, rd);
14527
14528 tcg_temp_free(t0);
14529 tcg_temp_free(t1);
14530}
14531
235785e8
AM
14532static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14533 int base, int16_t offset)
3c824109 14534{
3c824109
NF
14535 TCGv t0, t1;
14536
36c6711b 14537 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3a4ef3b7 14538 gen_reserved_instruction(ctx);
d796321b
FB
14539 return;
14540 }
14541
3c824109
NF
14542 t0 = tcg_temp_new();
14543 t1 = tcg_temp_new();
8e9ade68 14544
3c824109
NF
14545 gen_base_offset_addr(ctx, t0, base, offset);
14546
14547 switch (opc) {
14548 case LWP:
36c6711b 14549 if (rd == base) {
3a4ef3b7 14550 gen_reserved_instruction(ctx);
36c6711b
EJ
14551 return;
14552 }
5f68f5ae 14553 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14554 gen_store_gpr(t1, rd);
14555 tcg_gen_movi_tl(t1, 4);
14556 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14557 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
235785e8 14558 gen_store_gpr(t1, rd + 1);
3c824109
NF
14559 break;
14560 case SWP:
3c824109 14561 gen_load_gpr(t1, rd);
5f68f5ae 14562 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14563 tcg_gen_movi_tl(t1, 4);
14564 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 14565 gen_load_gpr(t1, rd + 1);
5f68f5ae 14566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14567 break;
14568#ifdef TARGET_MIPS64
14569 case LDP:
36c6711b 14570 if (rd == base) {
3a4ef3b7 14571 gen_reserved_instruction(ctx);
36c6711b
EJ
14572 return;
14573 }
5f68f5ae 14574 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14575 gen_store_gpr(t1, rd);
14576 tcg_gen_movi_tl(t1, 8);
14577 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14578 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
235785e8 14579 gen_store_gpr(t1, rd + 1);
3c824109
NF
14580 break;
14581 case SDP:
3c824109 14582 gen_load_gpr(t1, rd);
5f68f5ae 14583 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14584 tcg_gen_movi_tl(t1, 8);
14585 gen_op_addr_add(ctx, t0, t0, t1);
235785e8 14586 gen_load_gpr(t1, rd + 1);
5f68f5ae 14587 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14588 break;
14589#endif
6af0bf9c 14590 }
3c824109
NF
14591 tcg_temp_free(t0);
14592 tcg_temp_free(t1);
14593}
618b0fe9 14594
d208ac0c
LA
14595static void gen_sync(int stype)
14596{
14597 TCGBar tcg_mo = TCG_BAR_SC;
14598
14599 switch (stype) {
14600 case 0x4: /* SYNC_WMB */
14601 tcg_mo |= TCG_MO_ST_ST;
14602 break;
14603 case 0x10: /* SYNC_MB */
14604 tcg_mo |= TCG_MO_ALL;
14605 break;
14606 case 0x11: /* SYNC_ACQUIRE */
14607 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14608 break;
14609 case 0x12: /* SYNC_RELEASE */
14610 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14611 break;
14612 case 0x13: /* SYNC_RMB */
14613 tcg_mo |= TCG_MO_LD_LD;
14614 break;
14615 default:
14616 tcg_mo |= TCG_MO_ALL;
14617 break;
14618 }
14619
14620 tcg_gen_mb(tcg_mo);
14621}
14622
235785e8 14623static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
14624{
14625 int extension = (ctx->opcode >> 6) & 0x3f;
14626 int minor = (ctx->opcode >> 12) & 0xf;
14627 uint32_t mips32_op;
14628
14629 switch (extension) {
14630 case TEQ:
14631 mips32_op = OPC_TEQ;
14632 goto do_trap;
14633 case TGE:
14634 mips32_op = OPC_TGE;
14635 goto do_trap;
14636 case TGEU:
14637 mips32_op = OPC_TGEU;
14638 goto do_trap;
14639 case TLT:
14640 mips32_op = OPC_TLT;
14641 goto do_trap;
14642 case TLTU:
14643 mips32_op = OPC_TLTU;
14644 goto do_trap;
14645 case TNE:
14646 mips32_op = OPC_TNE;
14647 do_trap:
14648 gen_trap(ctx, mips32_op, rs, rt, -1);
14649 break;
14650#ifndef CONFIG_USER_ONLY
14651 case MFC0:
14652 case MFC0 + 32:
2e15497c 14653 check_cp0_enabled(ctx);
3c824109
NF
14654 if (rt == 0) {
14655 /* Treat as NOP. */
14656 break;
14657 }
d75c135e 14658 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14659 break;
14660 case MTC0:
14661 case MTC0 + 32:
2e15497c 14662 check_cp0_enabled(ctx);
3c824109
NF
14663 {
14664 TCGv t0 = tcg_temp_new();
618b0fe9 14665
3c824109 14666 gen_load_gpr(t0, rt);
d75c135e 14667 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14668 tcg_temp_free(t0);
14669 }
14670 break;
14671#endif
a1fc6246
LA
14672 case 0x2a:
14673 switch (minor & 3) {
14674 case MADD_ACC:
14675 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14676 break;
14677 case MADDU_ACC:
14678 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14679 break;
14680 case MSUB_ACC:
14681 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14682 break;
14683 case MSUBU_ACC:
14684 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14685 break;
14686 default:
14687 goto pool32axf_invalid;
14688 }
14689 break;
14690 case 0x32:
14691 switch (minor & 3) {
14692 case MULT_ACC:
14693 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14694 break;
14695 case MULTU_ACC:
14696 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14697 break;
14698 default:
14699 goto pool32axf_invalid;
14700 }
14701 break;
3c824109
NF
14702 case 0x2c:
14703 switch (minor) {
e0332095 14704 case BITSWAP:
2e211e0a 14705 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
14706 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14707 break;
3c824109
NF
14708 case SEB:
14709 gen_bshfl(ctx, OPC_SEB, rs, rt);
14710 break;
14711 case SEH:
14712 gen_bshfl(ctx, OPC_SEH, rs, rt);
14713 break;
14714 case CLO:
14715 mips32_op = OPC_CLO;
14716 goto do_cl;
14717 case CLZ:
14718 mips32_op = OPC_CLZ;
14719 do_cl:
bbd5e4a2 14720 check_insn(ctx, ISA_MIPS_R1);
3c824109
NF
14721 gen_cl(ctx, mips32_op, rt, rs);
14722 break;
14723 case RDHWR:
2e211e0a 14724 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b00c7218 14725 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
14726 break;
14727 case WSBH:
14728 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14729 break;
14730 case MULT:
2e211e0a 14731 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14732 mips32_op = OPC_MULT;
26135ead 14733 goto do_mul;
3c824109 14734 case MULTU:
2e211e0a 14735 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14736 mips32_op = OPC_MULTU;
26135ead 14737 goto do_mul;
3c824109 14738 case DIV:
2e211e0a 14739 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14740 mips32_op = OPC_DIV;
26135ead 14741 goto do_div;
3c824109 14742 case DIVU:
2e211e0a 14743 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14744 mips32_op = OPC_DIVU;
26135ead
RS
14745 goto do_div;
14746 do_div:
bbd5e4a2 14747 check_insn(ctx, ISA_MIPS_R1);
26135ead
RS
14748 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14749 break;
3c824109 14750 case MADD:
2e211e0a 14751 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14752 mips32_op = OPC_MADD;
26135ead 14753 goto do_mul;
3c824109 14754 case MADDU:
2e211e0a 14755 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14756 mips32_op = OPC_MADDU;
26135ead 14757 goto do_mul;
3c824109 14758 case MSUB:
2e211e0a 14759 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14760 mips32_op = OPC_MSUB;
26135ead 14761 goto do_mul;
3c824109 14762 case MSUBU:
2e211e0a 14763 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 14764 mips32_op = OPC_MSUBU;
26135ead 14765 do_mul:
bbd5e4a2 14766 check_insn(ctx, ISA_MIPS_R1);
a1fc6246 14767 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
14768 break;
14769 default:
14770 goto pool32axf_invalid;
14771 }
14772 break;
14773 case 0x34:
14774 switch (minor) {
14775 case MFC2:
14776 case MTC2:
14777 case MFHC2:
14778 case MTHC2:
14779 case CFC2:
14780 case CTC2:
14781 generate_exception_err(ctx, EXCP_CpU, 2);
14782 break;
14783 default:
14784 goto pool32axf_invalid;
14785 }
14786 break;
14787 case 0x3c:
14788 switch (minor) {
65935f07
YK
14789 case JALR: /* JALRC */
14790 case JALR_HB: /* JALRC_HB */
2e211e0a 14791 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
14792 /* JALRC, JALRC_HB */
14793 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14794 } else {
14795 /* JALR, JALR_HB */
14796 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14797 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14798 }
3c824109
NF
14799 break;
14800 case JALRS:
14801 case JALRS_HB:
2e211e0a 14802 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
14803 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14804 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14805 break;
14806 default:
14807 goto pool32axf_invalid;
14808 }
14809 break;
14810 case 0x05:
14811 switch (minor) {
14812 case RDPGPR:
2e15497c 14813 check_cp0_enabled(ctx);
7a47bae5 14814 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 14815 gen_load_srsgpr(rs, rt);
3c824109
NF
14816 break;
14817 case WRPGPR:
2e15497c 14818 check_cp0_enabled(ctx);
7a47bae5 14819 check_insn(ctx, ISA_MIPS_R2);
1bf5902d 14820 gen_store_srsgpr(rs, rt);
3c824109
NF
14821 break;
14822 default:
14823 goto pool32axf_invalid;
14824 }
14825 break;
14826#ifndef CONFIG_USER_ONLY
14827 case 0x0d:
14828 switch (minor) {
14829 case TLBP:
14830 mips32_op = OPC_TLBP;
14831 goto do_cp0;
14832 case TLBR:
14833 mips32_op = OPC_TLBR;
14834 goto do_cp0;
14835 case TLBWI:
14836 mips32_op = OPC_TLBWI;
14837 goto do_cp0;
14838 case TLBWR:
14839 mips32_op = OPC_TLBWR;
14840 goto do_cp0;
e60ec063
YK
14841 case TLBINV:
14842 mips32_op = OPC_TLBINV;
14843 goto do_cp0;
14844 case TLBINVF:
14845 mips32_op = OPC_TLBINVF;
14846 goto do_cp0;
3c824109
NF
14847 case WAIT:
14848 mips32_op = OPC_WAIT;
14849 goto do_cp0;
14850 case DERET:
14851 mips32_op = OPC_DERET;
14852 goto do_cp0;
14853 case ERET:
14854 mips32_op = OPC_ERET;
14855 do_cp0:
14856 gen_cp0(env, ctx, mips32_op, rt, rs);
14857 break;
14858 default:
14859 goto pool32axf_invalid;
14860 }
14861 break;
14862 case 0x1d:
14863 switch (minor) {
14864 case DI:
2e15497c 14865 check_cp0_enabled(ctx);
3c824109
NF
14866 {
14867 TCGv t0 = tcg_temp_new();
14868
14869 save_cpu_state(ctx, 1);
895c2d04 14870 gen_helper_di(t0, cpu_env);
3c824109 14871 gen_store_gpr(t0, rs);
71375b59
AM
14872 /*
14873 * Stop translation as we may have switched the execution
14874 * mode.
14875 */
eeb3bba8 14876 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
14877 tcg_temp_free(t0);
14878 }
14879 break;
14880 case EI:
2e15497c 14881 check_cp0_enabled(ctx);
3c824109
NF
14882 {
14883 TCGv t0 = tcg_temp_new();
14884
14885 save_cpu_state(ctx, 1);
895c2d04 14886 gen_helper_ei(t0, cpu_env);
3c824109 14887 gen_store_gpr(t0, rs);
7480515f
AM
14888 /*
14889 * DISAS_STOP isn't sufficient, we need to ensure we break out
14890 * of translated code to check for pending interrupts.
14891 */
eeb3bba8
EC
14892 gen_save_pc(ctx->base.pc_next + 4);
14893 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
14894 tcg_temp_free(t0);
14895 }
14896 break;
14897 default:
14898 goto pool32axf_invalid;
14899 }
14900 break;
14901#endif
14902 case 0x2d:
14903 switch (minor) {
14904 case SYNC:
d208ac0c 14905 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
14906 break;
14907 case SYSCALL:
9c708c7f 14908 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
14909 break;
14910 case SDBBP:
3b3c1694
LA
14911 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14912 gen_helper_do_semihosting(cpu_env);
14913 } else {
bbd5e4a2 14914 check_insn(ctx, ISA_MIPS_R1);
e0332095 14915 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 14916 gen_reserved_instruction(ctx);
e0332095 14917 } else {
9c708c7f 14918 generate_exception_end(ctx, EXCP_DBp);
e0332095 14919 }
3b3c1694 14920 }
3c824109
NF
14921 break;
14922 default:
14923 goto pool32axf_invalid;
14924 }
14925 break;
a1fc6246 14926 case 0x01:
26135ead 14927 switch (minor & 3) {
a1fc6246 14928 case MFHI_ACC:
26135ead 14929 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 14930 break;
a1fc6246 14931 case MFLO_ACC:
26135ead 14932 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 14933 break;
a1fc6246 14934 case MTHI_ACC:
26135ead 14935 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 14936 break;
a1fc6246 14937 case MTLO_ACC:
26135ead 14938 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
14939 break;
14940 default:
14941 goto pool32axf_invalid;
14942 }
14943 break;
a1fc6246 14944 case 0x35:
2e211e0a 14945 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a1fc6246
LA
14946 switch (minor) {
14947 case MFHI32:
14948 gen_HILO(ctx, OPC_MFHI, 0, rs);
14949 break;
14950 case MFLO32:
14951 gen_HILO(ctx, OPC_MFLO, 0, rs);
14952 break;
14953 case MTHI32:
14954 gen_HILO(ctx, OPC_MTHI, 0, rs);
14955 break;
14956 case MTLO32:
14957 gen_HILO(ctx, OPC_MTLO, 0, rs);
14958 break;
14959 default:
14960 goto pool32axf_invalid;
14961 }
14962 break;
3c824109
NF
14963 default:
14964 pool32axf_invalid:
14965 MIPS_INVAL("pool32axf");
3a4ef3b7 14966 gen_reserved_instruction(ctx);
3c824109
NF
14967 break;
14968 }
14969}
14970
7480515f
AM
14971/*
14972 * Values for microMIPS fmt field. Variable-width, depending on which
14973 * formats the instruction supports.
14974 */
3c824109
NF
14975enum {
14976 FMT_SD_S = 0,
14977 FMT_SD_D = 1,
14978
14979 FMT_SDPS_S = 0,
14980 FMT_SDPS_D = 1,
14981 FMT_SDPS_PS = 2,
14982
14983 FMT_SWL_S = 0,
14984 FMT_SWL_W = 1,
14985 FMT_SWL_L = 2,
14986
14987 FMT_DWL_D = 0,
14988 FMT_DWL_W = 1,
14989 FMT_DWL_L = 2
14990};
14991
d75c135e 14992static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
14993{
14994 int extension = (ctx->opcode >> 6) & 0x3ff;
14995 uint32_t mips32_op;
14996
71375b59
AM
14997#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
14998#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
14999#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
3c824109
NF
15000
15001 switch (extension) {
15002 case FLOAT_1BIT_FMT(CFC1, 0):
15003 mips32_op = OPC_CFC1;
15004 goto do_cp1;
15005 case FLOAT_1BIT_FMT(CTC1, 0):
15006 mips32_op = OPC_CTC1;
15007 goto do_cp1;
15008 case FLOAT_1BIT_FMT(MFC1, 0):
15009 mips32_op = OPC_MFC1;
15010 goto do_cp1;
15011 case FLOAT_1BIT_FMT(MTC1, 0):
15012 mips32_op = OPC_MTC1;
15013 goto do_cp1;
15014 case FLOAT_1BIT_FMT(MFHC1, 0):
15015 mips32_op = OPC_MFHC1;
15016 goto do_cp1;
15017 case FLOAT_1BIT_FMT(MTHC1, 0):
15018 mips32_op = OPC_MTHC1;
15019 do_cp1:
15020 gen_cp1(ctx, mips32_op, rt, rs);
15021 break;
15022
15023 /* Reciprocal square root */
15024 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15025 mips32_op = OPC_RSQRT_S;
15026 goto do_unaryfp;
15027 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15028 mips32_op = OPC_RSQRT_D;
15029 goto do_unaryfp;
15030
15031 /* Square root */
15032 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15033 mips32_op = OPC_SQRT_S;
15034 goto do_unaryfp;
15035 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15036 mips32_op = OPC_SQRT_D;
15037 goto do_unaryfp;
15038
15039 /* Reciprocal */
15040 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15041 mips32_op = OPC_RECIP_S;
15042 goto do_unaryfp;
15043 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15044 mips32_op = OPC_RECIP_D;
15045 goto do_unaryfp;
15046
15047 /* Floor */
15048 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15049 mips32_op = OPC_FLOOR_L_S;
15050 goto do_unaryfp;
15051 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15052 mips32_op = OPC_FLOOR_L_D;
15053 goto do_unaryfp;
15054 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15055 mips32_op = OPC_FLOOR_W_S;
15056 goto do_unaryfp;
15057 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15058 mips32_op = OPC_FLOOR_W_D;
15059 goto do_unaryfp;
15060
15061 /* Ceiling */
15062 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15063 mips32_op = OPC_CEIL_L_S;
15064 goto do_unaryfp;
15065 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15066 mips32_op = OPC_CEIL_L_D;
15067 goto do_unaryfp;
15068 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15069 mips32_op = OPC_CEIL_W_S;
15070 goto do_unaryfp;
15071 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15072 mips32_op = OPC_CEIL_W_D;
15073 goto do_unaryfp;
15074
15075 /* Truncation */
15076 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15077 mips32_op = OPC_TRUNC_L_S;
15078 goto do_unaryfp;
15079 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15080 mips32_op = OPC_TRUNC_L_D;
15081 goto do_unaryfp;
15082 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15083 mips32_op = OPC_TRUNC_W_S;
15084 goto do_unaryfp;
15085 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15086 mips32_op = OPC_TRUNC_W_D;
15087 goto do_unaryfp;
15088
15089 /* Round */
15090 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15091 mips32_op = OPC_ROUND_L_S;
15092 goto do_unaryfp;
15093 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15094 mips32_op = OPC_ROUND_L_D;
15095 goto do_unaryfp;
15096 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15097 mips32_op = OPC_ROUND_W_S;
15098 goto do_unaryfp;
15099 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15100 mips32_op = OPC_ROUND_W_D;
15101 goto do_unaryfp;
15102
15103 /* Integer to floating-point conversion */
15104 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15105 mips32_op = OPC_CVT_L_S;
15106 goto do_unaryfp;
15107 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15108 mips32_op = OPC_CVT_L_D;
15109 goto do_unaryfp;
15110 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15111 mips32_op = OPC_CVT_W_S;
15112 goto do_unaryfp;
15113 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15114 mips32_op = OPC_CVT_W_D;
15115 goto do_unaryfp;
15116
15117 /* Paired-foo conversions */
15118 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15119 mips32_op = OPC_CVT_S_PL;
15120 goto do_unaryfp;
15121 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15122 mips32_op = OPC_CVT_S_PU;
15123 goto do_unaryfp;
15124 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15125 mips32_op = OPC_CVT_PW_PS;
15126 goto do_unaryfp;
15127 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15128 mips32_op = OPC_CVT_PS_PW;
15129 goto do_unaryfp;
15130
15131 /* Floating-point moves */
15132 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15133 mips32_op = OPC_MOV_S;
15134 goto do_unaryfp;
15135 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15136 mips32_op = OPC_MOV_D;
15137 goto do_unaryfp;
15138 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15139 mips32_op = OPC_MOV_PS;
15140 goto do_unaryfp;
15141
15142 /* Absolute value */
15143 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15144 mips32_op = OPC_ABS_S;
15145 goto do_unaryfp;
15146 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15147 mips32_op = OPC_ABS_D;
15148 goto do_unaryfp;
15149 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15150 mips32_op = OPC_ABS_PS;
15151 goto do_unaryfp;
15152
15153 /* Negation */
15154 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15155 mips32_op = OPC_NEG_S;
15156 goto do_unaryfp;
15157 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15158 mips32_op = OPC_NEG_D;
15159 goto do_unaryfp;
15160 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15161 mips32_op = OPC_NEG_PS;
15162 goto do_unaryfp;
15163
15164 /* Reciprocal square root step */
15165 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15166 mips32_op = OPC_RSQRT1_S;
15167 goto do_unaryfp;
15168 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15169 mips32_op = OPC_RSQRT1_D;
15170 goto do_unaryfp;
15171 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15172 mips32_op = OPC_RSQRT1_PS;
15173 goto do_unaryfp;
15174
15175 /* Reciprocal step */
15176 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15177 mips32_op = OPC_RECIP1_S;
15178 goto do_unaryfp;
15179 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15180 mips32_op = OPC_RECIP1_S;
15181 goto do_unaryfp;
15182 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15183 mips32_op = OPC_RECIP1_PS;
15184 goto do_unaryfp;
15185
15186 /* Conversions from double */
15187 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15188 mips32_op = OPC_CVT_D_S;
15189 goto do_unaryfp;
15190 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15191 mips32_op = OPC_CVT_D_W;
15192 goto do_unaryfp;
15193 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15194 mips32_op = OPC_CVT_D_L;
15195 goto do_unaryfp;
15196
15197 /* Conversions from single */
15198 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15199 mips32_op = OPC_CVT_S_D;
15200 goto do_unaryfp;
15201 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15202 mips32_op = OPC_CVT_S_W;
15203 goto do_unaryfp;
15204 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15205 mips32_op = OPC_CVT_S_L;
15206 do_unaryfp:
15207 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15208 break;
15209
15210 /* Conditional moves on floating-point codes */
15211 case COND_FLOAT_MOV(MOVT, 0):
15212 case COND_FLOAT_MOV(MOVT, 1):
15213 case COND_FLOAT_MOV(MOVT, 2):
15214 case COND_FLOAT_MOV(MOVT, 3):
15215 case COND_FLOAT_MOV(MOVT, 4):
15216 case COND_FLOAT_MOV(MOVT, 5):
15217 case COND_FLOAT_MOV(MOVT, 6):
15218 case COND_FLOAT_MOV(MOVT, 7):
2e211e0a 15219 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15220 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15221 break;
15222 case COND_FLOAT_MOV(MOVF, 0):
15223 case COND_FLOAT_MOV(MOVF, 1):
15224 case COND_FLOAT_MOV(MOVF, 2):
15225 case COND_FLOAT_MOV(MOVF, 3):
15226 case COND_FLOAT_MOV(MOVF, 4):
15227 case COND_FLOAT_MOV(MOVF, 5):
15228 case COND_FLOAT_MOV(MOVF, 6):
15229 case COND_FLOAT_MOV(MOVF, 7):
2e211e0a 15230 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15231 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15232 break;
15233 default:
15234 MIPS_INVAL("pool32fxf");
3a4ef3b7 15235 gen_reserved_instruction(ctx);
3c824109
NF
15236 break;
15237 }
15238}
15239
f60eeb0c 15240static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15241{
15242 int32_t offset;
15243 uint16_t insn;
15244 int rt, rs, rd, rr;
15245 int16_t imm;
8fffc646 15246 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
15247 uint32_t cond, fmt, cc;
15248
0ab8e33a 15249 insn = translator_lduw(env, ctx->base.pc_next + 2);
3c824109
NF
15250 ctx->opcode = (ctx->opcode << 16) | insn;
15251
15252 rt = (ctx->opcode >> 21) & 0x1f;
15253 rs = (ctx->opcode >> 16) & 0x1f;
15254 rd = (ctx->opcode >> 11) & 0x1f;
15255 rr = (ctx->opcode >> 6) & 0x1f;
15256 imm = (int16_t) ctx->opcode;
15257
15258 op = (ctx->opcode >> 26) & 0x3f;
15259 switch (op) {
15260 case POOL32A:
15261 minor = ctx->opcode & 0x3f;
15262 switch (minor) {
15263 case 0x00:
15264 minor = (ctx->opcode >> 6) & 0xf;
15265 switch (minor) {
15266 case SLL32:
15267 mips32_op = OPC_SLL;
15268 goto do_shifti;
15269 case SRA:
15270 mips32_op = OPC_SRA;
15271 goto do_shifti;
15272 case SRL32:
15273 mips32_op = OPC_SRL;
15274 goto do_shifti;
15275 case ROTR:
15276 mips32_op = OPC_ROTR;
15277 do_shifti:
d75c135e 15278 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 15279 break;
e0332095 15280 case SELEQZ:
2e211e0a 15281 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15282 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15283 break;
15284 case SELNEZ:
2e211e0a 15285 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15286 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15287 break;
b00c7218 15288 case R6_RDHWR:
2e211e0a 15289 check_insn(ctx, ISA_MIPS_R6);
b00c7218
YK
15290 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15291 break;
3c824109
NF
15292 default:
15293 goto pool32a_invalid;
15294 }
15295 break;
15296 case 0x10:
15297 minor = (ctx->opcode >> 6) & 0xf;
15298 switch (minor) {
15299 /* Arithmetic */
15300 case ADD:
15301 mips32_op = OPC_ADD;
15302 goto do_arith;
15303 case ADDU32:
15304 mips32_op = OPC_ADDU;
15305 goto do_arith;
15306 case SUB:
15307 mips32_op = OPC_SUB;
15308 goto do_arith;
15309 case SUBU32:
15310 mips32_op = OPC_SUBU;
15311 goto do_arith;
15312 case MUL:
2e211e0a 15313 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15314 mips32_op = OPC_MUL;
15315 do_arith:
d75c135e 15316 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15317 break;
15318 /* Shifts */
15319 case SLLV:
15320 mips32_op = OPC_SLLV;
15321 goto do_shift;
15322 case SRLV:
15323 mips32_op = OPC_SRLV;
15324 goto do_shift;
15325 case SRAV:
15326 mips32_op = OPC_SRAV;
15327 goto do_shift;
15328 case ROTRV:
15329 mips32_op = OPC_ROTRV;
15330 do_shift:
d75c135e 15331 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15332 break;
15333 /* Logical operations */
15334 case AND:
15335 mips32_op = OPC_AND;
15336 goto do_logic;
15337 case OR32:
15338 mips32_op = OPC_OR;
15339 goto do_logic;
15340 case NOR:
15341 mips32_op = OPC_NOR;
15342 goto do_logic;
15343 case XOR32:
15344 mips32_op = OPC_XOR;
15345 do_logic:
d75c135e 15346 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15347 break;
15348 /* Set less than */
15349 case SLT:
15350 mips32_op = OPC_SLT;
15351 goto do_slt;
15352 case SLTU:
15353 mips32_op = OPC_SLTU;
15354 do_slt:
d75c135e 15355 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15356 break;
15357 default:
15358 goto pool32a_invalid;
15359 }
15360 break;
15361 case 0x18:
15362 minor = (ctx->opcode >> 6) & 0xf;
15363 switch (minor) {
15364 /* Conditional moves */
e0332095 15365 case MOVN: /* MUL */
2e211e0a 15366 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15367 /* MUL */
15368 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15369 } else {
15370 /* MOVN */
15371 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15372 }
15373 break;
15374 case MOVZ: /* MUH */
2e211e0a 15375 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15376 /* MUH */
15377 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15378 } else {
15379 /* MOVZ */
15380 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15381 }
15382 break;
15383 case MULU:
2e211e0a 15384 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15385 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15386 break;
15387 case MUHU:
2e211e0a 15388 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15389 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15390 break;
15391 case LWXS: /* DIV */
2e211e0a 15392 if (ctx->insn_flags & ISA_MIPS_R6) {
e0332095
YK
15393 /* DIV */
15394 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15395 } else {
15396 /* LWXS */
15397 gen_ldxs(ctx, rs, rt, rd);
15398 }
15399 break;
15400 case MOD:
2e211e0a 15401 check_insn(ctx, ISA_MIPS_R6);
e0332095
YK
15402 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15403 break;
15404 case R6_DIVU:
2e211e0a 15405 check_insn(ctx, ISA_MIPS_R6);
e0332095 15406 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 15407 break;
e0332095 15408 case MODU:
2e211e0a 15409 check_insn(ctx, ISA_MIPS_R6);
e0332095 15410 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
15411 break;
15412 default:
15413 goto pool32a_invalid;
15414 }
15415 break;
15416 case INS:
15417 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15418 return;
e0332095 15419 case LSA:
2e211e0a 15420 check_insn(ctx, ISA_MIPS_R6);
a685f7d0 15421 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
e0332095
YK
15422 break;
15423 case ALIGN:
2e211e0a 15424 check_insn(ctx, ISA_MIPS_R6);
821f2008 15425 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 15426 break;
3c824109
NF
15427 case EXT:
15428 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15429 return;
15430 case POOL32AXF:
240ce26a 15431 gen_pool32axf(env, ctx, rt, rs);
3c824109 15432 break;
dbd8af98 15433 case BREAK32:
9c708c7f 15434 generate_exception_end(ctx, EXCP_BREAK);
3c824109 15435 break;
bb238210 15436 case SIGRIE:
2e211e0a 15437 check_insn(ctx, ISA_MIPS_R6);
3a4ef3b7 15438 gen_reserved_instruction(ctx);
bb238210 15439 break;
3c824109
NF
15440 default:
15441 pool32a_invalid:
15442 MIPS_INVAL("pool32a");
3a4ef3b7 15443 gen_reserved_instruction(ctx);
3c824109
NF
15444 break;
15445 }
15446 break;
15447 case POOL32B:
15448 minor = (ctx->opcode >> 12) & 0xf;
15449 switch (minor) {
15450 case CACHE:
2e15497c 15451 check_cp0_enabled(ctx);
0d74a222
LA
15452 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15453 gen_cache_operation(ctx, rt, rs, imm);
15454 }
3c824109
NF
15455 break;
15456 case LWC2:
15457 case SWC2:
15458 /* COP2: Not implemented. */
15459 generate_exception_err(ctx, EXCP_CpU, 2);
15460 break;
3c824109
NF
15461#ifdef TARGET_MIPS64
15462 case LDP:
15463 case SDP:
d9224450
MR
15464 check_insn(ctx, ISA_MIPS3);
15465 check_mips_64(ctx);
3c824109 15466#endif
146dd620 15467 /* fall through */
d9224450
MR
15468 case LWP:
15469 case SWP:
3c824109
NF
15470 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15471 break;
3c824109
NF
15472#ifdef TARGET_MIPS64
15473 case LDM:
15474 case SDM:
d9224450
MR
15475 check_insn(ctx, ISA_MIPS3);
15476 check_mips_64(ctx);
3c824109 15477#endif
146dd620 15478 /* fall through */
d9224450
MR
15479 case LWM32:
15480 case SWM32:
3c824109
NF
15481 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15482 break;
15483 default:
15484 MIPS_INVAL("pool32b");
3a4ef3b7 15485 gen_reserved_instruction(ctx);
3c824109
NF
15486 break;
15487 }
15488 break;
15489 case POOL32F:
5ab5c041 15490 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
15491 minor = ctx->opcode & 0x3f;
15492 check_cp1_enabled(ctx);
15493 switch (minor) {
15494 case ALNV_PS:
2e211e0a 15495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15496 mips32_op = OPC_ALNV_PS;
15497 goto do_madd;
15498 case MADD_S:
2e211e0a 15499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15500 mips32_op = OPC_MADD_S;
15501 goto do_madd;
15502 case MADD_D:
2e211e0a 15503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15504 mips32_op = OPC_MADD_D;
15505 goto do_madd;
15506 case MADD_PS:
2e211e0a 15507 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15508 mips32_op = OPC_MADD_PS;
15509 goto do_madd;
15510 case MSUB_S:
2e211e0a 15511 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15512 mips32_op = OPC_MSUB_S;
15513 goto do_madd;
15514 case MSUB_D:
2e211e0a 15515 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15516 mips32_op = OPC_MSUB_D;
15517 goto do_madd;
15518 case MSUB_PS:
2e211e0a 15519 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15520 mips32_op = OPC_MSUB_PS;
15521 goto do_madd;
15522 case NMADD_S:
2e211e0a 15523 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15524 mips32_op = OPC_NMADD_S;
15525 goto do_madd;
15526 case NMADD_D:
2e211e0a 15527 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15528 mips32_op = OPC_NMADD_D;
15529 goto do_madd;
15530 case NMADD_PS:
2e211e0a 15531 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15532 mips32_op = OPC_NMADD_PS;
15533 goto do_madd;
15534 case NMSUB_S:
2e211e0a 15535 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15536 mips32_op = OPC_NMSUB_S;
15537 goto do_madd;
15538 case NMSUB_D:
2e211e0a 15539 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15540 mips32_op = OPC_NMSUB_D;
15541 goto do_madd;
15542 case NMSUB_PS:
2e211e0a 15543 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15544 mips32_op = OPC_NMSUB_PS;
15545 do_madd:
15546 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15547 break;
15548 case CABS_COND_FMT:
2e211e0a 15549 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15550 cond = (ctx->opcode >> 6) & 0xf;
15551 cc = (ctx->opcode >> 13) & 0x7;
15552 fmt = (ctx->opcode >> 10) & 0x3;
15553 switch (fmt) {
15554 case 0x0:
15555 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15556 break;
15557 case 0x1:
15558 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15559 break;
15560 case 0x2:
15561 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15562 break;
15563 default:
15564 goto pool32f_invalid;
15565 }
15566 break;
15567 case C_COND_FMT:
2e211e0a 15568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15569 cond = (ctx->opcode >> 6) & 0xf;
15570 cc = (ctx->opcode >> 13) & 0x7;
15571 fmt = (ctx->opcode >> 10) & 0x3;
15572 switch (fmt) {
15573 case 0x0:
15574 gen_cmp_s(ctx, cond, rt, rs, cc);
15575 break;
15576 case 0x1:
15577 gen_cmp_d(ctx, cond, rt, rs, cc);
15578 break;
15579 case 0x2:
15580 gen_cmp_ps(ctx, cond, rt, rs, cc);
15581 break;
15582 default:
15583 goto pool32f_invalid;
15584 }
15585 break;
2a24a7ba 15586 case CMP_CONDN_S:
2e211e0a 15587 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15588 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15589 break;
15590 case CMP_CONDN_D:
2e211e0a 15591 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15592 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15593 break;
3c824109 15594 case POOL32FXF:
d75c135e 15595 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
15596 break;
15597 case 0x00:
15598 /* PLL foo */
15599 switch ((ctx->opcode >> 6) & 0x7) {
15600 case PLL_PS:
15601 mips32_op = OPC_PLL_PS;
15602 goto do_ps;
15603 case PLU_PS:
15604 mips32_op = OPC_PLU_PS;
15605 goto do_ps;
15606 case PUL_PS:
15607 mips32_op = OPC_PUL_PS;
15608 goto do_ps;
15609 case PUU_PS:
15610 mips32_op = OPC_PUU_PS;
15611 goto do_ps;
15612 case CVT_PS_S:
2e211e0a 15613 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15614 mips32_op = OPC_CVT_PS_S;
15615 do_ps:
15616 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15617 break;
15618 default:
15619 goto pool32f_invalid;
15620 }
15621 break;
2a24a7ba 15622 case MIN_FMT:
2e211e0a 15623 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15624 switch ((ctx->opcode >> 9) & 0x3) {
15625 case FMT_SDPS_S:
15626 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15627 break;
15628 case FMT_SDPS_D:
15629 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15630 break;
15631 default:
15632 goto pool32f_invalid;
15633 }
15634 break;
3c824109
NF
15635 case 0x08:
15636 /* [LS][WDU]XC1 */
15637 switch ((ctx->opcode >> 6) & 0x7) {
15638 case LWXC1:
2e211e0a 15639 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15640 mips32_op = OPC_LWXC1;
15641 goto do_ldst_cp1;
15642 case SWXC1:
2e211e0a 15643 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15644 mips32_op = OPC_SWXC1;
15645 goto do_ldst_cp1;
15646 case LDXC1:
2e211e0a 15647 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15648 mips32_op = OPC_LDXC1;
15649 goto do_ldst_cp1;
15650 case SDXC1:
2e211e0a 15651 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15652 mips32_op = OPC_SDXC1;
15653 goto do_ldst_cp1;
15654 case LUXC1:
2e211e0a 15655 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15656 mips32_op = OPC_LUXC1;
15657 goto do_ldst_cp1;
15658 case SUXC1:
2e211e0a 15659 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15660 mips32_op = OPC_SUXC1;
15661 do_ldst_cp1:
15662 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15663 break;
15664 default:
15665 goto pool32f_invalid;
15666 }
15667 break;
2a24a7ba 15668 case MAX_FMT:
2e211e0a 15669 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15670 switch ((ctx->opcode >> 9) & 0x3) {
15671 case FMT_SDPS_S:
15672 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15673 break;
15674 case FMT_SDPS_D:
15675 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15676 break;
15677 default:
15678 goto pool32f_invalid;
15679 }
15680 break;
3c824109
NF
15681 case 0x18:
15682 /* 3D insns */
2e211e0a 15683 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15684 fmt = (ctx->opcode >> 9) & 0x3;
15685 switch ((ctx->opcode >> 6) & 0x7) {
15686 case RSQRT2_FMT:
15687 switch (fmt) {
15688 case FMT_SDPS_S:
15689 mips32_op = OPC_RSQRT2_S;
15690 goto do_3d;
15691 case FMT_SDPS_D:
15692 mips32_op = OPC_RSQRT2_D;
15693 goto do_3d;
15694 case FMT_SDPS_PS:
15695 mips32_op = OPC_RSQRT2_PS;
15696 goto do_3d;
15697 default:
15698 goto pool32f_invalid;
15699 }
15700 break;
15701 case RECIP2_FMT:
15702 switch (fmt) {
15703 case FMT_SDPS_S:
15704 mips32_op = OPC_RECIP2_S;
15705 goto do_3d;
15706 case FMT_SDPS_D:
15707 mips32_op = OPC_RECIP2_D;
15708 goto do_3d;
15709 case FMT_SDPS_PS:
15710 mips32_op = OPC_RECIP2_PS;
15711 goto do_3d;
15712 default:
15713 goto pool32f_invalid;
15714 }
15715 break;
15716 case ADDR_PS:
15717 mips32_op = OPC_ADDR_PS;
15718 goto do_3d;
15719 case MULR_PS:
15720 mips32_op = OPC_MULR_PS;
15721 do_3d:
15722 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15723 break;
15724 default:
15725 goto pool32f_invalid;
15726 }
15727 break;
15728 case 0x20:
2a24a7ba 15729 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
15730 cc = (ctx->opcode >> 13) & 0x7;
15731 fmt = (ctx->opcode >> 9) & 0x3;
15732 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba 15733 case MOVF_FMT: /* RINT_FMT */
2e211e0a 15734 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
15735 /* RINT_FMT */
15736 switch (fmt) {
15737 case FMT_SDPS_S:
15738 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15739 break;
15740 case FMT_SDPS_D:
15741 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15742 break;
15743 default:
15744 goto pool32f_invalid;
15745 }
15746 } else {
15747 /* MOVF_FMT */
15748 switch (fmt) {
15749 case FMT_SDPS_S:
15750 gen_movcf_s(ctx, rs, rt, cc, 0);
15751 break;
15752 case FMT_SDPS_D:
15753 gen_movcf_d(ctx, rs, rt, cc, 0);
15754 break;
15755 case FMT_SDPS_PS:
15756 check_ps(ctx);
15757 gen_movcf_ps(ctx, rs, rt, cc, 0);
15758 break;
15759 default:
15760 goto pool32f_invalid;
15761 }
3c824109
NF
15762 }
15763 break;
2a24a7ba 15764 case MOVT_FMT: /* CLASS_FMT */
2e211e0a 15765 if (ctx->insn_flags & ISA_MIPS_R6) {
2a24a7ba
YK
15766 /* CLASS_FMT */
15767 switch (fmt) {
15768 case FMT_SDPS_S:
15769 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15770 break;
15771 case FMT_SDPS_D:
15772 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15773 break;
15774 default:
15775 goto pool32f_invalid;
15776 }
15777 } else {
15778 /* MOVT_FMT */
15779 switch (fmt) {
15780 case FMT_SDPS_S:
15781 gen_movcf_s(ctx, rs, rt, cc, 1);
15782 break;
15783 case FMT_SDPS_D:
15784 gen_movcf_d(ctx, rs, rt, cc, 1);
15785 break;
15786 case FMT_SDPS_PS:
15787 check_ps(ctx);
15788 gen_movcf_ps(ctx, rs, rt, cc, 1);
15789 break;
15790 default:
15791 goto pool32f_invalid;
15792 }
3c824109
NF
15793 }
15794 break;
15795 case PREFX:
2e211e0a 15796 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15797 break;
15798 default:
15799 goto pool32f_invalid;
15800 }
15801 break;
15802#define FINSN_3ARG_SDPS(prfx) \
15803 switch ((ctx->opcode >> 8) & 0x3) { \
15804 case FMT_SDPS_S: \
15805 mips32_op = OPC_##prfx##_S; \
15806 goto do_fpop; \
15807 case FMT_SDPS_D: \
15808 mips32_op = OPC_##prfx##_D; \
15809 goto do_fpop; \
15810 case FMT_SDPS_PS: \
e29c9628 15811 check_ps(ctx); \
3c824109
NF
15812 mips32_op = OPC_##prfx##_PS; \
15813 goto do_fpop; \
15814 default: \
15815 goto pool32f_invalid; \
15816 }
2a24a7ba 15817 case MINA_FMT:
2e211e0a 15818 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15819 switch ((ctx->opcode >> 9) & 0x3) {
15820 case FMT_SDPS_S:
15821 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15822 break;
15823 case FMT_SDPS_D:
15824 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15825 break;
15826 default:
15827 goto pool32f_invalid;
15828 }
15829 break;
15830 case MAXA_FMT:
2e211e0a 15831 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15832 switch ((ctx->opcode >> 9) & 0x3) {
15833 case FMT_SDPS_S:
15834 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15835 break;
15836 case FMT_SDPS_D:
15837 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15838 break;
15839 default:
15840 goto pool32f_invalid;
15841 }
15842 break;
3c824109
NF
15843 case 0x30:
15844 /* regular FP ops */
15845 switch ((ctx->opcode >> 6) & 0x3) {
15846 case ADD_FMT:
15847 FINSN_3ARG_SDPS(ADD);
15848 break;
15849 case SUB_FMT:
15850 FINSN_3ARG_SDPS(SUB);
15851 break;
15852 case MUL_FMT:
15853 FINSN_3ARG_SDPS(MUL);
15854 break;
15855 case DIV_FMT:
15856 fmt = (ctx->opcode >> 8) & 0x3;
15857 if (fmt == 1) {
15858 mips32_op = OPC_DIV_D;
15859 } else if (fmt == 0) {
15860 mips32_op = OPC_DIV_S;
15861 } else {
15862 goto pool32f_invalid;
15863 }
15864 goto do_fpop;
15865 default:
15866 goto pool32f_invalid;
15867 }
15868 break;
15869 case 0x38:
15870 /* cmovs */
2a24a7ba 15871 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 15872 case MOVN_FMT: /* SELEQZ_FMT */
2e211e0a 15873 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 15874 /* SELEQZ_FMT */
2a24a7ba
YK
15875 switch ((ctx->opcode >> 9) & 0x3) {
15876 case FMT_SDPS_S:
fdac60cd 15877 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
15878 break;
15879 case FMT_SDPS_D:
fdac60cd 15880 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
15881 break;
15882 default:
15883 goto pool32f_invalid;
15884 }
15885 } else {
15886 /* MOVN_FMT */
15887 FINSN_3ARG_SDPS(MOVN);
15888 }
15889 break;
15890 case MOVN_FMT_04:
2e211e0a 15891 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15892 FINSN_3ARG_SDPS(MOVN);
15893 break;
fdac60cd 15894 case MOVZ_FMT: /* SELNEZ_FMT */
2e211e0a 15895 if (ctx->insn_flags & ISA_MIPS_R6) {
fdac60cd 15896 /* SELNEZ_FMT */
2a24a7ba
YK
15897 switch ((ctx->opcode >> 9) & 0x3) {
15898 case FMT_SDPS_S:
fdac60cd 15899 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
15900 break;
15901 case FMT_SDPS_D:
fdac60cd 15902 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
15903 break;
15904 default:
15905 goto pool32f_invalid;
15906 }
15907 } else {
15908 /* MOVZ_FMT */
15909 FINSN_3ARG_SDPS(MOVZ);
15910 }
15911 break;
15912 case MOVZ_FMT_05:
2e211e0a 15913 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
15914 FINSN_3ARG_SDPS(MOVZ);
15915 break;
2a24a7ba 15916 case SEL_FMT:
2e211e0a 15917 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15918 switch ((ctx->opcode >> 9) & 0x3) {
15919 case FMT_SDPS_S:
15920 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15921 break;
15922 case FMT_SDPS_D:
15923 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15924 break;
15925 default:
15926 goto pool32f_invalid;
15927 }
15928 break;
15929 case MADDF_FMT:
2e211e0a 15930 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15931 switch ((ctx->opcode >> 9) & 0x3) {
15932 case FMT_SDPS_S:
15933 mips32_op = OPC_MADDF_S;
15934 goto do_fpop;
15935 case FMT_SDPS_D:
15936 mips32_op = OPC_MADDF_D;
15937 goto do_fpop;
15938 default:
15939 goto pool32f_invalid;
15940 }
15941 break;
15942 case MSUBF_FMT:
2e211e0a 15943 check_insn(ctx, ISA_MIPS_R6);
2a24a7ba
YK
15944 switch ((ctx->opcode >> 9) & 0x3) {
15945 case FMT_SDPS_S:
15946 mips32_op = OPC_MSUBF_S;
15947 goto do_fpop;
15948 case FMT_SDPS_D:
15949 mips32_op = OPC_MSUBF_D;
15950 goto do_fpop;
15951 default:
15952 goto pool32f_invalid;
15953 }
15954 break;
3c824109
NF
15955 default:
15956 goto pool32f_invalid;
15957 }
15958 break;
15959 do_fpop:
15960 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15961 break;
15962 default:
15963 pool32f_invalid:
15964 MIPS_INVAL("pool32f");
3a4ef3b7 15965 gen_reserved_instruction(ctx);
3c824109
NF
15966 break;
15967 }
15968 } else {
15969 generate_exception_err(ctx, EXCP_CpU, 1);
15970 }
15971 break;
15972 case POOL32I:
15973 minor = (ctx->opcode >> 21) & 0x1f;
15974 switch (minor) {
15975 case BLTZ:
2e211e0a 15976 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15977 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15978 break;
3c824109 15979 case BLTZAL:
2e211e0a 15980 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15981 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15982 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15983 break;
3c824109 15984 case BLTZALS:
2e211e0a 15985 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15986 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15987 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15988 break;
3c824109 15989 case BGEZ:
2e211e0a 15990 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15991 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15992 break;
3c824109 15993 case BGEZAL:
2e211e0a 15994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
15995 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15996 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15997 break;
3c824109 15998 case BGEZALS:
2e211e0a 15999 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
16000 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16001 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16002 break;
3c824109 16003 case BLEZ:
2e211e0a 16004 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103
YK
16005 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16006 break;
3c824109 16007 case BGTZ:
2e211e0a 16008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b231c103 16009 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16010 break;
16011
16012 /* Traps */
65935f07 16013 case TLTI: /* BC1EQZC */
2e211e0a 16014 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16015 /* BC1EQZC */
16016 check_cp1_enabled(ctx);
16017 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16018 } else {
16019 /* TLTI */
16020 mips32_op = OPC_TLTI;
16021 goto do_trapi;
16022 }
16023 break;
16024 case TGEI: /* BC1NEZC */
2e211e0a 16025 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16026 /* BC1NEZC */
16027 check_cp1_enabled(ctx);
16028 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16029 } else {
16030 /* TGEI */
16031 mips32_op = OPC_TGEI;
16032 goto do_trapi;
16033 }
16034 break;
3c824109 16035 case TLTIU:
2e211e0a 16036 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16037 mips32_op = OPC_TLTIU;
16038 goto do_trapi;
16039 case TGEIU:
2e211e0a 16040 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16041 mips32_op = OPC_TGEIU;
16042 goto do_trapi;
3b4a5489 16043 case TNEI: /* SYNCI */
2e211e0a 16044 if (ctx->insn_flags & ISA_MIPS_R6) {
3b4a5489 16045 /* SYNCI */
7480515f
AM
16046 /*
16047 * Break the TB to be able to sync copied instructions
16048 * immediately.
16049 */
eeb3bba8 16050 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16051 } else {
16052 /* TNEI */
16053 mips32_op = OPC_TNEI;
16054 goto do_trapi;
16055 }
16056 break;
3c824109 16057 case TEQI:
2e211e0a 16058 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16059 mips32_op = OPC_TEQI;
16060 do_trapi:
16061 gen_trap(ctx, mips32_op, rs, -1, imm);
16062 break;
16063
16064 case BNEZC:
16065 case BEQZC:
2e211e0a 16066 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16067 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16068 4, rs, 0, imm << 1, 0);
7480515f
AM
16069 /*
16070 * Compact branches don't have a delay slot, so just let
16071 * the normal delay slot handling take us to the branch
16072 * target.
16073 */
3c824109
NF
16074 break;
16075 case LUI:
2e211e0a 16076 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5e88759a 16077 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16078 break;
16079 case SYNCI:
2e211e0a 16080 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7480515f
AM
16081 /*
16082 * Break the TB to be able to sync copied instructions
16083 * immediately.
16084 */
eeb3bba8 16085 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16086 break;
16087 case BC2F:
16088 case BC2T:
2e211e0a 16089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16090 /* COP2: Not implemented. */
16091 generate_exception_err(ctx, EXCP_CpU, 2);
16092 break;
16093 case BC1F:
2e211e0a 16094 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16095 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16096 goto do_cp1branch;
16097 case BC1T:
2e211e0a 16098 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16099 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16100 goto do_cp1branch;
16101 case BC1ANY4F:
2e211e0a 16102 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16103 mips32_op = OPC_BC1FANY4;
16104 goto do_cp1mips3d;
16105 case BC1ANY4T:
2e211e0a 16106 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109
NF
16107 mips32_op = OPC_BC1TANY4;
16108 do_cp1mips3d:
16109 check_cop1x(ctx);
d75c135e 16110 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16111 /* Fall through */
16112 do_cp1branch:
272f458d
MR
16113 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16114 check_cp1_enabled(ctx);
16115 gen_compute_branch1(ctx, mips32_op,
16116 (ctx->opcode >> 18) & 0x7, imm << 1);
16117 } else {
16118 generate_exception_err(ctx, EXCP_CpU, 1);
16119 }
3c824109 16120 break;
3c824109
NF
16121 default:
16122 MIPS_INVAL("pool32i");
3a4ef3b7 16123 gen_reserved_instruction(ctx);
3c824109
NF
16124 break;
16125 }
16126 break;
16127 case POOL32C:
16128 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489 16129 offset = sextract32(ctx->opcode, 0,
2e211e0a 16130 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
3c824109
NF
16131 switch (minor) {
16132 case LWL:
2e211e0a 16133 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16134 mips32_op = OPC_LWL;
5c13fdfd 16135 goto do_ld_lr;
3c824109 16136 case SWL:
2e211e0a 16137 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16138 mips32_op = OPC_SWL;
5c13fdfd 16139 goto do_st_lr;
3c824109 16140 case LWR:
2e211e0a 16141 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16142 mips32_op = OPC_LWR;
5c13fdfd 16143 goto do_ld_lr;
3c824109 16144 case SWR:
2e211e0a 16145 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16146 mips32_op = OPC_SWR;
5c13fdfd 16147 goto do_st_lr;
3c824109
NF
16148#if defined(TARGET_MIPS64)
16149 case LDL:
d9224450
MR
16150 check_insn(ctx, ISA_MIPS3);
16151 check_mips_64(ctx);
2e211e0a 16152 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16153 mips32_op = OPC_LDL;
5c13fdfd 16154 goto do_ld_lr;
3c824109 16155 case SDL:
d9224450
MR
16156 check_insn(ctx, ISA_MIPS3);
16157 check_mips_64(ctx);
2e211e0a 16158 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16159 mips32_op = OPC_SDL;
5c13fdfd 16160 goto do_st_lr;
3c824109 16161 case LDR:
d9224450
MR
16162 check_insn(ctx, ISA_MIPS3);
16163 check_mips_64(ctx);
2e211e0a 16164 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16165 mips32_op = OPC_LDR;
5c13fdfd 16166 goto do_ld_lr;
3c824109 16167 case SDR:
d9224450
MR
16168 check_insn(ctx, ISA_MIPS3);
16169 check_mips_64(ctx);
2e211e0a 16170 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16171 mips32_op = OPC_SDR;
5c13fdfd 16172 goto do_st_lr;
3c824109 16173 case LWU:
d9224450
MR
16174 check_insn(ctx, ISA_MIPS3);
16175 check_mips_64(ctx);
3c824109 16176 mips32_op = OPC_LWU;
5c13fdfd 16177 goto do_ld_lr;
3c824109 16178 case LLD:
d9224450
MR
16179 check_insn(ctx, ISA_MIPS3);
16180 check_mips_64(ctx);
3c824109 16181 mips32_op = OPC_LLD;
5c13fdfd 16182 goto do_ld_lr;
3c824109
NF
16183#endif
16184 case LL:
16185 mips32_op = OPC_LL;
5c13fdfd
AJ
16186 goto do_ld_lr;
16187 do_ld_lr:
3b4a5489 16188 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
16189 break;
16190 do_st_lr:
8fffc646 16191 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
16192 break;
16193 case SC:
33a07fa2 16194 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
3c824109
NF
16195 break;
16196#if defined(TARGET_MIPS64)
16197 case SCD:
d9224450
MR
16198 check_insn(ctx, ISA_MIPS3);
16199 check_mips_64(ctx);
33a07fa2 16200 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
3c824109
NF
16201 break;
16202#endif
8fffc646
JH
16203 case LD_EVA:
16204 if (!ctx->eva) {
16205 MIPS_INVAL("pool32c ld-eva");
3a4ef3b7 16206 gen_reserved_instruction(ctx);
8fffc646
JH
16207 break;
16208 }
16209 check_cp0_enabled(ctx);
16210
16211 minor2 = (ctx->opcode >> 9) & 0x7;
16212 offset = sextract32(ctx->opcode, 0, 9);
16213 switch (minor2) {
16214 case LBUE:
16215 mips32_op = OPC_LBUE;
16216 goto do_ld_lr;
16217 case LHUE:
16218 mips32_op = OPC_LHUE;
16219 goto do_ld_lr;
16220 case LWLE:
2e211e0a 16221 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16222 mips32_op = OPC_LWLE;
16223 goto do_ld_lr;
16224 case LWRE:
2e211e0a 16225 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16226 mips32_op = OPC_LWRE;
16227 goto do_ld_lr;
16228 case LBE:
16229 mips32_op = OPC_LBE;
16230 goto do_ld_lr;
16231 case LHE:
16232 mips32_op = OPC_LHE;
16233 goto do_ld_lr;
16234 case LLE:
16235 mips32_op = OPC_LLE;
16236 goto do_ld_lr;
16237 case LWE:
16238 mips32_op = OPC_LWE;
16239 goto do_ld_lr;
16240 };
16241 break;
16242 case ST_EVA:
16243 if (!ctx->eva) {
16244 MIPS_INVAL("pool32c st-eva");
3a4ef3b7 16245 gen_reserved_instruction(ctx);
8fffc646
JH
16246 break;
16247 }
16248 check_cp0_enabled(ctx);
16249
16250 minor2 = (ctx->opcode >> 9) & 0x7;
16251 offset = sextract32(ctx->opcode, 0, 9);
16252 switch (minor2) {
16253 case SWLE:
2e211e0a 16254 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16255 mips32_op = OPC_SWLE;
16256 goto do_st_lr;
16257 case SWRE:
2e211e0a 16258 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8fffc646
JH
16259 mips32_op = OPC_SWRE;
16260 goto do_st_lr;
16261 case PREFE:
16262 /* Treat as no-op */
2e211e0a 16263 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
8fffc646
JH
16264 /* hint codes 24-31 are reserved and signal RI */
16265 generate_exception(ctx, EXCP_RI);
16266 }
16267 break;
16268 case CACHEE:
16269 /* Treat as no-op */
16270 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16271 gen_cache_operation(ctx, rt, rs, offset);
16272 }
16273 break;
16274 case SBE:
16275 mips32_op = OPC_SBE;
16276 goto do_st_lr;
16277 case SHE:
16278 mips32_op = OPC_SHE;
16279 goto do_st_lr;
16280 case SCE:
33a07fa2 16281 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
8fffc646
JH
16282 break;
16283 case SWE:
16284 mips32_op = OPC_SWE;
16285 goto do_st_lr;
16286 };
16287 break;
3c824109
NF
16288 case PREF:
16289 /* Treat as no-op */
2e211e0a 16290 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
3b4a5489
YK
16291 /* hint codes 24-31 are reserved and signal RI */
16292 generate_exception(ctx, EXCP_RI);
16293 }
3c824109
NF
16294 break;
16295 default:
16296 MIPS_INVAL("pool32c");
3a4ef3b7 16297 gen_reserved_instruction(ctx);
3c824109
NF
16298 break;
16299 }
16300 break;
ab39ee45 16301 case ADDI32: /* AUI, LUI */
2e211e0a 16302 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
16303 /* AUI, LUI */
16304 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16305 } else {
16306 /* ADDI32 */
16307 mips32_op = OPC_ADDI;
16308 goto do_addi;
16309 }
16310 break;
3c824109
NF
16311 case ADDIU32:
16312 mips32_op = OPC_ADDIU;
16313 do_addi:
d75c135e 16314 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16315 break;
16316
16317 /* Logical operations */
16318 case ORI32:
16319 mips32_op = OPC_ORI;
16320 goto do_logici;
16321 case XORI32:
16322 mips32_op = OPC_XORI;
16323 goto do_logici;
16324 case ANDI32:
16325 mips32_op = OPC_ANDI;
16326 do_logici:
d75c135e 16327 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16328 break;
16329
16330 /* Set less than immediate */
16331 case SLTI32:
16332 mips32_op = OPC_SLTI;
16333 goto do_slti;
16334 case SLTIU32:
16335 mips32_op = OPC_SLTIU;
16336 do_slti:
d75c135e 16337 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16338 break;
16339 case JALX32:
2e211e0a 16340 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16341 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
16342 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16343 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 16344 break;
65935f07 16345 case JALS32: /* BOVC, BEQC, BEQZALC */
2e211e0a 16346 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16347 if (rs >= rt) {
16348 /* BOVC */
16349 mips32_op = OPC_BOVC;
16350 } else if (rs < rt && rs == 0) {
16351 /* BEQZALC */
16352 mips32_op = OPC_BEQZALC;
16353 } else {
16354 /* BEQC */
16355 mips32_op = OPC_BEQC;
16356 }
16357 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16358 } else {
16359 /* JALS32 */
16360 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16361 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16362 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16363 }
3c824109 16364 break;
65935f07 16365 case BEQ32: /* BC */
2e211e0a 16366 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16367 /* BC */
16368 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16369 sextract32(ctx->opcode << 1, 0, 27));
16370 } else {
16371 /* BEQ32 */
16372 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16373 }
3c824109 16374 break;
65935f07 16375 case BNE32: /* BALC */
2e211e0a 16376 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16377 /* BALC */
16378 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16379 sextract32(ctx->opcode << 1, 0, 27));
16380 } else {
16381 /* BNE32 */
16382 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16383 }
3c824109 16384 break;
65935f07 16385 case J32: /* BGTZC, BLTZC, BLTC */
2e211e0a 16386 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16387 if (rs == 0 && rt != 0) {
16388 /* BGTZC */
16389 mips32_op = OPC_BGTZC;
16390 } else if (rs != 0 && rt != 0 && rs == rt) {
16391 /* BLTZC */
16392 mips32_op = OPC_BLTZC;
16393 } else {
16394 /* BLTC */
16395 mips32_op = OPC_BLTC;
16396 }
16397 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16398 } else {
16399 /* J32 */
16400 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16401 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16402 }
3c824109 16403 break;
65935f07 16404 case JAL32: /* BLEZC, BGEZC, BGEC */
2e211e0a 16405 if (ctx->insn_flags & ISA_MIPS_R6) {
65935f07
YK
16406 if (rs == 0 && rt != 0) {
16407 /* BLEZC */
16408 mips32_op = OPC_BLEZC;
16409 } else if (rs != 0 && rt != 0 && rs == rt) {
16410 /* BGEZC */
16411 mips32_op = OPC_BGEZC;
16412 } else {
16413 /* BGEC */
16414 mips32_op = OPC_BGEC;
16415 }
16416 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16417 } else {
16418 /* JAL32 */
16419 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16420 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16421 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16422 }
3c824109
NF
16423 break;
16424 /* Floating point (COP1) */
16425 case LWC132:
16426 mips32_op = OPC_LWC1;
16427 goto do_cop1;
16428 case LDC132:
16429 mips32_op = OPC_LDC1;
16430 goto do_cop1;
16431 case SWC132:
16432 mips32_op = OPC_SWC1;
16433 goto do_cop1;
16434 case SDC132:
16435 mips32_op = OPC_SDC1;
16436 do_cop1:
5ab5c041 16437 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 16438 break;
ab39ee45 16439 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
2e211e0a 16440 if (ctx->insn_flags & ISA_MIPS_R6) {
ab39ee45
YK
16441 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16442 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
16443 case ADDIUPC_00:
16444 case ADDIUPC_01:
16445 case ADDIUPC_02:
16446 case ADDIUPC_03:
16447 case ADDIUPC_04:
16448 case ADDIUPC_05:
16449 case ADDIUPC_06:
16450 case ADDIUPC_07:
eeb3bba8 16451 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16452 break;
16453 case AUIPC:
eeb3bba8 16454 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
16455 break;
16456 case ALUIPC:
eeb3bba8 16457 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 16458 break;
c38a1d52
AR
16459 case LWPC_08:
16460 case LWPC_09:
16461 case LWPC_0A:
16462 case LWPC_0B:
16463 case LWPC_0C:
16464 case LWPC_0D:
16465 case LWPC_0E:
16466 case LWPC_0F:
eeb3bba8 16467 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16468 break;
16469 default:
16470 generate_exception(ctx, EXCP_RI);
16471 break;
16472 }
16473 } else {
16474 /* ADDIUPC */
3c824109 16475 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 16476 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
16477
16478 gen_addiupc(ctx, reg, offset, 0, 0);
16479 }
16480 break;
65935f07 16481 case BNVC: /* BNEC, BNEZALC */
2e211e0a 16482 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16483 if (rs >= rt) {
16484 /* BNVC */
16485 mips32_op = OPC_BNVC;
16486 } else if (rs < rt && rs == 0) {
16487 /* BNEZALC */
16488 mips32_op = OPC_BNEZALC;
16489 } else {
16490 /* BNEC */
16491 mips32_op = OPC_BNEC;
16492 }
16493 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16494 break;
16495 case R6_BNEZC: /* JIALC */
2e211e0a 16496 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16497 if (rt != 0) {
16498 /* BNEZC */
16499 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16500 sextract32(ctx->opcode << 1, 0, 22));
16501 } else {
16502 /* JIALC */
16503 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16504 }
16505 break;
16506 case R6_BEQZC: /* JIC */
2e211e0a 16507 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16508 if (rt != 0) {
16509 /* BEQZC */
16510 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16511 sextract32(ctx->opcode << 1, 0, 22));
16512 } else {
16513 /* JIC */
16514 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16515 }
16516 break;
16517 case BLEZALC: /* BGEZALC, BGEUC */
2e211e0a 16518 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16519 if (rs == 0 && rt != 0) {
16520 /* BLEZALC */
16521 mips32_op = OPC_BLEZALC;
16522 } else if (rs != 0 && rt != 0 && rs == rt) {
16523 /* BGEZALC */
16524 mips32_op = OPC_BGEZALC;
16525 } else {
16526 /* BGEUC */
16527 mips32_op = OPC_BGEUC;
16528 }
16529 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16530 break;
16531 case BGTZALC: /* BLTZALC, BLTUC */
2e211e0a 16532 check_insn(ctx, ISA_MIPS_R6);
65935f07
YK
16533 if (rs == 0 && rt != 0) {
16534 /* BGTZALC */
16535 mips32_op = OPC_BGTZALC;
16536 } else if (rs != 0 && rt != 0 && rs == rt) {
16537 /* BLTZALC */
16538 mips32_op = OPC_BLTZALC;
16539 } else {
16540 /* BLTUC */
16541 mips32_op = OPC_BLTUC;
16542 }
16543 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16544 break;
3c824109
NF
16545 /* Loads and stores */
16546 case LB32:
16547 mips32_op = OPC_LB;
5c13fdfd 16548 goto do_ld;
3c824109
NF
16549 case LBU32:
16550 mips32_op = OPC_LBU;
5c13fdfd 16551 goto do_ld;
3c824109
NF
16552 case LH32:
16553 mips32_op = OPC_LH;
5c13fdfd 16554 goto do_ld;
3c824109
NF
16555 case LHU32:
16556 mips32_op = OPC_LHU;
5c13fdfd 16557 goto do_ld;
3c824109
NF
16558 case LW32:
16559 mips32_op = OPC_LW;
5c13fdfd 16560 goto do_ld;
3c824109
NF
16561#ifdef TARGET_MIPS64
16562 case LD32:
d9224450
MR
16563 check_insn(ctx, ISA_MIPS3);
16564 check_mips_64(ctx);
3c824109 16565 mips32_op = OPC_LD;
5c13fdfd 16566 goto do_ld;
3c824109 16567 case SD32:
d9224450
MR
16568 check_insn(ctx, ISA_MIPS3);
16569 check_mips_64(ctx);
3c824109 16570 mips32_op = OPC_SD;
5c13fdfd 16571 goto do_st;
3c824109
NF
16572#endif
16573 case SB32:
16574 mips32_op = OPC_SB;
5c13fdfd 16575 goto do_st;
3c824109
NF
16576 case SH32:
16577 mips32_op = OPC_SH;
5c13fdfd 16578 goto do_st;
3c824109
NF
16579 case SW32:
16580 mips32_op = OPC_SW;
5c13fdfd
AJ
16581 goto do_st;
16582 do_ld:
d75c135e 16583 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
16584 break;
16585 do_st:
16586 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16587 break;
16588 default:
3a4ef3b7 16589 gen_reserved_instruction(ctx);
3c824109
NF
16590 break;
16591 }
16592}
16593
235785e8 16594static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16595{
16596 uint32_t op;
16597
16598 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
16599 if (ctx->base.pc_next & 0x1) {
16600 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 16601 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
16602 return 2;
16603 }
16604
16605 op = (ctx->opcode >> 10) & 0x3f;
16606 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
16607 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16608 switch (op & 0x7) { /* MSB-3..MSB-5 */
16609 case 0:
16610 /* POOL32A, POOL32B, POOL32I, POOL32C */
16611 case 4:
16612 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16613 case 5:
16614 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16615 case 6:
16616 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16617 case 7:
16618 /* LB32, LH32, LWC132, LDC132, LW32 */
16619 if (ctx->hflags & MIPS_HFLAG_BDS16) {
3a4ef3b7 16620 gen_reserved_instruction(ctx);
3c824109
NF
16621 return 2;
16622 }
16623 break;
b231c103
YK
16624 case 1:
16625 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16626 case 2:
16627 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16628 case 3:
16629 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16630 if (ctx->hflags & MIPS_HFLAG_BDS32) {
3a4ef3b7 16631 gen_reserved_instruction(ctx);
3c824109
NF
16632 return 2;
16633 }
16634 break;
3c824109
NF
16635 }
16636 }
b231c103 16637
3c824109
NF
16638 switch (op) {
16639 case POOL16A:
16640 {
16641 int rd = mmreg(uMIPS_RD(ctx->opcode));
16642 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16643 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16644 uint32_t opc = 0;
16645
16646 switch (ctx->opcode & 0x1) {
16647 case ADDU16:
16648 opc = OPC_ADDU;
16649 break;
16650 case SUBU16:
16651 opc = OPC_SUBU;
16652 break;
16653 }
2e211e0a 16654 if (ctx->insn_flags & ISA_MIPS_R6) {
7480515f
AM
16655 /*
16656 * In the Release 6, the register number location in
ed7ce6c0
YK
16657 * the instruction encoding has changed.
16658 */
16659 gen_arith(ctx, opc, rs1, rd, rs2);
16660 } else {
16661 gen_arith(ctx, opc, rd, rs1, rs2);
16662 }
3c824109
NF
16663 }
16664 break;
16665 case POOL16B:
16666 {
16667 int rd = mmreg(uMIPS_RD(ctx->opcode));
16668 int rs = mmreg(uMIPS_RS(ctx->opcode));
16669 int amount = (ctx->opcode >> 1) & 0x7;
16670 uint32_t opc = 0;
16671 amount = amount == 0 ? 8 : amount;
16672
16673 switch (ctx->opcode & 0x1) {
16674 case SLL16:
16675 opc = OPC_SLL;
16676 break;
16677 case SRL16:
16678 opc = OPC_SRL;
16679 break;
16680 }
16681
d75c135e 16682 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
16683 }
16684 break;
16685 case POOL16C:
2e211e0a 16686 if (ctx->insn_flags & ISA_MIPS_R6) {
ed7ce6c0
YK
16687 gen_pool16c_r6_insn(ctx);
16688 } else {
16689 gen_pool16c_insn(ctx);
16690 }
3c824109
NF
16691 break;
16692 case LWGP16:
16693 {
16694 int rd = mmreg(uMIPS_RD(ctx->opcode));
16695 int rb = 28; /* GP */
16696 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16697
d75c135e 16698 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16699 }
16700 break;
16701 case POOL16F:
2e211e0a 16702 check_insn_opc_removed(ctx, ISA_MIPS_R6);
3c824109 16703 if (ctx->opcode & 1) {
3a4ef3b7 16704 gen_reserved_instruction(ctx);
3c824109
NF
16705 } else {
16706 /* MOVEP */
16707 int enc_dest = uMIPS_RD(ctx->opcode);
16708 int enc_rt = uMIPS_RS2(ctx->opcode);
16709 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 16710 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
16711 }
16712 break;
16713 case LBU16:
16714 {
16715 int rd = mmreg(uMIPS_RD(ctx->opcode));
16716 int rb = mmreg(uMIPS_RS(ctx->opcode));
16717 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16718 offset = (offset == 0xf ? -1 : offset);
16719
d75c135e 16720 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
16721 }
16722 break;
16723 case LHU16:
16724 {
16725 int rd = mmreg(uMIPS_RD(ctx->opcode));
16726 int rb = mmreg(uMIPS_RS(ctx->opcode));
16727 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16728
d75c135e 16729 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
16730 }
16731 break;
16732 case LWSP16:
16733 {
16734 int rd = (ctx->opcode >> 5) & 0x1f;
16735 int rb = 29; /* SP */
16736 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16737
d75c135e 16738 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16739 }
16740 break;
16741 case LW16:
16742 {
16743 int rd = mmreg(uMIPS_RD(ctx->opcode));
16744 int rb = mmreg(uMIPS_RS(ctx->opcode));
16745 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16746
d75c135e 16747 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16748 }
16749 break;
16750 case SB16:
16751 {
16752 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16753 int rb = mmreg(uMIPS_RS(ctx->opcode));
16754 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16755
5c13fdfd 16756 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
16757 }
16758 break;
16759 case SH16:
16760 {
16761 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16762 int rb = mmreg(uMIPS_RS(ctx->opcode));
16763 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16764
5c13fdfd 16765 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
16766 }
16767 break;
16768 case SWSP16:
16769 {
16770 int rd = (ctx->opcode >> 5) & 0x1f;
16771 int rb = 29; /* SP */
16772 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16773
5c13fdfd 16774 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16775 }
16776 break;
16777 case SW16:
16778 {
16779 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16780 int rb = mmreg(uMIPS_RS(ctx->opcode));
16781 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16782
5c13fdfd 16783 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16784 }
16785 break;
16786 case MOVE16:
16787 {
16788 int rd = uMIPS_RD5(ctx->opcode);
16789 int rs = uMIPS_RS5(ctx->opcode);
16790
7215d7e7 16791 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
16792 }
16793 break;
16794 case ANDI16:
d75c135e 16795 gen_andi16(ctx);
3c824109
NF
16796 break;
16797 case POOL16D:
16798 switch (ctx->opcode & 0x1) {
16799 case ADDIUS5:
d75c135e 16800 gen_addius5(ctx);
3c824109
NF
16801 break;
16802 case ADDIUSP:
d75c135e 16803 gen_addiusp(ctx);
3c824109
NF
16804 break;
16805 }
16806 break;
16807 case POOL16E:
16808 switch (ctx->opcode & 0x1) {
16809 case ADDIUR2:
d75c135e 16810 gen_addiur2(ctx);
3c824109
NF
16811 break;
16812 case ADDIUR1SP:
d75c135e 16813 gen_addiur1sp(ctx);
3c824109
NF
16814 break;
16815 }
16816 break;
65935f07 16817 case B16: /* BC16 */
3c824109 16818 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07 16819 sextract32(ctx->opcode, 0, 10) << 1,
2e211e0a 16820 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
3c824109 16821 break;
65935f07
YK
16822 case BNEZ16: /* BNEZC16 */
16823 case BEQZ16: /* BEQZC16 */
3c824109
NF
16824 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16825 mmreg(uMIPS_RD(ctx->opcode)),
65935f07 16826 0, sextract32(ctx->opcode, 0, 7) << 1,
2e211e0a 16827 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
65935f07 16828
3c824109
NF
16829 break;
16830 case LI16:
16831 {
16832 int reg = mmreg(uMIPS_RD(ctx->opcode));
16833 int imm = ZIMM(ctx->opcode, 0, 7);
16834
16835 imm = (imm == 0x7f ? -1 : imm);
16836 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16837 }
16838 break;
3c824109 16839 case RES_29:
3c824109 16840 case RES_31:
3c824109 16841 case RES_39:
3a4ef3b7 16842 gen_reserved_instruction(ctx);
3c824109
NF
16843 break;
16844 default:
f60eeb0c 16845 decode_micromips32_opc(env, ctx);
3c824109
NF
16846 return 4;
16847 }
16848
16849 return 2;
16850}
16851
261c95a0
YK
16852/*
16853 *
16854 * nanoMIPS opcodes
16855 *
16856 */
16857
16858/* MAJOR, P16, and P32 pools opcodes */
16859enum {
16860 NM_P_ADDIU = 0x00,
16861 NM_ADDIUPC = 0x01,
16862 NM_MOVE_BALC = 0x02,
16863 NM_P16_MV = 0x04,
16864 NM_LW16 = 0x05,
16865 NM_BC16 = 0x06,
16866 NM_P16_SR = 0x07,
16867
16868 NM_POOL32A = 0x08,
16869 NM_P_BAL = 0x0a,
16870 NM_P16_SHIFT = 0x0c,
16871 NM_LWSP16 = 0x0d,
16872 NM_BALC16 = 0x0e,
16873 NM_P16_4X4 = 0x0f,
16874
16875 NM_P_GP_W = 0x10,
16876 NM_P_GP_BH = 0x11,
16877 NM_P_J = 0x12,
16878 NM_P16C = 0x14,
16879 NM_LWGP16 = 0x15,
16880 NM_P16_LB = 0x17,
16881
16882 NM_P48I = 0x18,
16883 NM_P16_A1 = 0x1c,
16884 NM_LW4X4 = 0x1d,
16885 NM_P16_LH = 0x1f,
16886
16887 NM_P_U12 = 0x20,
16888 NM_P_LS_U12 = 0x21,
16889 NM_P_BR1 = 0x22,
16890 NM_P16_A2 = 0x24,
16891 NM_SW16 = 0x25,
16892 NM_BEQZC16 = 0x26,
16893
16894 NM_POOL32F = 0x28,
16895 NM_P_LS_S9 = 0x29,
16896 NM_P_BR2 = 0x2a,
16897
16898 NM_P16_ADDU = 0x2c,
16899 NM_SWSP16 = 0x2d,
16900 NM_BNEZC16 = 0x2e,
16901 NM_MOVEP = 0x2f,
16902
16903 NM_POOL32S = 0x30,
16904 NM_P_BRI = 0x32,
16905 NM_LI16 = 0x34,
16906 NM_SWGP16 = 0x35,
16907 NM_P16_BR = 0x36,
16908
16909 NM_P_LUI = 0x38,
16910 NM_ANDI16 = 0x3c,
16911 NM_SW4X4 = 0x3d,
16912 NM_MOVEPREV = 0x3f,
16913};
16914
16915/* POOL32A instruction pool */
16916enum {
16917 NM_POOL32A0 = 0x00,
16918 NM_SPECIAL2 = 0x01,
16919 NM_COP2_1 = 0x02,
16920 NM_UDI = 0x03,
16921 NM_POOL32A5 = 0x05,
16922 NM_POOL32A7 = 0x07,
16923};
16924
16925/* P.GP.W instruction pool */
16926enum {
16927 NM_ADDIUGP_W = 0x00,
16928 NM_LWGP = 0x02,
16929 NM_SWGP = 0x03,
16930};
16931
16932/* P48I instruction pool */
16933enum {
16934 NM_LI48 = 0x00,
16935 NM_ADDIU48 = 0x01,
16936 NM_ADDIUGP48 = 0x02,
16937 NM_ADDIUPC48 = 0x03,
16938 NM_LWPC48 = 0x0b,
16939 NM_SWPC48 = 0x0f,
16940};
16941
16942/* P.U12 instruction pool */
16943enum {
16944 NM_ORI = 0x00,
16945 NM_XORI = 0x01,
16946 NM_ANDI = 0x02,
16947 NM_P_SR = 0x03,
16948 NM_SLTI = 0x04,
16949 NM_SLTIU = 0x05,
16950 NM_SEQI = 0x06,
16951 NM_ADDIUNEG = 0x08,
16952 NM_P_SHIFT = 0x0c,
16953 NM_P_ROTX = 0x0d,
16954 NM_P_INS = 0x0e,
16955 NM_P_EXT = 0x0f,
16956};
16957
16958/* POOL32F instruction pool */
16959enum {
16960 NM_POOL32F_0 = 0x00,
16961 NM_POOL32F_3 = 0x03,
16962 NM_POOL32F_5 = 0x05,
16963};
16964
16965/* POOL32S instruction pool */
16966enum {
16967 NM_POOL32S_0 = 0x00,
16968 NM_POOL32S_4 = 0x04,
16969};
16970
16971/* P.LUI instruction pool */
16972enum {
16973 NM_LUI = 0x00,
16974 NM_ALUIPC = 0x01,
16975};
16976
16977/* P.GP.BH instruction pool */
16978enum {
16979 NM_LBGP = 0x00,
16980 NM_SBGP = 0x01,
16981 NM_LBUGP = 0x02,
16982 NM_ADDIUGP_B = 0x03,
16983 NM_P_GP_LH = 0x04,
16984 NM_P_GP_SH = 0x05,
16985 NM_P_GP_CP1 = 0x06,
16986};
16987
16988/* P.LS.U12 instruction pool */
16989enum {
16990 NM_LB = 0x00,
16991 NM_SB = 0x01,
16992 NM_LBU = 0x02,
16993 NM_P_PREFU12 = 0x03,
16994 NM_LH = 0x04,
16995 NM_SH = 0x05,
16996 NM_LHU = 0x06,
16997 NM_LWU = 0x07,
16998 NM_LW = 0x08,
16999 NM_SW = 0x09,
17000 NM_LWC1 = 0x0a,
17001 NM_SWC1 = 0x0b,
17002 NM_LDC1 = 0x0e,
17003 NM_SDC1 = 0x0f,
17004};
17005
17006/* P.LS.S9 instruction pool */
17007enum {
17008 NM_P_LS_S0 = 0x00,
17009 NM_P_LS_S1 = 0x01,
17010 NM_P_LS_E0 = 0x02,
17011 NM_P_LS_WM = 0x04,
17012 NM_P_LS_UAWM = 0x05,
17013};
17014
17015/* P.BAL instruction pool */
17016enum {
17017 NM_BC = 0x00,
17018 NM_BALC = 0x01,
17019};
17020
17021/* P.J instruction pool */
17022enum {
17023 NM_JALRC = 0x00,
17024 NM_JALRC_HB = 0x01,
17025 NM_P_BALRSC = 0x08,
17026};
17027
17028/* P.BR1 instruction pool */
17029enum {
17030 NM_BEQC = 0x00,
17031 NM_P_BR3A = 0x01,
17032 NM_BGEC = 0x02,
17033 NM_BGEUC = 0x03,
17034};
17035
17036/* P.BR2 instruction pool */
17037enum {
17038 NM_BNEC = 0x00,
17039 NM_BLTC = 0x02,
17040 NM_BLTUC = 0x03,
17041};
17042
17043/* P.BRI instruction pool */
17044enum {
17045 NM_BEQIC = 0x00,
17046 NM_BBEQZC = 0x01,
17047 NM_BGEIC = 0x02,
17048 NM_BGEIUC = 0x03,
17049 NM_BNEIC = 0x04,
17050 NM_BBNEZC = 0x05,
17051 NM_BLTIC = 0x06,
17052 NM_BLTIUC = 0x07,
17053};
17054
17055/* P16.SHIFT instruction pool */
17056enum {
17057 NM_SLL16 = 0x00,
17058 NM_SRL16 = 0x01,
17059};
17060
17061/* POOL16C instruction pool */
17062enum {
17063 NM_POOL16C_0 = 0x00,
17064 NM_LWXS16 = 0x01,
17065};
17066
17067/* P16.A1 instruction pool */
17068enum {
17069 NM_ADDIUR1SP = 0x01,
17070};
17071
17072/* P16.A2 instruction pool */
17073enum {
17074 NM_ADDIUR2 = 0x00,
17075 NM_P_ADDIURS5 = 0x01,
17076};
17077
17078/* P16.ADDU instruction pool */
17079enum {
17080 NM_ADDU16 = 0x00,
17081 NM_SUBU16 = 0x01,
17082};
17083
17084/* P16.SR instruction pool */
17085enum {
17086 NM_SAVE16 = 0x00,
17087 NM_RESTORE_JRC16 = 0x01,
17088};
17089
17090/* P16.4X4 instruction pool */
17091enum {
17092 NM_ADDU4X4 = 0x00,
17093 NM_MUL4X4 = 0x01,
17094};
17095
17096/* P16.LB instruction pool */
17097enum {
17098 NM_LB16 = 0x00,
17099 NM_SB16 = 0x01,
17100 NM_LBU16 = 0x02,
17101};
17102
17103/* P16.LH instruction pool */
17104enum {
17105 NM_LH16 = 0x00,
17106 NM_SH16 = 0x01,
17107 NM_LHU16 = 0x02,
17108};
17109
17110/* P.RI instruction pool */
17111enum {
17112 NM_SIGRIE = 0x00,
17113 NM_P_SYSCALL = 0x01,
17114 NM_BREAK = 0x02,
17115 NM_SDBBP = 0x03,
17116};
17117
17118/* POOL32A0 instruction pool */
17119enum {
17120 NM_P_TRAP = 0x00,
17121 NM_SEB = 0x01,
17122 NM_SLLV = 0x02,
17123 NM_MUL = 0x03,
17124 NM_MFC0 = 0x06,
17125 NM_MFHC0 = 0x07,
17126 NM_SEH = 0x09,
17127 NM_SRLV = 0x0a,
17128 NM_MUH = 0x0b,
17129 NM_MTC0 = 0x0e,
17130 NM_MTHC0 = 0x0f,
17131 NM_SRAV = 0x12,
17132 NM_MULU = 0x13,
17133 NM_ROTRV = 0x1a,
17134 NM_MUHU = 0x1b,
17135 NM_ADD = 0x22,
17136 NM_DIV = 0x23,
17137 NM_ADDU = 0x2a,
17138 NM_MOD = 0x2b,
17139 NM_SUB = 0x32,
17140 NM_DIVU = 0x33,
17141 NM_RDHWR = 0x38,
17142 NM_SUBU = 0x3a,
17143 NM_MODU = 0x3b,
17144 NM_P_CMOVE = 0x42,
17145 NM_FORK = 0x45,
17146 NM_MFTR = 0x46,
17147 NM_MFHTR = 0x47,
17148 NM_AND = 0x4a,
17149 NM_YIELD = 0x4d,
17150 NM_MTTR = 0x4e,
17151 NM_MTHTR = 0x4f,
17152 NM_OR = 0x52,
17153 NM_D_E_MT_VPE = 0x56,
17154 NM_NOR = 0x5a,
17155 NM_XOR = 0x62,
17156 NM_SLT = 0x6a,
17157 NM_P_SLTU = 0x72,
17158 NM_SOV = 0x7a,
17159};
17160
ba1e8117
AM
17161/* CRC32 instruction pool */
17162enum {
17163 NM_CRC32B = 0x00,
17164 NM_CRC32H = 0x01,
17165 NM_CRC32W = 0x02,
17166 NM_CRC32CB = 0x04,
17167 NM_CRC32CH = 0x05,
17168 NM_CRC32CW = 0x06,
17169};
17170
b3979b6f
SM
17171/* POOL32A5 instruction pool */
17172enum {
17173 NM_CMP_EQ_PH = 0x00,
17174 NM_CMP_LT_PH = 0x08,
17175 NM_CMP_LE_PH = 0x10,
17176 NM_CMPGU_EQ_QB = 0x18,
17177 NM_CMPGU_LT_QB = 0x20,
17178 NM_CMPGU_LE_QB = 0x28,
17179 NM_CMPGDU_EQ_QB = 0x30,
17180 NM_CMPGDU_LT_QB = 0x38,
17181 NM_CMPGDU_LE_QB = 0x40,
17182 NM_CMPU_EQ_QB = 0x48,
17183 NM_CMPU_LT_QB = 0x50,
17184 NM_CMPU_LE_QB = 0x58,
17185 NM_ADDQ_S_W = 0x60,
17186 NM_SUBQ_S_W = 0x68,
17187 NM_ADDSC = 0x70,
17188 NM_ADDWC = 0x78,
17189
17190 NM_ADDQ_S_PH = 0x01,
17191 NM_ADDQH_R_PH = 0x09,
17192 NM_ADDQH_R_W = 0x11,
17193 NM_ADDU_S_QB = 0x19,
17194 NM_ADDU_S_PH = 0x21,
17195 NM_ADDUH_R_QB = 0x29,
17196 NM_SHRAV_R_PH = 0x31,
17197 NM_SHRAV_R_QB = 0x39,
17198 NM_SUBQ_S_PH = 0x41,
17199 NM_SUBQH_R_PH = 0x49,
17200 NM_SUBQH_R_W = 0x51,
17201 NM_SUBU_S_QB = 0x59,
17202 NM_SUBU_S_PH = 0x61,
17203 NM_SUBUH_R_QB = 0x69,
17204 NM_SHLLV_S_PH = 0x71,
17205 NM_PRECR_SRA_R_PH_W = 0x79,
17206
17207 NM_MULEU_S_PH_QBL = 0x12,
17208 NM_MULEU_S_PH_QBR = 0x1a,
17209 NM_MULQ_RS_PH = 0x22,
17210 NM_MULQ_S_PH = 0x2a,
17211 NM_MULQ_RS_W = 0x32,
17212 NM_MULQ_S_W = 0x3a,
17213 NM_APPEND = 0x42,
17214 NM_MODSUB = 0x52,
17215 NM_SHRAV_R_W = 0x5a,
17216 NM_SHRLV_PH = 0x62,
17217 NM_SHRLV_QB = 0x6a,
17218 NM_SHLLV_QB = 0x72,
17219 NM_SHLLV_S_W = 0x7a,
17220
17221 NM_SHILO = 0x03,
17222
17223 NM_MULEQ_S_W_PHL = 0x04,
17224 NM_MULEQ_S_W_PHR = 0x0c,
17225
17226 NM_MUL_S_PH = 0x05,
17227 NM_PRECR_QB_PH = 0x0d,
17228 NM_PRECRQ_QB_PH = 0x15,
17229 NM_PRECRQ_PH_W = 0x1d,
17230 NM_PRECRQ_RS_PH_W = 0x25,
17231 NM_PRECRQU_S_QB_PH = 0x2d,
17232 NM_PACKRL_PH = 0x35,
17233 NM_PICK_QB = 0x3d,
17234 NM_PICK_PH = 0x45,
17235
17236 NM_SHRA_R_W = 0x5e,
17237 NM_SHRA_R_PH = 0x66,
17238 NM_SHLL_S_PH = 0x76,
17239 NM_SHLL_S_W = 0x7e,
17240
17241 NM_REPL_PH = 0x07
17242};
17243
261c95a0
YK
17244/* POOL32A7 instruction pool */
17245enum {
17246 NM_P_LSX = 0x00,
17247 NM_LSA = 0x01,
17248 NM_EXTW = 0x03,
17249 NM_POOL32AXF = 0x07,
17250};
17251
17252/* P.SR instruction pool */
17253enum {
17254 NM_PP_SR = 0x00,
17255 NM_P_SR_F = 0x01,
17256};
17257
17258/* P.SHIFT instruction pool */
17259enum {
17260 NM_P_SLL = 0x00,
17261 NM_SRL = 0x02,
17262 NM_SRA = 0x04,
17263 NM_ROTR = 0x06,
17264};
17265
17266/* P.ROTX instruction pool */
17267enum {
17268 NM_ROTX = 0x00,
17269};
17270
17271/* P.INS instruction pool */
17272enum {
17273 NM_INS = 0x00,
17274};
17275
17276/* P.EXT instruction pool */
17277enum {
17278 NM_EXT = 0x00,
17279};
17280
17281/* POOL32F_0 (fmt) instruction pool */
17282enum {
17283 NM_RINT_S = 0x04,
17284 NM_RINT_D = 0x44,
17285 NM_ADD_S = 0x06,
17286 NM_SELEQZ_S = 0x07,
17287 NM_SELEQZ_D = 0x47,
17288 NM_CLASS_S = 0x0c,
17289 NM_CLASS_D = 0x4c,
17290 NM_SUB_S = 0x0e,
17291 NM_SELNEZ_S = 0x0f,
17292 NM_SELNEZ_D = 0x4f,
17293 NM_MUL_S = 0x16,
17294 NM_SEL_S = 0x17,
17295 NM_SEL_D = 0x57,
17296 NM_DIV_S = 0x1e,
17297 NM_ADD_D = 0x26,
17298 NM_SUB_D = 0x2e,
17299 NM_MUL_D = 0x36,
17300 NM_MADDF_S = 0x37,
17301 NM_MADDF_D = 0x77,
17302 NM_DIV_D = 0x3e,
17303 NM_MSUBF_S = 0x3f,
17304 NM_MSUBF_D = 0x7f,
17305};
17306
17307/* POOL32F_3 instruction pool */
17308enum {
17309 NM_MIN_FMT = 0x00,
17310 NM_MAX_FMT = 0x01,
17311 NM_MINA_FMT = 0x04,
17312 NM_MAXA_FMT = 0x05,
17313 NM_POOL32FXF = 0x07,
17314};
17315
17316/* POOL32F_5 instruction pool */
17317enum {
17318 NM_CMP_CONDN_S = 0x00,
17319 NM_CMP_CONDN_D = 0x02,
17320};
17321
17322/* P.GP.LH instruction pool */
17323enum {
17324 NM_LHGP = 0x00,
17325 NM_LHUGP = 0x01,
17326};
17327
17328/* P.GP.SH instruction pool */
17329enum {
17330 NM_SHGP = 0x00,
17331};
17332
17333/* P.GP.CP1 instruction pool */
17334enum {
17335 NM_LWC1GP = 0x00,
17336 NM_SWC1GP = 0x01,
17337 NM_LDC1GP = 0x02,
17338 NM_SDC1GP = 0x03,
17339};
17340
17341/* P.LS.S0 instruction pool */
17342enum {
17343 NM_LBS9 = 0x00,
17344 NM_LHS9 = 0x04,
17345 NM_LWS9 = 0x08,
17346 NM_LDS9 = 0x0c,
17347
17348 NM_SBS9 = 0x01,
17349 NM_SHS9 = 0x05,
17350 NM_SWS9 = 0x09,
17351 NM_SDS9 = 0x0d,
17352
17353 NM_LBUS9 = 0x02,
17354 NM_LHUS9 = 0x06,
17355 NM_LWC1S9 = 0x0a,
17356 NM_LDC1S9 = 0x0e,
17357
17358 NM_P_PREFS9 = 0x03,
17359 NM_LWUS9 = 0x07,
17360 NM_SWC1S9 = 0x0b,
17361 NM_SDC1S9 = 0x0f,
17362};
17363
17364/* P.LS.S1 instruction pool */
17365enum {
17366 NM_ASET_ACLR = 0x02,
17367 NM_UALH = 0x04,
17368 NM_UASH = 0x05,
17369 NM_CACHE = 0x07,
17370 NM_P_LL = 0x0a,
17371 NM_P_SC = 0x0b,
17372};
17373
0d30b3bb
DN
17374/* P.LS.E0 instruction pool */
17375enum {
17376 NM_LBE = 0x00,
17377 NM_SBE = 0x01,
17378 NM_LBUE = 0x02,
17379 NM_P_PREFE = 0x03,
17380 NM_LHE = 0x04,
17381 NM_SHE = 0x05,
17382 NM_LHUE = 0x06,
17383 NM_CACHEE = 0x07,
17384 NM_LWE = 0x08,
17385 NM_SWE = 0x09,
17386 NM_P_LLE = 0x0a,
17387 NM_P_SCE = 0x0b,
17388};
17389
17390/* P.PREFE instruction pool */
17391enum {
17392 NM_SYNCIE = 0x00,
17393 NM_PREFE = 0x01,
17394};
17395
17396/* P.LLE instruction pool */
17397enum {
17398 NM_LLE = 0x00,
17399 NM_LLWPE = 0x01,
17400};
17401
17402/* P.SCE instruction pool */
17403enum {
17404 NM_SCE = 0x00,
17405 NM_SCWPE = 0x01,
17406};
17407
261c95a0
YK
17408/* P.LS.WM instruction pool */
17409enum {
17410 NM_LWM = 0x00,
17411 NM_SWM = 0x01,
17412};
17413
17414/* P.LS.UAWM instruction pool */
17415enum {
17416 NM_UALWM = 0x00,
17417 NM_UASWM = 0x01,
17418};
17419
17420/* P.BR3A instruction pool */
17421enum {
17422 NM_BC1EQZC = 0x00,
17423 NM_BC1NEZC = 0x01,
17424 NM_BC2EQZC = 0x02,
17425 NM_BC2NEZC = 0x03,
17426 NM_BPOSGE32C = 0x04,
17427};
17428
17429/* P16.RI instruction pool */
17430enum {
17431 NM_P16_SYSCALL = 0x01,
17432 NM_BREAK16 = 0x02,
17433 NM_SDBBP16 = 0x03,
17434};
17435
17436/* POOL16C_0 instruction pool */
17437enum {
17438 NM_POOL16C_00 = 0x00,
17439};
17440
17441/* P16.JRC instruction pool */
17442enum {
17443 NM_JRC = 0x00,
17444 NM_JALRC16 = 0x01,
17445};
17446
17447/* P.SYSCALL instruction pool */
17448enum {
17449 NM_SYSCALL = 0x00,
17450 NM_HYPCALL = 0x01,
17451};
17452
17453/* P.TRAP instruction pool */
17454enum {
17455 NM_TEQ = 0x00,
17456 NM_TNE = 0x01,
17457};
17458
17459/* P.CMOVE instruction pool */
17460enum {
17461 NM_MOVZ = 0x00,
17462 NM_MOVN = 0x01,
17463};
17464
17465/* POOL32Axf instruction pool */
17466enum {
b3979b6f
SM
17467 NM_POOL32AXF_1 = 0x01,
17468 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
17469 NM_POOL32AXF_4 = 0x04,
17470 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
17471 NM_POOL32AXF_7 = 0x07,
17472};
17473
17474/* POOL32Axf_1 instruction pool */
17475enum {
17476 NM_POOL32AXF_1_0 = 0x00,
17477 NM_POOL32AXF_1_1 = 0x01,
17478 NM_POOL32AXF_1_3 = 0x03,
17479 NM_POOL32AXF_1_4 = 0x04,
17480 NM_POOL32AXF_1_5 = 0x05,
17481 NM_POOL32AXF_1_7 = 0x07,
17482};
17483
17484/* POOL32Axf_2 instruction pool */
17485enum {
17486 NM_POOL32AXF_2_0_7 = 0x00,
17487 NM_POOL32AXF_2_8_15 = 0x01,
17488 NM_POOL32AXF_2_16_23 = 0x02,
17489 NM_POOL32AXF_2_24_31 = 0x03,
17490};
17491
17492/* POOL32Axf_7 instruction pool */
17493enum {
17494 NM_SHRA_R_QB = 0x0,
17495 NM_SHRL_PH = 0x1,
17496 NM_REPL_QB = 0x2,
17497};
17498
17499/* POOL32Axf_1_0 instruction pool */
17500enum {
17501 NM_MFHI = 0x0,
17502 NM_MFLO = 0x1,
17503 NM_MTHI = 0x2,
17504 NM_MTLO = 0x3,
17505};
17506
17507/* POOL32Axf_1_1 instruction pool */
17508enum {
17509 NM_MTHLIP = 0x0,
17510 NM_SHILOV = 0x1,
17511};
17512
17513/* POOL32Axf_1_3 instruction pool */
17514enum {
17515 NM_RDDSP = 0x0,
17516 NM_WRDSP = 0x1,
17517 NM_EXTP = 0x2,
17518 NM_EXTPDP = 0x3,
17519};
17520
17521/* POOL32Axf_1_4 instruction pool */
17522enum {
17523 NM_SHLL_QB = 0x0,
17524 NM_SHRL_QB = 0x1,
17525};
17526
17527/* POOL32Axf_1_5 instruction pool */
17528enum {
17529 NM_MAQ_S_W_PHR = 0x0,
17530 NM_MAQ_S_W_PHL = 0x1,
17531 NM_MAQ_SA_W_PHR = 0x2,
17532 NM_MAQ_SA_W_PHL = 0x3,
17533};
17534
17535/* POOL32Axf_1_7 instruction pool */
17536enum {
17537 NM_EXTR_W = 0x0,
17538 NM_EXTR_R_W = 0x1,
17539 NM_EXTR_RS_W = 0x2,
17540 NM_EXTR_S_H = 0x3,
17541};
17542
17543/* POOL32Axf_2_0_7 instruction pool */
17544enum {
17545 NM_DPA_W_PH = 0x0,
17546 NM_DPAQ_S_W_PH = 0x1,
17547 NM_DPS_W_PH = 0x2,
17548 NM_DPSQ_S_W_PH = 0x3,
17549 NM_BALIGN = 0x4,
17550 NM_MADD = 0x5,
17551 NM_MULT = 0x6,
17552 NM_EXTRV_W = 0x7,
17553};
17554
17555/* POOL32Axf_2_8_15 instruction pool */
17556enum {
17557 NM_DPAX_W_PH = 0x0,
17558 NM_DPAQ_SA_L_W = 0x1,
17559 NM_DPSX_W_PH = 0x2,
17560 NM_DPSQ_SA_L_W = 0x3,
17561 NM_MADDU = 0x5,
17562 NM_MULTU = 0x6,
17563 NM_EXTRV_R_W = 0x7,
17564};
17565
17566/* POOL32Axf_2_16_23 instruction pool */
17567enum {
17568 NM_DPAU_H_QBL = 0x0,
17569 NM_DPAQX_S_W_PH = 0x1,
17570 NM_DPSU_H_QBL = 0x2,
17571 NM_DPSQX_S_W_PH = 0x3,
17572 NM_EXTPV = 0x4,
17573 NM_MSUB = 0x5,
17574 NM_MULSA_W_PH = 0x6,
17575 NM_EXTRV_RS_W = 0x7,
17576};
17577
17578/* POOL32Axf_2_24_31 instruction pool */
17579enum {
17580 NM_DPAU_H_QBR = 0x0,
17581 NM_DPAQX_SA_W_PH = 0x1,
17582 NM_DPSU_H_QBR = 0x2,
17583 NM_DPSQX_SA_W_PH = 0x3,
17584 NM_EXTPDPV = 0x4,
17585 NM_MSUBU = 0x5,
17586 NM_MULSAQ_S_W_PH = 0x6,
17587 NM_EXTRV_S_H = 0x7,
261c95a0
YK
17588};
17589
17590/* POOL32Axf_{4, 5} instruction pool */
17591enum {
17592 NM_CLO = 0x25,
17593 NM_CLZ = 0x2d,
17594
17595 NM_TLBP = 0x01,
17596 NM_TLBR = 0x09,
17597 NM_TLBWI = 0x11,
17598 NM_TLBWR = 0x19,
17599 NM_TLBINV = 0x03,
17600 NM_TLBINVF = 0x0b,
17601 NM_DI = 0x23,
17602 NM_EI = 0x2b,
17603 NM_RDPGPR = 0x70,
17604 NM_WRPGPR = 0x78,
17605 NM_WAIT = 0x61,
17606 NM_DERET = 0x71,
17607 NM_ERETX = 0x79,
b3979b6f
SM
17608
17609 /* nanoMIPS DSP instructions */
17610 NM_ABSQ_S_QB = 0x00,
17611 NM_ABSQ_S_PH = 0x08,
17612 NM_ABSQ_S_W = 0x10,
17613 NM_PRECEQ_W_PHL = 0x28,
17614 NM_PRECEQ_W_PHR = 0x30,
17615 NM_PRECEQU_PH_QBL = 0x38,
17616 NM_PRECEQU_PH_QBR = 0x48,
17617 NM_PRECEU_PH_QBL = 0x58,
17618 NM_PRECEU_PH_QBR = 0x68,
17619 NM_PRECEQU_PH_QBLA = 0x39,
17620 NM_PRECEQU_PH_QBRA = 0x49,
17621 NM_PRECEU_PH_QBLA = 0x59,
17622 NM_PRECEU_PH_QBRA = 0x69,
17623 NM_REPLV_PH = 0x01,
17624 NM_REPLV_QB = 0x09,
17625 NM_BITREV = 0x18,
17626 NM_INSV = 0x20,
17627 NM_RADDU_W_QB = 0x78,
17628
17629 NM_BITSWAP = 0x05,
17630 NM_WSBH = 0x3d,
261c95a0
YK
17631};
17632
17633/* PP.SR instruction pool */
17634enum {
17635 NM_SAVE = 0x00,
17636 NM_RESTORE = 0x02,
17637 NM_RESTORE_JRC = 0x03,
17638};
17639
17640/* P.SR.F instruction pool */
17641enum {
17642 NM_SAVEF = 0x00,
17643 NM_RESTOREF = 0x01,
17644};
17645
17646/* P16.SYSCALL instruction pool */
17647enum {
17648 NM_SYSCALL16 = 0x00,
17649 NM_HYPCALL16 = 0x01,
17650};
17651
17652/* POOL16C_00 instruction pool */
17653enum {
17654 NM_NOT16 = 0x00,
17655 NM_XOR16 = 0x01,
17656 NM_AND16 = 0x02,
17657 NM_OR16 = 0x03,
17658};
17659
17660/* PP.LSX and PP.LSXS instruction pool */
17661enum {
17662 NM_LBX = 0x00,
17663 NM_LHX = 0x04,
17664 NM_LWX = 0x08,
17665 NM_LDX = 0x0c,
17666
17667 NM_SBX = 0x01,
17668 NM_SHX = 0x05,
17669 NM_SWX = 0x09,
17670 NM_SDX = 0x0d,
17671
17672 NM_LBUX = 0x02,
17673 NM_LHUX = 0x06,
17674 NM_LWC1X = 0x0a,
17675 NM_LDC1X = 0x0e,
17676
17677 NM_LWUX = 0x07,
17678 NM_SWC1X = 0x0b,
17679 NM_SDC1X = 0x0f,
17680
17681 NM_LHXS = 0x04,
17682 NM_LWXS = 0x08,
17683 NM_LDXS = 0x0c,
17684
17685 NM_SHXS = 0x05,
17686 NM_SWXS = 0x09,
17687 NM_SDXS = 0x0d,
17688
17689 NM_LHUXS = 0x06,
17690 NM_LWC1XS = 0x0a,
17691 NM_LDC1XS = 0x0e,
17692
17693 NM_LWUXS = 0x07,
17694 NM_SWC1XS = 0x0b,
17695 NM_SDC1XS = 0x0f,
17696};
17697
17698/* ERETx instruction pool */
17699enum {
17700 NM_ERET = 0x00,
17701 NM_ERETNC = 0x01,
17702};
17703
17704/* POOL32FxF_{0, 1} insturction pool */
17705enum {
17706 NM_CFC1 = 0x40,
17707 NM_CTC1 = 0x60,
17708 NM_MFC1 = 0x80,
17709 NM_MTC1 = 0xa0,
17710 NM_MFHC1 = 0xc0,
17711 NM_MTHC1 = 0xe0,
17712
17713 NM_CVT_S_PL = 0x84,
17714 NM_CVT_S_PU = 0xa4,
17715
17716 NM_CVT_L_S = 0x004,
17717 NM_CVT_L_D = 0x104,
17718 NM_CVT_W_S = 0x024,
17719 NM_CVT_W_D = 0x124,
17720
17721 NM_RSQRT_S = 0x008,
17722 NM_RSQRT_D = 0x108,
17723
17724 NM_SQRT_S = 0x028,
17725 NM_SQRT_D = 0x128,
17726
17727 NM_RECIP_S = 0x048,
17728 NM_RECIP_D = 0x148,
17729
17730 NM_FLOOR_L_S = 0x00c,
17731 NM_FLOOR_L_D = 0x10c,
17732
17733 NM_FLOOR_W_S = 0x02c,
17734 NM_FLOOR_W_D = 0x12c,
17735
17736 NM_CEIL_L_S = 0x04c,
17737 NM_CEIL_L_D = 0x14c,
17738 NM_CEIL_W_S = 0x06c,
17739 NM_CEIL_W_D = 0x16c,
17740 NM_TRUNC_L_S = 0x08c,
17741 NM_TRUNC_L_D = 0x18c,
17742 NM_TRUNC_W_S = 0x0ac,
17743 NM_TRUNC_W_D = 0x1ac,
17744 NM_ROUND_L_S = 0x0cc,
17745 NM_ROUND_L_D = 0x1cc,
17746 NM_ROUND_W_S = 0x0ec,
17747 NM_ROUND_W_D = 0x1ec,
17748
17749 NM_MOV_S = 0x01,
17750 NM_MOV_D = 0x81,
17751 NM_ABS_S = 0x0d,
17752 NM_ABS_D = 0x8d,
17753 NM_NEG_S = 0x2d,
17754 NM_NEG_D = 0xad,
17755 NM_CVT_D_S = 0x04d,
17756 NM_CVT_D_W = 0x0cd,
17757 NM_CVT_D_L = 0x14d,
17758 NM_CVT_S_D = 0x06d,
17759 NM_CVT_S_W = 0x0ed,
17760 NM_CVT_S_L = 0x16d,
17761};
17762
17763/* P.LL instruction pool */
17764enum {
17765 NM_LL = 0x00,
17766 NM_LLWP = 0x01,
17767};
17768
17769/* P.SC instruction pool */
17770enum {
17771 NM_SC = 0x00,
17772 NM_SCWP = 0x01,
17773};
17774
17775/* P.DVP instruction pool */
17776enum {
17777 NM_DVP = 0x00,
17778 NM_EVP = 0x01,
17779};
17780
c533c0f4
AM
17781
17782/*
17783 *
17784 * nanoMIPS decoding engine
17785 *
17786 */
17787
6bfa9f4c
AM
17788
17789/* extraction utilities */
17790
99e49abf
AM
17791#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17792#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17793#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
6bfa9f4c
AM
17794#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17795#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17796
ea4ca3c2
YK
17797/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17798static inline int decode_gpr_gpr3(int r)
17799{
17800 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17801
17802 return map[r & 0x7];
17803}
17804
8bdb7029
YK
17805/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17806static inline int decode_gpr_gpr3_src_store(int r)
17807{
17808 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17809
17810 return map[r & 0x7];
17811}
17812
ea4ca3c2
YK
17813/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17814static inline int decode_gpr_gpr4(int r)
17815{
17816 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17817 16, 17, 18, 19, 20, 21, 22, 23 };
17818
17819 return map[r & 0xf];
17820}
17821
8bdb7029
YK
17822/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17823static inline int decode_gpr_gpr4_zero(int r)
17824{
17825 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17826 16, 17, 18, 19, 20, 21, 22, 23 };
17827
17828 return map[r & 0xf];
17829}
17830
6bfa9f4c 17831
bf0718c5
SM
17832static void gen_adjust_sp(DisasContext *ctx, int u)
17833{
17834 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17835}
17836
17837static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17838 uint8_t gp, uint16_t u)
17839{
17840 int counter = 0;
17841 TCGv va = tcg_temp_new();
17842 TCGv t0 = tcg_temp_new();
17843
17844 while (counter != count) {
17845 bool use_gp = gp && (counter == count - 1);
17846 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17847 int this_offset = -((counter + 1) << 2);
17848 gen_base_offset_addr(ctx, va, 29, this_offset);
17849 gen_load_gpr(t0, this_rt);
17850 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17851 (MO_TEUL | ctx->default_tcg_memop_mask));
17852 counter++;
17853 }
17854
17855 /* adjust stack pointer */
17856 gen_adjust_sp(ctx, -u);
17857
17858 tcg_temp_free(t0);
17859 tcg_temp_free(va);
17860}
17861
17862static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17863 uint8_t gp, uint16_t u)
17864{
17865 int counter = 0;
17866 TCGv va = tcg_temp_new();
17867 TCGv t0 = tcg_temp_new();
17868
17869 while (counter != count) {
17870 bool use_gp = gp && (counter == count - 1);
17871 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17872 int this_offset = u - ((counter + 1) << 2);
17873 gen_base_offset_addr(ctx, va, 29, this_offset);
17874 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17875 ctx->default_tcg_memop_mask);
17876 tcg_gen_ext32s_tl(t0, t0);
17877 gen_store_gpr(t0, this_rt);
17878 counter++;
17879 }
17880
17881 /* adjust stack pointer */
17882 gen_adjust_sp(ctx, u);
17883
17884 tcg_temp_free(t0);
17885 tcg_temp_free(va);
17886}
17887
80845edf
YK
17888static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17889{
99e49abf
AM
17890 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
17891 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
80845edf
YK
17892
17893 switch (extract32(ctx->opcode, 2, 2)) {
17894 case NM_NOT16:
17895 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17896 break;
17897 case NM_AND16:
17898 gen_logic(ctx, OPC_AND, rt, rt, rs);
17899 break;
17900 case NM_XOR16:
17901 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17902 break;
17903 case NM_OR16:
17904 gen_logic(ctx, OPC_OR, rt, rt, rs);
17905 break;
17906 }
17907}
17908
0a1a6ed7 17909static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
17910{
17911 int rt = extract32(ctx->opcode, 21, 5);
17912 int rs = extract32(ctx->opcode, 16, 5);
17913 int rd = extract32(ctx->opcode, 11, 5);
17914
17915 switch (extract32(ctx->opcode, 3, 7)) {
17916 case NM_P_TRAP:
17917 switch (extract32(ctx->opcode, 10, 1)) {
17918 case NM_TEQ:
fb32f8c8 17919 check_nms(ctx);
e0cf0e65
YK
17920 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17921 break;
17922 case NM_TNE:
fb32f8c8 17923 check_nms(ctx);
e0cf0e65
YK
17924 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17925 break;
17926 }
17927 break;
17928 case NM_RDHWR:
fb32f8c8 17929 check_nms(ctx);
e0cf0e65
YK
17930 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17931 break;
17932 case NM_SEB:
fb32f8c8 17933 check_nms(ctx);
e0cf0e65
YK
17934 gen_bshfl(ctx, OPC_SEB, rs, rt);
17935 break;
17936 case NM_SEH:
17937 gen_bshfl(ctx, OPC_SEH, rs, rt);
17938 break;
17939 case NM_SLLV:
17940 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17941 break;
17942 case NM_SRLV:
17943 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17944 break;
17945 case NM_SRAV:
17946 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17947 break;
17948 case NM_ROTRV:
17949 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17950 break;
17951 case NM_ADD:
17952 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17953 break;
17954 case NM_ADDU:
17955 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17956 break;
17957 case NM_SUB:
fb32f8c8 17958 check_nms(ctx);
e0cf0e65
YK
17959 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17960 break;
17961 case NM_SUBU:
17962 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17963 break;
17964 case NM_P_CMOVE:
17965 switch (extract32(ctx->opcode, 10, 1)) {
17966 case NM_MOVZ:
17967 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17968 break;
17969 case NM_MOVN:
17970 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17971 break;
17972 }
17973 break;
17974 case NM_AND:
17975 gen_logic(ctx, OPC_AND, rd, rs, rt);
17976 break;
17977 case NM_OR:
17978 gen_logic(ctx, OPC_OR, rd, rs, rt);
17979 break;
17980 case NM_NOR:
17981 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17982 break;
17983 case NM_XOR:
17984 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17985 break;
17986 case NM_SLT:
17987 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17988 break;
17989 case NM_P_SLTU:
17990 if (rd == 0) {
17991 /* P_DVP */
17992#ifndef CONFIG_USER_ONLY
17993 TCGv t0 = tcg_temp_new();
17994 switch (extract32(ctx->opcode, 10, 1)) {
17995 case NM_DVP:
17996 if (ctx->vp) {
17997 check_cp0_enabled(ctx);
17998 gen_helper_dvp(t0, cpu_env);
17999 gen_store_gpr(t0, rt);
18000 }
18001 break;
18002 case NM_EVP:
18003 if (ctx->vp) {
18004 check_cp0_enabled(ctx);
18005 gen_helper_evp(t0, cpu_env);
18006 gen_store_gpr(t0, rt);
18007 }
18008 break;
18009 }
18010 tcg_temp_free(t0);
18011#endif
18012 } else {
18013 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18014 }
18015 break;
18016 case NM_SOV:
18017 {
18018 TCGv t0 = tcg_temp_new();
18019 TCGv t1 = tcg_temp_new();
18020 TCGv t2 = tcg_temp_new();
18021
18022 gen_load_gpr(t1, rs);
18023 gen_load_gpr(t2, rt);
18024 tcg_gen_add_tl(t0, t1, t2);
18025 tcg_gen_ext32s_tl(t0, t0);
18026 tcg_gen_xor_tl(t1, t1, t2);
18027 tcg_gen_xor_tl(t2, t0, t2);
18028 tcg_gen_andc_tl(t1, t2, t1);
18029
18030 /* operands of same sign, result different sign */
18031 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18032 gen_store_gpr(t0, rd);
18033
18034 tcg_temp_free(t0);
18035 tcg_temp_free(t1);
18036 tcg_temp_free(t2);
18037 }
18038 break;
18039 case NM_MUL:
18040 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18041 break;
18042 case NM_MUH:
18043 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18044 break;
18045 case NM_MULU:
18046 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18047 break;
18048 case NM_MUHU:
18049 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18050 break;
18051 case NM_DIV:
18052 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18053 break;
18054 case NM_MOD:
18055 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18056 break;
18057 case NM_DIVU:
18058 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18059 break;
18060 case NM_MODU:
18061 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18062 break;
18063#ifndef CONFIG_USER_ONLY
18064 case NM_MFC0:
18065 check_cp0_enabled(ctx);
18066 if (rt == 0) {
18067 /* Treat as NOP. */
18068 break;
18069 }
18070 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18071 break;
18072 case NM_MTC0:
18073 check_cp0_enabled(ctx);
18074 {
18075 TCGv t0 = tcg_temp_new();
18076
18077 gen_load_gpr(t0, rt);
18078 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18079 tcg_temp_free(t0);
18080 }
18081 break;
0a1a6ed7
SM
18082 case NM_D_E_MT_VPE:
18083 {
18084 uint8_t sc = extract32(ctx->opcode, 10, 1);
18085 TCGv t0 = tcg_temp_new();
18086
18087 switch (sc) {
18088 case 0:
18089 if (rs == 1) {
18090 /* DMT */
18091 check_cp0_mt(ctx);
18092 gen_helper_dmt(t0);
18093 gen_store_gpr(t0, rt);
18094 } else if (rs == 0) {
18095 /* DVPE */
18096 check_cp0_mt(ctx);
18097 gen_helper_dvpe(t0, cpu_env);
18098 gen_store_gpr(t0, rt);
18099 } else {
3a4ef3b7 18100 gen_reserved_instruction(ctx);
0a1a6ed7
SM
18101 }
18102 break;
18103 case 1:
18104 if (rs == 1) {
18105 /* EMT */
18106 check_cp0_mt(ctx);
18107 gen_helper_emt(t0);
18108 gen_store_gpr(t0, rt);
18109 } else if (rs == 0) {
18110 /* EVPE */
18111 check_cp0_mt(ctx);
18112 gen_helper_evpe(t0, cpu_env);
18113 gen_store_gpr(t0, rt);
18114 } else {
3a4ef3b7 18115 gen_reserved_instruction(ctx);
0a1a6ed7
SM
18116 }
18117 break;
18118 }
18119
18120 tcg_temp_free(t0);
18121 }
18122 break;
18123 case NM_FORK:
18124 check_mt(ctx);
18125 {
18126 TCGv t0 = tcg_temp_new();
18127 TCGv t1 = tcg_temp_new();
18128
18129 gen_load_gpr(t0, rt);
18130 gen_load_gpr(t1, rs);
18131 gen_helper_fork(t0, t1);
18132 tcg_temp_free(t0);
18133 tcg_temp_free(t1);
18134 }
18135 break;
18136 case NM_MFTR:
18137 case NM_MFHTR:
18138 check_cp0_enabled(ctx);
18139 if (rd == 0) {
18140 /* Treat as NOP. */
18141 return;
18142 }
18143 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18144 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18145 break;
18146 case NM_MTTR:
18147 case NM_MTHTR:
18148 check_cp0_enabled(ctx);
18149 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18150 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18151 break;
18152 case NM_YIELD:
18153 check_mt(ctx);
18154 {
18155 TCGv t0 = tcg_temp_new();
18156
18157 gen_load_gpr(t0, rs);
18158 gen_helper_yield(t0, cpu_env, t0);
18159 gen_store_gpr(t0, rt);
18160 tcg_temp_free(t0);
18161 }
18162 break;
e0cf0e65
YK
18163#endif
18164 default:
3a4ef3b7 18165 gen_reserved_instruction(ctx);
e0cf0e65
YK
18166 break;
18167 }
18168}
18169
2ed42efa
SM
18170/* dsp */
18171static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18172 int ret, int v1, int v2)
18173{
18174 TCGv_i32 t0;
18175 TCGv v0_t;
18176 TCGv v1_t;
18177
18178 t0 = tcg_temp_new_i32();
18179
18180 v0_t = tcg_temp_new();
18181 v1_t = tcg_temp_new();
18182
18183 tcg_gen_movi_i32(t0, v2 >> 3);
18184
18185 gen_load_gpr(v0_t, ret);
18186 gen_load_gpr(v1_t, v1);
18187
18188 switch (opc) {
18189 case NM_MAQ_S_W_PHR:
18190 check_dsp(ctx);
18191 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18192 break;
18193 case NM_MAQ_S_W_PHL:
18194 check_dsp(ctx);
18195 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18196 break;
18197 case NM_MAQ_SA_W_PHR:
18198 check_dsp(ctx);
18199 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18200 break;
18201 case NM_MAQ_SA_W_PHL:
18202 check_dsp(ctx);
18203 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18204 break;
18205 default:
3a4ef3b7 18206 gen_reserved_instruction(ctx);
2ed42efa
SM
18207 break;
18208 }
18209
18210 tcg_temp_free_i32(t0);
18211
18212 tcg_temp_free(v0_t);
18213 tcg_temp_free(v1_t);
18214}
18215
18216
18217static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18218 int ret, int v1, int v2)
18219{
18220 int16_t imm;
18221 TCGv t0 = tcg_temp_new();
18222 TCGv t1 = tcg_temp_new();
18223 TCGv v0_t = tcg_temp_new();
18224
18225 gen_load_gpr(v0_t, v1);
18226
18227 switch (opc) {
18228 case NM_POOL32AXF_1_0:
18229 check_dsp(ctx);
18230 switch (extract32(ctx->opcode, 12, 2)) {
18231 case NM_MFHI:
18232 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18233 break;
18234 case NM_MFLO:
18235 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18236 break;
18237 case NM_MTHI:
18238 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18239 break;
18240 case NM_MTLO:
18241 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18242 break;
18243 }
18244 break;
18245 case NM_POOL32AXF_1_1:
18246 check_dsp(ctx);
18247 switch (extract32(ctx->opcode, 12, 2)) {
18248 case NM_MTHLIP:
18249 tcg_gen_movi_tl(t0, v2);
18250 gen_helper_mthlip(t0, v0_t, cpu_env);
18251 break;
18252 case NM_SHILOV:
18253 tcg_gen_movi_tl(t0, v2 >> 3);
18254 gen_helper_shilo(t0, v0_t, cpu_env);
18255 break;
18256 default:
3a4ef3b7 18257 gen_reserved_instruction(ctx);
2ed42efa
SM
18258 break;
18259 }
18260 break;
18261 case NM_POOL32AXF_1_3:
18262 check_dsp(ctx);
18263 imm = extract32(ctx->opcode, 14, 7);
18264 switch (extract32(ctx->opcode, 12, 2)) {
18265 case NM_RDDSP:
18266 tcg_gen_movi_tl(t0, imm);
18267 gen_helper_rddsp(t0, t0, cpu_env);
18268 gen_store_gpr(t0, ret);
18269 break;
18270 case NM_WRDSP:
18271 gen_load_gpr(t0, ret);
18272 tcg_gen_movi_tl(t1, imm);
18273 gen_helper_wrdsp(t0, t1, cpu_env);
18274 break;
18275 case NM_EXTP:
18276 tcg_gen_movi_tl(t0, v2 >> 3);
18277 tcg_gen_movi_tl(t1, v1);
18278 gen_helper_extp(t0, t0, t1, cpu_env);
18279 gen_store_gpr(t0, ret);
18280 break;
18281 case NM_EXTPDP:
18282 tcg_gen_movi_tl(t0, v2 >> 3);
18283 tcg_gen_movi_tl(t1, v1);
18284 gen_helper_extpdp(t0, t0, t1, cpu_env);
18285 gen_store_gpr(t0, ret);
18286 break;
18287 }
18288 break;
18289 case NM_POOL32AXF_1_4:
18290 check_dsp(ctx);
18291 tcg_gen_movi_tl(t0, v2 >> 2);
18292 switch (extract32(ctx->opcode, 12, 1)) {
18293 case NM_SHLL_QB:
18294 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18295 gen_store_gpr(t0, ret);
18296 break;
18297 case NM_SHRL_QB:
18298 gen_helper_shrl_qb(t0, t0, v0_t);
18299 gen_store_gpr(t0, ret);
18300 break;
18301 }
18302 break;
18303 case NM_POOL32AXF_1_5:
18304 opc = extract32(ctx->opcode, 12, 2);
18305 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18306 break;
18307 case NM_POOL32AXF_1_7:
18308 check_dsp(ctx);
18309 tcg_gen_movi_tl(t0, v2 >> 3);
18310 tcg_gen_movi_tl(t1, v1);
18311 switch (extract32(ctx->opcode, 12, 2)) {
18312 case NM_EXTR_W:
18313 gen_helper_extr_w(t0, t0, t1, cpu_env);
18314 gen_store_gpr(t0, ret);
18315 break;
18316 case NM_EXTR_R_W:
18317 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18318 gen_store_gpr(t0, ret);
18319 break;
18320 case NM_EXTR_RS_W:
18321 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18322 gen_store_gpr(t0, ret);
18323 break;
18324 case NM_EXTR_S_H:
18325 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18326 gen_store_gpr(t0, ret);
18327 break;
18328 }
18329 break;
18330 default:
3a4ef3b7 18331 gen_reserved_instruction(ctx);
2ed42efa
SM
18332 break;
18333 }
18334
18335 tcg_temp_free(t0);
18336 tcg_temp_free(t1);
18337 tcg_temp_free(v0_t);
18338}
18339
8b3698b2
SM
18340static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18341 TCGv v0, TCGv v1, int rd)
18342{
18343 TCGv_i32 t0;
18344
18345 t0 = tcg_temp_new_i32();
18346
18347 tcg_gen_movi_i32(t0, rd >> 3);
18348
18349 switch (opc) {
18350 case NM_POOL32AXF_2_0_7:
18351 switch (extract32(ctx->opcode, 9, 3)) {
18352 case NM_DPA_W_PH:
908f6be1 18353 check_dsp_r2(ctx);
8b3698b2
SM
18354 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18355 break;
18356 case NM_DPAQ_S_W_PH:
18357 check_dsp(ctx);
18358 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18359 break;
18360 case NM_DPS_W_PH:
908f6be1 18361 check_dsp_r2(ctx);
8b3698b2
SM
18362 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18363 break;
18364 case NM_DPSQ_S_W_PH:
18365 check_dsp(ctx);
18366 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18367 break;
18368 default:
3a4ef3b7 18369 gen_reserved_instruction(ctx);
8b3698b2
SM
18370 break;
18371 }
18372 break;
18373 case NM_POOL32AXF_2_8_15:
18374 switch (extract32(ctx->opcode, 9, 3)) {
18375 case NM_DPAX_W_PH:
908f6be1 18376 check_dsp_r2(ctx);
8b3698b2
SM
18377 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18378 break;
18379 case NM_DPAQ_SA_L_W:
18380 check_dsp(ctx);
18381 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18382 break;
18383 case NM_DPSX_W_PH:
908f6be1 18384 check_dsp_r2(ctx);
8b3698b2
SM
18385 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18386 break;
18387 case NM_DPSQ_SA_L_W:
18388 check_dsp(ctx);
18389 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18390 break;
18391 default:
3a4ef3b7 18392 gen_reserved_instruction(ctx);
8b3698b2
SM
18393 break;
18394 }
18395 break;
18396 case NM_POOL32AXF_2_16_23:
18397 switch (extract32(ctx->opcode, 9, 3)) {
18398 case NM_DPAU_H_QBL:
18399 check_dsp(ctx);
18400 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18401 break;
18402 case NM_DPAQX_S_W_PH:
908f6be1 18403 check_dsp_r2(ctx);
8b3698b2
SM
18404 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18405 break;
18406 case NM_DPSU_H_QBL:
18407 check_dsp(ctx);
18408 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18409 break;
18410 case NM_DPSQX_S_W_PH:
908f6be1 18411 check_dsp_r2(ctx);
8b3698b2
SM
18412 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18413 break;
18414 case NM_MULSA_W_PH:
908f6be1 18415 check_dsp_r2(ctx);
8b3698b2
SM
18416 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18417 break;
18418 default:
3a4ef3b7 18419 gen_reserved_instruction(ctx);
8b3698b2
SM
18420 break;
18421 }
18422 break;
18423 case NM_POOL32AXF_2_24_31:
18424 switch (extract32(ctx->opcode, 9, 3)) {
18425 case NM_DPAU_H_QBR:
18426 check_dsp(ctx);
18427 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18428 break;
18429 case NM_DPAQX_SA_W_PH:
908f6be1 18430 check_dsp_r2(ctx);
8b3698b2
SM
18431 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18432 break;
18433 case NM_DPSU_H_QBR:
18434 check_dsp(ctx);
18435 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18436 break;
18437 case NM_DPSQX_SA_W_PH:
908f6be1 18438 check_dsp_r2(ctx);
8b3698b2
SM
18439 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18440 break;
18441 case NM_MULSAQ_S_W_PH:
18442 check_dsp(ctx);
18443 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18444 break;
18445 default:
3a4ef3b7 18446 gen_reserved_instruction(ctx);
8b3698b2
SM
18447 break;
18448 }
18449 break;
18450 default:
3a4ef3b7 18451 gen_reserved_instruction(ctx);
8b3698b2
SM
18452 break;
18453 }
18454
18455 tcg_temp_free_i32(t0);
18456}
18457
18458static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18459 int rt, int rs, int rd)
18460{
18461 int ret = rt;
18462 TCGv t0 = tcg_temp_new();
18463 TCGv t1 = tcg_temp_new();
18464 TCGv v0_t = tcg_temp_new();
18465 TCGv v1_t = tcg_temp_new();
18466
18467 gen_load_gpr(v0_t, rt);
18468 gen_load_gpr(v1_t, rs);
18469
18470 switch (opc) {
18471 case NM_POOL32AXF_2_0_7:
18472 switch (extract32(ctx->opcode, 9, 3)) {
18473 case NM_DPA_W_PH:
18474 case NM_DPAQ_S_W_PH:
18475 case NM_DPS_W_PH:
18476 case NM_DPSQ_S_W_PH:
18477 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18478 break;
18479 case NM_BALIGN:
908f6be1 18480 check_dsp_r2(ctx);
8b3698b2
SM
18481 if (rt != 0) {
18482 gen_load_gpr(t0, rs);
18483 rd &= 3;
18484 if (rd != 0 && rd != 2) {
18485 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18486 tcg_gen_ext32u_tl(t0, t0);
18487 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18488 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18489 }
18490 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18491 }
18492 break;
18493 case NM_MADD:
18494 check_dsp(ctx);
18495 {
18496 int acc = extract32(ctx->opcode, 14, 2);
18497 TCGv_i64 t2 = tcg_temp_new_i64();
18498 TCGv_i64 t3 = tcg_temp_new_i64();
18499
18500 gen_load_gpr(t0, rt);
18501 gen_load_gpr(t1, rs);
18502 tcg_gen_ext_tl_i64(t2, t0);
18503 tcg_gen_ext_tl_i64(t3, t1);
18504 tcg_gen_mul_i64(t2, t2, t3);
18505 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18506 tcg_gen_add_i64(t2, t2, t3);
18507 tcg_temp_free_i64(t3);
18508 gen_move_low32(cpu_LO[acc], t2);
18509 gen_move_high32(cpu_HI[acc], t2);
18510 tcg_temp_free_i64(t2);
18511 }
18512 break;
18513 case NM_MULT:
18514 check_dsp(ctx);
18515 {
18516 int acc = extract32(ctx->opcode, 14, 2);
18517 TCGv_i32 t2 = tcg_temp_new_i32();
18518 TCGv_i32 t3 = tcg_temp_new_i32();
18519
18520 gen_load_gpr(t0, rs);
18521 gen_load_gpr(t1, rt);
18522 tcg_gen_trunc_tl_i32(t2, t0);
18523 tcg_gen_trunc_tl_i32(t3, t1);
18524 tcg_gen_muls2_i32(t2, t3, t2, t3);
18525 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18526 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18527 tcg_temp_free_i32(t2);
18528 tcg_temp_free_i32(t3);
18529 }
18530 break;
18531 case NM_EXTRV_W:
18532 check_dsp(ctx);
18533 gen_load_gpr(v1_t, rs);
18534 tcg_gen_movi_tl(t0, rd >> 3);
18535 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18536 gen_store_gpr(t0, ret);
18537 break;
18538 }
18539 break;
18540 case NM_POOL32AXF_2_8_15:
18541 switch (extract32(ctx->opcode, 9, 3)) {
18542 case NM_DPAX_W_PH:
18543 case NM_DPAQ_SA_L_W:
18544 case NM_DPSX_W_PH:
18545 case NM_DPSQ_SA_L_W:
18546 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18547 break;
18548 case NM_MADDU:
18549 check_dsp(ctx);
18550 {
18551 int acc = extract32(ctx->opcode, 14, 2);
18552 TCGv_i64 t2 = tcg_temp_new_i64();
18553 TCGv_i64 t3 = tcg_temp_new_i64();
18554
18555 gen_load_gpr(t0, rs);
18556 gen_load_gpr(t1, rt);
18557 tcg_gen_ext32u_tl(t0, t0);
18558 tcg_gen_ext32u_tl(t1, t1);
18559 tcg_gen_extu_tl_i64(t2, t0);
18560 tcg_gen_extu_tl_i64(t3, t1);
18561 tcg_gen_mul_i64(t2, t2, t3);
18562 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18563 tcg_gen_add_i64(t2, t2, t3);
18564 tcg_temp_free_i64(t3);
18565 gen_move_low32(cpu_LO[acc], t2);
18566 gen_move_high32(cpu_HI[acc], t2);
18567 tcg_temp_free_i64(t2);
18568 }
18569 break;
18570 case NM_MULTU:
18571 check_dsp(ctx);
18572 {
18573 int acc = extract32(ctx->opcode, 14, 2);
18574 TCGv_i32 t2 = tcg_temp_new_i32();
18575 TCGv_i32 t3 = tcg_temp_new_i32();
18576
18577 gen_load_gpr(t0, rs);
18578 gen_load_gpr(t1, rt);
18579 tcg_gen_trunc_tl_i32(t2, t0);
18580 tcg_gen_trunc_tl_i32(t3, t1);
18581 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18582 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18583 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18584 tcg_temp_free_i32(t2);
18585 tcg_temp_free_i32(t3);
18586 }
18587 break;
18588 case NM_EXTRV_R_W:
18589 check_dsp(ctx);
18590 tcg_gen_movi_tl(t0, rd >> 3);
18591 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18592 gen_store_gpr(t0, ret);
18593 break;
18594 default:
3a4ef3b7 18595 gen_reserved_instruction(ctx);
8b3698b2
SM
18596 break;
18597 }
18598 break;
18599 case NM_POOL32AXF_2_16_23:
18600 switch (extract32(ctx->opcode, 9, 3)) {
18601 case NM_DPAU_H_QBL:
18602 case NM_DPAQX_S_W_PH:
18603 case NM_DPSU_H_QBL:
18604 case NM_DPSQX_S_W_PH:
18605 case NM_MULSA_W_PH:
18606 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18607 break;
18608 case NM_EXTPV:
18609 check_dsp(ctx);
18610 tcg_gen_movi_tl(t0, rd >> 3);
18611 gen_helper_extp(t0, t0, v1_t, cpu_env);
18612 gen_store_gpr(t0, ret);
18613 break;
18614 case NM_MSUB:
18615 check_dsp(ctx);
18616 {
18617 int acc = extract32(ctx->opcode, 14, 2);
18618 TCGv_i64 t2 = tcg_temp_new_i64();
18619 TCGv_i64 t3 = tcg_temp_new_i64();
18620
18621 gen_load_gpr(t0, rs);
18622 gen_load_gpr(t1, rt);
18623 tcg_gen_ext_tl_i64(t2, t0);
18624 tcg_gen_ext_tl_i64(t3, t1);
18625 tcg_gen_mul_i64(t2, t2, t3);
18626 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18627 tcg_gen_sub_i64(t2, t3, t2);
18628 tcg_temp_free_i64(t3);
18629 gen_move_low32(cpu_LO[acc], t2);
18630 gen_move_high32(cpu_HI[acc], t2);
18631 tcg_temp_free_i64(t2);
18632 }
18633 break;
18634 case NM_EXTRV_RS_W:
18635 check_dsp(ctx);
18636 tcg_gen_movi_tl(t0, rd >> 3);
18637 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18638 gen_store_gpr(t0, ret);
18639 break;
18640 }
18641 break;
18642 case NM_POOL32AXF_2_24_31:
18643 switch (extract32(ctx->opcode, 9, 3)) {
18644 case NM_DPAU_H_QBR:
18645 case NM_DPAQX_SA_W_PH:
18646 case NM_DPSU_H_QBR:
18647 case NM_DPSQX_SA_W_PH:
18648 case NM_MULSAQ_S_W_PH:
18649 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18650 break;
18651 case NM_EXTPDPV:
18652 check_dsp(ctx);
18653 tcg_gen_movi_tl(t0, rd >> 3);
18654 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18655 gen_store_gpr(t0, ret);
18656 break;
18657 case NM_MSUBU:
18658 check_dsp(ctx);
18659 {
18660 int acc = extract32(ctx->opcode, 14, 2);
18661 TCGv_i64 t2 = tcg_temp_new_i64();
18662 TCGv_i64 t3 = tcg_temp_new_i64();
18663
18664 gen_load_gpr(t0, rs);
18665 gen_load_gpr(t1, rt);
18666 tcg_gen_ext32u_tl(t0, t0);
18667 tcg_gen_ext32u_tl(t1, t1);
18668 tcg_gen_extu_tl_i64(t2, t0);
18669 tcg_gen_extu_tl_i64(t3, t1);
18670 tcg_gen_mul_i64(t2, t2, t3);
18671 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18672 tcg_gen_sub_i64(t2, t3, t2);
18673 tcg_temp_free_i64(t3);
18674 gen_move_low32(cpu_LO[acc], t2);
18675 gen_move_high32(cpu_HI[acc], t2);
18676 tcg_temp_free_i64(t2);
18677 }
18678 break;
18679 case NM_EXTRV_S_H:
18680 check_dsp(ctx);
18681 tcg_gen_movi_tl(t0, rd >> 3);
18682 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18683 gen_store_gpr(t0, ret);
18684 break;
18685 }
18686 break;
18687 default:
3a4ef3b7 18688 gen_reserved_instruction(ctx);
8b3698b2
SM
18689 break;
18690 }
18691
18692 tcg_temp_free(t0);
18693 tcg_temp_free(t1);
18694
18695 tcg_temp_free(v0_t);
18696 tcg_temp_free(v1_t);
18697}
18698
4c75c985
SM
18699static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18700 int rt, int rs)
18701{
18702 int ret = rt;
18703 TCGv t0 = tcg_temp_new();
18704 TCGv v0_t = tcg_temp_new();
18705
18706 gen_load_gpr(v0_t, rs);
18707
18708 switch (opc) {
18709 case NM_ABSQ_S_QB:
908f6be1 18710 check_dsp_r2(ctx);
4c75c985
SM
18711 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18712 gen_store_gpr(v0_t, ret);
18713 break;
18714 case NM_ABSQ_S_PH:
18715 check_dsp(ctx);
18716 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18717 gen_store_gpr(v0_t, ret);
18718 break;
18719 case NM_ABSQ_S_W:
18720 check_dsp(ctx);
18721 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18722 gen_store_gpr(v0_t, ret);
18723 break;
18724 case NM_PRECEQ_W_PHL:
18725 check_dsp(ctx);
18726 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18727 tcg_gen_ext32s_tl(v0_t, v0_t);
18728 gen_store_gpr(v0_t, ret);
18729 break;
18730 case NM_PRECEQ_W_PHR:
18731 check_dsp(ctx);
18732 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18733 tcg_gen_shli_tl(v0_t, v0_t, 16);
18734 tcg_gen_ext32s_tl(v0_t, v0_t);
18735 gen_store_gpr(v0_t, ret);
18736 break;
18737 case NM_PRECEQU_PH_QBL:
18738 check_dsp(ctx);
18739 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18740 gen_store_gpr(v0_t, ret);
18741 break;
18742 case NM_PRECEQU_PH_QBR:
18743 check_dsp(ctx);
18744 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18745 gen_store_gpr(v0_t, ret);
18746 break;
18747 case NM_PRECEQU_PH_QBLA:
18748 check_dsp(ctx);
18749 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18750 gen_store_gpr(v0_t, ret);
18751 break;
18752 case NM_PRECEQU_PH_QBRA:
18753 check_dsp(ctx);
18754 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18755 gen_store_gpr(v0_t, ret);
18756 break;
18757 case NM_PRECEU_PH_QBL:
18758 check_dsp(ctx);
18759 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18760 gen_store_gpr(v0_t, ret);
18761 break;
18762 case NM_PRECEU_PH_QBR:
18763 check_dsp(ctx);
18764 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18765 gen_store_gpr(v0_t, ret);
18766 break;
18767 case NM_PRECEU_PH_QBLA:
18768 check_dsp(ctx);
18769 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18770 gen_store_gpr(v0_t, ret);
18771 break;
18772 case NM_PRECEU_PH_QBRA:
18773 check_dsp(ctx);
18774 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18775 gen_store_gpr(v0_t, ret);
18776 break;
18777 case NM_REPLV_PH:
18778 check_dsp(ctx);
18779 tcg_gen_ext16u_tl(v0_t, v0_t);
18780 tcg_gen_shli_tl(t0, v0_t, 16);
18781 tcg_gen_or_tl(v0_t, v0_t, t0);
18782 tcg_gen_ext32s_tl(v0_t, v0_t);
18783 gen_store_gpr(v0_t, ret);
18784 break;
18785 case NM_REPLV_QB:
18786 check_dsp(ctx);
18787 tcg_gen_ext8u_tl(v0_t, v0_t);
18788 tcg_gen_shli_tl(t0, v0_t, 8);
18789 tcg_gen_or_tl(v0_t, v0_t, t0);
18790 tcg_gen_shli_tl(t0, v0_t, 16);
18791 tcg_gen_or_tl(v0_t, v0_t, t0);
18792 tcg_gen_ext32s_tl(v0_t, v0_t);
18793 gen_store_gpr(v0_t, ret);
18794 break;
18795 case NM_BITREV:
18796 check_dsp(ctx);
18797 gen_helper_bitrev(v0_t, v0_t);
18798 gen_store_gpr(v0_t, ret);
18799 break;
18800 case NM_INSV:
18801 check_dsp(ctx);
18802 {
18803 TCGv tv0 = tcg_temp_new();
18804
18805 gen_load_gpr(tv0, rt);
18806 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18807 gen_store_gpr(v0_t, ret);
18808 tcg_temp_free(tv0);
18809 }
18810 break;
18811 case NM_RADDU_W_QB:
18812 check_dsp(ctx);
18813 gen_helper_raddu_w_qb(v0_t, v0_t);
18814 gen_store_gpr(v0_t, ret);
18815 break;
18816 case NM_BITSWAP:
18817 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18818 break;
18819 case NM_CLO:
fb32f8c8 18820 check_nms(ctx);
4c75c985
SM
18821 gen_cl(ctx, OPC_CLO, ret, rs);
18822 break;
18823 case NM_CLZ:
fb32f8c8 18824 check_nms(ctx);
4c75c985
SM
18825 gen_cl(ctx, OPC_CLZ, ret, rs);
18826 break;
18827 case NM_WSBH:
18828 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18829 break;
18830 default:
3a4ef3b7 18831 gen_reserved_instruction(ctx);
4c75c985
SM
18832 break;
18833 }
18834
18835 tcg_temp_free(v0_t);
18836 tcg_temp_free(t0);
18837}
18838
0b591184
SM
18839static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18840 int rt, int rs, int rd)
18841{
18842 TCGv t0 = tcg_temp_new();
18843 TCGv rs_t = tcg_temp_new();
18844
18845 gen_load_gpr(rs_t, rs);
18846
18847 switch (opc) {
18848 case NM_SHRA_R_QB:
908f6be1 18849 check_dsp_r2(ctx);
0b591184
SM
18850 tcg_gen_movi_tl(t0, rd >> 2);
18851 switch (extract32(ctx->opcode, 12, 1)) {
18852 case 0:
18853 /* NM_SHRA_QB */
18854 gen_helper_shra_qb(t0, t0, rs_t);
18855 gen_store_gpr(t0, rt);
18856 break;
18857 case 1:
18858 /* NM_SHRA_R_QB */
18859 gen_helper_shra_r_qb(t0, t0, rs_t);
18860 gen_store_gpr(t0, rt);
18861 break;
18862 }
18863 break;
18864 case NM_SHRL_PH:
908f6be1 18865 check_dsp_r2(ctx);
0b591184
SM
18866 tcg_gen_movi_tl(t0, rd >> 1);
18867 gen_helper_shrl_ph(t0, t0, rs_t);
18868 gen_store_gpr(t0, rt);
18869 break;
18870 case NM_REPL_QB:
18871 check_dsp(ctx);
18872 {
18873 int16_t imm;
18874 target_long result;
18875 imm = extract32(ctx->opcode, 13, 8);
18876 result = (uint32_t)imm << 24 |
18877 (uint32_t)imm << 16 |
18878 (uint32_t)imm << 8 |
18879 (uint32_t)imm;
18880 result = (int32_t)result;
18881 tcg_gen_movi_tl(t0, result);
18882 gen_store_gpr(t0, rt);
18883 }
18884 break;
18885 default:
3a4ef3b7 18886 gen_reserved_instruction(ctx);
0b591184
SM
18887 break;
18888 }
18889 tcg_temp_free(t0);
18890 tcg_temp_free(rs_t);
18891}
18892
2ed42efa 18893
64224187
YK
18894static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18895{
64224187
YK
18896 int rt = extract32(ctx->opcode, 21, 5);
18897 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 18898 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
18899
18900 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
18901 case NM_POOL32AXF_1:
18902 {
18903 int32_t op1 = extract32(ctx->opcode, 9, 3);
18904 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18905 }
18906 break;
18907 case NM_POOL32AXF_2:
8b3698b2
SM
18908 {
18909 int32_t op1 = extract32(ctx->opcode, 12, 2);
18910 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18911 }
2ed42efa 18912 break;
64224187 18913 case NM_POOL32AXF_4:
4c75c985
SM
18914 {
18915 int32_t op1 = extract32(ctx->opcode, 9, 7);
18916 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18917 }
2ed42efa 18918 break;
64224187
YK
18919 case NM_POOL32AXF_5:
18920 switch (extract32(ctx->opcode, 9, 7)) {
18921#ifndef CONFIG_USER_ONLY
18922 case NM_TLBP:
18923 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18924 break;
18925 case NM_TLBR:
18926 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18927 break;
18928 case NM_TLBWI:
18929 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18930 break;
18931 case NM_TLBWR:
18932 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18933 break;
18934 case NM_TLBINV:
18935 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18936 break;
18937 case NM_TLBINVF:
18938 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18939 break;
18940 case NM_DI:
18941 check_cp0_enabled(ctx);
18942 {
18943 TCGv t0 = tcg_temp_new();
18944
18945 save_cpu_state(ctx, 1);
18946 gen_helper_di(t0, cpu_env);
18947 gen_store_gpr(t0, rt);
18948 /* Stop translation as we may have switched the execution mode */
18949 ctx->base.is_jmp = DISAS_STOP;
18950 tcg_temp_free(t0);
18951 }
18952 break;
18953 case NM_EI:
18954 check_cp0_enabled(ctx);
18955 {
18956 TCGv t0 = tcg_temp_new();
18957
18958 save_cpu_state(ctx, 1);
18959 gen_helper_ei(t0, cpu_env);
18960 gen_store_gpr(t0, rt);
18961 /* Stop translation as we may have switched the execution mode */
18962 ctx->base.is_jmp = DISAS_STOP;
18963 tcg_temp_free(t0);
18964 }
18965 break;
18966 case NM_RDPGPR:
298d43c9 18967 check_cp0_enabled(ctx);
64224187
YK
18968 gen_load_srsgpr(rs, rt);
18969 break;
18970 case NM_WRPGPR:
298d43c9 18971 check_cp0_enabled(ctx);
64224187
YK
18972 gen_store_srsgpr(rs, rt);
18973 break;
18974 case NM_WAIT:
18975 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18976 break;
18977 case NM_DERET:
18978 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18979 break;
18980 case NM_ERETX:
18981 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18982 break;
18983#endif
18984 default:
3a4ef3b7 18985 gen_reserved_instruction(ctx);
64224187
YK
18986 break;
18987 }
18988 break;
2ed42efa 18989 case NM_POOL32AXF_7:
0b591184
SM
18990 {
18991 int32_t op1 = extract32(ctx->opcode, 9, 3);
18992 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18993 }
2ed42efa 18994 break;
64224187 18995 default:
3a4ef3b7 18996 gen_reserved_instruction(ctx);
64224187
YK
18997 break;
18998 }
18999}
19000
11d0fc10
SM
19001/* Immediate Value Compact Branches */
19002static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19003 int rt, int32_t imm, int32_t offset)
19004{
10266143 19005 TCGCond cond = TCG_COND_ALWAYS;
11d0fc10
SM
19006 TCGv t0 = tcg_temp_new();
19007 TCGv t1 = tcg_temp_new();
19008
19009 gen_load_gpr(t0, rt);
19010 tcg_gen_movi_tl(t1, imm);
19011 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19012
19013 /* Load needed operands and calculate btarget */
19014 switch (opc) {
19015 case NM_BEQIC:
19016 if (rt == 0 && imm == 0) {
19017 /* Unconditional branch */
19018 } else if (rt == 0 && imm != 0) {
19019 /* Treat as NOP */
19020 goto out;
19021 } else {
11d0fc10
SM
19022 cond = TCG_COND_EQ;
19023 }
19024 break;
19025 case NM_BBEQZC:
19026 case NM_BBNEZC:
fb32f8c8 19027 check_nms(ctx);
11d0fc10 19028 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
3a4ef3b7 19029 gen_reserved_instruction(ctx);
11d0fc10
SM
19030 goto out;
19031 } else if (rt == 0 && opc == NM_BBEQZC) {
19032 /* Unconditional branch */
19033 } else if (rt == 0 && opc == NM_BBNEZC) {
19034 /* Treat as NOP */
19035 goto out;
19036 } else {
19037 tcg_gen_shri_tl(t0, t0, imm);
19038 tcg_gen_andi_tl(t0, t0, 1);
19039 tcg_gen_movi_tl(t1, 0);
11d0fc10
SM
19040 if (opc == NM_BBEQZC) {
19041 cond = TCG_COND_EQ;
19042 } else {
19043 cond = TCG_COND_NE;
19044 }
19045 }
19046 break;
19047 case NM_BNEIC:
19048 if (rt == 0 && imm == 0) {
19049 /* Treat as NOP */
19050 goto out;
19051 } else if (rt == 0 && imm != 0) {
19052 /* Unconditional branch */
19053 } else {
11d0fc10
SM
19054 cond = TCG_COND_NE;
19055 }
19056 break;
19057 case NM_BGEIC:
19058 if (rt == 0 && imm == 0) {
19059 /* Unconditional branch */
19060 } else {
11d0fc10
SM
19061 cond = TCG_COND_GE;
19062 }
19063 break;
19064 case NM_BLTIC:
11d0fc10
SM
19065 cond = TCG_COND_LT;
19066 break;
19067 case NM_BGEIUC:
19068 if (rt == 0 && imm == 0) {
19069 /* Unconditional branch */
19070 } else {
11d0fc10
SM
19071 cond = TCG_COND_GEU;
19072 }
19073 break;
19074 case NM_BLTIUC:
11d0fc10
SM
19075 cond = TCG_COND_LTU;
19076 break;
19077 default:
19078 MIPS_INVAL("Immediate Value Compact branch");
3a4ef3b7 19079 gen_reserved_instruction(ctx);
11d0fc10
SM
19080 goto out;
19081 }
19082
697b7b6b
SM
19083 /* branch completion */
19084 clear_branch_hflags(ctx);
19085 ctx->base.is_jmp = DISAS_NORETURN;
19086
10266143 19087 if (cond == TCG_COND_ALWAYS) {
63978560 19088 /* Unconditional compact branch */
11d0fc10
SM
19089 gen_goto_tb(ctx, 0, ctx->btarget);
19090 } else {
19091 /* Conditional compact branch */
19092 TCGLabel *fs = gen_new_label();
19093
19094 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19095
19096 gen_goto_tb(ctx, 1, ctx->btarget);
19097 gen_set_label(fs);
19098
19099 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19100 }
19101
19102out:
19103 tcg_temp_free(t0);
19104 tcg_temp_free(t1);
19105}
19106
19107/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19108static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19109 int rt)
19110{
19111 TCGv t0 = tcg_temp_new();
19112 TCGv t1 = tcg_temp_new();
19113
19114 /* load rs */
19115 gen_load_gpr(t0, rs);
19116
19117 /* link */
19118 if (rt != 0) {
19119 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19120 }
19121
19122 /* calculate btarget */
19123 tcg_gen_shli_tl(t0, t0, 1);
19124 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19125 gen_op_addr_add(ctx, btarget, t1, t0);
19126
697b7b6b
SM
19127 /* branch completion */
19128 clear_branch_hflags(ctx);
19129 ctx->base.is_jmp = DISAS_NORETURN;
19130
11d0fc10
SM
19131 /* unconditional branch to register */
19132 tcg_gen_mov_tl(cpu_PC, btarget);
19133 tcg_gen_lookup_and_goto_ptr();
19134
19135 tcg_temp_free(t0);
19136 tcg_temp_free(t1);
19137}
19138
19139/* nanoMIPS Branches */
19140static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19141 int rs, int rt, int32_t offset)
19142{
19143 int bcond_compute = 0;
19144 TCGv t0 = tcg_temp_new();
19145 TCGv t1 = tcg_temp_new();
19146
19147 /* Load needed operands and calculate btarget */
19148 switch (opc) {
19149 /* compact branch */
19150 case OPC_BGEC:
19151 case OPC_BLTC:
19152 gen_load_gpr(t0, rs);
19153 gen_load_gpr(t1, rt);
19154 bcond_compute = 1;
19155 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19156 break;
19157 case OPC_BGEUC:
19158 case OPC_BLTUC:
19159 if (rs == 0 || rs == rt) {
19160 /* OPC_BLEZALC, OPC_BGEZALC */
19161 /* OPC_BGTZALC, OPC_BLTZALC */
19162 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19163 }
19164 gen_load_gpr(t0, rs);
19165 gen_load_gpr(t1, rt);
19166 bcond_compute = 1;
19167 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19168 break;
19169 case OPC_BC:
19170 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19171 break;
19172 case OPC_BEQZC:
19173 if (rs != 0) {
19174 /* OPC_BEQZC, OPC_BNEZC */
19175 gen_load_gpr(t0, rs);
19176 bcond_compute = 1;
19177 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19178 } else {
19179 /* OPC_JIC, OPC_JIALC */
19180 TCGv tbase = tcg_temp_new();
19181 TCGv toffset = tcg_temp_new();
19182
19183 gen_load_gpr(tbase, rt);
19184 tcg_gen_movi_tl(toffset, offset);
19185 gen_op_addr_add(ctx, btarget, tbase, toffset);
19186 tcg_temp_free(tbase);
19187 tcg_temp_free(toffset);
19188 }
19189 break;
19190 default:
19191 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 19192 gen_reserved_instruction(ctx);
11d0fc10
SM
19193 goto out;
19194 }
19195
19196 if (bcond_compute == 0) {
63978560 19197 /* Unconditional compact branch */
11d0fc10
SM
19198 switch (opc) {
19199 case OPC_BC:
19200 gen_goto_tb(ctx, 0, ctx->btarget);
19201 break;
19202 default:
19203 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 19204 gen_reserved_instruction(ctx);
11d0fc10
SM
19205 goto out;
19206 }
19207 } else {
19208 /* Conditional compact branch */
19209 TCGLabel *fs = gen_new_label();
19210
19211 switch (opc) {
19212 case OPC_BGEUC:
19213 if (rs == 0 && rt != 0) {
19214 /* OPC_BLEZALC */
19215 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19216 } else if (rs != 0 && rt != 0 && rs == rt) {
19217 /* OPC_BGEZALC */
19218 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19219 } else {
19220 /* OPC_BGEUC */
19221 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19222 }
19223 break;
19224 case OPC_BLTUC:
19225 if (rs == 0 && rt != 0) {
19226 /* OPC_BGTZALC */
19227 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19228 } else if (rs != 0 && rt != 0 && rs == rt) {
19229 /* OPC_BLTZALC */
19230 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19231 } else {
19232 /* OPC_BLTUC */
19233 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19234 }
19235 break;
19236 case OPC_BGEC:
19237 if (rs == 0 && rt != 0) {
19238 /* OPC_BLEZC */
19239 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19240 } else if (rs != 0 && rt != 0 && rs == rt) {
19241 /* OPC_BGEZC */
19242 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19243 } else {
19244 /* OPC_BGEC */
19245 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19246 }
19247 break;
19248 case OPC_BLTC:
19249 if (rs == 0 && rt != 0) {
19250 /* OPC_BGTZC */
19251 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19252 } else if (rs != 0 && rt != 0 && rs == rt) {
19253 /* OPC_BLTZC */
19254 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19255 } else {
19256 /* OPC_BLTC */
19257 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19258 }
19259 break;
19260 case OPC_BEQZC:
19261 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19262 break;
19263 default:
19264 MIPS_INVAL("Compact conditional branch/jump");
3a4ef3b7 19265 gen_reserved_instruction(ctx);
11d0fc10
SM
19266 goto out;
19267 }
19268
697b7b6b
SM
19269 /* branch completion */
19270 clear_branch_hflags(ctx);
19271 ctx->base.is_jmp = DISAS_NORETURN;
19272
11d0fc10
SM
19273 /* Generating branch here as compact branches don't have delay slot */
19274 gen_goto_tb(ctx, 1, ctx->btarget);
19275 gen_set_label(fs);
19276
19277 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19278 }
19279
19280out:
19281 tcg_temp_free(t0);
19282 tcg_temp_free(t1);
19283}
19284
19285
19286/* nanoMIPS CP1 Branches */
19287static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19288 int32_t ft, int32_t offset)
19289{
19290 target_ulong btarget;
19291 TCGv_i64 t0 = tcg_temp_new_i64();
19292
19293 gen_load_fpr64(ctx, t0, ft);
19294 tcg_gen_andi_i64(t0, t0, 1);
19295
19296 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19297
19298 switch (op) {
19299 case NM_BC1EQZC:
19300 tcg_gen_xori_i64(t0, t0, 1);
19301 ctx->hflags |= MIPS_HFLAG_BC;
19302 break;
19303 case NM_BC1NEZC:
19304 /* t0 already set */
19305 ctx->hflags |= MIPS_HFLAG_BC;
19306 break;
19307 default:
19308 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 19309 gen_reserved_instruction(ctx);
11d0fc10
SM
19310 goto out;
19311 }
19312
19313 tcg_gen_trunc_i64_tl(bcond, t0);
19314
19315 ctx->btarget = btarget;
19316
19317out:
19318 tcg_temp_free_i64(t0);
19319}
19320
eac52664
YK
19321
19322static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19323{
19324 TCGv t0, t1;
19325 t0 = tcg_temp_new();
19326 t1 = tcg_temp_new();
19327
19328 gen_load_gpr(t0, rs);
19329 gen_load_gpr(t1, rt);
19330
19331 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19332 /* PP.LSXS instructions require shifting */
19333 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 19334 case NM_SHXS:
fb32f8c8 19335 check_nms(ctx);
45152d05 19336 /* fall through */
fb32f8c8 19337 case NM_LHXS:
eac52664
YK
19338 case NM_LHUXS:
19339 tcg_gen_shli_tl(t0, t0, 1);
19340 break;
eac52664 19341 case NM_SWXS:
fb32f8c8 19342 check_nms(ctx);
45152d05 19343 /* fall through */
fb32f8c8 19344 case NM_LWXS:
eac52664
YK
19345 case NM_LWC1XS:
19346 case NM_SWC1XS:
19347 tcg_gen_shli_tl(t0, t0, 2);
19348 break;
19349 case NM_LDC1XS:
19350 case NM_SDC1XS:
19351 tcg_gen_shli_tl(t0, t0, 3);
19352 break;
19353 }
19354 }
19355 gen_op_addr_add(ctx, t0, t0, t1);
19356
19357 switch (extract32(ctx->opcode, 7, 4)) {
19358 case NM_LBX:
19359 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19360 MO_SB);
19361 gen_store_gpr(t0, rd);
19362 break;
19363 case NM_LHX:
19364 /*case NM_LHXS:*/
19365 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19366 MO_TESW);
19367 gen_store_gpr(t0, rd);
19368 break;
19369 case NM_LWX:
19370 /*case NM_LWXS:*/
19371 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19372 MO_TESL);
19373 gen_store_gpr(t0, rd);
19374 break;
19375 case NM_LBUX:
19376 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19377 MO_UB);
19378 gen_store_gpr(t0, rd);
19379 break;
19380 case NM_LHUX:
19381 /*case NM_LHUXS:*/
19382 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19383 MO_TEUW);
19384 gen_store_gpr(t0, rd);
19385 break;
19386 case NM_SBX:
fb32f8c8 19387 check_nms(ctx);
eac52664
YK
19388 gen_load_gpr(t1, rd);
19389 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19390 MO_8);
19391 break;
19392 case NM_SHX:
19393 /*case NM_SHXS:*/
fb32f8c8 19394 check_nms(ctx);
eac52664
YK
19395 gen_load_gpr(t1, rd);
19396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19397 MO_TEUW);
19398 break;
19399 case NM_SWX:
19400 /*case NM_SWXS:*/
fb32f8c8 19401 check_nms(ctx);
eac52664
YK
19402 gen_load_gpr(t1, rd);
19403 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19404 MO_TEUL);
19405 break;
19406 case NM_LWC1X:
19407 /*case NM_LWC1XS:*/
19408 case NM_LDC1X:
19409 /*case NM_LDC1XS:*/
19410 case NM_SWC1X:
19411 /*case NM_SWC1XS:*/
19412 case NM_SDC1X:
19413 /*case NM_SDC1XS:*/
19414 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19415 check_cp1_enabled(ctx);
19416 switch (extract32(ctx->opcode, 7, 4)) {
19417 case NM_LWC1X:
19418 /*case NM_LWC1XS:*/
19419 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19420 break;
19421 case NM_LDC1X:
19422 /*case NM_LDC1XS:*/
19423 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19424 break;
19425 case NM_SWC1X:
19426 /*case NM_SWC1XS:*/
19427 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19428 break;
19429 case NM_SDC1X:
19430 /*case NM_SDC1XS:*/
19431 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19432 break;
19433 }
19434 } else {
19435 generate_exception_err(ctx, EXCP_CpU, 1);
19436 }
19437 break;
19438 default:
3a4ef3b7 19439 gen_reserved_instruction(ctx);
eac52664
YK
19440 break;
19441 }
19442
19443 tcg_temp_free(t0);
19444 tcg_temp_free(t1);
19445}
19446
579b8ea9
YK
19447static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19448{
19449 int rt, rs, rd;
19450
19451 rt = extract32(ctx->opcode, 21, 5);
19452 rs = extract32(ctx->opcode, 16, 5);
19453 rd = extract32(ctx->opcode, 11, 5);
19454
19455 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
3a4ef3b7 19456 gen_reserved_instruction(ctx);
579b8ea9
YK
19457 return;
19458 }
19459 check_cp1_enabled(ctx);
19460 switch (extract32(ctx->opcode, 0, 3)) {
19461 case NM_POOL32F_0:
19462 switch (extract32(ctx->opcode, 3, 7)) {
19463 case NM_RINT_S:
19464 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19465 break;
19466 case NM_RINT_D:
19467 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19468 break;
19469 case NM_CLASS_S:
19470 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19471 break;
19472 case NM_CLASS_D:
19473 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19474 break;
19475 case NM_ADD_S:
19476 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19477 break;
19478 case NM_ADD_D:
19479 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19480 break;
19481 case NM_SUB_S:
19482 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19483 break;
19484 case NM_SUB_D:
19485 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19486 break;
19487 case NM_MUL_S:
19488 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19489 break;
19490 case NM_MUL_D:
19491 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19492 break;
19493 case NM_DIV_S:
19494 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19495 break;
19496 case NM_DIV_D:
19497 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19498 break;
19499 case NM_SELEQZ_S:
19500 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19501 break;
19502 case NM_SELEQZ_D:
19503 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19504 break;
19505 case NM_SELNEZ_S:
19506 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19507 break;
19508 case NM_SELNEZ_D:
19509 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19510 break;
19511 case NM_SEL_S:
19512 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19513 break;
19514 case NM_SEL_D:
19515 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19516 break;
19517 case NM_MADDF_S:
19518 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19519 break;
19520 case NM_MADDF_D:
19521 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19522 break;
19523 case NM_MSUBF_S:
19524 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19525 break;
19526 case NM_MSUBF_D:
19527 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19528 break;
19529 default:
3a4ef3b7 19530 gen_reserved_instruction(ctx);
579b8ea9
YK
19531 break;
19532 }
19533 break;
19534 case NM_POOL32F_3:
19535 switch (extract32(ctx->opcode, 3, 3)) {
19536 case NM_MIN_FMT:
19537 switch (extract32(ctx->opcode, 9, 1)) {
19538 case FMT_SDPS_S:
19539 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19540 break;
19541 case FMT_SDPS_D:
19542 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19543 break;
19544 }
19545 break;
19546 case NM_MAX_FMT:
19547 switch (extract32(ctx->opcode, 9, 1)) {
19548 case FMT_SDPS_S:
19549 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19550 break;
19551 case FMT_SDPS_D:
19552 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19553 break;
19554 }
19555 break;
19556 case NM_MINA_FMT:
19557 switch (extract32(ctx->opcode, 9, 1)) {
19558 case FMT_SDPS_S:
19559 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19560 break;
19561 case FMT_SDPS_D:
19562 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19563 break;
19564 }
19565 break;
19566 case NM_MAXA_FMT:
19567 switch (extract32(ctx->opcode, 9, 1)) {
19568 case FMT_SDPS_S:
19569 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19570 break;
19571 case FMT_SDPS_D:
19572 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19573 break;
19574 }
19575 break;
19576 case NM_POOL32FXF:
19577 switch (extract32(ctx->opcode, 6, 8)) {
19578 case NM_CFC1:
19579 gen_cp1(ctx, OPC_CFC1, rt, rs);
19580 break;
19581 case NM_CTC1:
19582 gen_cp1(ctx, OPC_CTC1, rt, rs);
19583 break;
19584 case NM_MFC1:
19585 gen_cp1(ctx, OPC_MFC1, rt, rs);
19586 break;
19587 case NM_MTC1:
19588 gen_cp1(ctx, OPC_MTC1, rt, rs);
19589 break;
19590 case NM_MFHC1:
19591 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19592 break;
19593 case NM_MTHC1:
19594 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19595 break;
19596 case NM_CVT_S_PL:
19597 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19598 break;
19599 case NM_CVT_S_PU:
19600 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19601 break;
19602 default:
19603 switch (extract32(ctx->opcode, 6, 9)) {
19604 case NM_CVT_L_S:
19605 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19606 break;
19607 case NM_CVT_L_D:
19608 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19609 break;
19610 case NM_CVT_W_S:
19611 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19612 break;
19613 case NM_CVT_W_D:
19614 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19615 break;
19616 case NM_RSQRT_S:
19617 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19618 break;
19619 case NM_RSQRT_D:
19620 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19621 break;
19622 case NM_SQRT_S:
19623 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19624 break;
19625 case NM_SQRT_D:
19626 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19627 break;
19628 case NM_RECIP_S:
19629 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19630 break;
19631 case NM_RECIP_D:
19632 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19633 break;
19634 case NM_FLOOR_L_S:
19635 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19636 break;
19637 case NM_FLOOR_L_D:
19638 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19639 break;
19640 case NM_FLOOR_W_S:
19641 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19642 break;
19643 case NM_FLOOR_W_D:
19644 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19645 break;
19646 case NM_CEIL_L_S:
19647 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19648 break;
19649 case NM_CEIL_L_D:
19650 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19651 break;
19652 case NM_CEIL_W_S:
19653 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19654 break;
19655 case NM_CEIL_W_D:
19656 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19657 break;
19658 case NM_TRUNC_L_S:
19659 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19660 break;
19661 case NM_TRUNC_L_D:
19662 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19663 break;
19664 case NM_TRUNC_W_S:
19665 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19666 break;
19667 case NM_TRUNC_W_D:
19668 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19669 break;
19670 case NM_ROUND_L_S:
19671 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19672 break;
19673 case NM_ROUND_L_D:
19674 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19675 break;
19676 case NM_ROUND_W_S:
19677 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19678 break;
19679 case NM_ROUND_W_D:
19680 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19681 break;
19682 case NM_MOV_S:
19683 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19684 break;
19685 case NM_MOV_D:
19686 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19687 break;
19688 case NM_ABS_S:
19689 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19690 break;
19691 case NM_ABS_D:
19692 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19693 break;
19694 case NM_NEG_S:
19695 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19696 break;
19697 case NM_NEG_D:
19698 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19699 break;
19700 case NM_CVT_D_S:
19701 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19702 break;
19703 case NM_CVT_D_W:
19704 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19705 break;
19706 case NM_CVT_D_L:
19707 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19708 break;
19709 case NM_CVT_S_D:
19710 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19711 break;
19712 case NM_CVT_S_W:
19713 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19714 break;
19715 case NM_CVT_S_L:
19716 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19717 break;
19718 default:
3a4ef3b7 19719 gen_reserved_instruction(ctx);
579b8ea9
YK
19720 break;
19721 }
19722 break;
19723 }
19724 break;
19725 }
19726 break;
19727 case NM_POOL32F_5:
19728 switch (extract32(ctx->opcode, 3, 3)) {
19729 case NM_CMP_CONDN_S:
19730 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19731 break;
19732 case NM_CMP_CONDN_D:
19733 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19734 break;
19735 default:
3a4ef3b7 19736 gen_reserved_instruction(ctx);
579b8ea9
YK
19737 break;
19738 }
19739 break;
19740 default:
3a4ef3b7 19741 gen_reserved_instruction(ctx);
579b8ea9
YK
19742 break;
19743 }
19744}
19745
3285a3e4
SM
19746static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19747 int rd, int rs, int rt)
19748{
19749 int ret = rd;
19750 TCGv t0 = tcg_temp_new();
19751 TCGv v1_t = tcg_temp_new();
19752 TCGv v2_t = tcg_temp_new();
19753
19754 gen_load_gpr(v1_t, rs);
19755 gen_load_gpr(v2_t, rt);
19756
19757 switch (opc) {
19758 case NM_CMP_EQ_PH:
19759 check_dsp(ctx);
19760 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19761 break;
19762 case NM_CMP_LT_PH:
19763 check_dsp(ctx);
19764 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19765 break;
19766 case NM_CMP_LE_PH:
19767 check_dsp(ctx);
19768 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19769 break;
19770 case NM_CMPU_EQ_QB:
19771 check_dsp(ctx);
19772 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19773 break;
19774 case NM_CMPU_LT_QB:
19775 check_dsp(ctx);
19776 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19777 break;
19778 case NM_CMPU_LE_QB:
19779 check_dsp(ctx);
19780 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19781 break;
19782 case NM_CMPGU_EQ_QB:
19783 check_dsp(ctx);
19784 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19785 gen_store_gpr(v1_t, ret);
19786 break;
19787 case NM_CMPGU_LT_QB:
19788 check_dsp(ctx);
19789 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19790 gen_store_gpr(v1_t, ret);
19791 break;
19792 case NM_CMPGU_LE_QB:
19793 check_dsp(ctx);
19794 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19795 gen_store_gpr(v1_t, ret);
19796 break;
19797 case NM_CMPGDU_EQ_QB:
908f6be1 19798 check_dsp_r2(ctx);
3285a3e4
SM
19799 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19800 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19801 gen_store_gpr(v1_t, ret);
19802 break;
19803 case NM_CMPGDU_LT_QB:
908f6be1 19804 check_dsp_r2(ctx);
3285a3e4
SM
19805 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19806 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19807 gen_store_gpr(v1_t, ret);
19808 break;
19809 case NM_CMPGDU_LE_QB:
908f6be1 19810 check_dsp_r2(ctx);
3285a3e4
SM
19811 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19812 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19813 gen_store_gpr(v1_t, ret);
19814 break;
19815 case NM_PACKRL_PH:
19816 check_dsp(ctx);
19817 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19818 gen_store_gpr(v1_t, ret);
19819 break;
19820 case NM_PICK_QB:
19821 check_dsp(ctx);
19822 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19823 gen_store_gpr(v1_t, ret);
19824 break;
19825 case NM_PICK_PH:
19826 check_dsp(ctx);
19827 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19828 gen_store_gpr(v1_t, ret);
19829 break;
19830 case NM_ADDQ_S_W:
19831 check_dsp(ctx);
19832 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19833 gen_store_gpr(v1_t, ret);
19834 break;
19835 case NM_SUBQ_S_W:
19836 check_dsp(ctx);
19837 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19838 gen_store_gpr(v1_t, ret);
19839 break;
19840 case NM_ADDSC:
19841 check_dsp(ctx);
19842 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19843 gen_store_gpr(v1_t, ret);
19844 break;
19845 case NM_ADDWC:
19846 check_dsp(ctx);
19847 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19848 gen_store_gpr(v1_t, ret);
19849 break;
19850 case NM_ADDQ_S_PH:
19851 check_dsp(ctx);
19852 switch (extract32(ctx->opcode, 10, 1)) {
19853 case 0:
19854 /* ADDQ_PH */
19855 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19856 gen_store_gpr(v1_t, ret);
19857 break;
19858 case 1:
19859 /* ADDQ_S_PH */
19860 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19861 gen_store_gpr(v1_t, ret);
19862 break;
19863 }
19864 break;
19865 case NM_ADDQH_R_PH:
908f6be1 19866 check_dsp_r2(ctx);
3285a3e4
SM
19867 switch (extract32(ctx->opcode, 10, 1)) {
19868 case 0:
19869 /* ADDQH_PH */
19870 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19871 gen_store_gpr(v1_t, ret);
19872 break;
19873 case 1:
19874 /* ADDQH_R_PH */
19875 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19876 gen_store_gpr(v1_t, ret);
19877 break;
19878 }
19879 break;
19880 case NM_ADDQH_R_W:
908f6be1 19881 check_dsp_r2(ctx);
3285a3e4
SM
19882 switch (extract32(ctx->opcode, 10, 1)) {
19883 case 0:
19884 /* ADDQH_W */
19885 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19886 gen_store_gpr(v1_t, ret);
19887 break;
19888 case 1:
19889 /* ADDQH_R_W */
19890 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19891 gen_store_gpr(v1_t, ret);
19892 break;
19893 }
19894 break;
19895 case NM_ADDU_S_QB:
19896 check_dsp(ctx);
19897 switch (extract32(ctx->opcode, 10, 1)) {
19898 case 0:
19899 /* ADDU_QB */
19900 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19901 gen_store_gpr(v1_t, ret);
19902 break;
19903 case 1:
19904 /* ADDU_S_QB */
19905 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19906 gen_store_gpr(v1_t, ret);
19907 break;
19908 }
19909 break;
19910 case NM_ADDU_S_PH:
908f6be1 19911 check_dsp_r2(ctx);
3285a3e4
SM
19912 switch (extract32(ctx->opcode, 10, 1)) {
19913 case 0:
19914 /* ADDU_PH */
19915 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19916 gen_store_gpr(v1_t, ret);
19917 break;
19918 case 1:
19919 /* ADDU_S_PH */
19920 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19921 gen_store_gpr(v1_t, ret);
19922 break;
19923 }
19924 break;
19925 case NM_ADDUH_R_QB:
908f6be1 19926 check_dsp_r2(ctx);
3285a3e4
SM
19927 switch (extract32(ctx->opcode, 10, 1)) {
19928 case 0:
19929 /* ADDUH_QB */
19930 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19931 gen_store_gpr(v1_t, ret);
19932 break;
19933 case 1:
19934 /* ADDUH_R_QB */
19935 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19936 gen_store_gpr(v1_t, ret);
19937 break;
19938 }
19939 break;
19940 case NM_SHRAV_R_PH:
19941 check_dsp(ctx);
19942 switch (extract32(ctx->opcode, 10, 1)) {
19943 case 0:
19944 /* SHRAV_PH */
19945 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19946 gen_store_gpr(v1_t, ret);
19947 break;
19948 case 1:
19949 /* SHRAV_R_PH */
19950 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19951 gen_store_gpr(v1_t, ret);
19952 break;
19953 }
19954 break;
19955 case NM_SHRAV_R_QB:
908f6be1 19956 check_dsp_r2(ctx);
3285a3e4
SM
19957 switch (extract32(ctx->opcode, 10, 1)) {
19958 case 0:
19959 /* SHRAV_QB */
19960 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19961 gen_store_gpr(v1_t, ret);
19962 break;
19963 case 1:
19964 /* SHRAV_R_QB */
19965 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19966 gen_store_gpr(v1_t, ret);
19967 break;
19968 }
19969 break;
19970 case NM_SUBQ_S_PH:
19971 check_dsp(ctx);
19972 switch (extract32(ctx->opcode, 10, 1)) {
19973 case 0:
19974 /* SUBQ_PH */
19975 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19976 gen_store_gpr(v1_t, ret);
19977 break;
19978 case 1:
19979 /* SUBQ_S_PH */
19980 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19981 gen_store_gpr(v1_t, ret);
19982 break;
19983 }
19984 break;
19985 case NM_SUBQH_R_PH:
908f6be1 19986 check_dsp_r2(ctx);
3285a3e4
SM
19987 switch (extract32(ctx->opcode, 10, 1)) {
19988 case 0:
19989 /* SUBQH_PH */
19990 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19991 gen_store_gpr(v1_t, ret);
19992 break;
19993 case 1:
19994 /* SUBQH_R_PH */
19995 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19996 gen_store_gpr(v1_t, ret);
19997 break;
19998 }
19999 break;
20000 case NM_SUBQH_R_W:
908f6be1 20001 check_dsp_r2(ctx);
3285a3e4
SM
20002 switch (extract32(ctx->opcode, 10, 1)) {
20003 case 0:
20004 /* SUBQH_W */
20005 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20006 gen_store_gpr(v1_t, ret);
20007 break;
20008 case 1:
20009 /* SUBQH_R_W */
20010 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20011 gen_store_gpr(v1_t, ret);
20012 break;
20013 }
20014 break;
20015 case NM_SUBU_S_QB:
20016 check_dsp(ctx);
20017 switch (extract32(ctx->opcode, 10, 1)) {
20018 case 0:
20019 /* SUBU_QB */
20020 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20021 gen_store_gpr(v1_t, ret);
20022 break;
20023 case 1:
20024 /* SUBU_S_QB */
20025 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20026 gen_store_gpr(v1_t, ret);
20027 break;
20028 }
20029 break;
20030 case NM_SUBU_S_PH:
908f6be1 20031 check_dsp_r2(ctx);
3285a3e4
SM
20032 switch (extract32(ctx->opcode, 10, 1)) {
20033 case 0:
20034 /* SUBU_PH */
20035 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20036 gen_store_gpr(v1_t, ret);
20037 break;
20038 case 1:
20039 /* SUBU_S_PH */
20040 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20041 gen_store_gpr(v1_t, ret);
20042 break;
20043 }
20044 break;
20045 case NM_SUBUH_R_QB:
908f6be1 20046 check_dsp_r2(ctx);
3285a3e4
SM
20047 switch (extract32(ctx->opcode, 10, 1)) {
20048 case 0:
20049 /* SUBUH_QB */
20050 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20051 gen_store_gpr(v1_t, ret);
20052 break;
20053 case 1:
20054 /* SUBUH_R_QB */
20055 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20056 gen_store_gpr(v1_t, ret);
20057 break;
20058 }
20059 break;
20060 case NM_SHLLV_S_PH:
20061 check_dsp(ctx);
20062 switch (extract32(ctx->opcode, 10, 1)) {
20063 case 0:
20064 /* SHLLV_PH */
20065 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20066 gen_store_gpr(v1_t, ret);
20067 break;
20068 case 1:
20069 /* SHLLV_S_PH */
20070 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20071 gen_store_gpr(v1_t, ret);
20072 break;
20073 }
20074 break;
20075 case NM_PRECR_SRA_R_PH_W:
908f6be1 20076 check_dsp_r2(ctx);
3285a3e4
SM
20077 switch (extract32(ctx->opcode, 10, 1)) {
20078 case 0:
20079 /* PRECR_SRA_PH_W */
20080 {
20081 TCGv_i32 sa_t = tcg_const_i32(rd);
20082 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20083 cpu_gpr[rt]);
20084 gen_store_gpr(v1_t, rt);
20085 tcg_temp_free_i32(sa_t);
20086 }
20087 break;
20088 case 1:
20089 /* PRECR_SRA_R_PH_W */
20090 {
20091 TCGv_i32 sa_t = tcg_const_i32(rd);
20092 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20093 cpu_gpr[rt]);
20094 gen_store_gpr(v1_t, rt);
20095 tcg_temp_free_i32(sa_t);
20096 }
20097 break;
20098 }
20099 break;
20100 case NM_MULEU_S_PH_QBL:
20101 check_dsp(ctx);
20102 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20103 gen_store_gpr(v1_t, ret);
20104 break;
20105 case NM_MULEU_S_PH_QBR:
20106 check_dsp(ctx);
20107 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20108 gen_store_gpr(v1_t, ret);
20109 break;
20110 case NM_MULQ_RS_PH:
20111 check_dsp(ctx);
20112 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20113 gen_store_gpr(v1_t, ret);
20114 break;
20115 case NM_MULQ_S_PH:
908f6be1 20116 check_dsp_r2(ctx);
3285a3e4
SM
20117 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20118 gen_store_gpr(v1_t, ret);
20119 break;
20120 case NM_MULQ_RS_W:
908f6be1 20121 check_dsp_r2(ctx);
3285a3e4
SM
20122 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20123 gen_store_gpr(v1_t, ret);
20124 break;
20125 case NM_MULQ_S_W:
908f6be1 20126 check_dsp_r2(ctx);
3285a3e4
SM
20127 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20128 gen_store_gpr(v1_t, ret);
20129 break;
20130 case NM_APPEND:
908f6be1 20131 check_dsp_r2(ctx);
3285a3e4
SM
20132 gen_load_gpr(t0, rs);
20133 if (rd != 0) {
20134 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20135 }
20136 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20137 break;
20138 case NM_MODSUB:
20139 check_dsp(ctx);
20140 gen_helper_modsub(v1_t, v1_t, v2_t);
20141 gen_store_gpr(v1_t, ret);
20142 break;
20143 case NM_SHRAV_R_W:
20144 check_dsp(ctx);
20145 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20146 gen_store_gpr(v1_t, ret);
20147 break;
20148 case NM_SHRLV_PH:
908f6be1 20149 check_dsp_r2(ctx);
3285a3e4
SM
20150 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20151 gen_store_gpr(v1_t, ret);
20152 break;
20153 case NM_SHRLV_QB:
20154 check_dsp(ctx);
20155 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20156 gen_store_gpr(v1_t, ret);
20157 break;
20158 case NM_SHLLV_QB:
20159 check_dsp(ctx);
20160 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20161 gen_store_gpr(v1_t, ret);
20162 break;
20163 case NM_SHLLV_S_W:
20164 check_dsp(ctx);
20165 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20166 gen_store_gpr(v1_t, ret);
20167 break;
20168 case NM_SHILO:
20169 check_dsp(ctx);
20170 {
20171 TCGv tv0 = tcg_temp_new();
20172 TCGv tv1 = tcg_temp_new();
20173 int16_t imm = extract32(ctx->opcode, 16, 7);
20174
20175 tcg_gen_movi_tl(tv0, rd >> 3);
20176 tcg_gen_movi_tl(tv1, imm);
20177 gen_helper_shilo(tv0, tv1, cpu_env);
96342d53
PMD
20178 tcg_temp_free(tv1);
20179 tcg_temp_free(tv0);
3285a3e4
SM
20180 }
20181 break;
20182 case NM_MULEQ_S_W_PHL:
20183 check_dsp(ctx);
20184 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20185 gen_store_gpr(v1_t, ret);
20186 break;
20187 case NM_MULEQ_S_W_PHR:
20188 check_dsp(ctx);
20189 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20190 gen_store_gpr(v1_t, ret);
20191 break;
20192 case NM_MUL_S_PH:
908f6be1 20193 check_dsp_r2(ctx);
3285a3e4
SM
20194 switch (extract32(ctx->opcode, 10, 1)) {
20195 case 0:
20196 /* MUL_PH */
20197 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20198 gen_store_gpr(v1_t, ret);
20199 break;
20200 case 1:
20201 /* MUL_S_PH */
20202 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20203 gen_store_gpr(v1_t, ret);
20204 break;
20205 }
20206 break;
20207 case NM_PRECR_QB_PH:
908f6be1 20208 check_dsp_r2(ctx);
3285a3e4
SM
20209 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20210 gen_store_gpr(v1_t, ret);
20211 break;
20212 case NM_PRECRQ_QB_PH:
20213 check_dsp(ctx);
20214 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20215 gen_store_gpr(v1_t, ret);
20216 break;
20217 case NM_PRECRQ_PH_W:
20218 check_dsp(ctx);
20219 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20220 gen_store_gpr(v1_t, ret);
20221 break;
20222 case NM_PRECRQ_RS_PH_W:
20223 check_dsp(ctx);
20224 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20225 gen_store_gpr(v1_t, ret);
20226 break;
20227 case NM_PRECRQU_S_QB_PH:
20228 check_dsp(ctx);
20229 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20230 gen_store_gpr(v1_t, ret);
20231 break;
20232 case NM_SHRA_R_W:
20233 check_dsp(ctx);
20234 tcg_gen_movi_tl(t0, rd);
20235 gen_helper_shra_r_w(v1_t, t0, v1_t);
20236 gen_store_gpr(v1_t, rt);
20237 break;
20238 case NM_SHRA_R_PH:
20239 check_dsp(ctx);
20240 tcg_gen_movi_tl(t0, rd >> 1);
20241 switch (extract32(ctx->opcode, 10, 1)) {
20242 case 0:
20243 /* SHRA_PH */
20244 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 20245 gen_store_gpr(v1_t, rt);
d5ebcbaf 20246 break;
3285a3e4
SM
20247 case 1:
20248 /* SHRA_R_PH */
20249 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20250 gen_store_gpr(v1_t, rt);
20251 break;
20252 }
20253 break;
20254 case NM_SHLL_S_PH:
20255 check_dsp(ctx);
20256 tcg_gen_movi_tl(t0, rd >> 1);
20257 switch (extract32(ctx->opcode, 10, 2)) {
20258 case 0:
20259 /* SHLL_PH */
20260 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20261 gen_store_gpr(v1_t, rt);
20262 break;
20263 case 2:
20264 /* SHLL_S_PH */
20265 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20266 gen_store_gpr(v1_t, rt);
20267 break;
20268 default:
3a4ef3b7 20269 gen_reserved_instruction(ctx);
3285a3e4
SM
20270 break;
20271 }
20272 break;
20273 case NM_SHLL_S_W:
20274 check_dsp(ctx);
20275 tcg_gen_movi_tl(t0, rd);
20276 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20277 gen_store_gpr(v1_t, rt);
20278 break;
20279 case NM_REPL_PH:
20280 check_dsp(ctx);
20281 {
20282 int16_t imm;
20283 imm = sextract32(ctx->opcode, 11, 11);
20284 imm = (int16_t)(imm << 6) >> 6;
20285 if (rt != 0) {
20286 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20287 }
20288 }
20289 break;
20290 default:
3a4ef3b7 20291 gen_reserved_instruction(ctx);
3285a3e4
SM
20292 break;
20293 }
6eb22310
PMD
20294
20295 tcg_temp_free(v2_t);
20296 tcg_temp_free(v1_t);
20297 tcg_temp_free(t0);
3285a3e4
SM
20298}
20299
c0280983
YK
20300static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20301{
20302 uint16_t insn;
20303 uint32_t op;
eac52664 20304 int rt, rs, rd;
c0280983
YK
20305 int offset;
20306 int imm;
20307
0ab8e33a 20308 insn = translator_lduw(env, ctx->base.pc_next + 2);
c0280983
YK
20309 ctx->opcode = (ctx->opcode << 16) | insn;
20310
20311 rt = extract32(ctx->opcode, 21, 5);
20312 rs = extract32(ctx->opcode, 16, 5);
eac52664 20313 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
20314
20315 op = extract32(ctx->opcode, 26, 6);
20316 switch (op) {
20317 case NM_P_ADDIU:
20318 if (rt == 0) {
20319 /* P.RI */
20320 switch (extract32(ctx->opcode, 19, 2)) {
20321 case NM_SIGRIE:
20322 default:
3a4ef3b7 20323 gen_reserved_instruction(ctx);
c0280983
YK
20324 break;
20325 case NM_P_SYSCALL:
20326 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20327 generate_exception_end(ctx, EXCP_SYSCALL);
20328 } else {
3a4ef3b7 20329 gen_reserved_instruction(ctx);
c0280983
YK
20330 }
20331 break;
20332 case NM_BREAK:
20333 generate_exception_end(ctx, EXCP_BREAK);
20334 break;
20335 case NM_SDBBP:
20336 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20337 gen_helper_do_semihosting(cpu_env);
20338 } else {
20339 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 20340 gen_reserved_instruction(ctx);
c0280983
YK
20341 } else {
20342 generate_exception_end(ctx, EXCP_DBp);
20343 }
20344 }
20345 break;
20346 }
20347 } else {
20348 /* NM_ADDIU */
20349 imm = extract32(ctx->opcode, 0, 16);
20350 if (rs != 0) {
20351 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20352 } else {
20353 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20354 }
20355 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20356 }
20357 break;
20358 case NM_ADDIUPC:
20359 if (rt != 0) {
20360 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20361 extract32(ctx->opcode, 1, 20) << 1;
20362 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20363 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20364 }
20365 break;
20366 case NM_POOL32A:
e0cf0e65
YK
20367 switch (ctx->opcode & 0x07) {
20368 case NM_POOL32A0:
0a1a6ed7 20369 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 20370 break;
3285a3e4
SM
20371 case NM_POOL32A5:
20372 {
20373 int32_t op1 = extract32(ctx->opcode, 3, 7);
20374 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20375 }
20376 break;
e0cf0e65 20377 case NM_POOL32A7:
64224187 20378 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
20379 case NM_P_LSX:
20380 gen_p_lsx(ctx, rd, rs, rt);
20381 break;
20382 case NM_LSA:
7480515f
AM
20383 /*
20384 * In nanoMIPS, the shift field directly encodes the shift
eac52664 20385 * amount, meaning that the supported shift values are in
7480515f
AM
20386 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20387 */
a685f7d0 20388 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
eac52664 20389 break;
821f2008
JH
20390 case NM_EXTW:
20391 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20392 break;
64224187
YK
20393 case NM_POOL32AXF:
20394 gen_pool32axf_nanomips_insn(env, ctx);
20395 break;
20396 default:
3a4ef3b7 20397 gen_reserved_instruction(ctx);
64224187
YK
20398 break;
20399 }
e0cf0e65
YK
20400 break;
20401 default:
3a4ef3b7 20402 gen_reserved_instruction(ctx);
e0cf0e65
YK
20403 break;
20404 }
c0280983
YK
20405 break;
20406 case NM_P_GP_W:
20407 switch (ctx->opcode & 0x03) {
20408 case NM_ADDIUGP_W:
20409 if (rt != 0) {
20410 offset = extract32(ctx->opcode, 0, 21);
20411 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20412 }
20413 break;
20414 case NM_LWGP:
20415 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20416 break;
20417 case NM_SWGP:
20418 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20419 break;
20420 default:
3a4ef3b7 20421 gen_reserved_instruction(ctx);
c0280983
YK
20422 break;
20423 }
20424 break;
20425 case NM_P48I:
7ef009b2 20426 {
0ab8e33a 20427 insn = translator_lduw(env, ctx->base.pc_next + 4);
7ef009b2
YK
20428 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20429 switch (extract32(ctx->opcode, 16, 5)) {
20430 case NM_LI48:
fb32f8c8 20431 check_nms(ctx);
7ef009b2
YK
20432 if (rt != 0) {
20433 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20434 }
20435 break;
20436 case NM_ADDIU48:
fb32f8c8 20437 check_nms(ctx);
7ef009b2
YK
20438 if (rt != 0) {
20439 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20440 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20441 }
20442 break;
20443 case NM_ADDIUGP48:
fb32f8c8 20444 check_nms(ctx);
7ef009b2
YK
20445 if (rt != 0) {
20446 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20447 }
20448 break;
20449 case NM_ADDIUPC48:
fb32f8c8 20450 check_nms(ctx);
7ef009b2
YK
20451 if (rt != 0) {
20452 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20453 addr_off);
20454
20455 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20456 }
20457 break;
20458 case NM_LWPC48:
fb32f8c8 20459 check_nms(ctx);
7ef009b2
YK
20460 if (rt != 0) {
20461 TCGv t0;
20462 t0 = tcg_temp_new();
20463
20464 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20465 addr_off);
20466
20467 tcg_gen_movi_tl(t0, addr);
20468 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20469 tcg_temp_free(t0);
20470 }
20471 break;
20472 case NM_SWPC48:
fb32f8c8 20473 check_nms(ctx);
7ef009b2
YK
20474 {
20475 TCGv t0, t1;
20476 t0 = tcg_temp_new();
20477 t1 = tcg_temp_new();
20478
20479 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20480 addr_off);
20481
20482 tcg_gen_movi_tl(t0, addr);
20483 gen_load_gpr(t1, rt);
20484
20485 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20486
20487 tcg_temp_free(t0);
20488 tcg_temp_free(t1);
20489 }
20490 break;
20491 default:
3a4ef3b7 20492 gen_reserved_instruction(ctx);
7ef009b2
YK
20493 break;
20494 }
20495 return 6;
20496 }
c0280983
YK
20497 case NM_P_U12:
20498 switch (extract32(ctx->opcode, 12, 4)) {
20499 case NM_ORI:
20500 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20501 break;
20502 case NM_XORI:
20503 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20504 break;
20505 case NM_ANDI:
20506 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20507 break;
20508 case NM_P_SR:
20509 switch (extract32(ctx->opcode, 20, 1)) {
20510 case NM_PP_SR:
20511 switch (ctx->opcode & 3) {
20512 case NM_SAVE:
20513 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20514 extract32(ctx->opcode, 2, 1),
20515 extract32(ctx->opcode, 3, 9) << 3);
20516 break;
20517 case NM_RESTORE:
20518 case NM_RESTORE_JRC:
20519 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20520 extract32(ctx->opcode, 2, 1),
20521 extract32(ctx->opcode, 3, 9) << 3);
20522 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20523 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20524 }
20525 break;
20526 default:
3a4ef3b7 20527 gen_reserved_instruction(ctx);
c0280983
YK
20528 break;
20529 }
20530 break;
20531 case NM_P_SR_F:
3a4ef3b7 20532 gen_reserved_instruction(ctx);
c0280983
YK
20533 break;
20534 }
20535 break;
20536 case NM_SLTI:
20537 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20538 break;
20539 case NM_SLTIU:
20540 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20541 break;
20542 case NM_SEQI:
20543 {
20544 TCGv t0 = tcg_temp_new();
20545
20546 imm = extract32(ctx->opcode, 0, 12);
20547 gen_load_gpr(t0, rs);
20548 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20549 gen_store_gpr(t0, rt);
20550
20551 tcg_temp_free(t0);
20552 }
20553 break;
20554 case NM_ADDIUNEG:
20555 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20556 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20557 break;
20558 case NM_P_SHIFT:
20559 {
20560 int shift = extract32(ctx->opcode, 0, 5);
20561 switch (extract32(ctx->opcode, 5, 4)) {
20562 case NM_P_SLL:
20563 if (rt == 0 && shift == 0) {
20564 /* NOP */
20565 } else if (rt == 0 && shift == 3) {
20566 /* EHB - treat as NOP */
20567 } else if (rt == 0 && shift == 5) {
20568 /* PAUSE - treat as NOP */
20569 } else if (rt == 0 && shift == 6) {
20570 /* SYNC */
20571 gen_sync(extract32(ctx->opcode, 16, 5));
20572 } else {
20573 /* SLL */
20574 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20575 extract32(ctx->opcode, 0, 5));
20576 }
20577 break;
20578 case NM_SRL:
20579 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20580 extract32(ctx->opcode, 0, 5));
20581 break;
20582 case NM_SRA:
20583 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20584 extract32(ctx->opcode, 0, 5));
20585 break;
20586 case NM_ROTR:
20587 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20588 extract32(ctx->opcode, 0, 5));
20589 break;
20590 }
20591 }
20592 break;
20593 case NM_P_ROTX:
fb32f8c8 20594 check_nms(ctx);
e222f506
MF
20595 if (rt != 0) {
20596 TCGv t0 = tcg_temp_new();
20597 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20598 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20599 << 1);
20600 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20601
20602 gen_load_gpr(t0, rs);
20603 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20604 tcg_temp_free(t0);
20605
20606 tcg_temp_free_i32(shift);
20607 tcg_temp_free_i32(shiftx);
20608 tcg_temp_free_i32(stripe);
20609 }
c0280983
YK
20610 break;
20611 case NM_P_INS:
20612 switch (((ctx->opcode >> 10) & 2) |
20613 (extract32(ctx->opcode, 5, 1))) {
20614 case NM_INS:
fb32f8c8 20615 check_nms(ctx);
c0280983
YK
20616 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20617 extract32(ctx->opcode, 6, 5));
20618 break;
20619 default:
3a4ef3b7 20620 gen_reserved_instruction(ctx);
c0280983
YK
20621 break;
20622 }
20623 break;
20624 case NM_P_EXT:
20625 switch (((ctx->opcode >> 10) & 2) |
20626 (extract32(ctx->opcode, 5, 1))) {
20627 case NM_EXT:
fb32f8c8 20628 check_nms(ctx);
c0280983
YK
20629 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20630 extract32(ctx->opcode, 6, 5));
20631 break;
20632 default:
3a4ef3b7 20633 gen_reserved_instruction(ctx);
c0280983
YK
20634 break;
20635 }
20636 break;
20637 default:
3a4ef3b7 20638 gen_reserved_instruction(ctx);
c0280983
YK
20639 break;
20640 }
20641 break;
20642 case NM_POOL32F:
579b8ea9 20643 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
20644 break;
20645 case NM_POOL32S:
20646 break;
20647 case NM_P_LUI:
20648 switch (extract32(ctx->opcode, 1, 1)) {
20649 case NM_LUI:
20650 if (rt != 0) {
20651 tcg_gen_movi_tl(cpu_gpr[rt],
20652 sextract32(ctx->opcode, 0, 1) << 31 |
20653 extract32(ctx->opcode, 2, 10) << 21 |
20654 extract32(ctx->opcode, 12, 9) << 12);
20655 }
20656 break;
20657 case NM_ALUIPC:
20658 if (rt != 0) {
20659 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20660 extract32(ctx->opcode, 2, 10) << 21 |
20661 extract32(ctx->opcode, 12, 9) << 12;
20662 target_long addr;
20663 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20664 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20665 }
20666 break;
20667 }
20668 break;
20669 case NM_P_GP_BH:
8f1d9b6d
YK
20670 {
20671 uint32_t u = extract32(ctx->opcode, 0, 18);
20672
20673 switch (extract32(ctx->opcode, 18, 3)) {
20674 case NM_LBGP:
20675 gen_ld(ctx, OPC_LB, rt, 28, u);
20676 break;
20677 case NM_SBGP:
20678 gen_st(ctx, OPC_SB, rt, 28, u);
20679 break;
20680 case NM_LBUGP:
20681 gen_ld(ctx, OPC_LBU, rt, 28, u);
20682 break;
20683 case NM_ADDIUGP_B:
20684 if (rt != 0) {
20685 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20686 }
20687 break;
20688 case NM_P_GP_LH:
20689 u &= ~1;
20690 switch (ctx->opcode & 1) {
20691 case NM_LHGP:
20692 gen_ld(ctx, OPC_LH, rt, 28, u);
20693 break;
20694 case NM_LHUGP:
20695 gen_ld(ctx, OPC_LHU, rt, 28, u);
20696 break;
20697 }
20698 break;
20699 case NM_P_GP_SH:
20700 u &= ~1;
20701 switch (ctx->opcode & 1) {
20702 case NM_SHGP:
20703 gen_st(ctx, OPC_SH, rt, 28, u);
20704 break;
20705 default:
3a4ef3b7 20706 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20707 break;
20708 }
20709 break;
20710 case NM_P_GP_CP1:
20711 u &= ~0x3;
20712 switch (ctx->opcode & 0x3) {
20713 case NM_LWC1GP:
20714 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20715 break;
20716 case NM_LDC1GP:
20717 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20718 break;
20719 case NM_SWC1GP:
20720 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20721 break;
20722 case NM_SDC1GP:
20723 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20724 break;
20725 }
20726 break;
20727 default:
3a4ef3b7 20728 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20729 break;
20730 }
20731 }
c0280983
YK
20732 break;
20733 case NM_P_LS_U12:
8f1d9b6d
YK
20734 {
20735 uint32_t u = extract32(ctx->opcode, 0, 12);
20736
20737 switch (extract32(ctx->opcode, 12, 4)) {
20738 case NM_P_PREFU12:
20739 if (rt == 31) {
20740 /* SYNCI */
7480515f
AM
20741 /*
20742 * Break the TB to be able to sync copied instructions
20743 * immediately.
20744 */
8f1d9b6d
YK
20745 ctx->base.is_jmp = DISAS_STOP;
20746 } else {
20747 /* PREF */
20748 /* Treat as NOP. */
20749 }
20750 break;
20751 case NM_LB:
20752 gen_ld(ctx, OPC_LB, rt, rs, u);
20753 break;
20754 case NM_LH:
20755 gen_ld(ctx, OPC_LH, rt, rs, u);
20756 break;
20757 case NM_LW:
20758 gen_ld(ctx, OPC_LW, rt, rs, u);
20759 break;
20760 case NM_LBU:
20761 gen_ld(ctx, OPC_LBU, rt, rs, u);
20762 break;
20763 case NM_LHU:
20764 gen_ld(ctx, OPC_LHU, rt, rs, u);
20765 break;
20766 case NM_SB:
20767 gen_st(ctx, OPC_SB, rt, rs, u);
20768 break;
20769 case NM_SH:
20770 gen_st(ctx, OPC_SH, rt, rs, u);
20771 break;
20772 case NM_SW:
20773 gen_st(ctx, OPC_SW, rt, rs, u);
20774 break;
20775 case NM_LWC1:
20776 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20777 break;
20778 case NM_LDC1:
20779 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20780 break;
20781 case NM_SWC1:
20782 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20783 break;
20784 case NM_SDC1:
20785 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20786 break;
20787 default:
3a4ef3b7 20788 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20789 break;
20790 }
20791 }
c0280983
YK
20792 break;
20793 case NM_P_LS_S9:
8f1d9b6d
YK
20794 {
20795 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20796 extract32(ctx->opcode, 0, 8);
20797
20798 switch (extract32(ctx->opcode, 8, 3)) {
20799 case NM_P_LS_S0:
20800 switch (extract32(ctx->opcode, 11, 4)) {
20801 case NM_LBS9:
20802 gen_ld(ctx, OPC_LB, rt, rs, s);
20803 break;
20804 case NM_LHS9:
20805 gen_ld(ctx, OPC_LH, rt, rs, s);
20806 break;
20807 case NM_LWS9:
20808 gen_ld(ctx, OPC_LW, rt, rs, s);
20809 break;
20810 case NM_LBUS9:
20811 gen_ld(ctx, OPC_LBU, rt, rs, s);
20812 break;
20813 case NM_LHUS9:
20814 gen_ld(ctx, OPC_LHU, rt, rs, s);
20815 break;
20816 case NM_SBS9:
20817 gen_st(ctx, OPC_SB, rt, rs, s);
20818 break;
20819 case NM_SHS9:
20820 gen_st(ctx, OPC_SH, rt, rs, s);
20821 break;
20822 case NM_SWS9:
20823 gen_st(ctx, OPC_SW, rt, rs, s);
20824 break;
20825 case NM_LWC1S9:
20826 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20827 break;
20828 case NM_LDC1S9:
20829 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20830 break;
20831 case NM_SWC1S9:
20832 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20833 break;
20834 case NM_SDC1S9:
20835 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20836 break;
20837 case NM_P_PREFS9:
20838 if (rt == 31) {
20839 /* SYNCI */
7480515f
AM
20840 /*
20841 * Break the TB to be able to sync copied instructions
20842 * immediately.
20843 */
8f1d9b6d
YK
20844 ctx->base.is_jmp = DISAS_STOP;
20845 } else {
20846 /* PREF */
20847 /* Treat as NOP. */
20848 }
20849 break;
20850 default:
3a4ef3b7 20851 gen_reserved_instruction(ctx);
8f1d9b6d
YK
20852 break;
20853 }
20854 break;
20855 case NM_P_LS_S1:
20856 switch (extract32(ctx->opcode, 11, 4)) {
20857 case NM_UALH:
20858 case NM_UASH:
fb32f8c8 20859 check_nms(ctx);
8f1d9b6d
YK
20860 {
20861 TCGv t0 = tcg_temp_new();
20862 TCGv t1 = tcg_temp_new();
20863
20864 gen_base_offset_addr(ctx, t0, rs, s);
20865
20866 switch (extract32(ctx->opcode, 11, 4)) {
20867 case NM_UALH:
20868 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20869 MO_UNALN);
20870 gen_store_gpr(t0, rt);
20871 break;
20872 case NM_UASH:
20873 gen_load_gpr(t1, rt);
20874 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20875 MO_UNALN);
20876 break;
20877 }
20878 tcg_temp_free(t0);
20879 tcg_temp_free(t1);
20880 }
20881 break;
20882 case NM_P_LL:
20883 switch (ctx->opcode & 0x03) {
20884 case NM_LL:
20885 gen_ld(ctx, OPC_LL, rt, rs, s);
20886 break;
20887 case NM_LLWP:
0b16dcd1
AR
20888 check_xnp(ctx);
20889 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
20890 break;
20891 }
20892 break;
20893 case NM_P_SC:
20894 switch (ctx->opcode & 0x03) {
20895 case NM_SC:
33a07fa2 20896 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
8f1d9b6d
YK
20897 break;
20898 case NM_SCWP:
0b16dcd1 20899 check_xnp(ctx);
8d5388c1
AM
20900 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20901 false);
8f1d9b6d
YK
20902 break;
20903 }
20904 break;
20905 case NM_CACHE:
20906 check_cp0_enabled(ctx);
20907 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20908 gen_cache_operation(ctx, rt, rs, s);
20909 }
20910 break;
20911 }
20912 break;
d046a9ea
DN
20913 case NM_P_LS_E0:
20914 switch (extract32(ctx->opcode, 11, 4)) {
20915 case NM_LBE:
20916 check_eva(ctx);
20917 check_cp0_enabled(ctx);
20918 gen_ld(ctx, OPC_LBE, rt, rs, s);
20919 break;
20920 case NM_SBE:
20921 check_eva(ctx);
20922 check_cp0_enabled(ctx);
20923 gen_st(ctx, OPC_SBE, rt, rs, s);
20924 break;
20925 case NM_LBUE:
20926 check_eva(ctx);
20927 check_cp0_enabled(ctx);
20928 gen_ld(ctx, OPC_LBUE, rt, rs, s);
20929 break;
20930 case NM_P_PREFE:
20931 if (rt == 31) {
20932 /* case NM_SYNCIE */
20933 check_eva(ctx);
20934 check_cp0_enabled(ctx);
7480515f
AM
20935 /*
20936 * Break the TB to be able to sync copied instructions
20937 * immediately.
20938 */
d046a9ea
DN
20939 ctx->base.is_jmp = DISAS_STOP;
20940 } else {
20941 /* case NM_PREFE */
20942 check_eva(ctx);
20943 check_cp0_enabled(ctx);
20944 /* Treat as NOP. */
20945 }
20946 break;
20947 case NM_LHE:
20948 check_eva(ctx);
20949 check_cp0_enabled(ctx);
20950 gen_ld(ctx, OPC_LHE, rt, rs, s);
20951 break;
20952 case NM_SHE:
20953 check_eva(ctx);
20954 check_cp0_enabled(ctx);
20955 gen_st(ctx, OPC_SHE, rt, rs, s);
20956 break;
20957 case NM_LHUE:
20958 check_eva(ctx);
20959 check_cp0_enabled(ctx);
20960 gen_ld(ctx, OPC_LHUE, rt, rs, s);
20961 break;
20962 case NM_CACHEE:
84c2fdc3
PMD
20963 check_eva(ctx);
20964 check_cp0_enabled(ctx);
d046a9ea
DN
20965 check_nms_dl_il_sl_tl_l2c(ctx);
20966 gen_cache_operation(ctx, rt, rs, s);
20967 break;
20968 case NM_LWE:
20969 check_eva(ctx);
20970 check_cp0_enabled(ctx);
20971 gen_ld(ctx, OPC_LWE, rt, rs, s);
20972 break;
20973 case NM_SWE:
20974 check_eva(ctx);
20975 check_cp0_enabled(ctx);
20976 gen_st(ctx, OPC_SWE, rt, rs, s);
20977 break;
20978 case NM_P_LLE:
20979 switch (extract32(ctx->opcode, 2, 2)) {
20980 case NM_LLE:
20981 check_xnp(ctx);
20982 check_eva(ctx);
20983 check_cp0_enabled(ctx);
20984 gen_ld(ctx, OPC_LLE, rt, rs, s);
20985 break;
20986 case NM_LLWPE:
20987 check_xnp(ctx);
20988 check_eva(ctx);
20989 check_cp0_enabled(ctx);
20990 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 20991 break;
d046a9ea 20992 default:
3a4ef3b7 20993 gen_reserved_instruction(ctx);
d046a9ea
DN
20994 break;
20995 }
20996 break;
20997 case NM_P_SCE:
20998 switch (extract32(ctx->opcode, 2, 2)) {
20999 case NM_SCE:
21000 check_xnp(ctx);
21001 check_eva(ctx);
21002 check_cp0_enabled(ctx);
33a07fa2 21003 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
d046a9ea
DN
21004 break;
21005 case NM_SCWPE:
21006 check_xnp(ctx);
21007 check_eva(ctx);
21008 check_cp0_enabled(ctx);
8d5388c1
AM
21009 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21010 true);
2431a422 21011 break;
d046a9ea 21012 default:
3a4ef3b7 21013 gen_reserved_instruction(ctx);
d046a9ea
DN
21014 break;
21015 }
21016 break;
21017 }
21018 break;
8f1d9b6d
YK
21019 case NM_P_LS_WM:
21020 case NM_P_LS_UAWM:
fb32f8c8 21021 check_nms(ctx);
8f1d9b6d
YK
21022 {
21023 int count = extract32(ctx->opcode, 12, 3);
21024 int counter = 0;
21025
21026 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21027 extract32(ctx->opcode, 0, 8);
21028 TCGv va = tcg_temp_new();
21029 TCGv t1 = tcg_temp_new();
14776ab5 21030 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
8f1d9b6d
YK
21031 NM_P_LS_UAWM ? MO_UNALN : 0;
21032
21033 count = (count == 0) ? 8 : count;
21034 while (counter != count) {
21035 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21036 int this_offset = offset + (counter << 2);
21037
21038 gen_base_offset_addr(ctx, va, rs, this_offset);
21039
21040 switch (extract32(ctx->opcode, 11, 1)) {
21041 case NM_LWM:
21042 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21043 memop | MO_TESL);
21044 gen_store_gpr(t1, this_rt);
21045 if ((this_rt == rs) &&
21046 (counter != (count - 1))) {
21047 /* UNPREDICTABLE */
21048 }
21049 break;
21050 case NM_SWM:
21051 this_rt = (rt == 0) ? 0 : this_rt;
21052 gen_load_gpr(t1, this_rt);
21053 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21054 memop | MO_TEUL);
21055 break;
21056 }
21057 counter++;
21058 }
21059 tcg_temp_free(va);
21060 tcg_temp_free(t1);
21061 }
21062 break;
21063 default:
3a4ef3b7 21064 gen_reserved_instruction(ctx);
8f1d9b6d
YK
21065 break;
21066 }
21067 }
c0280983
YK
21068 break;
21069 case NM_MOVE_BALC:
fb32f8c8 21070 check_nms(ctx);
11d0fc10
SM
21071 {
21072 TCGv t0 = tcg_temp_new();
21073 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21074 extract32(ctx->opcode, 1, 20) << 1;
21075 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21076 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21077 extract32(ctx->opcode, 21, 3));
21078 gen_load_gpr(t0, rt);
21079 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21080 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21081 tcg_temp_free(t0);
21082 }
c0280983
YK
21083 break;
21084 case NM_P_BAL:
11d0fc10
SM
21085 {
21086 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21087 extract32(ctx->opcode, 1, 24) << 1;
21088
21089 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21090 /* BC */
21091 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21092 } else {
21093 /* BALC */
21094 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21095 }
21096 }
c0280983
YK
21097 break;
21098 case NM_P_J:
11d0fc10
SM
21099 switch (extract32(ctx->opcode, 12, 4)) {
21100 case NM_JALRC:
21101 case NM_JALRC_HB:
21102 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21103 break;
21104 case NM_P_BALRSC:
21105 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21106 break;
21107 default:
3a4ef3b7 21108 gen_reserved_instruction(ctx);
11d0fc10
SM
21109 break;
21110 }
c0280983
YK
21111 break;
21112 case NM_P_BR1:
11d0fc10
SM
21113 {
21114 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21115 extract32(ctx->opcode, 1, 13) << 1;
21116 switch (extract32(ctx->opcode, 14, 2)) {
21117 case NM_BEQC:
fb32f8c8 21118 check_nms(ctx);
11d0fc10
SM
21119 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21120 break;
21121 case NM_P_BR3A:
21122 s = sextract32(ctx->opcode, 0, 1) << 14 |
21123 extract32(ctx->opcode, 1, 13) << 1;
21124 check_cp1_enabled(ctx);
21125 switch (extract32(ctx->opcode, 16, 5)) {
21126 case NM_BC1EQZC:
21127 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21128 break;
21129 case NM_BC1NEZC:
21130 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21131 break;
6d033ca7 21132 case NM_BPOSGE32C:
908f6be1 21133 check_dsp_r3(ctx);
6d033ca7
SM
21134 {
21135 int32_t imm = extract32(ctx->opcode, 1, 13) |
21136 extract32(ctx->opcode, 0, 1) << 13;
21137
21138 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
e5e6f00c 21139 imm << 1);
6d033ca7
SM
21140 }
21141 break;
11d0fc10 21142 default:
3a4ef3b7 21143 gen_reserved_instruction(ctx);
11d0fc10
SM
21144 break;
21145 }
21146 break;
21147 case NM_BGEC:
21148 if (rs == rt) {
21149 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21150 } else {
21151 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21152 }
21153 break;
21154 case NM_BGEUC:
21155 if (rs == rt || rt == 0) {
21156 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21157 } else if (rs == 0) {
21158 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21159 } else {
21160 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21161 }
21162 break;
21163 }
21164 }
c0280983
YK
21165 break;
21166 case NM_P_BR2:
11d0fc10
SM
21167 {
21168 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21169 extract32(ctx->opcode, 1, 13) << 1;
21170 switch (extract32(ctx->opcode, 14, 2)) {
21171 case NM_BNEC:
fb32f8c8 21172 check_nms(ctx);
11d0fc10
SM
21173 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21174 break;
21175 case NM_BLTC:
21176 if (rs != 0 && rt != 0 && rs == rt) {
21177 /* NOP */
21178 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21179 } else {
21180 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21181 }
21182 break;
21183 case NM_BLTUC:
21184 if (rs == 0 || rs == rt) {
21185 /* NOP */
21186 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21187 } else {
21188 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21189 }
21190 break;
21191 default:
3a4ef3b7 21192 gen_reserved_instruction(ctx);
11d0fc10
SM
21193 break;
21194 }
21195 }
c0280983
YK
21196 break;
21197 case NM_P_BRI:
11d0fc10
SM
21198 {
21199 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21200 extract32(ctx->opcode, 1, 10) << 1;
21201 uint32_t u = extract32(ctx->opcode, 11, 7);
21202
21203 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21204 rt, u, s);
21205 }
c0280983
YK
21206 break;
21207 default:
3a4ef3b7 21208 gen_reserved_instruction(ctx);
c0280983
YK
21209 break;
21210 }
21211 return 4;
21212}
21213
c533c0f4
AM
21214static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21215{
ea4ca3c2 21216 uint32_t op;
99e49abf
AM
21217 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21218 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21219 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
8bdb7029 21220 int offset;
ea4ca3c2
YK
21221 int imm;
21222
21223 /* make sure instructions are on a halfword boundary */
21224 if (ctx->base.pc_next & 0x1) {
21225 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21226 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21227 tcg_temp_free(tmp);
21228 generate_exception_end(ctx, EXCP_AdEL);
21229 return 2;
21230 }
21231
21232 op = extract32(ctx->opcode, 10, 6);
21233 switch (op) {
21234 case NM_P16_MV:
8869ad02
YK
21235 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21236 if (rt != 0) {
21237 /* MOVE */
21238 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21239 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21240 } else {
21241 /* P16.RI */
21242 switch (extract32(ctx->opcode, 3, 2)) {
21243 case NM_P16_SYSCALL:
21244 if (extract32(ctx->opcode, 2, 1) == 0) {
21245 generate_exception_end(ctx, EXCP_SYSCALL);
21246 } else {
3a4ef3b7 21247 gen_reserved_instruction(ctx);
8869ad02
YK
21248 }
21249 break;
21250 case NM_BREAK16:
21251 generate_exception_end(ctx, EXCP_BREAK);
21252 break;
21253 case NM_SDBBP16:
21254 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21255 gen_helper_do_semihosting(cpu_env);
21256 } else {
21257 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 21258 gen_reserved_instruction(ctx);
8869ad02
YK
21259 } else {
21260 generate_exception_end(ctx, EXCP_DBp);
21261 }
21262 }
21263 break;
21264 default:
3a4ef3b7 21265 gen_reserved_instruction(ctx);
8869ad02
YK
21266 break;
21267 }
21268 }
ea4ca3c2
YK
21269 break;
21270 case NM_P16_SHIFT:
c46562fb
YK
21271 {
21272 int shift = extract32(ctx->opcode, 0, 3);
21273 uint32_t opc = 0;
21274 shift = (shift == 0) ? 8 : shift;
21275
21276 switch (extract32(ctx->opcode, 3, 1)) {
21277 case NM_SLL16:
21278 opc = OPC_SLL;
21279 break;
21280 case NM_SRL16:
21281 opc = OPC_SRL;
21282 break;
21283 }
21284 gen_shift_imm(ctx, opc, rt, rs, shift);
21285 }
ea4ca3c2
YK
21286 break;
21287 case NM_P16C:
8bdb7029
YK
21288 switch (ctx->opcode & 1) {
21289 case NM_POOL16C_0:
80845edf 21290 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
21291 break;
21292 case NM_LWXS16:
21293 gen_ldxs(ctx, rt, rs, rd);
21294 break;
21295 }
ea4ca3c2
YK
21296 break;
21297 case NM_P16_A1:
21298 switch (extract32(ctx->opcode, 6, 1)) {
21299 case NM_ADDIUR1SP:
21300 imm = extract32(ctx->opcode, 0, 6) << 2;
21301 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21302 break;
21303 default:
3a4ef3b7 21304 gen_reserved_instruction(ctx);
ea4ca3c2
YK
21305 break;
21306 }
21307 break;
21308 case NM_P16_A2:
21309 switch (extract32(ctx->opcode, 3, 1)) {
21310 case NM_ADDIUR2:
21311 imm = extract32(ctx->opcode, 0, 3) << 2;
21312 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21313 break;
21314 case NM_P_ADDIURS5:
21315 rt = extract32(ctx->opcode, 5, 5);
21316 if (rt != 0) {
21317 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21318 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21319 (extract32(ctx->opcode, 0, 3));
21320 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21321 }
21322 break;
21323 }
21324 break;
21325 case NM_P16_ADDU:
21326 switch (ctx->opcode & 0x1) {
21327 case NM_ADDU16:
21328 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21329 break;
21330 case NM_SUBU16:
21331 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21332 break;
21333 }
21334 break;
21335 case NM_P16_4X4:
21336 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21337 extract32(ctx->opcode, 5, 3);
21338 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21339 extract32(ctx->opcode, 0, 3);
21340 rt = decode_gpr_gpr4(rt);
21341 rs = decode_gpr_gpr4(rs);
21342 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21343 (extract32(ctx->opcode, 3, 1))) {
21344 case NM_ADDU4X4:
fb32f8c8 21345 check_nms(ctx);
ea4ca3c2
YK
21346 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21347 break;
21348 case NM_MUL4X4:
fb32f8c8 21349 check_nms(ctx);
ea4ca3c2
YK
21350 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21351 break;
21352 default:
3a4ef3b7 21353 gen_reserved_instruction(ctx);
ea4ca3c2
YK
21354 break;
21355 }
21356 break;
21357 case NM_LI16:
8869ad02
YK
21358 {
21359 int imm = extract32(ctx->opcode, 0, 7);
21360 imm = (imm == 0x7f ? -1 : imm);
21361 if (rt != 0) {
21362 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21363 }
21364 }
ea4ca3c2
YK
21365 break;
21366 case NM_ANDI16:
80845edf
YK
21367 {
21368 uint32_t u = extract32(ctx->opcode, 0, 4);
21369 u = (u == 12) ? 0xff :
21370 (u == 13) ? 0xffff : u;
21371 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21372 }
ea4ca3c2
YK
21373 break;
21374 case NM_P16_LB:
8bdb7029
YK
21375 offset = extract32(ctx->opcode, 0, 2);
21376 switch (extract32(ctx->opcode, 2, 2)) {
21377 case NM_LB16:
21378 gen_ld(ctx, OPC_LB, rt, rs, offset);
21379 break;
21380 case NM_SB16:
21381 rt = decode_gpr_gpr3_src_store(
99e49abf 21382 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21383 gen_st(ctx, OPC_SB, rt, rs, offset);
21384 break;
21385 case NM_LBU16:
21386 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21387 break;
21388 default:
3a4ef3b7 21389 gen_reserved_instruction(ctx);
8bdb7029
YK
21390 break;
21391 }
ea4ca3c2
YK
21392 break;
21393 case NM_P16_LH:
8bdb7029
YK
21394 offset = extract32(ctx->opcode, 1, 2) << 1;
21395 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21396 case NM_LH16:
21397 gen_ld(ctx, OPC_LH, rt, rs, offset);
21398 break;
21399 case NM_SH16:
21400 rt = decode_gpr_gpr3_src_store(
99e49abf 21401 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21402 gen_st(ctx, OPC_SH, rt, rs, offset);
21403 break;
21404 case NM_LHU16:
21405 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21406 break;
21407 default:
3a4ef3b7 21408 gen_reserved_instruction(ctx);
8bdb7029
YK
21409 break;
21410 }
ea4ca3c2
YK
21411 break;
21412 case NM_LW16:
8bdb7029
YK
21413 offset = extract32(ctx->opcode, 0, 4) << 2;
21414 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21415 break;
21416 case NM_LWSP16:
8bdb7029
YK
21417 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21418 offset = extract32(ctx->opcode, 0, 5) << 2;
21419 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
21420 break;
21421 case NM_LW4X4:
fb32f8c8 21422 check_nms(ctx);
8bdb7029
YK
21423 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21424 extract32(ctx->opcode, 5, 3);
21425 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21426 extract32(ctx->opcode, 0, 3);
21427 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21428 (extract32(ctx->opcode, 8, 1) << 2);
21429 rt = decode_gpr_gpr4(rt);
21430 rs = decode_gpr_gpr4(rs);
21431 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21432 break;
21433 case NM_SW4X4:
fb32f8c8 21434 check_nms(ctx);
8bdb7029
YK
21435 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21436 extract32(ctx->opcode, 5, 3);
21437 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21438 extract32(ctx->opcode, 0, 3);
21439 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21440 (extract32(ctx->opcode, 8, 1) << 2);
21441 rt = decode_gpr_gpr4_zero(rt);
21442 rs = decode_gpr_gpr4(rs);
21443 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21444 break;
21445 case NM_LWGP16:
8bdb7029
YK
21446 offset = extract32(ctx->opcode, 0, 7) << 2;
21447 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
21448 break;
21449 case NM_SWSP16:
8bdb7029
YK
21450 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21451 offset = extract32(ctx->opcode, 0, 5) << 2;
21452 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
21453 break;
21454 case NM_SW16:
8bdb7029 21455 rt = decode_gpr_gpr3_src_store(
99e49abf
AM
21456 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21457 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
8bdb7029
YK
21458 offset = extract32(ctx->opcode, 0, 4) << 2;
21459 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21460 break;
21461 case NM_SWGP16:
8bdb7029 21462 rt = decode_gpr_gpr3_src_store(
99e49abf 21463 NANOMIPS_EXTRACT_RT3(ctx->opcode));
8bdb7029
YK
21464 offset = extract32(ctx->opcode, 0, 7) << 2;
21465 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
21466 break;
21467 case NM_BC16:
764371d2
SM
21468 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21469 (sextract32(ctx->opcode, 0, 1) << 10) |
21470 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21471 break;
21472 case NM_BALC16:
764371d2
SM
21473 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21474 (sextract32(ctx->opcode, 0, 1) << 10) |
21475 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21476 break;
21477 case NM_BEQZC16:
764371d2
SM
21478 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21479 (sextract32(ctx->opcode, 0, 1) << 7) |
21480 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21481 break;
21482 case NM_BNEZC16:
764371d2
SM
21483 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21484 (sextract32(ctx->opcode, 0, 1) << 7) |
21485 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21486 break;
21487 case NM_P16_BR:
764371d2
SM
21488 switch (ctx->opcode & 0xf) {
21489 case 0:
21490 /* P16.JRC */
21491 switch (extract32(ctx->opcode, 4, 1)) {
21492 case NM_JRC:
21493 gen_compute_branch_nm(ctx, OPC_JR, 2,
21494 extract32(ctx->opcode, 5, 5), 0, 0);
21495 break;
21496 case NM_JALRC16:
21497 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21498 extract32(ctx->opcode, 5, 5), 31, 0);
21499 break;
21500 }
21501 break;
21502 default:
21503 {
21504 /* P16.BRI */
21505 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21506 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21507 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21508 extract32(ctx->opcode, 0, 4) << 1);
21509 }
21510 break;
21511 }
ea4ca3c2
YK
21512 break;
21513 case NM_P16_SR:
bf0718c5
SM
21514 {
21515 int count = extract32(ctx->opcode, 0, 4);
21516 int u = extract32(ctx->opcode, 4, 4) << 4;
21517
21518 rt = 30 + extract32(ctx->opcode, 9, 1);
21519 switch (extract32(ctx->opcode, 8, 1)) {
21520 case NM_SAVE16:
21521 gen_save(ctx, rt, count, 0, u);
21522 break;
21523 case NM_RESTORE_JRC16:
21524 gen_restore(ctx, rt, count, 0, u);
21525 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21526 break;
21527 }
21528 }
ea4ca3c2
YK
21529 break;
21530 case NM_MOVEP:
ea4ca3c2 21531 case NM_MOVEPREV:
fb32f8c8 21532 check_nms(ctx);
4d18232c
YK
21533 {
21534 static const int gpr2reg1[] = {4, 5, 6, 7};
21535 static const int gpr2reg2[] = {5, 6, 7, 8};
21536 int re;
21537 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21538 extract32(ctx->opcode, 8, 1);
21539 int r1 = gpr2reg1[rd2];
21540 int r2 = gpr2reg2[rd2];
21541 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21542 extract32(ctx->opcode, 0, 3);
21543 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21544 extract32(ctx->opcode, 5, 3);
21545 TCGv t0 = tcg_temp_new();
21546 TCGv t1 = tcg_temp_new();
21547 if (op == NM_MOVEP) {
21548 rd = r1;
21549 re = r2;
21550 rs = decode_gpr_gpr4_zero(r3);
21551 rt = decode_gpr_gpr4_zero(r4);
21552 } else {
21553 rd = decode_gpr_gpr4(r3);
21554 re = decode_gpr_gpr4(r4);
21555 rs = r1;
21556 rt = r2;
21557 }
21558 gen_load_gpr(t0, rs);
21559 gen_load_gpr(t1, rt);
21560 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21561 tcg_gen_mov_tl(cpu_gpr[re], t1);
21562 tcg_temp_free(t0);
21563 tcg_temp_free(t1);
21564 }
ea4ca3c2
YK
21565 break;
21566 default:
c0280983 21567 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
21568 }
21569
c533c0f4
AM
21570 return 2;
21571}
21572
21573
9b1a1d68 21574/* MIPSDSP functions. */
d75c135e 21575static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
21576 int rd, int base, int offset)
21577{
9b1a1d68
JL
21578 TCGv t0;
21579
9b1a1d68
JL
21580 check_dsp(ctx);
21581 t0 = tcg_temp_new();
21582
21583 if (base == 0) {
21584 gen_load_gpr(t0, offset);
21585 } else if (offset == 0) {
21586 gen_load_gpr(t0, base);
21587 } else {
21588 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21589 }
21590
9b1a1d68
JL
21591 switch (opc) {
21592 case OPC_LBUX:
5f68f5ae 21593 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 21594 gen_store_gpr(t0, rd);
9b1a1d68
JL
21595 break;
21596 case OPC_LHX:
5f68f5ae 21597 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 21598 gen_store_gpr(t0, rd);
9b1a1d68
JL
21599 break;
21600 case OPC_LWX:
5f68f5ae 21601 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 21602 gen_store_gpr(t0, rd);
9b1a1d68
JL
21603 break;
21604#if defined(TARGET_MIPS64)
21605 case OPC_LDX:
5f68f5ae 21606 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 21607 gen_store_gpr(t0, rd);
9b1a1d68
JL
21608 break;
21609#endif
21610 }
9b1a1d68
JL
21611 tcg_temp_free(t0);
21612}
21613
461c08df
JL
21614static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21615 int ret, int v1, int v2)
21616{
461c08df
JL
21617 TCGv v1_t;
21618 TCGv v2_t;
21619
21620 if (ret == 0) {
21621 /* Treat as NOP. */
461c08df
JL
21622 return;
21623 }
21624
21625 v1_t = tcg_temp_new();
21626 v2_t = tcg_temp_new();
21627
21628 gen_load_gpr(v1_t, v1);
21629 gen_load_gpr(v2_t, v2);
21630
21631 switch (op1) {
21632 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21633 case OPC_MULT_G_2E:
908f6be1 21634 check_dsp_r2(ctx);
461c08df
JL
21635 switch (op2) {
21636 case OPC_ADDUH_QB:
21637 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21638 break;
21639 case OPC_ADDUH_R_QB:
21640 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21641 break;
21642 case OPC_ADDQH_PH:
21643 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21644 break;
21645 case OPC_ADDQH_R_PH:
21646 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21647 break;
21648 case OPC_ADDQH_W:
21649 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21650 break;
21651 case OPC_ADDQH_R_W:
21652 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21653 break;
21654 case OPC_SUBUH_QB:
21655 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21656 break;
21657 case OPC_SUBUH_R_QB:
21658 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21659 break;
21660 case OPC_SUBQH_PH:
21661 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21662 break;
21663 case OPC_SUBQH_R_PH:
21664 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21665 break;
21666 case OPC_SUBQH_W:
21667 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21668 break;
21669 case OPC_SUBQH_R_W:
21670 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21671 break;
21672 }
21673 break;
21674 case OPC_ABSQ_S_PH_DSP:
21675 switch (op2) {
21676 case OPC_ABSQ_S_QB:
908f6be1 21677 check_dsp_r2(ctx);
461c08df
JL
21678 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21679 break;
21680 case OPC_ABSQ_S_PH:
21681 check_dsp(ctx);
21682 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21683 break;
21684 case OPC_ABSQ_S_W:
21685 check_dsp(ctx);
21686 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21687 break;
21688 case OPC_PRECEQ_W_PHL:
21689 check_dsp(ctx);
21690 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21691 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21692 break;
21693 case OPC_PRECEQ_W_PHR:
21694 check_dsp(ctx);
21695 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21696 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21697 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21698 break;
21699 case OPC_PRECEQU_PH_QBL:
21700 check_dsp(ctx);
21701 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21702 break;
21703 case OPC_PRECEQU_PH_QBR:
21704 check_dsp(ctx);
21705 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21706 break;
21707 case OPC_PRECEQU_PH_QBLA:
21708 check_dsp(ctx);
21709 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21710 break;
21711 case OPC_PRECEQU_PH_QBRA:
21712 check_dsp(ctx);
21713 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21714 break;
21715 case OPC_PRECEU_PH_QBL:
21716 check_dsp(ctx);
21717 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21718 break;
21719 case OPC_PRECEU_PH_QBR:
21720 check_dsp(ctx);
21721 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21722 break;
21723 case OPC_PRECEU_PH_QBLA:
21724 check_dsp(ctx);
21725 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21726 break;
21727 case OPC_PRECEU_PH_QBRA:
21728 check_dsp(ctx);
21729 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21730 break;
21731 }
21732 break;
21733 case OPC_ADDU_QB_DSP:
21734 switch (op2) {
21735 case OPC_ADDQ_PH:
21736 check_dsp(ctx);
21737 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21738 break;
21739 case OPC_ADDQ_S_PH:
21740 check_dsp(ctx);
21741 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21742 break;
21743 case OPC_ADDQ_S_W:
21744 check_dsp(ctx);
21745 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21746 break;
21747 case OPC_ADDU_QB:
21748 check_dsp(ctx);
21749 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21750 break;
21751 case OPC_ADDU_S_QB:
21752 check_dsp(ctx);
21753 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21754 break;
21755 case OPC_ADDU_PH:
908f6be1 21756 check_dsp_r2(ctx);
461c08df
JL
21757 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21758 break;
21759 case OPC_ADDU_S_PH:
908f6be1 21760 check_dsp_r2(ctx);
461c08df
JL
21761 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21762 break;
21763 case OPC_SUBQ_PH:
21764 check_dsp(ctx);
21765 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21766 break;
21767 case OPC_SUBQ_S_PH:
21768 check_dsp(ctx);
21769 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21770 break;
21771 case OPC_SUBQ_S_W:
21772 check_dsp(ctx);
21773 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21774 break;
21775 case OPC_SUBU_QB:
21776 check_dsp(ctx);
21777 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21778 break;
21779 case OPC_SUBU_S_QB:
21780 check_dsp(ctx);
21781 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21782 break;
21783 case OPC_SUBU_PH:
908f6be1 21784 check_dsp_r2(ctx);
461c08df
JL
21785 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21786 break;
21787 case OPC_SUBU_S_PH:
908f6be1 21788 check_dsp_r2(ctx);
461c08df
JL
21789 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21790 break;
21791 case OPC_ADDSC:
21792 check_dsp(ctx);
21793 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21794 break;
21795 case OPC_ADDWC:
21796 check_dsp(ctx);
21797 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21798 break;
21799 case OPC_MODSUB:
21800 check_dsp(ctx);
21801 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21802 break;
21803 case OPC_RADDU_W_QB:
21804 check_dsp(ctx);
21805 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21806 break;
21807 }
21808 break;
21809 case OPC_CMPU_EQ_QB_DSP:
21810 switch (op2) {
21811 case OPC_PRECR_QB_PH:
908f6be1 21812 check_dsp_r2(ctx);
461c08df
JL
21813 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21814 break;
21815 case OPC_PRECRQ_QB_PH:
21816 check_dsp(ctx);
21817 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21818 break;
21819 case OPC_PRECR_SRA_PH_W:
908f6be1 21820 check_dsp_r2(ctx);
461c08df
JL
21821 {
21822 TCGv_i32 sa_t = tcg_const_i32(v2);
21823 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21824 cpu_gpr[ret]);
21825 tcg_temp_free_i32(sa_t);
21826 break;
21827 }
21828 case OPC_PRECR_SRA_R_PH_W:
908f6be1 21829 check_dsp_r2(ctx);
461c08df
JL
21830 {
21831 TCGv_i32 sa_t = tcg_const_i32(v2);
21832 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21833 cpu_gpr[ret]);
21834 tcg_temp_free_i32(sa_t);
21835 break;
21836 }
21837 case OPC_PRECRQ_PH_W:
21838 check_dsp(ctx);
21839 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21840 break;
21841 case OPC_PRECRQ_RS_PH_W:
21842 check_dsp(ctx);
21843 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21844 break;
21845 case OPC_PRECRQU_S_QB_PH:
21846 check_dsp(ctx);
21847 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21848 break;
21849 }
21850 break;
21851#ifdef TARGET_MIPS64
21852 case OPC_ABSQ_S_QH_DSP:
21853 switch (op2) {
21854 case OPC_PRECEQ_L_PWL:
21855 check_dsp(ctx);
21856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21857 break;
21858 case OPC_PRECEQ_L_PWR:
21859 check_dsp(ctx);
21860 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21861 break;
21862 case OPC_PRECEQ_PW_QHL:
21863 check_dsp(ctx);
21864 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21865 break;
21866 case OPC_PRECEQ_PW_QHR:
21867 check_dsp(ctx);
21868 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21869 break;
21870 case OPC_PRECEQ_PW_QHLA:
21871 check_dsp(ctx);
21872 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21873 break;
21874 case OPC_PRECEQ_PW_QHRA:
21875 check_dsp(ctx);
21876 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21877 break;
21878 case OPC_PRECEQU_QH_OBL:
21879 check_dsp(ctx);
21880 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21881 break;
21882 case OPC_PRECEQU_QH_OBR:
21883 check_dsp(ctx);
21884 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21885 break;
21886 case OPC_PRECEQU_QH_OBLA:
21887 check_dsp(ctx);
21888 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21889 break;
21890 case OPC_PRECEQU_QH_OBRA:
21891 check_dsp(ctx);
21892 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21893 break;
21894 case OPC_PRECEU_QH_OBL:
21895 check_dsp(ctx);
21896 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21897 break;
21898 case OPC_PRECEU_QH_OBR:
21899 check_dsp(ctx);
21900 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21901 break;
21902 case OPC_PRECEU_QH_OBLA:
21903 check_dsp(ctx);
21904 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21905 break;
21906 case OPC_PRECEU_QH_OBRA:
21907 check_dsp(ctx);
21908 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21909 break;
21910 case OPC_ABSQ_S_OB:
908f6be1 21911 check_dsp_r2(ctx);
461c08df
JL
21912 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21913 break;
21914 case OPC_ABSQ_S_PW:
21915 check_dsp(ctx);
21916 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21917 break;
21918 case OPC_ABSQ_S_QH:
21919 check_dsp(ctx);
21920 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21921 break;
21922 }
21923 break;
21924 case OPC_ADDU_OB_DSP:
21925 switch (op2) {
21926 case OPC_RADDU_L_OB:
21927 check_dsp(ctx);
21928 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21929 break;
21930 case OPC_SUBQ_PW:
21931 check_dsp(ctx);
21932 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21933 break;
21934 case OPC_SUBQ_S_PW:
21935 check_dsp(ctx);
21936 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21937 break;
21938 case OPC_SUBQ_QH:
21939 check_dsp(ctx);
21940 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21941 break;
21942 case OPC_SUBQ_S_QH:
21943 check_dsp(ctx);
21944 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21945 break;
21946 case OPC_SUBU_OB:
21947 check_dsp(ctx);
21948 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21949 break;
21950 case OPC_SUBU_S_OB:
21951 check_dsp(ctx);
21952 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21953 break;
21954 case OPC_SUBU_QH:
908f6be1 21955 check_dsp_r2(ctx);
461c08df
JL
21956 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21957 break;
21958 case OPC_SUBU_S_QH:
908f6be1 21959 check_dsp_r2(ctx);
461c08df
JL
21960 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21961 break;
21962 case OPC_SUBUH_OB:
908f6be1 21963 check_dsp_r2(ctx);
461c08df
JL
21964 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21965 break;
21966 case OPC_SUBUH_R_OB:
908f6be1 21967 check_dsp_r2(ctx);
461c08df
JL
21968 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21969 break;
21970 case OPC_ADDQ_PW:
21971 check_dsp(ctx);
21972 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21973 break;
21974 case OPC_ADDQ_S_PW:
21975 check_dsp(ctx);
21976 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21977 break;
21978 case OPC_ADDQ_QH:
21979 check_dsp(ctx);
21980 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21981 break;
21982 case OPC_ADDQ_S_QH:
21983 check_dsp(ctx);
21984 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21985 break;
21986 case OPC_ADDU_OB:
21987 check_dsp(ctx);
21988 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21989 break;
21990 case OPC_ADDU_S_OB:
21991 check_dsp(ctx);
21992 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21993 break;
21994 case OPC_ADDU_QH:
908f6be1 21995 check_dsp_r2(ctx);
461c08df
JL
21996 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21997 break;
21998 case OPC_ADDU_S_QH:
908f6be1 21999 check_dsp_r2(ctx);
461c08df
JL
22000 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22001 break;
22002 case OPC_ADDUH_OB:
908f6be1 22003 check_dsp_r2(ctx);
461c08df
JL
22004 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22005 break;
22006 case OPC_ADDUH_R_OB:
908f6be1 22007 check_dsp_r2(ctx);
461c08df
JL
22008 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22009 break;
22010 }
22011 break;
22012 case OPC_CMPU_EQ_OB_DSP:
22013 switch (op2) {
22014 case OPC_PRECR_OB_QH:
908f6be1 22015 check_dsp_r2(ctx);
461c08df
JL
22016 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22017 break;
22018 case OPC_PRECR_SRA_QH_PW:
908f6be1 22019 check_dsp_r2(ctx);
461c08df
JL
22020 {
22021 TCGv_i32 ret_t = tcg_const_i32(ret);
22022 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22023 tcg_temp_free_i32(ret_t);
22024 break;
22025 }
22026 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22027 check_dsp_r2(ctx);
461c08df
JL
22028 {
22029 TCGv_i32 sa_v = tcg_const_i32(ret);
22030 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22031 tcg_temp_free_i32(sa_v);
22032 break;
22033 }
22034 case OPC_PRECRQ_OB_QH:
22035 check_dsp(ctx);
22036 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22037 break;
22038 case OPC_PRECRQ_PW_L:
22039 check_dsp(ctx);
22040 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22041 break;
22042 case OPC_PRECRQ_QH_PW:
22043 check_dsp(ctx);
22044 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22045 break;
22046 case OPC_PRECRQ_RS_QH_PW:
22047 check_dsp(ctx);
22048 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22049 break;
22050 case OPC_PRECRQU_S_OB_QH:
22051 check_dsp(ctx);
22052 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22053 break;
22054 }
22055 break;
22056#endif
22057 }
22058
22059 tcg_temp_free(v1_t);
22060 tcg_temp_free(v2_t);
461c08df 22061}
9b1a1d68 22062
77c5fa8b
JL
22063static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22064 int ret, int v1, int v2)
22065{
22066 uint32_t op2;
77c5fa8b
JL
22067 TCGv t0;
22068 TCGv v1_t;
22069 TCGv v2_t;
22070
22071 if (ret == 0) {
22072 /* Treat as NOP. */
77c5fa8b
JL
22073 return;
22074 }
22075
22076 t0 = tcg_temp_new();
22077 v1_t = tcg_temp_new();
22078 v2_t = tcg_temp_new();
22079
22080 tcg_gen_movi_tl(t0, v1);
22081 gen_load_gpr(v1_t, v1);
22082 gen_load_gpr(v2_t, v2);
22083
22084 switch (opc) {
22085 case OPC_SHLL_QB_DSP:
22086 {
22087 op2 = MASK_SHLL_QB(ctx->opcode);
22088 switch (op2) {
22089 case OPC_SHLL_QB:
22090 check_dsp(ctx);
22091 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22092 break;
22093 case OPC_SHLLV_QB:
22094 check_dsp(ctx);
22095 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22096 break;
22097 case OPC_SHLL_PH:
22098 check_dsp(ctx);
22099 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22100 break;
22101 case OPC_SHLLV_PH:
22102 check_dsp(ctx);
22103 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22104 break;
22105 case OPC_SHLL_S_PH:
22106 check_dsp(ctx);
22107 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22108 break;
22109 case OPC_SHLLV_S_PH:
22110 check_dsp(ctx);
22111 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22112 break;
22113 case OPC_SHLL_S_W:
22114 check_dsp(ctx);
22115 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22116 break;
22117 case OPC_SHLLV_S_W:
22118 check_dsp(ctx);
22119 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22120 break;
22121 case OPC_SHRL_QB:
22122 check_dsp(ctx);
22123 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22124 break;
22125 case OPC_SHRLV_QB:
22126 check_dsp(ctx);
22127 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22128 break;
22129 case OPC_SHRL_PH:
908f6be1 22130 check_dsp_r2(ctx);
77c5fa8b
JL
22131 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22132 break;
22133 case OPC_SHRLV_PH:
908f6be1 22134 check_dsp_r2(ctx);
77c5fa8b
JL
22135 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22136 break;
22137 case OPC_SHRA_QB:
908f6be1 22138 check_dsp_r2(ctx);
77c5fa8b
JL
22139 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22140 break;
22141 case OPC_SHRA_R_QB:
908f6be1 22142 check_dsp_r2(ctx);
77c5fa8b
JL
22143 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22144 break;
22145 case OPC_SHRAV_QB:
908f6be1 22146 check_dsp_r2(ctx);
77c5fa8b
JL
22147 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22148 break;
22149 case OPC_SHRAV_R_QB:
908f6be1 22150 check_dsp_r2(ctx);
77c5fa8b
JL
22151 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22152 break;
22153 case OPC_SHRA_PH:
22154 check_dsp(ctx);
22155 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22156 break;
22157 case OPC_SHRA_R_PH:
22158 check_dsp(ctx);
22159 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22160 break;
22161 case OPC_SHRAV_PH:
22162 check_dsp(ctx);
22163 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22164 break;
22165 case OPC_SHRAV_R_PH:
22166 check_dsp(ctx);
22167 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22168 break;
22169 case OPC_SHRA_R_W:
22170 check_dsp(ctx);
22171 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22172 break;
22173 case OPC_SHRAV_R_W:
22174 check_dsp(ctx);
22175 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22176 break;
22177 default: /* Invalid */
22178 MIPS_INVAL("MASK SHLL.QB");
3a4ef3b7 22179 gen_reserved_instruction(ctx);
77c5fa8b
JL
22180 break;
22181 }
22182 break;
22183 }
22184#ifdef TARGET_MIPS64
22185 case OPC_SHLL_OB_DSP:
22186 op2 = MASK_SHLL_OB(ctx->opcode);
22187 switch (op2) {
22188 case OPC_SHLL_PW:
22189 check_dsp(ctx);
22190 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22191 break;
22192 case OPC_SHLLV_PW:
22193 check_dsp(ctx);
22194 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22195 break;
22196 case OPC_SHLL_S_PW:
22197 check_dsp(ctx);
22198 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22199 break;
22200 case OPC_SHLLV_S_PW:
22201 check_dsp(ctx);
22202 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22203 break;
22204 case OPC_SHLL_OB:
22205 check_dsp(ctx);
22206 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22207 break;
22208 case OPC_SHLLV_OB:
22209 check_dsp(ctx);
22210 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22211 break;
22212 case OPC_SHLL_QH:
22213 check_dsp(ctx);
22214 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22215 break;
22216 case OPC_SHLLV_QH:
22217 check_dsp(ctx);
22218 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22219 break;
22220 case OPC_SHLL_S_QH:
22221 check_dsp(ctx);
22222 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22223 break;
22224 case OPC_SHLLV_S_QH:
22225 check_dsp(ctx);
22226 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22227 break;
22228 case OPC_SHRA_OB:
908f6be1 22229 check_dsp_r2(ctx);
77c5fa8b
JL
22230 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22231 break;
22232 case OPC_SHRAV_OB:
908f6be1 22233 check_dsp_r2(ctx);
77c5fa8b
JL
22234 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22235 break;
22236 case OPC_SHRA_R_OB:
908f6be1 22237 check_dsp_r2(ctx);
77c5fa8b
JL
22238 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22239 break;
22240 case OPC_SHRAV_R_OB:
908f6be1 22241 check_dsp_r2(ctx);
77c5fa8b
JL
22242 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22243 break;
22244 case OPC_SHRA_PW:
22245 check_dsp(ctx);
22246 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22247 break;
22248 case OPC_SHRAV_PW:
22249 check_dsp(ctx);
22250 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22251 break;
22252 case OPC_SHRA_R_PW:
22253 check_dsp(ctx);
22254 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22255 break;
22256 case OPC_SHRAV_R_PW:
22257 check_dsp(ctx);
22258 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22259 break;
22260 case OPC_SHRA_QH:
22261 check_dsp(ctx);
22262 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22263 break;
22264 case OPC_SHRAV_QH:
22265 check_dsp(ctx);
22266 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22267 break;
22268 case OPC_SHRA_R_QH:
22269 check_dsp(ctx);
22270 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22271 break;
22272 case OPC_SHRAV_R_QH:
22273 check_dsp(ctx);
22274 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22275 break;
22276 case OPC_SHRL_OB:
22277 check_dsp(ctx);
22278 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22279 break;
22280 case OPC_SHRLV_OB:
22281 check_dsp(ctx);
22282 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22283 break;
22284 case OPC_SHRL_QH:
908f6be1 22285 check_dsp_r2(ctx);
77c5fa8b
JL
22286 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22287 break;
22288 case OPC_SHRLV_QH:
908f6be1 22289 check_dsp_r2(ctx);
77c5fa8b
JL
22290 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22291 break;
22292 default: /* Invalid */
22293 MIPS_INVAL("MASK SHLL.OB");
3a4ef3b7 22294 gen_reserved_instruction(ctx);
77c5fa8b
JL
22295 break;
22296 }
22297 break;
22298#endif
22299 }
22300
22301 tcg_temp_free(t0);
22302 tcg_temp_free(v1_t);
22303 tcg_temp_free(v2_t);
77c5fa8b
JL
22304}
22305
a22260ae
JL
22306static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22307 int ret, int v1, int v2, int check_ret)
22308{
a22260ae
JL
22309 TCGv_i32 t0;
22310 TCGv v1_t;
22311 TCGv v2_t;
22312
22313 if ((ret == 0) && (check_ret == 1)) {
22314 /* Treat as NOP. */
a22260ae
JL
22315 return;
22316 }
22317
22318 t0 = tcg_temp_new_i32();
22319 v1_t = tcg_temp_new();
22320 v2_t = tcg_temp_new();
22321
22322 tcg_gen_movi_i32(t0, ret);
22323 gen_load_gpr(v1_t, v1);
22324 gen_load_gpr(v2_t, v2);
22325
22326 switch (op1) {
7480515f
AM
22327 /*
22328 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22329 * the same mask and op1.
22330 */
a22260ae 22331 case OPC_MULT_G_2E:
908f6be1 22332 check_dsp_r2(ctx);
a22260ae
JL
22333 switch (op2) {
22334 case OPC_MUL_PH:
22335 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22336 break;
22337 case OPC_MUL_S_PH:
22338 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22339 break;
22340 case OPC_MULQ_S_W:
22341 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22342 break;
22343 case OPC_MULQ_RS_W:
22344 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22345 break;
22346 }
22347 break;
22348 case OPC_DPA_W_PH_DSP:
22349 switch (op2) {
22350 case OPC_DPAU_H_QBL:
22351 check_dsp(ctx);
22352 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22353 break;
22354 case OPC_DPAU_H_QBR:
22355 check_dsp(ctx);
22356 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22357 break;
22358 case OPC_DPSU_H_QBL:
22359 check_dsp(ctx);
22360 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22361 break;
22362 case OPC_DPSU_H_QBR:
22363 check_dsp(ctx);
22364 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22365 break;
22366 case OPC_DPA_W_PH:
908f6be1 22367 check_dsp_r2(ctx);
a22260ae
JL
22368 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22369 break;
22370 case OPC_DPAX_W_PH:
908f6be1 22371 check_dsp_r2(ctx);
a22260ae
JL
22372 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22373 break;
22374 case OPC_DPAQ_S_W_PH:
22375 check_dsp(ctx);
22376 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22377 break;
22378 case OPC_DPAQX_S_W_PH:
908f6be1 22379 check_dsp_r2(ctx);
a22260ae
JL
22380 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22381 break;
22382 case OPC_DPAQX_SA_W_PH:
908f6be1 22383 check_dsp_r2(ctx);
a22260ae
JL
22384 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22385 break;
22386 case OPC_DPS_W_PH:
908f6be1 22387 check_dsp_r2(ctx);
a22260ae
JL
22388 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22389 break;
22390 case OPC_DPSX_W_PH:
908f6be1 22391 check_dsp_r2(ctx);
a22260ae
JL
22392 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22393 break;
22394 case OPC_DPSQ_S_W_PH:
22395 check_dsp(ctx);
22396 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22397 break;
22398 case OPC_DPSQX_S_W_PH:
908f6be1 22399 check_dsp_r2(ctx);
a22260ae
JL
22400 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22401 break;
22402 case OPC_DPSQX_SA_W_PH:
908f6be1 22403 check_dsp_r2(ctx);
a22260ae
JL
22404 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22405 break;
22406 case OPC_MULSAQ_S_W_PH:
22407 check_dsp(ctx);
22408 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22409 break;
22410 case OPC_DPAQ_SA_L_W:
22411 check_dsp(ctx);
22412 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22413 break;
22414 case OPC_DPSQ_SA_L_W:
22415 check_dsp(ctx);
22416 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22417 break;
22418 case OPC_MAQ_S_W_PHL:
22419 check_dsp(ctx);
22420 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22421 break;
22422 case OPC_MAQ_S_W_PHR:
22423 check_dsp(ctx);
22424 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22425 break;
22426 case OPC_MAQ_SA_W_PHL:
22427 check_dsp(ctx);
22428 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22429 break;
22430 case OPC_MAQ_SA_W_PHR:
22431 check_dsp(ctx);
22432 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22433 break;
22434 case OPC_MULSA_W_PH:
908f6be1 22435 check_dsp_r2(ctx);
a22260ae
JL
22436 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22437 break;
22438 }
22439 break;
22440#ifdef TARGET_MIPS64
22441 case OPC_DPAQ_W_QH_DSP:
22442 {
22443 int ac = ret & 0x03;
22444 tcg_gen_movi_i32(t0, ac);
22445
22446 switch (op2) {
22447 case OPC_DMADD:
22448 check_dsp(ctx);
22449 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22450 break;
22451 case OPC_DMADDU:
22452 check_dsp(ctx);
22453 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22454 break;
22455 case OPC_DMSUB:
22456 check_dsp(ctx);
22457 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22458 break;
22459 case OPC_DMSUBU:
22460 check_dsp(ctx);
22461 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22462 break;
22463 case OPC_DPA_W_QH:
908f6be1 22464 check_dsp_r2(ctx);
a22260ae
JL
22465 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22466 break;
22467 case OPC_DPAQ_S_W_QH:
22468 check_dsp(ctx);
22469 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22470 break;
22471 case OPC_DPAQ_SA_L_PW:
22472 check_dsp(ctx);
22473 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22474 break;
22475 case OPC_DPAU_H_OBL:
22476 check_dsp(ctx);
22477 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22478 break;
22479 case OPC_DPAU_H_OBR:
22480 check_dsp(ctx);
22481 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22482 break;
22483 case OPC_DPS_W_QH:
908f6be1 22484 check_dsp_r2(ctx);
a22260ae
JL
22485 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22486 break;
22487 case OPC_DPSQ_S_W_QH:
22488 check_dsp(ctx);
22489 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22490 break;
22491 case OPC_DPSQ_SA_L_PW:
22492 check_dsp(ctx);
22493 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22494 break;
22495 case OPC_DPSU_H_OBL:
22496 check_dsp(ctx);
22497 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22498 break;
22499 case OPC_DPSU_H_OBR:
22500 check_dsp(ctx);
22501 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22502 break;
22503 case OPC_MAQ_S_L_PWL:
22504 check_dsp(ctx);
22505 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22506 break;
22507 case OPC_MAQ_S_L_PWR:
22508 check_dsp(ctx);
22509 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22510 break;
22511 case OPC_MAQ_S_W_QHLL:
22512 check_dsp(ctx);
22513 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22514 break;
22515 case OPC_MAQ_SA_W_QHLL:
22516 check_dsp(ctx);
22517 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22518 break;
22519 case OPC_MAQ_S_W_QHLR:
22520 check_dsp(ctx);
22521 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22522 break;
22523 case OPC_MAQ_SA_W_QHLR:
22524 check_dsp(ctx);
22525 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22526 break;
22527 case OPC_MAQ_S_W_QHRL:
22528 check_dsp(ctx);
22529 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22530 break;
22531 case OPC_MAQ_SA_W_QHRL:
22532 check_dsp(ctx);
22533 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22534 break;
22535 case OPC_MAQ_S_W_QHRR:
22536 check_dsp(ctx);
22537 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22538 break;
22539 case OPC_MAQ_SA_W_QHRR:
22540 check_dsp(ctx);
22541 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22542 break;
22543 case OPC_MULSAQ_S_L_PW:
22544 check_dsp(ctx);
22545 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22546 break;
22547 case OPC_MULSAQ_S_W_QH:
22548 check_dsp(ctx);
22549 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22550 break;
22551 }
22552 }
22553 break;
22554#endif
22555 case OPC_ADDU_QB_DSP:
22556 switch (op2) {
22557 case OPC_MULEU_S_PH_QBL:
22558 check_dsp(ctx);
22559 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22560 break;
22561 case OPC_MULEU_S_PH_QBR:
22562 check_dsp(ctx);
22563 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22564 break;
22565 case OPC_MULQ_RS_PH:
22566 check_dsp(ctx);
22567 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22568 break;
22569 case OPC_MULEQ_S_W_PHL:
22570 check_dsp(ctx);
22571 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_MULEQ_S_W_PHR:
22574 check_dsp(ctx);
22575 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22576 break;
22577 case OPC_MULQ_S_PH:
908f6be1 22578 check_dsp_r2(ctx);
a22260ae
JL
22579 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22580 break;
22581 }
22582 break;
22583#ifdef TARGET_MIPS64
22584 case OPC_ADDU_OB_DSP:
22585 switch (op2) {
22586 case OPC_MULEQ_S_PW_QHL:
22587 check_dsp(ctx);
22588 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22589 break;
22590 case OPC_MULEQ_S_PW_QHR:
22591 check_dsp(ctx);
22592 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22593 break;
22594 case OPC_MULEU_S_QH_OBL:
22595 check_dsp(ctx);
22596 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22597 break;
22598 case OPC_MULEU_S_QH_OBR:
22599 check_dsp(ctx);
22600 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22601 break;
22602 case OPC_MULQ_RS_QH:
22603 check_dsp(ctx);
22604 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22605 break;
22606 }
22607 break;
22608#endif
22609 }
22610
22611 tcg_temp_free_i32(t0);
22612 tcg_temp_free(v1_t);
22613 tcg_temp_free(v2_t);
a22260ae
JL
22614}
22615
d75c135e 22616static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
22617 int ret, int val)
22618{
1cb6686c
JL
22619 int16_t imm;
22620 TCGv t0;
22621 TCGv val_t;
22622
22623 if (ret == 0) {
22624 /* Treat as NOP. */
1cb6686c
JL
22625 return;
22626 }
22627
22628 t0 = tcg_temp_new();
22629 val_t = tcg_temp_new();
22630 gen_load_gpr(val_t, val);
22631
22632 switch (op1) {
22633 case OPC_ABSQ_S_PH_DSP:
22634 switch (op2) {
22635 case OPC_BITREV:
22636 check_dsp(ctx);
22637 gen_helper_bitrev(cpu_gpr[ret], val_t);
22638 break;
22639 case OPC_REPL_QB:
22640 check_dsp(ctx);
22641 {
22642 target_long result;
22643 imm = (ctx->opcode >> 16) & 0xFF;
22644 result = (uint32_t)imm << 24 |
22645 (uint32_t)imm << 16 |
22646 (uint32_t)imm << 8 |
22647 (uint32_t)imm;
22648 result = (int32_t)result;
22649 tcg_gen_movi_tl(cpu_gpr[ret], result);
22650 }
22651 break;
22652 case OPC_REPLV_QB:
22653 check_dsp(ctx);
22654 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22655 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22656 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22657 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22658 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22659 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22660 break;
22661 case OPC_REPL_PH:
22662 check_dsp(ctx);
22663 {
22664 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 22665 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
22666 tcg_gen_movi_tl(cpu_gpr[ret], \
22667 (target_long)((int32_t)imm << 16 | \
c4aaba92 22668 (uint16_t)imm));
1cb6686c
JL
22669 }
22670 break;
22671 case OPC_REPLV_PH:
22672 check_dsp(ctx);
22673 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22674 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22675 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22676 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22677 break;
22678 }
22679 break;
22680#ifdef TARGET_MIPS64
22681 case OPC_ABSQ_S_QH_DSP:
22682 switch (op2) {
22683 case OPC_REPL_OB:
22684 check_dsp(ctx);
22685 {
22686 target_long temp;
22687
22688 imm = (ctx->opcode >> 16) & 0xFF;
22689 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22690 temp = (temp << 16) | temp;
22691 temp = (temp << 32) | temp;
22692 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22693 break;
22694 }
22695 case OPC_REPL_PW:
22696 check_dsp(ctx);
22697 {
22698 target_long temp;
22699
22700 imm = (ctx->opcode >> 16) & 0x03FF;
22701 imm = (int16_t)(imm << 6) >> 6;
22702 temp = ((target_long)imm << 32) \
22703 | ((target_long)imm & 0xFFFFFFFF);
22704 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22705 break;
22706 }
22707 case OPC_REPL_QH:
22708 check_dsp(ctx);
22709 {
22710 target_long temp;
22711
22712 imm = (ctx->opcode >> 16) & 0x03FF;
22713 imm = (int16_t)(imm << 6) >> 6;
22714
22715 temp = ((uint64_t)(uint16_t)imm << 48) |
22716 ((uint64_t)(uint16_t)imm << 32) |
22717 ((uint64_t)(uint16_t)imm << 16) |
22718 (uint64_t)(uint16_t)imm;
22719 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22720 break;
22721 }
22722 case OPC_REPLV_OB:
22723 check_dsp(ctx);
22724 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22725 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22726 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22727 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22728 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22729 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22730 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22731 break;
22732 case OPC_REPLV_PW:
22733 check_dsp(ctx);
22734 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22735 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22736 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22737 break;
22738 case OPC_REPLV_QH:
22739 check_dsp(ctx);
22740 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22741 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22742 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22743 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22744 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22745 break;
22746 }
22747 break;
22748#endif
22749 }
22750 tcg_temp_free(t0);
22751 tcg_temp_free(val_t);
1cb6686c
JL
22752}
22753
26690560
JL
22754static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22755 uint32_t op1, uint32_t op2,
22756 int ret, int v1, int v2, int check_ret)
22757{
26690560
JL
22758 TCGv t1;
22759 TCGv v1_t;
22760 TCGv v2_t;
22761
22762 if ((ret == 0) && (check_ret == 1)) {
22763 /* Treat as NOP. */
26690560
JL
22764 return;
22765 }
22766
26690560
JL
22767 t1 = tcg_temp_new();
22768 v1_t = tcg_temp_new();
22769 v2_t = tcg_temp_new();
22770
22771 gen_load_gpr(v1_t, v1);
22772 gen_load_gpr(v2_t, v2);
22773
22774 switch (op1) {
26690560
JL
22775 case OPC_CMPU_EQ_QB_DSP:
22776 switch (op2) {
22777 case OPC_CMPU_EQ_QB:
22778 check_dsp(ctx);
22779 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_CMPU_LT_QB:
22782 check_dsp(ctx);
22783 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_CMPU_LE_QB:
22786 check_dsp(ctx);
22787 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22788 break;
22789 case OPC_CMPGU_EQ_QB:
22790 check_dsp(ctx);
22791 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22792 break;
22793 case OPC_CMPGU_LT_QB:
22794 check_dsp(ctx);
22795 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22796 break;
22797 case OPC_CMPGU_LE_QB:
22798 check_dsp(ctx);
22799 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22800 break;
22801 case OPC_CMPGDU_EQ_QB:
908f6be1 22802 check_dsp_r2(ctx);
26690560
JL
22803 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22804 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22805 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22806 tcg_gen_shli_tl(t1, t1, 24);
22807 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22808 break;
22809 case OPC_CMPGDU_LT_QB:
908f6be1 22810 check_dsp_r2(ctx);
26690560
JL
22811 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22812 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22813 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22814 tcg_gen_shli_tl(t1, t1, 24);
22815 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22816 break;
22817 case OPC_CMPGDU_LE_QB:
908f6be1 22818 check_dsp_r2(ctx);
26690560
JL
22819 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22820 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22821 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22822 tcg_gen_shli_tl(t1, t1, 24);
22823 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22824 break;
22825 case OPC_CMP_EQ_PH:
22826 check_dsp(ctx);
22827 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22828 break;
22829 case OPC_CMP_LT_PH:
22830 check_dsp(ctx);
22831 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22832 break;
22833 case OPC_CMP_LE_PH:
22834 check_dsp(ctx);
22835 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22836 break;
22837 case OPC_PICK_QB:
22838 check_dsp(ctx);
22839 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22840 break;
22841 case OPC_PICK_PH:
22842 check_dsp(ctx);
22843 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22844 break;
22845 case OPC_PACKRL_PH:
22846 check_dsp(ctx);
22847 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22848 break;
22849 }
22850 break;
22851#ifdef TARGET_MIPS64
22852 case OPC_CMPU_EQ_OB_DSP:
22853 switch (op2) {
22854 case OPC_CMP_EQ_PW:
22855 check_dsp(ctx);
22856 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22857 break;
22858 case OPC_CMP_LT_PW:
22859 check_dsp(ctx);
22860 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22861 break;
22862 case OPC_CMP_LE_PW:
22863 check_dsp(ctx);
22864 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22865 break;
22866 case OPC_CMP_EQ_QH:
22867 check_dsp(ctx);
22868 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22869 break;
22870 case OPC_CMP_LT_QH:
22871 check_dsp(ctx);
22872 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22873 break;
22874 case OPC_CMP_LE_QH:
22875 check_dsp(ctx);
22876 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22877 break;
22878 case OPC_CMPGDU_EQ_OB:
908f6be1 22879 check_dsp_r2(ctx);
26690560
JL
22880 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22881 break;
22882 case OPC_CMPGDU_LT_OB:
908f6be1 22883 check_dsp_r2(ctx);
26690560
JL
22884 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22885 break;
22886 case OPC_CMPGDU_LE_OB:
908f6be1 22887 check_dsp_r2(ctx);
26690560
JL
22888 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22889 break;
22890 case OPC_CMPGU_EQ_OB:
22891 check_dsp(ctx);
22892 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22893 break;
22894 case OPC_CMPGU_LT_OB:
22895 check_dsp(ctx);
22896 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22897 break;
22898 case OPC_CMPGU_LE_OB:
22899 check_dsp(ctx);
22900 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22901 break;
22902 case OPC_CMPU_EQ_OB:
22903 check_dsp(ctx);
22904 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22905 break;
22906 case OPC_CMPU_LT_OB:
22907 check_dsp(ctx);
22908 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22909 break;
22910 case OPC_CMPU_LE_OB:
22911 check_dsp(ctx);
22912 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22913 break;
22914 case OPC_PACKRL_PW:
22915 check_dsp(ctx);
22916 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22917 break;
22918 case OPC_PICK_OB:
22919 check_dsp(ctx);
22920 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22921 break;
22922 case OPC_PICK_PW:
22923 check_dsp(ctx);
22924 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22925 break;
22926 case OPC_PICK_QH:
22927 check_dsp(ctx);
22928 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22929 break;
22930 }
22931 break;
df6126a7
AJ
22932#endif
22933 }
22934
22935 tcg_temp_free(t1);
22936 tcg_temp_free(v1_t);
22937 tcg_temp_free(v2_t);
df6126a7
AJ
22938}
22939
22940static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22941 uint32_t op1, int rt, int rs, int sa)
22942{
df6126a7
AJ
22943 TCGv t0;
22944
908f6be1 22945 check_dsp_r2(ctx);
df6126a7
AJ
22946
22947 if (rt == 0) {
22948 /* Treat as NOP. */
df6126a7
AJ
22949 return;
22950 }
22951
22952 t0 = tcg_temp_new();
22953 gen_load_gpr(t0, rs);
22954
22955 switch (op1) {
22956 case OPC_APPEND_DSP:
22957 switch (MASK_APPEND(ctx->opcode)) {
22958 case OPC_APPEND:
22959 if (sa != 0) {
22960 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22961 }
22962 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22963 break;
22964 case OPC_PREPEND:
22965 if (sa != 0) {
22966 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22967 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22968 tcg_gen_shli_tl(t0, t0, 32 - sa);
22969 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22970 }
22971 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22972 break;
22973 case OPC_BALIGN:
22974 sa &= 3;
22975 if (sa != 0 && sa != 2) {
22976 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22977 tcg_gen_ext32u_tl(t0, t0);
22978 tcg_gen_shri_tl(t0, t0, 8 * (4 - 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 default: /* Invalid */
22984 MIPS_INVAL("MASK APPEND");
3a4ef3b7 22985 gen_reserved_instruction(ctx);
df6126a7
AJ
22986 break;
22987 }
22988 break;
22989#ifdef TARGET_MIPS64
26690560 22990 case OPC_DAPPEND_DSP:
df6126a7 22991 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 22992 case OPC_DAPPEND:
df6126a7
AJ
22993 if (sa != 0) {
22994 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22995 }
26690560
JL
22996 break;
22997 case OPC_PREPENDD:
df6126a7
AJ
22998 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22999 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23000 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23001 break;
23002 case OPC_PREPENDW:
df6126a7
AJ
23003 if (sa != 0) {
23004 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23005 tcg_gen_shli_tl(t0, t0, 64 - sa);
23006 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23007 }
26690560
JL
23008 break;
23009 case OPC_DBALIGN:
df6126a7
AJ
23010 sa &= 7;
23011 if (sa != 0 && sa != 2 && sa != 4) {
23012 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23013 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23014 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23015 }
26690560
JL
23016 break;
23017 default: /* Invalid */
23018 MIPS_INVAL("MASK DAPPEND");
3a4ef3b7 23019 gen_reserved_instruction(ctx);
26690560
JL
23020 break;
23021 }
23022 break;
23023#endif
23024 }
df6126a7 23025 tcg_temp_free(t0);
26690560
JL
23026}
23027
b53371ed
JL
23028static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23029 int ret, int v1, int v2, int check_ret)
23030
23031{
b53371ed
JL
23032 TCGv t0;
23033 TCGv t1;
23034 TCGv v1_t;
23035 TCGv v2_t;
23036 int16_t imm;
23037
23038 if ((ret == 0) && (check_ret == 1)) {
23039 /* Treat as NOP. */
b53371ed
JL
23040 return;
23041 }
23042
23043 t0 = tcg_temp_new();
23044 t1 = tcg_temp_new();
23045 v1_t = tcg_temp_new();
23046 v2_t = tcg_temp_new();
23047
23048 gen_load_gpr(v1_t, v1);
23049 gen_load_gpr(v2_t, v2);
23050
23051 switch (op1) {
23052 case OPC_EXTR_W_DSP:
23053 check_dsp(ctx);
23054 switch (op2) {
23055 case OPC_EXTR_W:
23056 tcg_gen_movi_tl(t0, v2);
23057 tcg_gen_movi_tl(t1, v1);
23058 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23059 break;
23060 case OPC_EXTR_R_W:
23061 tcg_gen_movi_tl(t0, v2);
23062 tcg_gen_movi_tl(t1, v1);
23063 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23064 break;
23065 case OPC_EXTR_RS_W:
23066 tcg_gen_movi_tl(t0, v2);
23067 tcg_gen_movi_tl(t1, v1);
23068 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23069 break;
23070 case OPC_EXTR_S_H:
23071 tcg_gen_movi_tl(t0, v2);
23072 tcg_gen_movi_tl(t1, v1);
23073 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23074 break;
23075 case OPC_EXTRV_S_H:
23076 tcg_gen_movi_tl(t0, v2);
23077 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23078 break;
23079 case OPC_EXTRV_W:
23080 tcg_gen_movi_tl(t0, v2);
23081 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23082 break;
23083 case OPC_EXTRV_R_W:
23084 tcg_gen_movi_tl(t0, v2);
23085 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23086 break;
23087 case OPC_EXTRV_RS_W:
23088 tcg_gen_movi_tl(t0, v2);
23089 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23090 break;
23091 case OPC_EXTP:
23092 tcg_gen_movi_tl(t0, v2);
23093 tcg_gen_movi_tl(t1, v1);
23094 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23095 break;
23096 case OPC_EXTPV:
23097 tcg_gen_movi_tl(t0, v2);
23098 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23099 break;
23100 case OPC_EXTPDP:
23101 tcg_gen_movi_tl(t0, v2);
23102 tcg_gen_movi_tl(t1, v1);
23103 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23104 break;
23105 case OPC_EXTPDPV:
23106 tcg_gen_movi_tl(t0, v2);
23107 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23108 break;
23109 case OPC_SHILO:
23110 imm = (ctx->opcode >> 20) & 0x3F;
23111 tcg_gen_movi_tl(t0, ret);
23112 tcg_gen_movi_tl(t1, imm);
23113 gen_helper_shilo(t0, t1, cpu_env);
23114 break;
23115 case OPC_SHILOV:
23116 tcg_gen_movi_tl(t0, ret);
23117 gen_helper_shilo(t0, v1_t, cpu_env);
23118 break;
23119 case OPC_MTHLIP:
23120 tcg_gen_movi_tl(t0, ret);
23121 gen_helper_mthlip(t0, v1_t, cpu_env);
23122 break;
23123 case OPC_WRDSP:
23124 imm = (ctx->opcode >> 11) & 0x3FF;
23125 tcg_gen_movi_tl(t0, imm);
23126 gen_helper_wrdsp(v1_t, t0, cpu_env);
23127 break;
23128 case OPC_RDDSP:
23129 imm = (ctx->opcode >> 16) & 0x03FF;
23130 tcg_gen_movi_tl(t0, imm);
23131 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23132 break;
23133 }
23134 break;
23135#ifdef TARGET_MIPS64
23136 case OPC_DEXTR_W_DSP:
23137 check_dsp(ctx);
23138 switch (op2) {
23139 case OPC_DMTHLIP:
23140 tcg_gen_movi_tl(t0, ret);
23141 gen_helper_dmthlip(v1_t, t0, cpu_env);
23142 break;
23143 case OPC_DSHILO:
23144 {
23145 int shift = (ctx->opcode >> 19) & 0x7F;
23146 int ac = (ctx->opcode >> 11) & 0x03;
23147 tcg_gen_movi_tl(t0, shift);
23148 tcg_gen_movi_tl(t1, ac);
23149 gen_helper_dshilo(t0, t1, cpu_env);
23150 break;
23151 }
23152 case OPC_DSHILOV:
23153 {
23154 int ac = (ctx->opcode >> 11) & 0x03;
23155 tcg_gen_movi_tl(t0, ac);
23156 gen_helper_dshilo(v1_t, t0, cpu_env);
23157 break;
23158 }
23159 case OPC_DEXTP:
23160 tcg_gen_movi_tl(t0, v2);
23161 tcg_gen_movi_tl(t1, v1);
23162
23163 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23164 break;
23165 case OPC_DEXTPV:
23166 tcg_gen_movi_tl(t0, v2);
23167 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23168 break;
23169 case OPC_DEXTPDP:
23170 tcg_gen_movi_tl(t0, v2);
23171 tcg_gen_movi_tl(t1, v1);
23172 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23173 break;
23174 case OPC_DEXTPDPV:
23175 tcg_gen_movi_tl(t0, v2);
23176 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23177 break;
23178 case OPC_DEXTR_L:
23179 tcg_gen_movi_tl(t0, v2);
23180 tcg_gen_movi_tl(t1, v1);
23181 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23182 break;
23183 case OPC_DEXTR_R_L:
23184 tcg_gen_movi_tl(t0, v2);
23185 tcg_gen_movi_tl(t1, v1);
23186 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23187 break;
23188 case OPC_DEXTR_RS_L:
23189 tcg_gen_movi_tl(t0, v2);
23190 tcg_gen_movi_tl(t1, v1);
23191 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23192 break;
23193 case OPC_DEXTR_W:
23194 tcg_gen_movi_tl(t0, v2);
23195 tcg_gen_movi_tl(t1, v1);
23196 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23197 break;
23198 case OPC_DEXTR_R_W:
23199 tcg_gen_movi_tl(t0, v2);
23200 tcg_gen_movi_tl(t1, v1);
23201 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23202 break;
23203 case OPC_DEXTR_RS_W:
23204 tcg_gen_movi_tl(t0, v2);
23205 tcg_gen_movi_tl(t1, v1);
23206 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23207 break;
23208 case OPC_DEXTR_S_H:
23209 tcg_gen_movi_tl(t0, v2);
23210 tcg_gen_movi_tl(t1, v1);
23211 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23212 break;
23213 case OPC_DEXTRV_S_H:
23214 tcg_gen_movi_tl(t0, v2);
23215 tcg_gen_movi_tl(t1, v1);
23216 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23217 break;
23218 case OPC_DEXTRV_L:
23219 tcg_gen_movi_tl(t0, v2);
23220 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23221 break;
23222 case OPC_DEXTRV_R_L:
23223 tcg_gen_movi_tl(t0, v2);
23224 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23225 break;
23226 case OPC_DEXTRV_RS_L:
23227 tcg_gen_movi_tl(t0, v2);
23228 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23229 break;
23230 case OPC_DEXTRV_W:
23231 tcg_gen_movi_tl(t0, v2);
23232 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23233 break;
23234 case OPC_DEXTRV_R_W:
23235 tcg_gen_movi_tl(t0, v2);
23236 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23237 break;
23238 case OPC_DEXTRV_RS_W:
23239 tcg_gen_movi_tl(t0, v2);
23240 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23241 break;
23242 }
23243 break;
23244#endif
23245 }
23246
23247 tcg_temp_free(t0);
23248 tcg_temp_free(t1);
23249 tcg_temp_free(v1_t);
23250 tcg_temp_free(v2_t);
b53371ed
JL
23251}
23252
9b1a1d68
JL
23253/* End MIPSDSP functions. */
23254
10dc65db
LA
23255static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23256{
4267d3e6 23257 int rs, rt, rd, sa;
b42ee5e1 23258 uint32_t op1, op2;
10dc65db
LA
23259
23260 rs = (ctx->opcode >> 21) & 0x1f;
23261 rt = (ctx->opcode >> 16) & 0x1f;
23262 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 23263 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23264
23265 op1 = MASK_SPECIAL(ctx->opcode);
23266 switch (op1) {
c2e19f3c
AM
23267 case OPC_MULT:
23268 case OPC_MULTU:
23269 case OPC_DIV:
23270 case OPC_DIVU:
b42ee5e1
LA
23271 op2 = MASK_R6_MULDIV(ctx->opcode);
23272 switch (op2) {
23273 case R6_OPC_MUL:
23274 case R6_OPC_MUH:
23275 case R6_OPC_MULU:
23276 case R6_OPC_MUHU:
23277 case R6_OPC_DIV:
23278 case R6_OPC_MOD:
23279 case R6_OPC_DIVU:
23280 case R6_OPC_MODU:
23281 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23282 break;
23283 default:
23284 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 23285 gen_reserved_instruction(ctx);
b42ee5e1
LA
23286 break;
23287 }
23288 break;
10dc65db
LA
23289 case OPC_SELEQZ:
23290 case OPC_SELNEZ:
23291 gen_cond_move(ctx, op1, rd, rs, rt);
23292 break;
4267d3e6
LA
23293 case R6_OPC_CLO:
23294 case R6_OPC_CLZ:
23295 if (rt == 0 && sa == 1) {
7480515f
AM
23296 /*
23297 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23298 * We need additionally to check other fields.
23299 */
4267d3e6
LA
23300 gen_cl(ctx, op1, rd, rs);
23301 } else {
3a4ef3b7 23302 gen_reserved_instruction(ctx);
4267d3e6
LA
23303 }
23304 break;
23305 case R6_OPC_SDBBP:
3b3c1694
LA
23306 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23307 gen_helper_do_semihosting(cpu_env);
faf1f68b 23308 } else {
3b3c1694 23309 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 23310 gen_reserved_instruction(ctx);
3b3c1694 23311 } else {
9c708c7f 23312 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23313 }
faf1f68b 23314 }
4267d3e6 23315 break;
b42ee5e1 23316#if defined(TARGET_MIPS64)
4267d3e6
LA
23317 case R6_OPC_DCLO:
23318 case R6_OPC_DCLZ:
23319 if (rt == 0 && sa == 1) {
7480515f
AM
23320 /*
23321 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23322 * We need additionally to check other fields.
23323 */
4267d3e6
LA
23324 check_mips_64(ctx);
23325 gen_cl(ctx, op1, rd, rs);
23326 } else {
3a4ef3b7 23327 gen_reserved_instruction(ctx);
4267d3e6
LA
23328 }
23329 break;
c2e19f3c
AM
23330 case OPC_DMULT:
23331 case OPC_DMULTU:
23332 case OPC_DDIV:
23333 case OPC_DDIVU:
23334
b42ee5e1
LA
23335 op2 = MASK_R6_MULDIV(ctx->opcode);
23336 switch (op2) {
23337 case R6_OPC_DMUL:
23338 case R6_OPC_DMUH:
23339 case R6_OPC_DMULU:
23340 case R6_OPC_DMUHU:
23341 case R6_OPC_DDIV:
23342 case R6_OPC_DMOD:
23343 case R6_OPC_DDIVU:
23344 case R6_OPC_DMODU:
23345 check_mips_64(ctx);
23346 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23347 break;
23348 default:
23349 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 23350 gen_reserved_instruction(ctx);
b42ee5e1
LA
23351 break;
23352 }
23353 break;
23354#endif
10dc65db
LA
23355 default: /* Invalid */
23356 MIPS_INVAL("special_r6");
3a4ef3b7 23357 gen_reserved_instruction(ctx);
10dc65db
LA
23358 break;
23359 }
23360}
23361
9dc324ce
FN
23362static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23363{
23364 int rs = extract32(ctx->opcode, 21, 5);
23365 int rt = extract32(ctx->opcode, 16, 5);
23366 int rd = extract32(ctx->opcode, 11, 5);
23367 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23368
23369 switch (op1) {
23370 case OPC_MOVN: /* Conditional move */
23371 case OPC_MOVZ:
23372 gen_cond_move(ctx, op1, rd, rs, rt);
23373 break;
23374 case OPC_MFHI: /* Move from HI/LO */
23375 case OPC_MFLO:
23376 gen_HILO(ctx, op1, 0, rd);
23377 break;
23378 case OPC_MTHI:
23379 case OPC_MTLO: /* Move to HI/LO */
23380 gen_HILO(ctx, op1, 0, rs);
23381 break;
23382 case OPC_MULT:
23383 case OPC_MULTU:
23384 gen_mul_txx9(ctx, op1, rd, rs, rt);
23385 break;
23386 case OPC_DIV:
23387 case OPC_DIVU:
23388 gen_muldiv(ctx, op1, 0, rs, rt);
23389 break;
23390#if defined(TARGET_MIPS64)
23391 case OPC_DMULT:
23392 case OPC_DMULTU:
23393 case OPC_DDIV:
23394 case OPC_DDIVU:
23395 check_insn_opc_user_only(ctx, INSN_R5900);
23396 gen_muldiv(ctx, op1, 0, rs, rt);
23397 break;
23398#endif
23399 case OPC_JR:
23400 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23401 break;
23402 default: /* Invalid */
23403 MIPS_INVAL("special_tx79");
3a4ef3b7 23404 gen_reserved_instruction(ctx);
9dc324ce
FN
23405 break;
23406 }
23407}
23408
10dc65db
LA
23409static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23410{
b42ee5e1 23411 int rs, rt, rd, sa;
10dc65db
LA
23412 uint32_t op1;
23413
23414 rs = (ctx->opcode >> 21) & 0x1f;
23415 rt = (ctx->opcode >> 16) & 0x1f;
23416 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 23417 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23418
23419 op1 = MASK_SPECIAL(ctx->opcode);
23420 switch (op1) {
23421 case OPC_MOVN: /* Conditional move */
23422 case OPC_MOVZ:
bbd5e4a2 23423 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
9dc324ce 23424 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
23425 gen_cond_move(ctx, op1, rd, rs, rt);
23426 break;
23427 case OPC_MFHI: /* Move from HI/LO */
23428 case OPC_MFLO:
23429 gen_HILO(ctx, op1, rs & 3, rd);
23430 break;
23431 case OPC_MTHI:
23432 case OPC_MTLO: /* Move to HI/LO */
23433 gen_HILO(ctx, op1, rd & 3, rs);
23434 break;
23435 case OPC_MOVCI:
bbd5e4a2 23436 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10dc65db
LA
23437 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23438 check_cp1_enabled(ctx);
23439 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23440 (ctx->opcode >> 16) & 1);
23441 } else {
23442 generate_exception_err(ctx, EXCP_CpU, 1);
23443 }
23444 break;
b42ee5e1
LA
23445 case OPC_MULT:
23446 case OPC_MULTU:
23447 if (sa) {
23448 check_insn(ctx, INSN_VR54XX);
23449 op1 = MASK_MUL_VR54XX(ctx->opcode);
23450 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23451 } else {
23452 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23453 }
23454 break;
23455 case OPC_DIV:
23456 case OPC_DIVU:
23457 gen_muldiv(ctx, op1, 0, rs, rt);
23458 break;
23459#if defined(TARGET_MIPS64)
c2e19f3c
AM
23460 case OPC_DMULT:
23461 case OPC_DMULTU:
23462 case OPC_DDIV:
23463 case OPC_DDIVU:
b42ee5e1
LA
23464 check_insn(ctx, ISA_MIPS3);
23465 check_mips_64(ctx);
23466 gen_muldiv(ctx, op1, 0, rs, rt);
23467 break;
23468#endif
0aefa333 23469 case OPC_JR:
b231c103 23470 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 23471 break;
4267d3e6
LA
23472 case OPC_SPIM:
23473#ifdef MIPS_STRICT_STANDARD
23474 MIPS_INVAL("SPIM");
3a4ef3b7 23475 gen_reserved_instruction(ctx);
4267d3e6
LA
23476#else
23477 /* Implemented as RI exception for now. */
23478 MIPS_INVAL("spim (unofficial)");
3a4ef3b7 23479 gen_reserved_instruction(ctx);
4267d3e6
LA
23480#endif
23481 break;
10dc65db
LA
23482 default: /* Invalid */
23483 MIPS_INVAL("special_legacy");
3a4ef3b7 23484 gen_reserved_instruction(ctx);
10dc65db
LA
23485 break;
23486 }
23487}
23488
099e5b4d 23489static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 23490{
3c824109 23491 int rs, rt, rd, sa;
099e5b4d 23492 uint32_t op1;
3c824109 23493
3c824109
NF
23494 rs = (ctx->opcode >> 21) & 0x1f;
23495 rt = (ctx->opcode >> 16) & 0x1f;
23496 rd = (ctx->opcode >> 11) & 0x1f;
23497 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
23498
23499 op1 = MASK_SPECIAL(ctx->opcode);
23500 switch (op1) {
23501 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
23502 if (sa == 5 && rd == 0 &&
23503 rs == 0 && rt == 0) { /* PAUSE */
2e211e0a 23504 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 23505 (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 23506 gen_reserved_instruction(ctx);
339cd2a8
LA
23507 break;
23508 }
23509 }
23510 /* Fallthrough */
099e5b4d
LA
23511 case OPC_SRA:
23512 gen_shift_imm(ctx, op1, rd, rt, sa);
23513 break;
23514 case OPC_SRL:
23515 switch ((ctx->opcode >> 21) & 0x1f) {
23516 case 1:
23517 /* rotr is decoded as srl on non-R2 CPUs */
7a47bae5 23518 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23519 op1 = OPC_ROTR;
ea63e2c3 23520 }
099e5b4d
LA
23521 /* Fallthrough */
23522 case 0:
23523 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 23524 break;
099e5b4d 23525 default:
3a4ef3b7 23526 gen_reserved_instruction(ctx);
ea63e2c3 23527 break;
099e5b4d
LA
23528 }
23529 break;
c2e19f3c
AM
23530 case OPC_ADD:
23531 case OPC_ADDU:
23532 case OPC_SUB:
23533 case OPC_SUBU:
099e5b4d
LA
23534 gen_arith(ctx, op1, rd, rs, rt);
23535 break;
23536 case OPC_SLLV: /* Shifts */
23537 case OPC_SRAV:
23538 gen_shift(ctx, op1, rd, rs, rt);
23539 break;
23540 case OPC_SRLV:
23541 switch ((ctx->opcode >> 6) & 0x1f) {
23542 case 1:
23543 /* rotrv is decoded as srlv on non-R2 CPUs */
7a47bae5 23544 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23545 op1 = OPC_ROTRV;
26135ead 23546 }
099e5b4d
LA
23547 /* Fallthrough */
23548 case 0:
23549 gen_shift(ctx, op1, rd, rs, rt);
26135ead 23550 break;
099e5b4d 23551 default:
3a4ef3b7 23552 gen_reserved_instruction(ctx);
6af0bf9c 23553 break;
099e5b4d
LA
23554 }
23555 break;
23556 case OPC_SLT: /* Set on less than */
23557 case OPC_SLTU:
23558 gen_slt(ctx, op1, rd, rs, rt);
23559 break;
23560 case OPC_AND: /* Logic*/
23561 case OPC_OR:
23562 case OPC_NOR:
23563 case OPC_XOR:
23564 gen_logic(ctx, op1, rd, rs, rt);
23565 break;
0aefa333 23566 case OPC_JALR:
b231c103 23567 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 23568 break;
c2e19f3c
AM
23569 case OPC_TGE: /* Traps */
23570 case OPC_TGEU:
23571 case OPC_TLT:
23572 case OPC_TLTU:
23573 case OPC_TEQ:
099e5b4d 23574 case OPC_TNE:
d9224450 23575 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
23576 gen_trap(ctx, op1, rs, rt, -1);
23577 break;
0e9524af
PMD
23578 case OPC_PMON:
23579 /* Pmon entry point, also R4010 selsl */
b48cfdff 23580#ifdef MIPS_STRICT_STANDARD
0e9524af
PMD
23581 MIPS_INVAL("PMON / selsl");
23582 gen_reserved_instruction(ctx);
b48cfdff 23583#else
0e9524af 23584 gen_helper_0e0i(pmon, sa);
b48cfdff 23585#endif
099e5b4d
LA
23586 break;
23587 case OPC_SYSCALL:
9c708c7f 23588 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
23589 break;
23590 case OPC_BREAK:
9c708c7f 23591 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 23592 break;
099e5b4d 23593 case OPC_SYNC:
d9224450 23594 check_insn(ctx, ISA_MIPS2);
d208ac0c 23595 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 23596 break;
4ad40f36 23597
d26bc211 23598#if defined(TARGET_MIPS64)
099e5b4d
LA
23599 /* MIPS64 specific opcodes */
23600 case OPC_DSLL:
23601 case OPC_DSRA:
23602 case OPC_DSLL32:
23603 case OPC_DSRA32:
23604 check_insn(ctx, ISA_MIPS3);
23605 check_mips_64(ctx);
23606 gen_shift_imm(ctx, op1, rd, rt, sa);
23607 break;
23608 case OPC_DSRL:
23609 switch ((ctx->opcode >> 21) & 0x1f) {
23610 case 1:
23611 /* drotr is decoded as dsrl on non-R2 CPUs */
7a47bae5 23612 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23613 op1 = OPC_DROTR;
ea63e2c3 23614 }
099e5b4d
LA
23615 /* Fallthrough */
23616 case 0:
d75c135e 23617 check_insn(ctx, ISA_MIPS3);
e189e748 23618 check_mips_64(ctx);
099e5b4d 23619 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23620 break;
099e5b4d 23621 default:
3a4ef3b7 23622 gen_reserved_instruction(ctx);
460f00c4 23623 break;
099e5b4d
LA
23624 }
23625 break;
23626 case OPC_DSRL32:
23627 switch ((ctx->opcode >> 21) & 0x1f) {
23628 case 1:
23629 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
7a47bae5 23630 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23631 op1 = OPC_DROTR32;
ea63e2c3 23632 }
099e5b4d
LA
23633 /* Fallthrough */
23634 case 0:
d75c135e 23635 check_insn(ctx, ISA_MIPS3);
e189e748 23636 check_mips_64(ctx);
099e5b4d 23637 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23638 break;
099e5b4d 23639 default:
3a4ef3b7 23640 gen_reserved_instruction(ctx);
6af0bf9c
FB
23641 break;
23642 }
23643 break;
c2e19f3c
AM
23644 case OPC_DADD:
23645 case OPC_DADDU:
23646 case OPC_DSUB:
23647 case OPC_DSUBU:
099e5b4d
LA
23648 check_insn(ctx, ISA_MIPS3);
23649 check_mips_64(ctx);
23650 gen_arith(ctx, op1, rd, rs, rt);
23651 break;
23652 case OPC_DSLLV:
23653 case OPC_DSRAV:
23654 check_insn(ctx, ISA_MIPS3);
23655 check_mips_64(ctx);
23656 gen_shift(ctx, op1, rd, rs, rt);
23657 break;
23658 case OPC_DSRLV:
23659 switch ((ctx->opcode >> 6) & 0x1f) {
23660 case 1:
23661 /* drotrv is decoded as dsrlv on non-R2 CPUs */
7a47bae5 23662 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 23663 op1 = OPC_DROTRV;
6af0bf9c 23664 }
099e5b4d
LA
23665 /* Fallthrough */
23666 case 0:
23667 check_insn(ctx, ISA_MIPS3);
e189e748 23668 check_mips_64(ctx);
099e5b4d 23669 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 23670 break;
099e5b4d 23671 default:
3a4ef3b7 23672 gen_reserved_instruction(ctx);
6af0bf9c
FB
23673 break;
23674 }
23675 break;
099e5b4d 23676#endif
10dc65db 23677 default:
2e211e0a 23678 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db 23679 decode_opc_special_r6(env, ctx);
9dc324ce
FN
23680 } else if (ctx->insn_flags & INSN_R5900) {
23681 decode_opc_special_tx79(env, ctx);
10dc65db
LA
23682 } else {
23683 decode_opc_special_legacy(env, ctx);
23684 }
23685 }
23686}
23687
d67da337 23688
10dc65db 23689static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
23690{
23691 int rs, rt, rd;
23692 uint32_t op1;
6c5c1e20 23693
099e5b4d
LA
23694 rs = (ctx->opcode >> 21) & 0x1f;
23695 rt = (ctx->opcode >> 16) & 0x1f;
23696 rd = (ctx->opcode >> 11) & 0x1f;
23697
23698 op1 = MASK_SPECIAL2(ctx->opcode);
23699 switch (op1) {
c2e19f3c
AM
23700 case OPC_MADD: /* Multiply and add/sub */
23701 case OPC_MADDU:
23702 case OPC_MSUB:
23703 case OPC_MSUBU:
bbd5e4a2 23704 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23705 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23706 break;
23707 case OPC_MUL:
099e5b4d
LA
23708 gen_arith(ctx, op1, rd, rs, rt);
23709 break;
fac5a073
LA
23710 case OPC_DIV_G_2F:
23711 case OPC_DIVU_G_2F:
23712 case OPC_MULT_G_2F:
23713 case OPC_MULTU_G_2F:
23714 case OPC_MOD_G_2F:
23715 case OPC_MODU_G_2F:
8e2d5831 23716 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
fac5a073
LA
23717 gen_loongson_integer(ctx, op1, rd, rs, rt);
23718 break;
099e5b4d
LA
23719 case OPC_CLO:
23720 case OPC_CLZ:
bbd5e4a2 23721 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23722 gen_cl(ctx, op1, rd, rs);
23723 break;
23724 case OPC_SDBBP:
3b3c1694
LA
23725 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23726 gen_helper_do_semihosting(cpu_env);
23727 } else {
7480515f
AM
23728 /*
23729 * XXX: not clear which exception should be raised
3b3c1694
LA
23730 * when in debug mode...
23731 */
bbd5e4a2 23732 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 23733 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23734 }
099e5b4d 23735 break;
9b1a1d68 23736#if defined(TARGET_MIPS64)
099e5b4d
LA
23737 case OPC_DCLO:
23738 case OPC_DCLZ:
bbd5e4a2 23739 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
23740 check_mips_64(ctx);
23741 gen_cl(ctx, op1, rd, rs);
23742 break;
4267d3e6
LA
23743 case OPC_DMULT_G_2F:
23744 case OPC_DMULTU_G_2F:
23745 case OPC_DDIV_G_2F:
23746 case OPC_DDIVU_G_2F:
23747 case OPC_DMOD_G_2F:
23748 case OPC_DMODU_G_2F:
8e2d5831 23749 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
4267d3e6
LA
23750 gen_loongson_integer(ctx, op1, rd, rs, rt);
23751 break;
10dc65db 23752#endif
4267d3e6
LA
23753 default: /* Invalid */
23754 MIPS_INVAL("special2_legacy");
3a4ef3b7 23755 gen_reserved_instruction(ctx);
4267d3e6 23756 break;
10dc65db
LA
23757 }
23758}
23759
23760static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23761{
15eacb9b
YK
23762 int rs, rt, rd, sa;
23763 uint32_t op1, op2;
10dc65db
LA
23764 int16_t imm;
23765
23766 rs = (ctx->opcode >> 21) & 0x1f;
23767 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
23768 rd = (ctx->opcode >> 11) & 0x1f;
23769 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23770 imm = (int16_t)ctx->opcode >> 7;
23771
23772 op1 = MASK_SPECIAL3(ctx->opcode);
23773 switch (op1) {
bf7910c6
LA
23774 case R6_OPC_PREF:
23775 if (rt >= 24) {
23776 /* hint codes 24-31 are reserved and signal RI */
3a4ef3b7 23777 gen_reserved_instruction(ctx);
bf7910c6
LA
23778 }
23779 /* Treat as NOP. */
23780 break;
23781 case R6_OPC_CACHE:
40d48212 23782 check_cp0_enabled(ctx);
0d74a222
LA
23783 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23784 gen_cache_operation(ctx, rt, rs, imm);
23785 }
bf7910c6 23786 break;
10dc65db 23787 case R6_OPC_SC:
33a07fa2 23788 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
23789 break;
23790 case R6_OPC_LL:
23791 gen_ld(ctx, op1, rt, rs, imm);
23792 break;
15eacb9b
YK
23793 case OPC_BSHFL:
23794 {
23795 if (rd == 0) {
23796 /* Treat as NOP. */
23797 break;
23798 }
15eacb9b
YK
23799 op2 = MASK_BSHFL(ctx->opcode);
23800 switch (op2) {
c2e19f3c 23801 case OPC_ALIGN:
373ecd38
AM
23802 case OPC_ALIGN_1:
23803 case OPC_ALIGN_2:
23804 case OPC_ALIGN_3:
821f2008 23805 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
23806 break;
23807 case OPC_BITSWAP:
1f1b4c00 23808 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23809 break;
23810 }
15eacb9b
YK
23811 }
23812 break;
99029be1
YK
23813#ifndef CONFIG_USER_ONLY
23814 case OPC_GINV:
23815 if (unlikely(ctx->gi <= 1)) {
3a4ef3b7 23816 gen_reserved_instruction(ctx);
99029be1
YK
23817 }
23818 check_cp0_enabled(ctx);
23819 switch ((ctx->opcode >> 6) & 3) {
23820 case 0: /* GINVI */
23821 /* Treat as NOP. */
23822 break;
23823 case 2: /* GINVT */
23824 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23825 break;
23826 default:
3a4ef3b7 23827 gen_reserved_instruction(ctx);
99029be1
YK
23828 break;
23829 }
23830 break;
23831#endif
bf7910c6
LA
23832#if defined(TARGET_MIPS64)
23833 case R6_OPC_SCD:
33a07fa2 23834 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
bf7910c6
LA
23835 break;
23836 case R6_OPC_LLD:
23837 gen_ld(ctx, op1, rt, rs, imm);
23838 break;
15eacb9b
YK
23839 case OPC_DBSHFL:
23840 check_mips_64(ctx);
23841 {
23842 if (rd == 0) {
23843 /* Treat as NOP. */
23844 break;
23845 }
15eacb9b
YK
23846 op2 = MASK_DBSHFL(ctx->opcode);
23847 switch (op2) {
c2e19f3c 23848 case OPC_DALIGN:
373ecd38
AM
23849 case OPC_DALIGN_1:
23850 case OPC_DALIGN_2:
23851 case OPC_DALIGN_3:
23852 case OPC_DALIGN_4:
23853 case OPC_DALIGN_5:
23854 case OPC_DALIGN_6:
23855 case OPC_DALIGN_7:
821f2008 23856 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
23857 break;
23858 case OPC_DBITSWAP:
1f1b4c00 23859 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23860 break;
23861 }
1f1b4c00 23862
15eacb9b
YK
23863 }
23864 break;
bf7910c6 23865#endif
10dc65db
LA
23866 default: /* Invalid */
23867 MIPS_INVAL("special3_r6");
3a4ef3b7 23868 gen_reserved_instruction(ctx);
10dc65db
LA
23869 break;
23870 }
23871}
23872
23873static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23874{
fac5a073 23875 int rs, rt, rd;
099e5b4d 23876 uint32_t op1, op2;
099e5b4d
LA
23877
23878 rs = (ctx->opcode >> 21) & 0x1f;
23879 rt = (ctx->opcode >> 16) & 0x1f;
23880 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
23881
23882 op1 = MASK_SPECIAL3(ctx->opcode);
23883 switch (op1) {
c2e19f3c
AM
23884 case OPC_DIV_G_2E:
23885 case OPC_DIVU_G_2E:
23886 case OPC_MOD_G_2E:
23887 case OPC_MODU_G_2E:
23888 case OPC_MULT_G_2E:
23889 case OPC_MULTU_G_2E:
7480515f
AM
23890 /*
23891 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23892 * the same mask and op1.
23893 */
908f6be1 23894 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 23895 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 23896 switch (op2) {
099e5b4d
LA
23897 case OPC_ADDUH_QB:
23898 case OPC_ADDUH_R_QB:
23899 case OPC_ADDQH_PH:
23900 case OPC_ADDQH_R_PH:
23901 case OPC_ADDQH_W:
23902 case OPC_ADDQH_R_W:
23903 case OPC_SUBUH_QB:
23904 case OPC_SUBUH_R_QB:
23905 case OPC_SUBQH_PH:
23906 case OPC_SUBQH_R_PH:
23907 case OPC_SUBQH_W:
23908 case OPC_SUBQH_R_W:
461c08df
JL
23909 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23910 break;
099e5b4d
LA
23911 case OPC_MUL_PH:
23912 case OPC_MUL_S_PH:
23913 case OPC_MULQ_S_W:
23914 case OPC_MULQ_RS_W:
23915 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 23916 break;
461c08df 23917 default:
099e5b4d 23918 MIPS_INVAL("MASK ADDUH.QB");
3a4ef3b7 23919 gen_reserved_instruction(ctx);
461c08df
JL
23920 break;
23921 }
099e5b4d
LA
23922 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23923 gen_loongson_integer(ctx, op1, rd, rs, rt);
23924 } else {
3a4ef3b7 23925 gen_reserved_instruction(ctx);
099e5b4d
LA
23926 }
23927 break;
23928 case OPC_LX_DSP:
23929 op2 = MASK_LX(ctx->opcode);
23930 switch (op2) {
23931#if defined(TARGET_MIPS64)
23932 case OPC_LDX:
23933#endif
23934 case OPC_LBUX:
23935 case OPC_LHX:
23936 case OPC_LWX:
23937 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23938 break;
23939 default: /* Invalid */
23940 MIPS_INVAL("MASK LX");
3a4ef3b7 23941 gen_reserved_instruction(ctx);
099e5b4d
LA
23942 break;
23943 }
23944 break;
23945 case OPC_ABSQ_S_PH_DSP:
23946 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23947 switch (op2) {
23948 case OPC_ABSQ_S_QB:
23949 case OPC_ABSQ_S_PH:
23950 case OPC_ABSQ_S_W:
23951 case OPC_PRECEQ_W_PHL:
23952 case OPC_PRECEQ_W_PHR:
23953 case OPC_PRECEQU_PH_QBL:
23954 case OPC_PRECEQU_PH_QBR:
23955 case OPC_PRECEQU_PH_QBLA:
23956 case OPC_PRECEQU_PH_QBRA:
23957 case OPC_PRECEU_PH_QBL:
23958 case OPC_PRECEU_PH_QBR:
23959 case OPC_PRECEU_PH_QBLA:
23960 case OPC_PRECEU_PH_QBRA:
23961 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23962 break;
23963 case OPC_BITREV:
23964 case OPC_REPL_QB:
23965 case OPC_REPLV_QB:
23966 case OPC_REPL_PH:
23967 case OPC_REPLV_PH:
23968 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23969 break;
23970 default:
23971 MIPS_INVAL("MASK ABSQ_S.PH");
3a4ef3b7 23972 gen_reserved_instruction(ctx);
099e5b4d
LA
23973 break;
23974 }
23975 break;
23976 case OPC_ADDU_QB_DSP:
23977 op2 = MASK_ADDU_QB(ctx->opcode);
23978 switch (op2) {
23979 case OPC_ADDQ_PH:
23980 case OPC_ADDQ_S_PH:
23981 case OPC_ADDQ_S_W:
23982 case OPC_ADDU_QB:
23983 case OPC_ADDU_S_QB:
23984 case OPC_ADDU_PH:
23985 case OPC_ADDU_S_PH:
23986 case OPC_SUBQ_PH:
23987 case OPC_SUBQ_S_PH:
23988 case OPC_SUBQ_S_W:
23989 case OPC_SUBU_QB:
23990 case OPC_SUBU_S_QB:
23991 case OPC_SUBU_PH:
23992 case OPC_SUBU_S_PH:
23993 case OPC_ADDSC:
23994 case OPC_ADDWC:
23995 case OPC_MODSUB:
23996 case OPC_RADDU_W_QB:
23997 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23998 break;
23999 case OPC_MULEU_S_PH_QBL:
24000 case OPC_MULEU_S_PH_QBR:
24001 case OPC_MULQ_RS_PH:
24002 case OPC_MULEQ_S_W_PHL:
24003 case OPC_MULEQ_S_W_PHR:
24004 case OPC_MULQ_S_PH:
24005 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24006 break;
24007 default: /* Invalid */
24008 MIPS_INVAL("MASK ADDU.QB");
3a4ef3b7 24009 gen_reserved_instruction(ctx);
461c08df 24010 break;
461c08df 24011
099e5b4d
LA
24012 }
24013 break;
24014 case OPC_CMPU_EQ_QB_DSP:
24015 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24016 switch (op2) {
24017 case OPC_PRECR_SRA_PH_W:
24018 case OPC_PRECR_SRA_R_PH_W:
24019 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 24020 break;
099e5b4d
LA
24021 case OPC_PRECR_QB_PH:
24022 case OPC_PRECRQ_QB_PH:
24023 case OPC_PRECRQ_PH_W:
24024 case OPC_PRECRQ_RS_PH_W:
24025 case OPC_PRECRQU_S_QB_PH:
24026 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 24027 break;
099e5b4d
LA
24028 case OPC_CMPU_EQ_QB:
24029 case OPC_CMPU_LT_QB:
24030 case OPC_CMPU_LE_QB:
24031 case OPC_CMP_EQ_PH:
24032 case OPC_CMP_LT_PH:
24033 case OPC_CMP_LE_PH:
24034 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 24035 break;
099e5b4d
LA
24036 case OPC_CMPGU_EQ_QB:
24037 case OPC_CMPGU_LT_QB:
24038 case OPC_CMPGU_LE_QB:
24039 case OPC_CMPGDU_EQ_QB:
24040 case OPC_CMPGDU_LT_QB:
24041 case OPC_CMPGDU_LE_QB:
24042 case OPC_PICK_QB:
24043 case OPC_PICK_PH:
24044 case OPC_PACKRL_PH:
24045 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24046 break;
24047 default: /* Invalid */
24048 MIPS_INVAL("MASK CMPU.EQ.QB");
3a4ef3b7 24049 gen_reserved_instruction(ctx);
099e5b4d
LA
24050 break;
24051 }
24052 break;
24053 case OPC_SHLL_QB_DSP:
24054 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24055 break;
24056 case OPC_DPA_W_PH_DSP:
24057 op2 = MASK_DPA_W_PH(ctx->opcode);
24058 switch (op2) {
24059 case OPC_DPAU_H_QBL:
24060 case OPC_DPAU_H_QBR:
24061 case OPC_DPSU_H_QBL:
24062 case OPC_DPSU_H_QBR:
24063 case OPC_DPA_W_PH:
24064 case OPC_DPAX_W_PH:
24065 case OPC_DPAQ_S_W_PH:
24066 case OPC_DPAQX_S_W_PH:
24067 case OPC_DPAQX_SA_W_PH:
24068 case OPC_DPS_W_PH:
24069 case OPC_DPSX_W_PH:
24070 case OPC_DPSQ_S_W_PH:
24071 case OPC_DPSQX_S_W_PH:
24072 case OPC_DPSQX_SA_W_PH:
24073 case OPC_MULSAQ_S_W_PH:
24074 case OPC_DPAQ_SA_L_W:
24075 case OPC_DPSQ_SA_L_W:
24076 case OPC_MAQ_S_W_PHL:
24077 case OPC_MAQ_S_W_PHR:
24078 case OPC_MAQ_SA_W_PHL:
24079 case OPC_MAQ_SA_W_PHR:
24080 case OPC_MULSA_W_PH:
24081 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24082 break;
24083 default: /* Invalid */
24084 MIPS_INVAL("MASK DPAW.PH");
3a4ef3b7 24085 gen_reserved_instruction(ctx);
099e5b4d
LA
24086 break;
24087 }
24088 break;
24089 case OPC_INSV_DSP:
24090 op2 = MASK_INSV(ctx->opcode);
24091 switch (op2) {
24092 case OPC_INSV:
24093 check_dsp(ctx);
24094 {
24095 TCGv t0, t1;
24096
24097 if (rt == 0) {
099e5b4d
LA
24098 break;
24099 }
24100
24101 t0 = tcg_temp_new();
24102 t1 = tcg_temp_new();
24103
24104 gen_load_gpr(t0, rt);
24105 gen_load_gpr(t1, rs);
24106
24107 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24108
24109 tcg_temp_free(t0);
24110 tcg_temp_free(t1);
a22260ae
JL
24111 break;
24112 }
099e5b4d
LA
24113 default: /* Invalid */
24114 MIPS_INVAL("MASK INSV");
3a4ef3b7 24115 gen_reserved_instruction(ctx);
099e5b4d
LA
24116 break;
24117 }
24118 break;
24119 case OPC_APPEND_DSP:
24120 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24121 break;
24122 case OPC_EXTR_W_DSP:
24123 op2 = MASK_EXTR_W(ctx->opcode);
24124 switch (op2) {
24125 case OPC_EXTR_W:
24126 case OPC_EXTR_R_W:
24127 case OPC_EXTR_RS_W:
24128 case OPC_EXTR_S_H:
24129 case OPC_EXTRV_S_H:
24130 case OPC_EXTRV_W:
24131 case OPC_EXTRV_R_W:
24132 case OPC_EXTRV_RS_W:
24133 case OPC_EXTP:
24134 case OPC_EXTPV:
24135 case OPC_EXTPDP:
24136 case OPC_EXTPDPV:
24137 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24138 break;
24139 case OPC_RDDSP:
24140 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24141 break;
24142 case OPC_SHILO:
24143 case OPC_SHILOV:
24144 case OPC_MTHLIP:
24145 case OPC_WRDSP:
24146 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24147 break;
24148 default: /* Invalid */
24149 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 24150 gen_reserved_instruction(ctx);
099e5b4d
LA
24151 break;
24152 }
24153 break;
099e5b4d 24154#if defined(TARGET_MIPS64)
c2e19f3c
AM
24155 case OPC_DDIV_G_2E:
24156 case OPC_DDIVU_G_2E:
24157 case OPC_DMULT_G_2E:
24158 case OPC_DMULTU_G_2E:
24159 case OPC_DMOD_G_2E:
24160 case OPC_DMODU_G_2E:
fac5a073
LA
24161 check_insn(ctx, INSN_LOONGSON2E);
24162 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 24163 break;
099e5b4d
LA
24164 case OPC_ABSQ_S_QH_DSP:
24165 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24166 switch (op2) {
24167 case OPC_PRECEQ_L_PWL:
24168 case OPC_PRECEQ_L_PWR:
24169 case OPC_PRECEQ_PW_QHL:
24170 case OPC_PRECEQ_PW_QHR:
24171 case OPC_PRECEQ_PW_QHLA:
24172 case OPC_PRECEQ_PW_QHRA:
24173 case OPC_PRECEQU_QH_OBL:
24174 case OPC_PRECEQU_QH_OBR:
24175 case OPC_PRECEQU_QH_OBLA:
24176 case OPC_PRECEQU_QH_OBRA:
24177 case OPC_PRECEU_QH_OBL:
24178 case OPC_PRECEU_QH_OBR:
24179 case OPC_PRECEU_QH_OBLA:
24180 case OPC_PRECEU_QH_OBRA:
24181 case OPC_ABSQ_S_OB:
24182 case OPC_ABSQ_S_PW:
24183 case OPC_ABSQ_S_QH:
24184 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24185 break;
24186 case OPC_REPL_OB:
24187 case OPC_REPL_PW:
24188 case OPC_REPL_QH:
24189 case OPC_REPLV_OB:
24190 case OPC_REPLV_PW:
24191 case OPC_REPLV_QH:
24192 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24193 break;
24194 default: /* Invalid */
24195 MIPS_INVAL("MASK ABSQ_S.QH");
3a4ef3b7 24196 gen_reserved_instruction(ctx);
099e5b4d
LA
24197 break;
24198 }
24199 break;
24200 case OPC_ADDU_OB_DSP:
24201 op2 = MASK_ADDU_OB(ctx->opcode);
24202 switch (op2) {
24203 case OPC_RADDU_L_OB:
24204 case OPC_SUBQ_PW:
24205 case OPC_SUBQ_S_PW:
24206 case OPC_SUBQ_QH:
24207 case OPC_SUBQ_S_QH:
24208 case OPC_SUBU_OB:
24209 case OPC_SUBU_S_OB:
24210 case OPC_SUBU_QH:
24211 case OPC_SUBU_S_QH:
24212 case OPC_SUBUH_OB:
24213 case OPC_SUBUH_R_OB:
24214 case OPC_ADDQ_PW:
24215 case OPC_ADDQ_S_PW:
24216 case OPC_ADDQ_QH:
24217 case OPC_ADDQ_S_QH:
24218 case OPC_ADDU_OB:
24219 case OPC_ADDU_S_OB:
24220 case OPC_ADDU_QH:
24221 case OPC_ADDU_S_QH:
24222 case OPC_ADDUH_OB:
24223 case OPC_ADDUH_R_OB:
24224 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 24225 break;
099e5b4d
LA
24226 case OPC_MULEQ_S_PW_QHL:
24227 case OPC_MULEQ_S_PW_QHR:
24228 case OPC_MULEU_S_QH_OBL:
24229 case OPC_MULEU_S_QH_OBR:
24230 case OPC_MULQ_RS_QH:
24231 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 24232 break;
099e5b4d
LA
24233 default: /* Invalid */
24234 MIPS_INVAL("MASK ADDU.OB");
3a4ef3b7 24235 gen_reserved_instruction(ctx);
26690560 24236 break;
099e5b4d
LA
24237 }
24238 break;
24239 case OPC_CMPU_EQ_OB_DSP:
24240 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24241 switch (op2) {
24242 case OPC_PRECR_SRA_QH_PW:
24243 case OPC_PRECR_SRA_R_QH_PW:
24244 /* Return value is rt. */
24245 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 24246 break;
099e5b4d
LA
24247 case OPC_PRECR_OB_QH:
24248 case OPC_PRECRQ_OB_QH:
24249 case OPC_PRECRQ_PW_L:
24250 case OPC_PRECRQ_QH_PW:
24251 case OPC_PRECRQ_RS_QH_PW:
24252 case OPC_PRECRQU_S_OB_QH:
24253 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 24254 break;
099e5b4d
LA
24255 case OPC_CMPU_EQ_OB:
24256 case OPC_CMPU_LT_OB:
24257 case OPC_CMPU_LE_OB:
24258 case OPC_CMP_EQ_QH:
24259 case OPC_CMP_LT_QH:
24260 case OPC_CMP_LE_QH:
24261 case OPC_CMP_EQ_PW:
24262 case OPC_CMP_LT_PW:
24263 case OPC_CMP_LE_PW:
24264 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 24265 break;
099e5b4d
LA
24266 case OPC_CMPGDU_EQ_OB:
24267 case OPC_CMPGDU_LT_OB:
24268 case OPC_CMPGDU_LE_OB:
24269 case OPC_CMPGU_EQ_OB:
24270 case OPC_CMPGU_LT_OB:
24271 case OPC_CMPGU_LE_OB:
24272 case OPC_PACKRL_PW:
24273 case OPC_PICK_OB:
24274 case OPC_PICK_PW:
24275 case OPC_PICK_QH:
24276 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 24277 break;
099e5b4d
LA
24278 default: /* Invalid */
24279 MIPS_INVAL("MASK CMPU_EQ.OB");
3a4ef3b7 24280 gen_reserved_instruction(ctx);
161f85e6 24281 break;
099e5b4d
LA
24282 }
24283 break;
24284 case OPC_DAPPEND_DSP:
24285 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24286 break;
24287 case OPC_DEXTR_W_DSP:
24288 op2 = MASK_DEXTR_W(ctx->opcode);
24289 switch (op2) {
24290 case OPC_DEXTP:
24291 case OPC_DEXTPDP:
24292 case OPC_DEXTPDPV:
24293 case OPC_DEXTPV:
24294 case OPC_DEXTR_L:
24295 case OPC_DEXTR_R_L:
24296 case OPC_DEXTR_RS_L:
24297 case OPC_DEXTR_W:
24298 case OPC_DEXTR_R_W:
24299 case OPC_DEXTR_RS_W:
24300 case OPC_DEXTR_S_H:
24301 case OPC_DEXTRV_L:
24302 case OPC_DEXTRV_R_L:
24303 case OPC_DEXTRV_RS_L:
24304 case OPC_DEXTRV_S_H:
24305 case OPC_DEXTRV_W:
24306 case OPC_DEXTRV_R_W:
24307 case OPC_DEXTRV_RS_W:
24308 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 24309 break;
099e5b4d
LA
24310 case OPC_DMTHLIP:
24311 case OPC_DSHILO:
24312 case OPC_DSHILOV:
24313 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 24314 break;
099e5b4d
LA
24315 default: /* Invalid */
24316 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 24317 gen_reserved_instruction(ctx);
461c08df 24318 break;
099e5b4d
LA
24319 }
24320 break;
24321 case OPC_DPAQ_W_QH_DSP:
24322 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24323 switch (op2) {
24324 case OPC_DPAU_H_OBL:
24325 case OPC_DPAU_H_OBR:
24326 case OPC_DPSU_H_OBL:
24327 case OPC_DPSU_H_OBR:
24328 case OPC_DPA_W_QH:
24329 case OPC_DPAQ_S_W_QH:
24330 case OPC_DPS_W_QH:
24331 case OPC_DPSQ_S_W_QH:
24332 case OPC_MULSAQ_S_W_QH:
24333 case OPC_DPAQ_SA_L_PW:
24334 case OPC_DPSQ_SA_L_PW:
24335 case OPC_MULSAQ_S_L_PW:
24336 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24337 break;
24338 case OPC_MAQ_S_W_QHLL:
24339 case OPC_MAQ_S_W_QHLR:
24340 case OPC_MAQ_S_W_QHRL:
24341 case OPC_MAQ_S_W_QHRR:
24342 case OPC_MAQ_SA_W_QHLL:
24343 case OPC_MAQ_SA_W_QHLR:
24344 case OPC_MAQ_SA_W_QHRL:
24345 case OPC_MAQ_SA_W_QHRR:
24346 case OPC_MAQ_S_L_PWL:
24347 case OPC_MAQ_S_L_PWR:
24348 case OPC_DMADD:
24349 case OPC_DMADDU:
24350 case OPC_DMSUB:
24351 case OPC_DMSUBU:
24352 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 24353 break;
099e5b4d
LA
24354 default: /* Invalid */
24355 MIPS_INVAL("MASK DPAQ.W.QH");
3a4ef3b7 24356 gen_reserved_instruction(ctx);
b53371ed 24357 break;
099e5b4d
LA
24358 }
24359 break;
24360 case OPC_DINSV_DSP:
24361 op2 = MASK_INSV(ctx->opcode);
24362 switch (op2) {
24363 case OPC_DINSV:
24364 {
24365 TCGv t0, t1;
24366
a071578b
PMD
24367 check_dsp(ctx);
24368
099e5b4d 24369 if (rt == 0) {
a22260ae
JL
24370 break;
24371 }
1cb6686c 24372
099e5b4d
LA
24373 t0 = tcg_temp_new();
24374 t1 = tcg_temp_new();
1cb6686c 24375
099e5b4d
LA
24376 gen_load_gpr(t0, rt);
24377 gen_load_gpr(t1, rs);
1cb6686c 24378
099e5b4d 24379 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 24380
099e5b4d
LA
24381 tcg_temp_free(t0);
24382 tcg_temp_free(t1);
77c5fa8b 24383 break;
099e5b4d 24384 }
7a387fff 24385 default: /* Invalid */
099e5b4d 24386 MIPS_INVAL("MASK DINSV");
3a4ef3b7 24387 gen_reserved_instruction(ctx);
7a387fff
TS
24388 break;
24389 }
24390 break;
099e5b4d
LA
24391 case OPC_SHLL_OB_DSP:
24392 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24393 break;
24394#endif
fac5a073
LA
24395 default: /* Invalid */
24396 MIPS_INVAL("special3_legacy");
3a4ef3b7 24397 gen_reserved_instruction(ctx);
fac5a073
LA
24398 break;
24399 }
24400}
24401
37b9aae2
MM
24402
24403#if defined(TARGET_MIPS64)
24404
874b2879 24405static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 24406{
c8341e00 24407 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
24408 int rs = extract32(ctx->opcode, 21, 5);
24409 int rt = extract32(ctx->opcode, 16, 5);
24410 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
24411
24412 switch (opc) {
baa609db
AM
24413 case MMI_OPC_MULT1:
24414 case MMI_OPC_MULTU1:
3b948f05
PMD
24415 case MMI_OPC_MADD:
24416 case MMI_OPC_MADDU:
a95c4c26
FN
24417 case MMI_OPC_MADD1:
24418 case MMI_OPC_MADDU1:
06de726b
FN
24419 gen_mul_txx9(ctx, opc, rd, rs, rt);
24420 break;
baa609db
AM
24421 case MMI_OPC_DIV1:
24422 case MMI_OPC_DIVU1:
c42171c3 24423 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 24424 break;
71b8a6b3
FN
24425 default:
24426 MIPS_INVAL("TX79 MMI class");
3a4ef3b7 24427 gen_reserved_instruction(ctx);
71b8a6b3
FN
24428 break;
24429 }
24430}
24431
874b2879 24432static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 24433{
3a4ef3b7 24434 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
f08099ad
FN
24435}
24436
874b2879 24437static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 24438{
3a4ef3b7 24439 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
24440}
24441
24442/*
24443 * The TX79-specific instruction Store Quadword
24444 *
24445 * +--------+-------+-------+------------------------+
24446 * | 011111 | base | rt | offset | SQ
24447 * +--------+-------+-------+------------------------+
24448 * 6 5 5 16
24449 *
24450 * has the same opcode as the Read Hardware Register instruction
24451 *
24452 * +--------+-------+-------+-------+-------+--------+
24453 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24454 * +--------+-------+-------+-------+-------+--------+
24455 * 6 5 5 5 5 6
24456 *
24457 * that is required, trapped and emulated by the Linux kernel. However, all
24458 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24459 * offset is odd. Therefore all valid SQ instructions can execute normally.
24460 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24461 * between SQ and RDHWR, as the Linux kernel does.
24462 */
874b2879 24463static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
24464{
24465 int base = extract32(ctx->opcode, 21, 5);
24466 int rt = extract32(ctx->opcode, 16, 5);
24467 int offset = extract32(ctx->opcode, 0, 16);
24468
24469#ifdef CONFIG_USER_ONLY
24470 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24471 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24472
24473 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24474 int rd = extract32(ctx->opcode, 11, 5);
24475
24476 gen_rdhwr(ctx, rt, rd, 0);
24477 return;
24478 }
24479#endif
24480
874b2879 24481 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
24482}
24483
37b9aae2
MM
24484#endif
24485
fac5a073
LA
24486static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24487{
24488 int rs, rt, rd, sa;
24489 uint32_t op1, op2;
76964147 24490 int16_t imm;
fac5a073
LA
24491
24492 rs = (ctx->opcode >> 21) & 0x1f;
24493 rt = (ctx->opcode >> 16) & 0x1f;
24494 rd = (ctx->opcode >> 11) & 0x1f;
24495 sa = (ctx->opcode >> 6) & 0x1f;
76964147 24496 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
24497
24498 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
24499
24500 /*
24501 * EVA loads and stores overlap Loongson 2E instructions decoded by
24502 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24503 * EVA is absent.
24504 */
24505 if (ctx->eva) {
24506 switch (op1) {
c2e19f3c
AM
24507 case OPC_LWLE:
24508 case OPC_LWRE:
c2e19f3c
AM
24509 case OPC_LBUE:
24510 case OPC_LHUE:
24511 case OPC_LBE:
24512 case OPC_LHE:
24513 case OPC_LLE:
24514 case OPC_LWE:
76964147
JH
24515 check_cp0_enabled(ctx);
24516 gen_ld(ctx, op1, rt, rs, imm);
24517 return;
c2e19f3c
AM
24518 case OPC_SWLE:
24519 case OPC_SWRE:
c2e19f3c
AM
24520 case OPC_SBE:
24521 case OPC_SHE:
76964147
JH
24522 case OPC_SWE:
24523 check_cp0_enabled(ctx);
24524 gen_st(ctx, op1, rt, rs, imm);
24525 return;
24526 case OPC_SCE:
24527 check_cp0_enabled(ctx);
33a07fa2 24528 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
24529 return;
24530 case OPC_CACHEE:
84c2fdc3 24531 check_eva(ctx);
76964147
JH
24532 check_cp0_enabled(ctx);
24533 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24534 gen_cache_operation(ctx, rt, rs, imm);
24535 }
76964147
JH
24536 return;
24537 case OPC_PREFE:
24538 check_cp0_enabled(ctx);
24539 /* Treat as NOP. */
24540 return;
24541 }
24542 }
24543
fac5a073
LA
24544 switch (op1) {
24545 case OPC_EXT:
24546 case OPC_INS:
7a47bae5 24547 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
24548 gen_bitops(ctx, op1, rt, rs, sa, rd);
24549 break;
24550 case OPC_BSHFL:
fac5a073 24551 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 24552 switch (op2) {
c2e19f3c 24553 case OPC_ALIGN:
373ecd38
AM
24554 case OPC_ALIGN_1:
24555 case OPC_ALIGN_2:
24556 case OPC_ALIGN_3:
15eacb9b 24557 case OPC_BITSWAP:
2e211e0a 24558 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
24559 decode_opc_special3_r6(env, ctx);
24560 break;
24561 default:
7a47bae5 24562 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
24563 gen_bshfl(ctx, op2, rt, rd);
24564 break;
24565 }
fac5a073
LA
24566 break;
24567#if defined(TARGET_MIPS64)
c2e19f3c
AM
24568 case OPC_DEXTM:
24569 case OPC_DEXTU:
24570 case OPC_DEXT:
24571 case OPC_DINSM:
24572 case OPC_DINSU:
24573 case OPC_DINS:
7a47bae5 24574 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
24575 check_mips_64(ctx);
24576 gen_bitops(ctx, op1, rt, rs, sa, rd);
24577 break;
24578 case OPC_DBSHFL:
fac5a073 24579 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 24580 switch (op2) {
c2e19f3c 24581 case OPC_DALIGN:
373ecd38
AM
24582 case OPC_DALIGN_1:
24583 case OPC_DALIGN_2:
24584 case OPC_DALIGN_3:
24585 case OPC_DALIGN_4:
24586 case OPC_DALIGN_5:
24587 case OPC_DALIGN_6:
24588 case OPC_DALIGN_7:
15eacb9b 24589 case OPC_DBITSWAP:
2e211e0a 24590 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
24591 decode_opc_special3_r6(env, ctx);
24592 break;
24593 default:
7a47bae5 24594 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
24595 check_mips_64(ctx);
24596 op2 = MASK_DBSHFL(ctx->opcode);
24597 gen_bshfl(ctx, op2, rt, rd);
24598 break;
24599 }
fac5a073
LA
24600 break;
24601#endif
24602 case OPC_RDHWR:
b00c7218 24603 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
24604 break;
24605 case OPC_FORK:
9affc1c5 24606 check_mt(ctx);
fac5a073
LA
24607 {
24608 TCGv t0 = tcg_temp_new();
24609 TCGv t1 = tcg_temp_new();
24610
24611 gen_load_gpr(t0, rt);
24612 gen_load_gpr(t1, rs);
24613 gen_helper_fork(t0, t1);
24614 tcg_temp_free(t0);
24615 tcg_temp_free(t1);
24616 }
24617 break;
24618 case OPC_YIELD:
9affc1c5 24619 check_mt(ctx);
fac5a073
LA
24620 {
24621 TCGv t0 = tcg_temp_new();
24622
fac5a073
LA
24623 gen_load_gpr(t0, rs);
24624 gen_helper_yield(t0, cpu_env, t0);
24625 gen_store_gpr(t0, rd);
24626 tcg_temp_free(t0);
24627 }
24628 break;
10dc65db 24629 default:
2e211e0a 24630 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db
LA
24631 decode_opc_special3_r6(env, ctx);
24632 } else {
24633 decode_opc_special3_legacy(env, ctx);
24634 }
099e5b4d
LA
24635 }
24636}
24637
80e64a38 24638static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
4c789546 24639{
80e64a38
PMD
24640 int32_t offset;
24641 int rs, rt, rd, sa;
24642 uint32_t op, op1;
24643 int16_t imm;
4c789546 24644
80e64a38
PMD
24645 op = MASK_OP_MAJOR(ctx->opcode);
24646 rs = (ctx->opcode >> 21) & 0x1f;
24647 rt = (ctx->opcode >> 16) & 0x1f;
24648 rd = (ctx->opcode >> 11) & 0x1f;
24649 sa = (ctx->opcode >> 6) & 0x1f;
24650 imm = (int16_t)ctx->opcode;
24651 switch (op) {
24652 case OPC_SPECIAL:
24653 decode_opc_special(env, ctx);
4c789546 24654 break;
80e64a38
PMD
24655 case OPC_SPECIAL2:
24656#if defined(TARGET_MIPS64)
24657 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24658 decode_mmi(env, ctx);
4f57f43c
PMD
24659 break;
24660 }
24661#endif
c7abe00a 24662 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
22345286
PMD
24663 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24664 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24665 } else {
e31b43ec 24666 decode_ase_mxu(ctx, ctx->opcode);
22345286 24667 }
4f57f43c 24668 break;
4c789546 24669 }
4f57f43c 24670 decode_opc_special2_legacy(env, ctx);
4c789546 24671 break;
80e64a38
PMD
24672 case OPC_SPECIAL3:
24673#if defined(TARGET_MIPS64)
24674 if (ctx->insn_flags & INSN_R5900) {
24675 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24676 } else {
24677 decode_opc_special3(env, ctx);
80e71591 24678 }
80e64a38
PMD
24679#else
24680 decode_opc_special3(env, ctx);
24681#endif
80e71591 24682 break;
80e64a38
PMD
24683 case OPC_REGIMM:
24684 op1 = MASK_REGIMM(ctx->opcode);
24685 switch (op1) {
24686 case OPC_BLTZL: /* REGIMM branches */
24687 case OPC_BGEZL:
24688 case OPC_BLTZALL:
24689 case OPC_BGEZALL:
24690 check_insn(ctx, ISA_MIPS2);
24691 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24692 /* Fallthrough */
24693 case OPC_BLTZ:
24694 case OPC_BGEZ:
24695 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
2e3eddb0 24696 break;
80e64a38
PMD
24697 case OPC_BLTZAL:
24698 case OPC_BGEZAL:
24699 if (ctx->insn_flags & ISA_MIPS_R6) {
24700 if (rs == 0) {
24701 /* OPC_NAL, OPC_BAL */
24702 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24703 } else {
24704 gen_reserved_instruction(ctx);
24705 }
24706 } else {
24707 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24708 }
2e3eddb0 24709 break;
80e64a38
PMD
24710 case OPC_TGEI: /* REGIMM traps */
24711 case OPC_TGEIU:
24712 case OPC_TLTI:
24713 case OPC_TLTIU:
24714 case OPC_TEQI:
24715
24716 case OPC_TNEI:
24717 check_insn(ctx, ISA_MIPS2);
24718 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24719 gen_trap(ctx, op1, rs, -1, imm);
2e3eddb0 24720 break;
80e64a38
PMD
24721 case OPC_SIGRIE:
24722 check_insn(ctx, ISA_MIPS_R6);
24723 gen_reserved_instruction(ctx);
2e3eddb0 24724 break;
80e64a38
PMD
24725 case OPC_SYNCI:
24726 check_insn(ctx, ISA_MIPS_R2);
24727 /*
24728 * Break the TB to be able to sync copied instructions
24729 * immediately.
24730 */
24731 ctx->base.is_jmp = DISAS_STOP;
2e3eddb0 24732 break;
80e64a38
PMD
24733 case OPC_BPOSGE32: /* MIPS DSP branch */
24734#if defined(TARGET_MIPS64)
24735 case OPC_BPOSGE64:
24736#endif
24737 check_dsp(ctx);
24738 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
a44d6d14 24739 break;
80e64a38
PMD
24740#if defined(TARGET_MIPS64)
24741 case OPC_DAHI:
24742 check_insn(ctx, ISA_MIPS_R6);
24743 check_mips_64(ctx);
24744 if (rs != 0) {
24745 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24746 }
a44d6d14 24747 break;
80e64a38
PMD
24748 case OPC_DATI:
24749 check_insn(ctx, ISA_MIPS_R6);
24750 check_mips_64(ctx);
24751 if (rs != 0) {
24752 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24753 }
a44d6d14 24754 break;
80e64a38
PMD
24755#endif
24756 default: /* Invalid */
24757 MIPS_INVAL("regimm");
24758 gen_reserved_instruction(ctx);
a44d6d14
AM
24759 break;
24760 }
24761 break;
80e64a38
PMD
24762 case OPC_CP0:
24763 check_cp0_enabled(ctx);
24764 op1 = MASK_CP0(ctx->opcode);
24765 switch (op1) {
24766 case OPC_MFC0:
24767 case OPC_MTC0:
24768 case OPC_MFTR:
24769 case OPC_MTTR:
24770 case OPC_MFHC0:
24771 case OPC_MTHC0:
24772#if defined(TARGET_MIPS64)
24773 case OPC_DMFC0:
24774 case OPC_DMTC0:
24775#endif
24776#ifndef CONFIG_USER_ONLY
24777 gen_cp0(env, ctx, op1, rt, rd);
24778#endif /* !CONFIG_USER_ONLY */
7a387fff 24779 break;
c38a1d52
AR
24780 case OPC_C0:
24781 case OPC_C0_1:
24782 case OPC_C0_2:
24783 case OPC_C0_3:
24784 case OPC_C0_4:
24785 case OPC_C0_5:
24786 case OPC_C0_6:
24787 case OPC_C0_7:
24788 case OPC_C0_8:
24789 case OPC_C0_9:
24790 case OPC_C0_A:
24791 case OPC_C0_B:
24792 case OPC_C0_C:
24793 case OPC_C0_D:
24794 case OPC_C0_E:
24795 case OPC_C0_F:
f1aa6320 24796#ifndef CONFIG_USER_ONLY
932e71cd 24797 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 24798#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
24799 break;
24800 case OPC_MFMC0:
8706c382 24801#ifndef CONFIG_USER_ONLY
932e71cd 24802 {
099e5b4d 24803 uint32_t op2;
35fbce2c 24804 TCGv t0 = tcg_temp_new();
6c5c1e20 24805
0eaef5aa 24806 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
24807 switch (op2) {
24808 case OPC_DMT:
9affc1c5 24809 check_cp0_mt(ctx);
9ed5726c 24810 gen_helper_dmt(t0);
35fbce2c 24811 gen_store_gpr(t0, rt);
6c5c1e20
TS
24812 break;
24813 case OPC_EMT:
9affc1c5 24814 check_cp0_mt(ctx);
9ed5726c 24815 gen_helper_emt(t0);
35fbce2c 24816 gen_store_gpr(t0, rt);
da80682b 24817 break;
6c5c1e20 24818 case OPC_DVPE:
9affc1c5 24819 check_cp0_mt(ctx);
895c2d04 24820 gen_helper_dvpe(t0, cpu_env);
35fbce2c 24821 gen_store_gpr(t0, rt);
6c5c1e20
TS
24822 break;
24823 case OPC_EVPE:
9affc1c5 24824 check_cp0_mt(ctx);
895c2d04 24825 gen_helper_evpe(t0, cpu_env);
35fbce2c 24826 gen_store_gpr(t0, rt);
6c5c1e20 24827 break;
01bc435b 24828 case OPC_DVP:
2e211e0a 24829 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
24830 if (ctx->vp) {
24831 gen_helper_dvp(t0, cpu_env);
24832 gen_store_gpr(t0, rt);
24833 }
24834 break;
24835 case OPC_EVP:
2e211e0a 24836 check_insn(ctx, ISA_MIPS_R6);
01bc435b
YK
24837 if (ctx->vp) {
24838 gen_helper_evp(t0, cpu_env);
24839 gen_store_gpr(t0, rt);
24840 }
24841 break;
6c5c1e20 24842 case OPC_DI:
7a47bae5 24843 check_insn(ctx, ISA_MIPS_R2);
867abc7e 24844 save_cpu_state(ctx, 1);
895c2d04 24845 gen_helper_di(t0, cpu_env);
35fbce2c 24846 gen_store_gpr(t0, rt);
7480515f
AM
24847 /*
24848 * Stop translation as we may have switched
24849 * the execution mode.
24850 */
eeb3bba8 24851 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
24852 break;
24853 case OPC_EI:
7a47bae5 24854 check_insn(ctx, ISA_MIPS_R2);
867abc7e 24855 save_cpu_state(ctx, 1);
895c2d04 24856 gen_helper_ei(t0, cpu_env);
35fbce2c 24857 gen_store_gpr(t0, rt);
7480515f
AM
24858 /*
24859 * DISAS_STOP isn't sufficient, we need to ensure we break
24860 * out of translated code to check for pending interrupts.
24861 */
eeb3bba8
EC
24862 gen_save_pc(ctx->base.pc_next + 4);
24863 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
24864 break;
24865 default: /* Invalid */
24866 MIPS_INVAL("mfmc0");
3a4ef3b7 24867 gen_reserved_instruction(ctx);
6c5c1e20
TS
24868 break;
24869 }
6c5c1e20 24870 tcg_temp_free(t0);
7a387fff 24871 }
0eaef5aa 24872#endif /* !CONFIG_USER_ONLY */
6af0bf9c 24873 break;
7a387fff 24874 case OPC_RDPGPR:
7a47bae5 24875 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 24876 gen_load_srsgpr(rt, rd);
ead9360e 24877 break;
7a387fff 24878 case OPC_WRPGPR:
7a47bae5 24879 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 24880 gen_store_srsgpr(rt, rd);
38121543 24881 break;
6af0bf9c 24882 default:
923617a3 24883 MIPS_INVAL("cp0");
3a4ef3b7 24884 gen_reserved_instruction(ctx);
6af0bf9c
FB
24885 break;
24886 }
24887 break;
31837be3 24888 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
2e211e0a 24889 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
24890 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24891 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24892 } else {
24893 /* OPC_ADDI */
24894 /* Arithmetic with immediate opcode */
24895 gen_arith_imm(ctx, op, rt, rs, imm);
24896 }
24897 break;
324d9e32 24898 case OPC_ADDIU:
d75c135e 24899 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 24900 break;
324d9e32
AJ
24901 case OPC_SLTI: /* Set on less than with immediate opcode */
24902 case OPC_SLTIU:
d75c135e 24903 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
24904 break;
24905 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 24906 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
24907 case OPC_ORI:
24908 case OPC_XORI:
d75c135e 24909 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 24910 break;
c2e19f3c
AM
24911 case OPC_J: /* Jump */
24912 case OPC_JAL:
7a387fff 24913 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 24914 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 24915 break;
31837be3
YK
24916 /* Branch */
24917 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
2e211e0a 24918 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 24919 if (rt == 0) {
3a4ef3b7 24920 gen_reserved_instruction(ctx);
31837be3
YK
24921 break;
24922 }
24923 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24924 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24925 } else {
24926 /* OPC_BLEZL */
b231c103 24927 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
24928 }
24929 break;
24930 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
2e211e0a 24931 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 24932 if (rt == 0) {
3a4ef3b7 24933 gen_reserved_instruction(ctx);
31837be3
YK
24934 break;
24935 }
24936 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24937 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24938 } else {
24939 /* OPC_BGTZL */
b231c103 24940 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
24941 }
24942 break;
24943 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24944 if (rt == 0) {
24945 /* OPC_BLEZ */
b231c103 24946 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 24947 } else {
2e211e0a 24948 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
24949 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24950 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24951 }
24952 break;
24953 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24954 if (rt == 0) {
24955 /* OPC_BGTZ */
b231c103 24956 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 24957 } else {
2e211e0a 24958 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
24959 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24960 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24961 }
24962 break;
24963 case OPC_BEQL:
24964 case OPC_BNEL:
d9224450 24965 check_insn(ctx, ISA_MIPS2);
2e211e0a 24966 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 24967 /* Fallthrough */
31837be3
YK
24968 case OPC_BEQ:
24969 case OPC_BNE:
b231c103 24970 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 24971 break;
d9224450
MR
24972 case OPC_LL: /* Load and stores */
24973 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
24974 if (ctx->insn_flags & INSN_R5900) {
24975 check_insn_opc_user_only(ctx, INSN_R5900);
24976 }
d9224450
MR
24977 /* Fallthrough */
24978 case OPC_LWL:
fecd2646 24979 case OPC_LWR:
c2e19f3c
AM
24980 case OPC_LB:
24981 case OPC_LH:
24982 case OPC_LW:
24983 case OPC_LWPC:
24984 case OPC_LBU:
24985 case OPC_LHU:
d75c135e 24986 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 24987 break;
fecd2646 24988 case OPC_SWL:
7a387fff 24989 case OPC_SWR:
c2e19f3c
AM
24990 case OPC_SB:
24991 case OPC_SH:
fecd2646 24992 case OPC_SW:
5c13fdfd 24993 gen_st(ctx, op, rt, rs, imm);
7a387fff 24994 break;
d66c7132 24995 case OPC_SC:
d9224450 24996 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
24997 if (ctx->insn_flags & INSN_R5900) {
24998 check_insn_opc_user_only(ctx, INSN_R5900);
24999 }
33a07fa2
LA
25000 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25001 break;
7a387fff 25002 case OPC_CACHE:
2e15497c 25003 check_cp0_enabled(ctx);
bbd5e4a2 25004 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
0d74a222
LA
25005 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25006 gen_cache_operation(ctx, rt, rs, imm);
25007 }
ead9360e 25008 /* Treat as NOP. */
34ae7b51 25009 break;
7a387fff 25010 case OPC_PREF:
992e8176
FN
25011 if (ctx->insn_flags & INSN_R5900) {
25012 /* Treat as NOP. */
25013 } else {
bbd5e4a2 25014 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
992e8176
FN
25015 /* Treat as NOP. */
25016 }
6af0bf9c 25017 break;
4ad40f36 25018
923617a3 25019 /* Floating point (COP1). */
7a387fff
TS
25020 case OPC_LWC1:
25021 case OPC_LDC1:
25022 case OPC_SWC1:
25023 case OPC_SDC1:
5ab5c041 25024 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
25025 break;
25026
7a387fff 25027 case OPC_CP1:
5692c6e1
YK
25028 op1 = MASK_CP1(ctx->opcode);
25029
25030 switch (op1) {
25031 case OPC_MFHC1:
25032 case OPC_MTHC1:
5e755519 25033 check_cp1_enabled(ctx);
7a47bae5 25034 check_insn(ctx, ISA_MIPS_R2);
146dd620 25035 /* fall through */
5692c6e1
YK
25036 case OPC_MFC1:
25037 case OPC_CFC1:
25038 case OPC_MTC1:
25039 case OPC_CTC1:
25040 check_cp1_enabled(ctx);
25041 gen_cp1(ctx, op1, rt, rd);
25042 break;
d26bc211 25043#if defined(TARGET_MIPS64)
5692c6e1
YK
25044 case OPC_DMFC1:
25045 case OPC_DMTC1:
25046 check_cp1_enabled(ctx);
25047 check_insn(ctx, ISA_MIPS3);
d9224450 25048 check_mips_64(ctx);
5692c6e1
YK
25049 gen_cp1(ctx, op1, rt, rd);
25050 break;
e189e748 25051#endif
5692c6e1
YK
25052 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25053 check_cp1_enabled(ctx);
2e211e0a 25054 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1 25055 /* OPC_BC1EQZ */
31837be3 25056 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25057 rt, imm << 2, 4);
5692c6e1
YK
25058 } else {
25059 /* OPC_BC1ANY2 */
b8aa4598 25060 check_cop1x(ctx);
d75c135e 25061 check_insn(ctx, ASE_MIPS3D);
d75c135e 25062 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 25063 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
25064 }
25065 break;
25066 case OPC_BC1NEZ:
25067 check_cp1_enabled(ctx);
2e211e0a 25068 check_insn(ctx, ISA_MIPS_R6);
5692c6e1 25069 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25070 rt, imm << 2, 4);
5692c6e1
YK
25071 break;
25072 case OPC_BC1ANY4:
25073 check_cp1_enabled(ctx);
2e211e0a 25074 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
25075 check_cop1x(ctx);
25076 check_insn(ctx, ASE_MIPS3D);
25077 /* fall through */
25078 case OPC_BC1:
25079 check_cp1_enabled(ctx);
2e211e0a 25080 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
25081 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25082 (rt >> 2) & 0x7, imm << 2);
25083 break;
25084 case OPC_PS_FMT:
e29c9628 25085 check_ps(ctx);
b6f3b233 25086 /* fall through */
5692c6e1
YK
25087 case OPC_S_FMT:
25088 case OPC_D_FMT:
25089 check_cp1_enabled(ctx);
25090 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25091 (imm >> 8) & 0x7);
25092 break;
25093 case OPC_W_FMT:
25094 case OPC_L_FMT:
25095 {
25096 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25097 check_cp1_enabled(ctx);
2e211e0a 25098 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1
YK
25099 switch (r6_op) {
25100 case R6_OPC_CMP_AF_S:
25101 case R6_OPC_CMP_UN_S:
25102 case R6_OPC_CMP_EQ_S:
25103 case R6_OPC_CMP_UEQ_S:
25104 case R6_OPC_CMP_LT_S:
25105 case R6_OPC_CMP_ULT_S:
25106 case R6_OPC_CMP_LE_S:
25107 case R6_OPC_CMP_ULE_S:
25108 case R6_OPC_CMP_SAF_S:
25109 case R6_OPC_CMP_SUN_S:
25110 case R6_OPC_CMP_SEQ_S:
25111 case R6_OPC_CMP_SEUQ_S:
25112 case R6_OPC_CMP_SLT_S:
25113 case R6_OPC_CMP_SULT_S:
25114 case R6_OPC_CMP_SLE_S:
25115 case R6_OPC_CMP_SULE_S:
25116 case R6_OPC_CMP_OR_S:
25117 case R6_OPC_CMP_UNE_S:
25118 case R6_OPC_CMP_NE_S:
25119 case R6_OPC_CMP_SOR_S:
25120 case R6_OPC_CMP_SUNE_S:
25121 case R6_OPC_CMP_SNE_S:
25122 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25123 break;
25124 case R6_OPC_CMP_AF_D:
25125 case R6_OPC_CMP_UN_D:
25126 case R6_OPC_CMP_EQ_D:
25127 case R6_OPC_CMP_UEQ_D:
25128 case R6_OPC_CMP_LT_D:
25129 case R6_OPC_CMP_ULT_D:
25130 case R6_OPC_CMP_LE_D:
25131 case R6_OPC_CMP_ULE_D:
25132 case R6_OPC_CMP_SAF_D:
25133 case R6_OPC_CMP_SUN_D:
25134 case R6_OPC_CMP_SEQ_D:
25135 case R6_OPC_CMP_SEUQ_D:
25136 case R6_OPC_CMP_SLT_D:
25137 case R6_OPC_CMP_SULT_D:
25138 case R6_OPC_CMP_SLE_D:
25139 case R6_OPC_CMP_SULE_D:
25140 case R6_OPC_CMP_OR_D:
25141 case R6_OPC_CMP_UNE_D:
25142 case R6_OPC_CMP_NE_D:
25143 case R6_OPC_CMP_SOR_D:
25144 case R6_OPC_CMP_SUNE_D:
25145 case R6_OPC_CMP_SNE_D:
25146 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25147 break;
25148 default:
d2bfa6e6
MR
25149 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25150 rt, rd, sa, (imm >> 8) & 0x7);
25151
5692c6e1 25152 break;
3f493883 25153 }
5692c6e1
YK
25154 } else {
25155 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25156 (imm >> 8) & 0x7);
36d23958 25157 }
5692c6e1
YK
25158 break;
25159 }
5692c6e1
YK
25160 default:
25161 MIPS_INVAL("cp1");
3a4ef3b7 25162 gen_reserved_instruction(ctx);
5692c6e1 25163 break;
6ea83fed 25164 }
4ad40f36
FB
25165 break;
25166
31837be3
YK
25167 /* Compact branches [R6] and COP2 [non-R6] */
25168 case OPC_BC: /* OPC_LWC2 */
25169 case OPC_BALC: /* OPC_SWC2 */
2e211e0a 25170 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25171 /* OPC_BC, OPC_BALC */
25172 gen_compute_compact_branch(ctx, op, 0, 0,
25173 sextract32(ctx->opcode << 2, 0, 28));
e10a0ca1
JY
25174 } else if (ctx->insn_flags & ASE_LEXT) {
25175 gen_loongson_lswc2(ctx, rt, rs, rd);
31837be3
YK
25176 } else {
25177 /* OPC_LWC2, OPC_SWC2 */
25178 /* COP2: Not implemented. */
25179 generate_exception_err(ctx, EXCP_CpU, 2);
25180 }
25181 break;
25182 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25183 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
2e211e0a 25184 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25185 if (rs != 0) {
25186 /* OPC_BEQZC, OPC_BNEZC */
25187 gen_compute_compact_branch(ctx, op, rs, 0,
25188 sextract32(ctx->opcode << 2, 0, 23));
25189 } else {
25190 /* OPC_JIC, OPC_JIALC */
25191 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25192 }
90e22a57
JY
25193 } else if (ctx->insn_flags & ASE_LEXT) {
25194 gen_loongson_lsdc2(ctx, rt, rs, rd);
31837be3
YK
25195 } else {
25196 /* OPC_LWC2, OPC_SWC2 */
25197 /* COP2: Not implemented. */
25198 generate_exception_err(ctx, EXCP_CpU, 2);
25199 }
4ad40f36 25200 break;
bd277fa1 25201 case OPC_CP2:
8e2d5831 25202 check_insn(ctx, ASE_LMMI);
bd277fa1
RH
25203 /* Note that these instructions use different fields. */
25204 gen_loongson_multimedia(ctx, sa, rd, rt);
25205 break;
4ad40f36 25206
7a387fff 25207 case OPC_CP3:
5ab5c041 25208 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 25209 check_cp1_enabled(ctx);
36d23958
TS
25210 op1 = MASK_CP3(ctx->opcode);
25211 switch (op1) {
d9224450
MR
25212 case OPC_LUXC1:
25213 case OPC_SUXC1:
7a47bae5 25214 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 25215 /* Fallthrough */
5a5012ec
TS
25216 case OPC_LWXC1:
25217 case OPC_LDXC1:
5a5012ec
TS
25218 case OPC_SWXC1:
25219 case OPC_SDXC1:
7a47bae5 25220 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
93b12ccc 25221 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 25222 break;
e0c84da7 25223 case OPC_PREFX:
7a47bae5 25224 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
ead9360e 25225 /* Treat as NOP. */
e0c84da7 25226 break;
5a5012ec 25227 case OPC_ALNV_PS:
7a47bae5 25228 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 25229 /* Fallthrough */
5a5012ec
TS
25230 case OPC_MADD_S:
25231 case OPC_MADD_D:
25232 case OPC_MADD_PS:
25233 case OPC_MSUB_S:
25234 case OPC_MSUB_D:
25235 case OPC_MSUB_PS:
25236 case OPC_NMADD_S:
25237 case OPC_NMADD_D:
25238 case OPC_NMADD_PS:
25239 case OPC_NMSUB_S:
25240 case OPC_NMSUB_D:
25241 case OPC_NMSUB_PS:
7a47bae5 25242 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
5a5012ec
TS
25243 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25244 break;
36d23958 25245 default:
923617a3 25246 MIPS_INVAL("cp3");
3a4ef3b7 25247 gen_reserved_instruction(ctx);
36d23958
TS
25248 break;
25249 }
25250 } else {
e397ee33 25251 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 25252 }
4ad40f36
FB
25253 break;
25254
d26bc211 25255#if defined(TARGET_MIPS64)
7a387fff 25256 /* MIPS64 opcodes */
96631327 25257 case OPC_LLD:
55fc7a69
FN
25258 if (ctx->insn_flags & INSN_R5900) {
25259 check_insn_opc_user_only(ctx, INSN_R5900);
25260 }
96631327 25261 /* fall through */
c2e19f3c
AM
25262 case OPC_LDL:
25263 case OPC_LDR:
fecd2646 25264 case OPC_LWU:
7a387fff 25265 case OPC_LD:
d75c135e 25266 check_insn(ctx, ISA_MIPS3);
5c13fdfd 25267 check_mips_64(ctx);
d75c135e 25268 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 25269 break;
c2e19f3c
AM
25270 case OPC_SDL:
25271 case OPC_SDR:
7a387fff 25272 case OPC_SD:
d75c135e 25273 check_insn(ctx, ISA_MIPS3);
e189e748 25274 check_mips_64(ctx);
5c13fdfd 25275 gen_st(ctx, op, rt, rs, imm);
7a387fff 25276 break;
d66c7132 25277 case OPC_SCD:
d75c135e 25278 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
25279 if (ctx->insn_flags & INSN_R5900) {
25280 check_insn_opc_user_only(ctx, INSN_R5900);
25281 }
d66c7132 25282 check_mips_64(ctx);
33a07fa2 25283 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
d66c7132 25284 break;
31837be3 25285 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
2e211e0a 25286 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25287 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25288 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25289 } else {
25290 /* OPC_DADDI */
25291 check_insn(ctx, ISA_MIPS3);
25292 check_mips_64(ctx);
25293 gen_arith_imm(ctx, op, rt, rs, imm);
25294 }
25295 break;
324d9e32 25296 case OPC_DADDIU:
d75c135e 25297 check_insn(ctx, ISA_MIPS3);
e189e748 25298 check_mips_64(ctx);
d75c135e 25299 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 25300 break;
31837be3
YK
25301#else
25302 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
2e211e0a 25303 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
25304 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25305 } else {
25306 MIPS_INVAL("major opcode");
3a4ef3b7 25307 gen_reserved_instruction(ctx);
31837be3
YK
25308 }
25309 break;
6af0bf9c 25310#endif
d4ea6acd 25311 case OPC_DAUI: /* OPC_JALX */
2e211e0a 25312 if (ctx->insn_flags & ISA_MIPS_R6) {
d4ea6acd
LA
25313#if defined(TARGET_MIPS64)
25314 /* OPC_DAUI */
25315 check_mips_64(ctx);
db77d852
LA
25316 if (rs == 0) {
25317 generate_exception(ctx, EXCP_RI);
25318 } else if (rt != 0) {
d4ea6acd
LA
25319 TCGv t0 = tcg_temp_new();
25320 gen_load_gpr(t0, rs);
25321 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25322 tcg_temp_free(t0);
25323 }
d4ea6acd 25324#else
3a4ef3b7 25325 gen_reserved_instruction(ctx);
d4ea6acd
LA
25326 MIPS_INVAL("major opcode");
25327#endif
25328 } else {
25329 /* OPC_JALX */
25330 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25331 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 25332 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 25333 }
364d4831 25334 break;
96e5b4c7 25335 case OPC_MDMX: /* MMI_OPC_LQ */
f08099ad 25336 if (ctx->insn_flags & INSN_R5900) {
37b9aae2 25337#if defined(TARGET_MIPS64)
96e5b4c7 25338 gen_mmi_lq(env, ctx);
37b9aae2 25339#endif
f08099ad
FN
25340 } else {
25341 /* MDMX: Not implemented. */
f08099ad 25342 }
d4ea6acd
LA
25343 break;
25344 case OPC_PCREL:
2e211e0a 25345 check_insn(ctx, ISA_MIPS_R6);
eeb3bba8 25346 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 25347 break;
6af0bf9c 25348 default: /* Invalid */
923617a3 25349 MIPS_INVAL("major opcode");
311edee7 25350 return false;
6af0bf9c 25351 }
311edee7
PMD
25352 return true;
25353}
25354
25355static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25356{
25357 /* make sure instructions are on a word boundary */
25358 if (ctx->base.pc_next & 0x3) {
25359 env->CP0_BadVAddr = ctx->base.pc_next;
25360 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25361 return;
25362 }
25363
25364 /* Handle blikely not taken case */
25365 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25366 TCGLabel *l1 = gen_new_label();
25367
25368 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25369 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25370 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25371 gen_set_label(l1);
25372 }
25373
96e5b4c7
PMD
25374 /* Transition to the auto-generated decoder. */
25375
25376 /* ISA extensions */
25377 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25378 return;
25379 }
25380
3f7a9278
PMD
25381 /* ISA (from latest to oldest) */
25382 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25383 return;
25384 }
ffc672aa
PMD
25385 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25386 return;
25387 }
3f7a9278 25388
311edee7
PMD
25389 if (decode_opc_legacy(env, ctx)) {
25390 return;
25391 }
25392
25393 gen_reserved_instruction(ctx);
6af0bf9c
FB
25394}
25395
18f440ed 25396static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 25397{
18f440ed 25398 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 25399 CPUMIPSState *env = cs->env_ptr;
12be9258 25400
18f440ed 25401 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
25402 ctx->saved_pc = -1;
25403 ctx->insn_flags = env->insn_flags;
25404 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 25405 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
25406 ctx->CP0_Config3 = env->CP0_Config3;
25407 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
25408 ctx->btarget = 0;
25409 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25410 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25411 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25412 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25413 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25414 ctx->PAMask = env->PAMask;
25415 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25416 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25417 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25418 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25419 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 25420 /* Restore delay slot state from the tb context. */
12be9258
EC
25421 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25422 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25423 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 25424 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
25425 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25426 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25427 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25428 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 25429 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
99029be1 25430 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
12be9258 25431 restore_cpu_state(env, ctx);
932e71cd 25432#ifdef CONFIG_USER_ONLY
12be9258 25433 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 25434#else
12be9258 25435 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 25436#endif
2e211e0a 25437 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
8a805609 25438 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
190ce7fb 25439
18f440ed
EC
25440 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25441 ctx->hflags);
25442}
12be9258 25443
18f440ed
EC
25444static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25445{
25446}
b933066a 25447
18f440ed
EC
25448static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25449{
25450 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25451
18f440ed
EC
25452 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25453 ctx->btarget);
25454}
31837be3 25455
18f440ed
EC
25456static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25457 const CPUBreakpoint *bp)
25458{
25459 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25460
18f440ed
EC
25461 save_cpu_state(ctx, 1);
25462 ctx->base.is_jmp = DISAS_NORETURN;
25463 gen_helper_raise_exception_debug(cpu_env);
7480515f
AM
25464 /*
25465 * The address covered by the breakpoint must be included in
25466 * [tb->pc, tb->pc + tb->size) in order to for it to be
25467 * properly cleared -- thus we increment the PC here so that
25468 * the logic setting tb->size below does the right thing.
25469 */
18f440ed
EC
25470 ctx->base.pc_next += 4;
25471 return true;
25472}
4ad40f36 25473
18f440ed
EC
25474static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25475{
25476 CPUMIPSState *env = cs->env_ptr;
25477 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25478 int insn_bytes;
25479 int is_slot;
4ad40f36 25480
18f440ed 25481 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4 25482 if (ctx->insn_flags & ISA_NANOMIPS32) {
0ab8e33a 25483 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
c533c0f4
AM
25484 insn_bytes = decode_nanomips_opc(env, ctx);
25485 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
0ab8e33a 25486 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
18f440ed
EC
25487 insn_bytes = 4;
25488 decode_opc(env, ctx);
25489 } else if (ctx->insn_flags & ASE_MICROMIPS) {
0ab8e33a 25490 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
18f440ed
EC
25491 insn_bytes = decode_micromips_opc(env, ctx);
25492 } else if (ctx->insn_flags & ASE_MIPS16) {
0ab8e33a 25493 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
18f440ed
EC
25494 insn_bytes = decode_mips16_opc(env, ctx);
25495 } else {
3a4ef3b7 25496 gen_reserved_instruction(ctx);
18f440ed
EC
25497 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25498 return;
25499 }
faf7aaa9 25500
18f440ed
EC
25501 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25502 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25503 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
25504 /*
25505 * Force to generate branch as there is neither delay nor
25506 * forbidden slot.
25507 */
18f440ed
EC
25508 is_slot = 1;
25509 }
25510 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25511 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
25512 /*
25513 * Force to generate branch as microMIPS R6 doesn't restrict
25514 * branches in the forbidden slot.
25515 */
18f440ed 25516 is_slot = 1;
eeb3bba8 25517 }
18f440ed
EC
25518 }
25519 if (is_slot) {
25520 gen_branch(ctx, insn_bytes);
25521 }
25522 ctx->base.pc_next += insn_bytes;
1b530a6d 25523
18f440ed
EC
25524 if (ctx->base.is_jmp != DISAS_NEXT) {
25525 return;
6af0bf9c 25526 }
7480515f
AM
25527 /*
25528 * Execute a branch and its delay slot as a single instruction.
25529 * This is what GDB expects and is consistent with what the
25530 * hardware does (e.g. if a delay slot instruction faults, the
25531 * reported PC is the PC of the branch).
25532 */
18f440ed
EC
25533 if (ctx->base.singlestep_enabled &&
25534 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25535 ctx->base.is_jmp = DISAS_TOO_MANY;
25536 }
25537 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25538 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 25539 }
18f440ed
EC
25540}
25541
25542static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25543{
25544 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25545
12be9258
EC
25546 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25547 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 25548 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 25549 } else {
12be9258 25550 switch (ctx->base.is_jmp) {
b28425ba 25551 case DISAS_STOP:
12be9258 25552 gen_save_pc(ctx->base.pc_next);
cd314a7d 25553 tcg_gen_lookup_and_goto_ptr();
df1561e2 25554 break;
b28425ba 25555 case DISAS_NEXT:
18f440ed 25556 case DISAS_TOO_MANY:
12be9258
EC
25557 save_cpu_state(ctx, 0);
25558 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 25559 break;
b28425ba 25560 case DISAS_EXIT:
07ea28b4 25561 tcg_gen_exit_tb(NULL, 0);
16c00cb2 25562 break;
b28425ba 25563 case DISAS_NORETURN:
5a5012ec 25564 break;
18f440ed
EC
25565 default:
25566 g_assert_not_reached();
6958549d 25567 }
6af0bf9c 25568 }
18f440ed
EC
25569}
25570
25571static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25572{
25573 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25574 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25575}
25576
25577static const TranslatorOps mips_tr_ops = {
25578 .init_disas_context = mips_tr_init_disas_context,
25579 .tb_start = mips_tr_tb_start,
25580 .insn_start = mips_tr_insn_start,
25581 .breakpoint_check = mips_tr_breakpoint_check,
25582 .translate_insn = mips_tr_translate_insn,
25583 .tb_stop = mips_tr_tb_stop,
25584 .disas_log = mips_tr_disas_log,
25585};
25586
8b86d6d2 25587void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
18f440ed
EC
25588{
25589 DisasContext ctx;
25590
8b86d6d2 25591 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
6af0bf9c
FB
25592}
25593
959c5da2
PMD
25594void mips_tcg_init(void)
25595{
25596 int i;
25597
25598 cpu_gpr[0] = NULL;
25599 for (i = 1; i < 32; i++)
25600 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25601 offsetof(CPUMIPSState,
25602 active_tc.gpr[i]),
25603 regnames[i]);
cefd68f6
PMD
25604#if defined(TARGET_MIPS64)
25605 cpu_gpr_hi[0] = NULL;
25606
25607 for (unsigned i = 1; i < 32; i++) {
b5b63d43
PMD
25608 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25609
cefd68f6
PMD
25610 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25611 offsetof(CPUMIPSState,
25612 active_tc.gpr_hi[i]),
b5b63d43 25613 rname);
cefd68f6
PMD
25614 }
25615#endif /* !TARGET_MIPS64 */
959c5da2
PMD
25616 for (i = 0; i < 32; i++) {
25617 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
863f264d 25618
959c5da2
PMD
25619 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25620 }
25621 msa_translate_init();
e1ccc054 25622 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 25623 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 25624 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 25625 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 25626 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 25627 regnames_HI[i]);
e1ccc054 25628 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 25629 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 25630 regnames_LO[i]);
4b2eb8d2 25631 }
e1ccc054 25632 cpu_dspctrl = tcg_global_mem_new(cpu_env,
71375b59
AM
25633 offsetof(CPUMIPSState,
25634 active_tc.DSPControl),
4b2eb8d2 25635 "DSPControl");
e1ccc054 25636 bcond = tcg_global_mem_new(cpu_env,
7db13fae 25637 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 25638 btarget = tcg_global_mem_new(cpu_env,
7db13fae 25639 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 25640 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 25641 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 25642
e1ccc054 25643 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25644 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 25645 "fcr0");
e1ccc054 25646 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25647 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 25648 "fcr31");
33a07fa2
LA
25649 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25650 "lladdr");
25651 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25652 "llval");
a168a796 25653
fe35ea94
PMD
25654 if (TARGET_LONG_BITS == 32) {
25655 mxu_translate_init();
eb5559f6 25656 }
39454628
TS
25657}
25658
bad729e2
RH
25659void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25660 target_ulong *data)
d2856f1a 25661{
bad729e2 25662 env->active_tc.PC = data[0];
d2856f1a 25663 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 25664 env->hflags |= data[1];
4636401d
AJ
25665 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25666 case MIPS_HFLAG_BR:
25667 break;
25668 case MIPS_HFLAG_BC:
25669 case MIPS_HFLAG_BL:
25670 case MIPS_HFLAG_B:
bad729e2 25671 env->btarget = data[2];
4636401d
AJ
25672 break;
25673 }
d2856f1a 25674}