]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/tcg/translate.c
target: Use vaddr in gen_intermediate_code
[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"
8cab4157 26#include "translate.h"
26aa3d9a 27#include "internal.h"
2ef6175a 28#include "exec/helper-proto.h"
d654e928 29#include "exec/translation-block.h"
6b5fe137 30#include "semihosting/semihost.h"
34b8ff25 31#include "trace.h"
8cab4157 32#include "disas/disas.h"
81ddae7c 33#include "fpu_helper.h"
a7e30d84 34
d53106c9
RH
35#define HELPER_H "helper.h"
36#include "exec/helper-info.c.inc"
37#undef HELPER_H
38
39
ecdbcb0a
PMD
40/*
41 * Many sysemu-only helpers are not reachable for user-only.
42 * Define stub generators here, so that we need not either sprinkle
43 * ifdefs through the translator, nor provide the helper function.
44 */
45#define STUB_HELPER(NAME, ...) \
46 static inline void gen_helper_##NAME(__VA_ARGS__) \
47 { g_assert_not_reached(); }
48
49#ifdef CONFIG_USER_ONLY
50STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
51#endif
52
e37e863f
FB
53enum {
54 /* indirect opcode tables */
7a387fff
TS
55 OPC_SPECIAL = (0x00 << 26),
56 OPC_REGIMM = (0x01 << 26),
57 OPC_CP0 = (0x10 << 26),
7a387fff
TS
58 OPC_CP2 = (0x12 << 26),
59 OPC_CP3 = (0x13 << 26),
60 OPC_SPECIAL2 = (0x1C << 26),
61 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 62 /* arithmetic with immediate */
7a387fff
TS
63 OPC_ADDI = (0x08 << 26),
64 OPC_ADDIU = (0x09 << 26),
65 OPC_SLTI = (0x0A << 26),
66 OPC_SLTIU = (0x0B << 26),
324d9e32 67 /* logic with immediate */
7a387fff
TS
68 OPC_ANDI = (0x0C << 26),
69 OPC_ORI = (0x0D << 26),
70 OPC_XORI = (0x0E << 26),
71 OPC_LUI = (0x0F << 26),
324d9e32 72 /* arithmetic with immediate */
7a387fff
TS
73 OPC_DADDI = (0x18 << 26),
74 OPC_DADDIU = (0x19 << 26),
e37e863f 75 /* Jump and branches */
7a387fff
TS
76 OPC_J = (0x02 << 26),
77 OPC_JAL = (0x03 << 26),
78 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
79 OPC_BEQL = (0x14 << 26),
80 OPC_BNE = (0x05 << 26),
81 OPC_BNEL = (0x15 << 26),
82 OPC_BLEZ = (0x06 << 26),
83 OPC_BLEZL = (0x16 << 26),
84 OPC_BGTZ = (0x07 << 26),
85 OPC_BGTZL = (0x17 << 26),
b231c103 86 OPC_JALX = (0x1D << 26),
d4ea6acd 87 OPC_DAUI = (0x1D << 26),
e37e863f 88 /* Load and stores */
7a387fff
TS
89 OPC_LDL = (0x1A << 26),
90 OPC_LDR = (0x1B << 26),
91 OPC_LB = (0x20 << 26),
92 OPC_LH = (0x21 << 26),
93 OPC_LWL = (0x22 << 26),
94 OPC_LW = (0x23 << 26),
364d4831 95 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
96 OPC_LBU = (0x24 << 26),
97 OPC_LHU = (0x25 << 26),
98 OPC_LWR = (0x26 << 26),
99 OPC_LWU = (0x27 << 26),
100 OPC_SB = (0x28 << 26),
101 OPC_SH = (0x29 << 26),
102 OPC_SWL = (0x2A << 26),
103 OPC_SW = (0x2B << 26),
104 OPC_SDL = (0x2C << 26),
105 OPC_SDR = (0x2D << 26),
106 OPC_SWR = (0x2E << 26),
107 OPC_LL = (0x30 << 26),
108 OPC_LLD = (0x34 << 26),
109 OPC_LD = (0x37 << 26),
364d4831 110 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
111 OPC_SC = (0x38 << 26),
112 OPC_SCD = (0x3C << 26),
113 OPC_SD = (0x3F << 26),
e37e863f 114 /* Floating point load/store */
7a387fff
TS
115 OPC_LWC1 = (0x31 << 26),
116 OPC_LWC2 = (0x32 << 26),
117 OPC_LDC1 = (0x35 << 26),
118 OPC_LDC2 = (0x36 << 26),
119 OPC_SWC1 = (0x39 << 26),
120 OPC_SWC2 = (0x3A << 26),
121 OPC_SDC1 = (0x3D << 26),
122 OPC_SDC2 = (0x3E << 26),
31837be3
YK
123 /* Compact Branches */
124 OPC_BLEZALC = (0x06 << 26),
125 OPC_BGEZALC = (0x06 << 26),
126 OPC_BGEUC = (0x06 << 26),
127 OPC_BGTZALC = (0x07 << 26),
128 OPC_BLTZALC = (0x07 << 26),
129 OPC_BLTUC = (0x07 << 26),
130 OPC_BOVC = (0x08 << 26),
131 OPC_BEQZALC = (0x08 << 26),
132 OPC_BEQC = (0x08 << 26),
133 OPC_BLEZC = (0x16 << 26),
134 OPC_BGEZC = (0x16 << 26),
135 OPC_BGEC = (0x16 << 26),
136 OPC_BGTZC = (0x17 << 26),
137 OPC_BLTZC = (0x17 << 26),
138 OPC_BLTC = (0x17 << 26),
139 OPC_BNVC = (0x18 << 26),
140 OPC_BNEZALC = (0x18 << 26),
141 OPC_BNEC = (0x18 << 26),
142 OPC_BC = (0x32 << 26),
143 OPC_BEQZC = (0x36 << 26),
144 OPC_JIC = (0x36 << 26),
145 OPC_BALC = (0x3A << 26),
146 OPC_BNEZC = (0x3E << 26),
147 OPC_JIALC = (0x3E << 26),
7a387fff
TS
148 /* MDMX ASE specific */
149 OPC_MDMX = (0x1E << 26),
e37e863f 150 /* Cache and prefetch */
7a387fff
TS
151 OPC_CACHE = (0x2F << 26),
152 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
153 /* PC-relative address computation / loads */
154 OPC_PCREL = (0x3B << 26),
155};
156
157/* PC-relative address computation / loads */
71375b59
AM
158#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
159#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
d4ea6acd
LA
160enum {
161 /* Instructions determined by bits 19 and 20 */
162 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
163 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
164 OPC_LWUPC = OPC_PCREL | (2 << 19),
165
166 /* Instructions determined by bits 16 ... 20 */
167 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
168 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
169
170 /* Other */
171 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
172};
173
174/* MIPS special opcodes */
71375b59 175#define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 176
e37e863f
FB
177enum {
178 /* Shifts */
7a387fff 179 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
180 /* NOP is SLL r0, r0, 0 */
181 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
182 /* EHB is SLL r0, r0, 3 */
183 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 184 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
185 OPC_SRA = 0x03 | OPC_SPECIAL,
186 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 187 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 188 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
189 OPC_SRAV = 0x07 | OPC_SPECIAL,
190 OPC_DSLLV = 0x14 | OPC_SPECIAL,
191 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 192 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
193 OPC_DSRAV = 0x17 | OPC_SPECIAL,
194 OPC_DSLL = 0x38 | OPC_SPECIAL,
195 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 196 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
197 OPC_DSRA = 0x3B | OPC_SPECIAL,
198 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
199 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 200 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 201 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 202 /* Multiplication / division */
7a387fff
TS
203 OPC_MULT = 0x18 | OPC_SPECIAL,
204 OPC_MULTU = 0x19 | OPC_SPECIAL,
205 OPC_DIV = 0x1A | OPC_SPECIAL,
206 OPC_DIVU = 0x1B | OPC_SPECIAL,
207 OPC_DMULT = 0x1C | OPC_SPECIAL,
208 OPC_DMULTU = 0x1D | OPC_SPECIAL,
209 OPC_DDIV = 0x1E | OPC_SPECIAL,
210 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 211
e37e863f 212 /* 2 registers arithmetic / logic */
7a387fff
TS
213 OPC_ADD = 0x20 | OPC_SPECIAL,
214 OPC_ADDU = 0x21 | OPC_SPECIAL,
215 OPC_SUB = 0x22 | OPC_SPECIAL,
216 OPC_SUBU = 0x23 | OPC_SPECIAL,
217 OPC_AND = 0x24 | OPC_SPECIAL,
218 OPC_OR = 0x25 | OPC_SPECIAL,
219 OPC_XOR = 0x26 | OPC_SPECIAL,
220 OPC_NOR = 0x27 | OPC_SPECIAL,
221 OPC_SLT = 0x2A | OPC_SPECIAL,
222 OPC_SLTU = 0x2B | OPC_SPECIAL,
223 OPC_DADD = 0x2C | OPC_SPECIAL,
224 OPC_DADDU = 0x2D | OPC_SPECIAL,
225 OPC_DSUB = 0x2E | OPC_SPECIAL,
226 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 227 /* Jumps */
7a387fff
TS
228 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
229 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 230 /* Traps */
7a387fff
TS
231 OPC_TGE = 0x30 | OPC_SPECIAL,
232 OPC_TGEU = 0x31 | OPC_SPECIAL,
233 OPC_TLT = 0x32 | OPC_SPECIAL,
234 OPC_TLTU = 0x33 | OPC_SPECIAL,
235 OPC_TEQ = 0x34 | OPC_SPECIAL,
236 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 237 /* HI / LO registers load & stores */
7a387fff
TS
238 OPC_MFHI = 0x10 | OPC_SPECIAL,
239 OPC_MTHI = 0x11 | OPC_SPECIAL,
240 OPC_MFLO = 0x12 | OPC_SPECIAL,
241 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 242 /* Conditional moves */
7a387fff
TS
243 OPC_MOVZ = 0x0A | OPC_SPECIAL,
244 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 245
b691d9d2
LA
246 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
247 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
248
7a387fff 249 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
250
251 /* Special */
a0d700e4 252 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
253 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
254 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 255 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
256 OPC_SYNC = 0x0F | OPC_SPECIAL,
257
7a387fff
TS
258 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
259 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
260 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
261 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
262};
263
7480515f
AM
264/*
265 * R6 Multiply and Divide instructions have the same opcode
266 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
267 */
71375b59 268#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
b42ee5e1
LA
269
270enum {
271 R6_OPC_MUL = OPC_MULT | (2 << 6),
272 R6_OPC_MUH = OPC_MULT | (3 << 6),
273 R6_OPC_MULU = OPC_MULTU | (2 << 6),
274 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
275 R6_OPC_DIV = OPC_DIV | (2 << 6),
276 R6_OPC_MOD = OPC_DIV | (3 << 6),
277 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
278 R6_OPC_MODU = OPC_DIVU | (3 << 6),
279
280 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
281 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
282 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
283 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
284 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
285 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
286 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
287 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
288
289 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
290 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
291 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
292 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
293 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
b42ee5e1
LA
294};
295
7a387fff 296/* REGIMM (rt field) opcodes */
71375b59 297#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
7a387fff
TS
298
299enum {
300 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
301 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
302 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
303 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
304 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
305 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
306 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
307 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
308 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
309 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
310 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
311 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
312 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
313 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 314 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 315 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
316
317 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
318 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
319};
320
7a387fff 321/* Special2 opcodes */
71375b59 322#define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff 323
e37e863f 324enum {
7a387fff
TS
325 /* Multiply & xxx operations */
326 OPC_MADD = 0x00 | OPC_SPECIAL2,
327 OPC_MADDU = 0x01 | OPC_SPECIAL2,
328 OPC_MUL = 0x02 | OPC_SPECIAL2,
329 OPC_MSUB = 0x04 | OPC_SPECIAL2,
330 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
331 /* Loongson 2F */
332 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
333 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
334 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
335 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
336 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
337 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
338 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
339 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
340 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
341 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
342 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
343 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 344 /* Misc */
7a387fff
TS
345 OPC_CLZ = 0x20 | OPC_SPECIAL2,
346 OPC_CLO = 0x21 | OPC_SPECIAL2,
347 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
348 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 349 /* Special */
7a387fff
TS
350 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
351};
352
353/* Special3 opcodes */
71375b59 354#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
7a387fff
TS
355
356enum {
357 OPC_EXT = 0x00 | OPC_SPECIAL3,
358 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
359 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
360 OPC_DEXT = 0x03 | OPC_SPECIAL3,
361 OPC_INS = 0x04 | OPC_SPECIAL3,
362 OPC_DINSM = 0x05 | OPC_SPECIAL3,
363 OPC_DINSU = 0x06 | OPC_SPECIAL3,
364 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
365 OPC_FORK = 0x08 | OPC_SPECIAL3,
366 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
367 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
368 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
369 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
99029be1 370 OPC_GINV = 0x3D | OPC_SPECIAL3,
161f85e6
AJ
371
372 /* Loongson 2E */
373 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
374 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
375 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
376 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
377 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
378 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
379 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
380 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
381 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
382 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
383 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
384 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
385
386 /* MIPS DSP Load */
387 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
388 /* MIPS DSP Arithmetic */
389 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 390 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 391 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 392 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
393 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
394 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
395 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 396 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
397 /* MIPS DSP GPR-Based Shift Sub-class */
398 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 399 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
400 /* MIPS DSP Multiply Sub-class insns */
401 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
402 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
403 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 404 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
405 /* DSP Bit/Manipulation Sub-class */
406 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 407 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 408 /* MIPS DSP Append Sub-class */
26690560 409 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 410 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
411 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
412 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 413 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 414
76964147
JH
415 /* EVA */
416 OPC_LWLE = 0x19 | OPC_SPECIAL3,
417 OPC_LWRE = 0x1A | OPC_SPECIAL3,
418 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
419 OPC_SBE = 0x1C | OPC_SPECIAL3,
420 OPC_SHE = 0x1D | OPC_SPECIAL3,
421 OPC_SCE = 0x1E | OPC_SPECIAL3,
422 OPC_SWE = 0x1F | OPC_SPECIAL3,
423 OPC_SWLE = 0x21 | OPC_SPECIAL3,
424 OPC_SWRE = 0x22 | OPC_SPECIAL3,
425 OPC_PREFE = 0x23 | OPC_SPECIAL3,
426 OPC_LBUE = 0x28 | OPC_SPECIAL3,
427 OPC_LHUE = 0x29 | OPC_SPECIAL3,
428 OPC_LBE = 0x2C | OPC_SPECIAL3,
429 OPC_LHE = 0x2D | OPC_SPECIAL3,
430 OPC_LLE = 0x2E | OPC_SPECIAL3,
431 OPC_LWE = 0x2F | OPC_SPECIAL3,
432
4368b29a 433 /* R6 */
bf7910c6
LA
434 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
435 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
436 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
437 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
438 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
439 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
440};
441
e10a0ca1
JY
442/* Loongson EXT load/store quad word opcodes */
443#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
444enum {
445 OPC_GSLQ = 0x0020 | OPC_LWC2,
446 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
447 OPC_GSSHFL = OPC_LWC2,
448 OPC_GSSQ = 0x0020 | OPC_SWC2,
449 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
450 OPC_GSSHFS = OPC_SWC2,
451};
452
fd723105
JY
453/* Loongson EXT shifted load/store opcodes */
454#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
455enum {
456 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
457 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
458 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
459 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
460 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
461 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
462 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
463 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
464};
465
90e22a57
JY
466/* Loongson EXT LDC2/SDC2 opcodes */
467#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
468
469enum {
470 OPC_GSLBX = 0x0 | OPC_LDC2,
471 OPC_GSLHX = 0x1 | OPC_LDC2,
472 OPC_GSLWX = 0x2 | OPC_LDC2,
473 OPC_GSLDX = 0x3 | OPC_LDC2,
474 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
475 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
476 OPC_GSSBX = 0x0 | OPC_SDC2,
477 OPC_GSSHX = 0x1 | OPC_SDC2,
478 OPC_GSSWX = 0x2 | OPC_SDC2,
479 OPC_GSSDX = 0x3 | OPC_SDC2,
480 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
481 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
482};
483
7a387fff 484/* BSHFL opcodes */
71375b59 485#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 486
e37e863f 487enum {
15eacb9b
YK
488 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
489 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
490 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
491 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
492 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
493 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
494 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 495 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
496};
497
7a387fff 498/* DBSHFL opcodes */
71375b59 499#define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
7a387fff 500
e37e863f 501enum {
15eacb9b
YK
502 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
503 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
504 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
505 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
506 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
507 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
508 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
509 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
510 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
511 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 512 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
513};
514
e45a93e2
JL
515/* MIPS DSP REGIMM opcodes */
516enum {
517 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 518 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
519};
520
71375b59 521#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
9b1a1d68
JL
522/* MIPS DSP Load */
523enum {
524 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
525 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
526 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 527 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
528};
529
71375b59 530#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
531enum {
532 /* MIPS DSP Arithmetic Sub-class */
533 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
534 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
535 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
536 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
537 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
538 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
539 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
540 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
541 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
542 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
543 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
544 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
545 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
546 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
549 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
550 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
553 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
554 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
555 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
556 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
557 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
558};
559
560#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
71375b59 561#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
562enum {
563 /* MIPS DSP Arithmetic Sub-class */
564 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
565 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
566 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
567 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
568 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
569 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
570 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
571 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
572 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
573 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
574 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
576 /* MIPS DSP Multiply Sub-class insns */
577 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
578 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
579 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
581};
582
71375b59 583#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
584enum {
585 /* MIPS DSP Arithmetic Sub-class */
586 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
587 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
588 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
589 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
590 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
591 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
592 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
593 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
594 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
595 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
599 /* DSP Bit/Manipulation Sub-class */
600 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
605};
606
71375b59 607#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
608enum {
609 /* MIPS DSP Arithmetic Sub-class */
610 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
611 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
612 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
613 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
614 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
615 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
616 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
617 /* DSP Compare-Pick Sub-class */
618 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
619 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
626 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
627 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 633};
a22260ae 634
71375b59 635#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
636enum {
637 /* MIPS DSP GPR-Based Shift Sub-class */
638 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
639 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
640 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
641 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
642 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
643 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
644 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
645 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
646 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
647 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
660};
461c08df 661
71375b59 662#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
663enum {
664 /* MIPS DSP Multiply Sub-class insns */
665 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
666 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
667 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
668 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
669 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
670 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
671 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
672 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
673 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
674 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
679 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
682 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
683 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
687};
688
71375b59 689#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
690enum {
691 /* DSP Bit/Manipulation Sub-class */
692 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
693};
694
71375b59 695#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 696enum {
df6126a7 697 /* MIPS DSP Append Sub-class */
26690560
JL
698 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
699 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
700 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
701};
702
71375b59 703#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
704enum {
705 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
706 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
707 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
708 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
709 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
710 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
711 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
712 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
713 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
714 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
715 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
718 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
719 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
720 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
721 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
722 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
723};
724
71375b59 725#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df
JL
726enum {
727 /* MIPS DSP Arithmetic Sub-class */
728 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
731 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
732 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
733 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
734 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
735 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
736 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
737 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
745 /* DSP Bit/Manipulation Sub-class */
746 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 752};
461c08df 753
71375b59 754#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 755enum {
a22260ae
JL
756 /* MIPS DSP Multiply Sub-class insns */
757 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
758 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
759 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
760 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
761 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
762 /* MIPS DSP Arithmetic Sub-class */
763 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
764 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
765 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
766 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
767 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
768 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
769 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
770 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
771 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
772 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
774 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
775 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
776 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
777 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
778 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
779 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
780 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
781 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
782 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
784};
461c08df 785
71375b59 786#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
461c08df 787enum {
26690560
JL
788 /* DSP Compare-Pick Sub-class */
789 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
796 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
797 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
798 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
808 /* MIPS DSP Arithmetic Sub-class */
809 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
817};
461c08df 818
71375b59 819#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
26690560 820enum {
df6126a7 821 /* DSP Append Sub-class */
26690560
JL
822 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
823 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
824 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
825 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
826};
26690560 827
71375b59 828#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
b53371ed
JL
829enum {
830 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
831 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
832 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
833 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
834 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
835 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
836 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
837 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
838 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
839 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
840 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
841 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
852};
853
71375b59 854#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
1cb6686c
JL
855enum {
856 /* DSP Bit/Manipulation Sub-class */
857 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
858};
1cb6686c 859
71375b59 860#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
a22260ae
JL
861enum {
862 /* MIPS DSP Multiply Sub-class insns */
863 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
868 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
869 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
870 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
871 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
872 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
889};
a22260ae 890
71375b59 891#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
77c5fa8b
JL
892enum {
893 /* MIPS DSP GPR-Based Shift Sub-class */
894 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
899 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
900 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
901 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
902 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
903 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
920};
77c5fa8b 921
7a387fff 922/* Coprocessor 0 (rs field) */
71375b59 923#define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
7a387fff 924
6ea83fed 925enum {
7a387fff
TS
926 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
927 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 928 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
929 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
930 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 931 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 932 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
933 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
934 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 935 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
936 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
937 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
938 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
939 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
940 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
941 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
942 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
943 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
944 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
945 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
946 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
947 OPC_C0_A = (0x1A << 21) | OPC_CP0,
948 OPC_C0_B = (0x1B << 21) | OPC_CP0,
949 OPC_C0_C = (0x1C << 21) | OPC_CP0,
950 OPC_C0_D = (0x1D << 21) | OPC_CP0,
951 OPC_C0_E = (0x1E << 21) | OPC_CP0,
952 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 953};
7a387fff
TS
954
955/* MFMC0 opcodes */
71375b59 956#define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
7a387fff
TS
957
958enum {
ead9360e
TS
959 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
960 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
961 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
962 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
963 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
964 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
965 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
966 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
967};
968
969/* Coprocessor 0 (with rs == C0) */
71375b59 970#define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
7a387fff
TS
971
972enum {
973 OPC_TLBR = 0x01 | OPC_C0,
974 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
975 OPC_TLBINV = 0x03 | OPC_C0,
976 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
977 OPC_TLBWR = 0x06 | OPC_C0,
978 OPC_TLBP = 0x08 | OPC_C0,
979 OPC_RFE = 0x10 | OPC_C0,
980 OPC_ERET = 0x18 | OPC_C0,
981 OPC_DERET = 0x1F | OPC_C0,
982 OPC_WAIT = 0x20 | OPC_C0,
983};
984
71375b59 985#define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
e0c84da7
TS
986
987enum {
988 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
989 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
990 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
991 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
992 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
993 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
994 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
995 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
996 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
997 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
998 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
999};
1000
8e2d5831 1001#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
bd277fa1
RH
1002
1003enum {
71375b59
AM
1004 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1012
1013 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1021
1022 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1023 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1024 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1026 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1027 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1028 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1029 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1030
1031 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1032 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1033 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1035 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1039
1040 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1041 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1042 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1046
1047 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1048 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1053
1054 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1055 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1060
1061 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1062 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1067
1068 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1069 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1070 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1071 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1072 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1074
1075 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1076 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1077 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1078 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1081
1082 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1083 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1084 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1085 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1086 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1088
1089 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1090 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1091 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1092 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1093 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1094 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
bd277fa1
RH
1095};
1096
1097
71375b59 1098#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
e0c84da7
TS
1099
1100enum {
71375b59
AM
1101 OPC_LWXC1 = 0x00 | OPC_CP3,
1102 OPC_LDXC1 = 0x01 | OPC_CP3,
1103 OPC_LUXC1 = 0x05 | OPC_CP3,
1104 OPC_SWXC1 = 0x08 | OPC_CP3,
1105 OPC_SDXC1 = 0x09 | OPC_CP3,
1106 OPC_SUXC1 = 0x0D | OPC_CP3,
1107 OPC_PREFX = 0x0F | OPC_CP3,
1108 OPC_ALNV_PS = 0x1E | OPC_CP3,
1109 OPC_MADD_S = 0x20 | OPC_CP3,
1110 OPC_MADD_D = 0x21 | OPC_CP3,
1111 OPC_MADD_PS = 0x26 | OPC_CP3,
1112 OPC_MSUB_S = 0x28 | OPC_CP3,
1113 OPC_MSUB_D = 0x29 | OPC_CP3,
1114 OPC_MSUB_PS = 0x2E | OPC_CP3,
1115 OPC_NMADD_S = 0x30 | OPC_CP3,
1116 OPC_NMADD_D = 0x31 | OPC_CP3,
1117 OPC_NMADD_PS = 0x36 | OPC_CP3,
1118 OPC_NMSUB_S = 0x38 | OPC_CP3,
1119 OPC_NMSUB_D = 0x39 | OPC_CP3,
1120 OPC_NMSUB_PS = 0x3E | OPC_CP3,
e0c84da7
TS
1121};
1122
497f072b 1123/*
baa609db
AM
1124 * MMI (MultiMedia Instruction) encodings
1125 * ======================================
f99c0d6d 1126 *
baa609db 1127 * MMI instructions encoding table keys:
f99c0d6d
FN
1128 *
1129 * * This code is reserved for future use. An attempt to execute it
1130 * causes a Reserved Instruction exception.
1131 * % This code indicates an instruction class. The instruction word
1132 * must be further decoded by examining additional tables that show
1133 * the values for other instruction fields.
1134 * # This code is reserved for the unsupported instructions DMULT,
1135 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1136 * to execute it causes a Reserved Instruction exception.
1137 *
baa609db 1138 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
1139 *
1140 * 31 26 0
1141 * +--------+----------------------------------------+
1142 * | opcode | |
1143 * +--------+----------------------------------------+
1144 *
1145 * opcode bits 28..26
1146 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1147 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1148 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1149 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1150 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1151 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1152 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1153 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1154 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1155 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1156 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 1157 */
b158d449 1158
f99c0d6d 1159enum {
baa609db 1160 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
baa609db 1161 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
1162};
1163
d3297211 1164/*
baa609db 1165 * MMI instructions with opcode field = MMI:
d3297211
FN
1166 *
1167 * 31 26 5 0
1168 * +--------+-------------------------------+--------+
1169 * | MMI | |function|
1170 * +--------+-------------------------------+--------+
1171 *
1172 * function bits 2..0
1173 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1174 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1175 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1176 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1177 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1178 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1179 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1180 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1181 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1182 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1183 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1184 */
1185
c8341e00 1186#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 1187enum {
baa609db
AM
1188 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1189 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
baa609db
AM
1190 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1191 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1192 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1193 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1194 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1195 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
dd581bf9
FN
1196};
1197
39454628 1198/* global register indices */
46c9e2b3 1199TCGv cpu_gpr[32], cpu_PC;
cefd68f6
PMD
1200/*
1201 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1202 * and the upper halves in cpu_gpr_hi[].
1203 */
1204TCGv_i64 cpu_gpr_hi[32];
9f5f7691 1205TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
46c9e2b3
PMD
1206static TCGv cpu_dspctrl, btarget;
1207TCGv bcond;
33a07fa2 1208static TCGv cpu_lladdr, cpu_llval;
41db4607 1209static TCGv_i32 hflags;
8758d1b8
PMD
1210TCGv_i32 fpu_fcr0, fpu_fcr31;
1211TCGv_i64 fpu_f64[32];
aa0bf00b 1212
06106772 1213static const char regnames_HI[][4] = {
d73ee8a2
RH
1214 "HI0", "HI1", "HI2", "HI3",
1215};
4b2eb8d2 1216
06106772 1217static const char regnames_LO[][4] = {
d73ee8a2
RH
1218 "LO0", "LO1", "LO2", "LO3",
1219};
4b2eb8d2 1220
8e9ade68 1221/* General purpose registers moves. */
46c9e2b3 1222void gen_load_gpr(TCGv t, int reg)
aaa9128a 1223{
dfae46c3 1224 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1f8929d2 1225 if (reg == 0) {
8e9ade68 1226 tcg_gen_movi_tl(t, 0);
1f8929d2 1227 } else {
4b2eb8d2 1228 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1f8929d2 1229 }
aaa9128a
TS
1230}
1231
46c9e2b3 1232void gen_store_gpr(TCGv t, int reg)
aaa9128a 1233{
dfae46c3 1234 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1f8929d2 1235 if (reg != 0) {
4b2eb8d2 1236 tcg_gen_mov_tl(cpu_gpr[reg], t);
1f8929d2 1237 }
aaa9128a
TS
1238}
1239
61f4e0ec
PMD
1240#if defined(TARGET_MIPS64)
1241void gen_load_gpr_hi(TCGv_i64 t, int reg)
1242{
dfae46c3 1243 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
61f4e0ec
PMD
1244 if (reg == 0) {
1245 tcg_gen_movi_i64(t, 0);
1246 } else {
1247 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1248 }
1249}
1250
1251void gen_store_gpr_hi(TCGv_i64 t, int reg)
1252{
dfae46c3 1253 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
61f4e0ec
PMD
1254 if (reg != 0) {
1255 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1256 }
1257}
1258#endif /* TARGET_MIPS64 */
1259
8e9ade68 1260/* Moves to/from shadow registers. */
235785e8 1261static inline void gen_load_srsgpr(int from, int to)
aaa9128a 1262{
d9bea114 1263 TCGv t0 = tcg_temp_new();
be24bb4f 1264
1f8929d2 1265 if (from == 0) {
d9bea114 1266 tcg_gen_movi_tl(t0, 0);
1f8929d2 1267 } else {
d9bea114 1268 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1269 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1270
ad75a51e 1271 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1272 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1273 tcg_gen_andi_i32(t2, t2, 0xf);
1274 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1275 tcg_gen_ext_i32_ptr(addr, t2);
ad75a51e 1276 tcg_gen_add_ptr(addr, tcg_env, addr);
aaa9128a 1277
d9bea114 1278 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
8e9ade68 1279 }
d9bea114 1280 gen_store_gpr(t0, to);
aaa9128a
TS
1281}
1282
71375b59 1283static inline void gen_store_srsgpr(int from, int to)
aaa9128a 1284{
be24bb4f 1285 if (to != 0) {
d9bea114
AJ
1286 TCGv t0 = tcg_temp_new();
1287 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1288 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1289
d9bea114 1290 gen_load_gpr(t0, from);
ad75a51e 1291 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1292 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1293 tcg_gen_andi_i32(t2, t2, 0xf);
1294 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1295 tcg_gen_ext_i32_ptr(addr, t2);
ad75a51e 1296 tcg_gen_add_ptr(addr, tcg_env, addr);
be24bb4f 1297
d9bea114 1298 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
8e9ade68 1299 }
aaa9128a
TS
1300}
1301
eab9944c
LA
1302/* Tests */
1303static inline void gen_save_pc(target_ulong pc)
1304{
1305 tcg_gen_movi_tl(cpu_PC, pc);
1306}
1307
1308static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1309{
1310 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
1311 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1312 gen_save_pc(ctx->base.pc_next);
1313 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
1314 }
1315 if (ctx->hflags != ctx->saved_hflags) {
1316 tcg_gen_movi_i32(hflags, ctx->hflags);
1317 ctx->saved_hflags = ctx->hflags;
1318 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1319 case MIPS_HFLAG_BR:
1320 break;
1321 case MIPS_HFLAG_BC:
1322 case MIPS_HFLAG_BL:
1323 case MIPS_HFLAG_B:
1324 tcg_gen_movi_tl(btarget, ctx->btarget);
1325 break;
1326 }
1327 }
1328}
1329
1330static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1331{
1332 ctx->saved_hflags = ctx->hflags;
1333 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1334 case MIPS_HFLAG_BR:
1335 break;
1336 case MIPS_HFLAG_BC:
1337 case MIPS_HFLAG_BL:
1338 case MIPS_HFLAG_B:
1339 ctx->btarget = env->btarget;
1340 break;
1341 }
1342}
1343
46c9e2b3 1344void generate_exception_err(DisasContext *ctx, int excp, int err)
eab9944c 1345{
eab9944c 1346 save_cpu_state(ctx, 1);
ad75a51e 1347 gen_helper_raise_exception_err(tcg_env, tcg_constant_i32(excp),
a8b18de7 1348 tcg_constant_i32(err));
eeb3bba8 1349 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
1350}
1351
46c9e2b3 1352void generate_exception(DisasContext *ctx, int excp)
eab9944c 1353{
ad75a51e 1354 gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
eab9944c
LA
1355}
1356
46c9e2b3 1357void generate_exception_end(DisasContext *ctx, int excp)
9c708c7f
PD
1358{
1359 generate_exception_err(ctx, excp, 0);
1360}
1361
6f3533dd
RH
1362void generate_exception_break(DisasContext *ctx, int code)
1363{
1364#ifdef CONFIG_USER_ONLY
1365 /* Pass the break code along to cpu_loop. */
ad75a51e 1366 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
6f3533dd
RH
1367 offsetof(CPUMIPSState, error_code));
1368#endif
1369 generate_exception_end(ctx, EXCP_BREAK);
1370}
1371
3a4ef3b7
PMD
1372void gen_reserved_instruction(DisasContext *ctx)
1373{
1374 generate_exception_end(ctx, EXCP_RI);
1375}
1376
aaa9128a 1377/* Floating point register moves. */
8758d1b8 1378void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1379{
7c979afd
LA
1380 if (ctx->hflags & MIPS_HFLAG_FRE) {
1381 generate_exception(ctx, EXCP_RI);
1382 }
ecc7b3aa 1383 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1384}
1385
8758d1b8 1386void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1387{
7c979afd
LA
1388 TCGv_i64 t64;
1389 if (ctx->hflags & MIPS_HFLAG_FRE) {
1390 generate_exception(ctx, EXCP_RI);
1391 }
1392 t64 = tcg_temp_new_i64();
d73ee8a2
RH
1393 tcg_gen_extu_i32_i64(t64, t);
1394 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
6d066274
AJ
1395}
1396
7f6613ce 1397static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1398{
7f6613ce 1399 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 1400 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 1401 } else {
7c979afd 1402 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 1403 }
6d066274
AJ
1404}
1405
7f6613ce 1406static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1407{
7f6613ce
PJ
1408 if (ctx->hflags & MIPS_HFLAG_F64) {
1409 TCGv_i64 t64 = tcg_temp_new_i64();
1410 tcg_gen_extu_i32_i64(t64, t);
1411 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
7f6613ce 1412 } else {
7c979afd 1413 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 1414 }
aa0bf00b 1415}
6ea83fed 1416
8758d1b8 1417void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1418{
f364515c 1419 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1420 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1421 } else {
d73ee8a2 1422 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1423 }
1424}
6ea83fed 1425
8758d1b8 1426void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1427{
f364515c 1428 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1429 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1430 } else {
d73ee8a2
RH
1431 TCGv_i64 t0;
1432 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1433 t0 = tcg_temp_new_i64();
6d066274 1434 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1435 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
aa0bf00b
TS
1436 }
1437}
6ea83fed 1438
8758d1b8 1439int get_fp_bit(int cc)
a16336e4 1440{
1f8929d2 1441 if (cc) {
d94536f4 1442 return 24 + cc;
1f8929d2 1443 } else {
d94536f4 1444 return 23;
1f8929d2 1445 }
a16336e4
TS
1446}
1447
48d38ca5 1448/* Addresses computation */
46c9e2b3 1449void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1450{
941694d0 1451 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1452
1453#if defined(TARGET_MIPS64)
01f72885 1454 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 1455 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1456 }
1457#endif
4ad40f36
FB
1458}
1459
bf0718c5
SM
1460static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1461 target_long ofs)
1462{
1463 tcg_gen_addi_tl(ret, base, ofs);
1464
1465#if defined(TARGET_MIPS64)
1466 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1467 tcg_gen_ext32s_i64(ret, ret);
1468 }
1469#endif
1470}
1471
31837be3
YK
1472/* Addresses computation (translation time) */
1473static target_long addr_add(DisasContext *ctx, target_long base,
1474 target_long offset)
1475{
1476 target_long sum = base + offset;
1477
1478#if defined(TARGET_MIPS64)
1479 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1480 sum = (int32_t)sum;
1481 }
1482#endif
1483 return sum;
1484}
1485
71f303cd 1486/* Sign-extract the low 32-bits to a target_long. */
46c9e2b3 1487void gen_move_low32(TCGv ret, TCGv_i64 arg)
1f1b4c00
YK
1488{
1489#if defined(TARGET_MIPS64)
71f303cd
RH
1490 tcg_gen_ext32s_i64(ret, arg);
1491#else
1492 tcg_gen_extrl_i64_i32(ret, arg);
1493#endif
1494}
1495
1496/* Sign-extract the high 32-bits to a target_long. */
46c9e2b3 1497void gen_move_high32(TCGv ret, TCGv_i64 arg)
71f303cd
RH
1498{
1499#if defined(TARGET_MIPS64)
1500 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 1501#else
71f303cd 1502 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
1503#endif
1504}
1505
905bdf72 1506bool check_cp0_enabled(DisasContext *ctx)
387a8fe5 1507{
1f8929d2 1508 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1509 generate_exception_end(ctx, EXCP_CpU);
905bdf72 1510 return false;
1f8929d2 1511 }
905bdf72 1512 return true;
387a8fe5
TS
1513}
1514
8758d1b8 1515void check_cp1_enabled(DisasContext *ctx)
5e755519 1516{
1f8929d2 1517 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
5e755519 1518 generate_exception_err(ctx, EXCP_CpU, 1);
1f8929d2 1519 }
5e755519
TS
1520}
1521
7480515f
AM
1522/*
1523 * Verify that the processor is running with COP1X instructions enabled.
1524 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1525 * opcode tables.
1526 */
8758d1b8 1527void check_cop1x(DisasContext *ctx)
b8aa4598 1528{
1f8929d2 1529 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
3a4ef3b7 1530 gen_reserved_instruction(ctx);
1f8929d2 1531 }
b8aa4598
TS
1532}
1533
7480515f
AM
1534/*
1535 * Verify that the processor is running with 64-bit floating-point
1536 * operations enabled.
1537 */
8758d1b8 1538void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1539{
2a2105a2 1540 if (unlikely(~ctx->hflags & MIPS_HFLAG_F64)) {
3a4ef3b7 1541 gen_reserved_instruction(ctx);
1f8929d2 1542 }
5e755519
TS
1543}
1544
1545/*
1546 * Verify if floating point register is valid; an operation is not defined
1547 * if bit 0 of any register specification is set and the FR bit in the
1548 * Status register equals zero, since the register numbers specify an
1549 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1550 * in the Status register equals one, both even and odd register numbers
1551 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1552 *
1553 * Multiple 64 bit wide registers can be checked by calling
1554 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1555 */
8758d1b8 1556void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1557{
1f8929d2 1558 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
3a4ef3b7 1559 gen_reserved_instruction(ctx);
1f8929d2 1560 }
5e755519
TS
1561}
1562
7480515f
AM
1563/*
1564 * Verify that the processor is running with DSP instructions enabled.
1565 * This is enabled by CP0 Status register MX(24) bit.
853c3240 1566 */
853c3240
JL
1567static inline void check_dsp(DisasContext *ctx)
1568{
1569 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 1570 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1571 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1572 } else {
3a4ef3b7 1573 gen_reserved_instruction(ctx);
ad153f15 1574 }
853c3240
JL
1575 }
1576}
1577
908f6be1 1578static inline void check_dsp_r2(DisasContext *ctx)
853c3240 1579{
908f6be1 1580 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 1581 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1582 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1583 } else {
3a4ef3b7 1584 gen_reserved_instruction(ctx);
ad153f15 1585 }
853c3240
JL
1586 }
1587}
1588
908f6be1 1589static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 1590{
908f6be1 1591 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
1592 if (ctx->insn_flags & ASE_DSP) {
1593 generate_exception_end(ctx, EXCP_DSPDIS);
1594 } else {
3a4ef3b7 1595 gen_reserved_instruction(ctx);
59e781fb
SM
1596 }
1597 }
1598}
1599
7480515f
AM
1600/*
1601 * This code generates a "reserved instruction" exception if the
1602 * CPU does not support the instruction set corresponding to flags.
1603 */
46c9e2b3 1604void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 1605{
d75c135e 1606 if (unlikely(!(ctx->insn_flags & flags))) {
3a4ef3b7 1607 gen_reserved_instruction(ctx);
d75c135e 1608 }
3a95e3a7
TS
1609}
1610
7480515f
AM
1611/*
1612 * This code generates a "reserved instruction" exception if the
1613 * CPU has corresponding flag set which indicates that the instruction
1614 * has been removed.
1615 */
f9c9cd63 1616static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
1617{
1618 if (unlikely(ctx->insn_flags & flags)) {
3a4ef3b7 1619 gen_reserved_instruction(ctx);
fecd2646
LA
1620 }
1621}
1622
96631327
FN
1623/*
1624 * The Linux kernel traps certain reserved instruction exceptions to
1625 * emulate the corresponding instructions. QEMU is the kernel in user
1626 * mode, so those traps are emulated by accepting the instructions.
1627 *
1628 * A reserved instruction exception is generated for flagged CPUs if
1629 * QEMU runs in system mode.
1630 */
1631static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1632{
1633#ifndef CONFIG_USER_ONLY
1634 check_insn_opc_removed(ctx, flags);
1635#endif
1636}
1637
7480515f
AM
1638/*
1639 * This code generates a "reserved instruction" exception if the
1640 * CPU does not support 64-bit paired-single (PS) floating point data type.
1641 */
e29c9628
YK
1642static inline void check_ps(DisasContext *ctx)
1643{
1644 if (unlikely(!ctx->ps)) {
1645 generate_exception(ctx, EXCP_RI);
1646 }
1647 check_cp1_64bitmode(ctx);
1648}
1649
7480515f 1650/*
d7efb693
PMD
1651 * This code generates a "reserved instruction" exception if cpu is not
1652 * 64-bit or 64-bit instructions are not enabled.
7480515f 1653 */
46c9e2b3 1654void check_mips_64(DisasContext *ctx)
e189e748 1655{
d7efb693 1656 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
3a4ef3b7 1657 gen_reserved_instruction(ctx);
1f8929d2 1658 }
e189e748
TS
1659}
1660
5204ea79
LA
1661#ifndef CONFIG_USER_ONLY
1662static inline void check_mvh(DisasContext *ctx)
1663{
1664 if (unlikely(!ctx->mvh)) {
1665 generate_exception(ctx, EXCP_RI);
1666 }
1667}
1668#endif
1669
0b16dcd1
AR
1670/*
1671 * This code generates a "reserved instruction" exception if the
1672 * Config5 XNP bit is set.
1673 */
1674static inline void check_xnp(DisasContext *ctx)
1675{
1676 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3a4ef3b7 1677 gen_reserved_instruction(ctx);
0b16dcd1
AR
1678 }
1679}
1680
5e31fdd5
YK
1681#ifndef CONFIG_USER_ONLY
1682/*
1683 * This code generates a "reserved instruction" exception if the
1684 * Config3 PW bit is NOT set.
1685 */
1686static inline void check_pw(DisasContext *ctx)
1687{
1688 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3a4ef3b7 1689 gen_reserved_instruction(ctx);
5e31fdd5
YK
1690 }
1691}
1692#endif
1693
9affc1c5
AR
1694/*
1695 * This code generates a "reserved instruction" exception if the
1696 * Config3 MT bit is NOT set.
1697 */
1698static inline void check_mt(DisasContext *ctx)
1699{
1700 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1701 gen_reserved_instruction(ctx);
9affc1c5
AR
1702 }
1703}
1704
1705#ifndef CONFIG_USER_ONLY
1706/*
1707 * This code generates a "coprocessor unusable" exception if CP0 is not
1708 * available, and, if that is not the case, generates a "reserved instruction"
1709 * exception if the Config5 MT bit is NOT set. This is needed for availability
1710 * control of some of MT ASE instructions.
1711 */
1712static inline void check_cp0_mt(DisasContext *ctx)
1713{
1714 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
11a75118 1715 generate_exception_end(ctx, EXCP_CpU);
9affc1c5
AR
1716 } else {
1717 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3a4ef3b7 1718 gen_reserved_instruction(ctx);
9affc1c5
AR
1719 }
1720 }
1721}
1722#endif
1723
fb32f8c8
DN
1724/*
1725 * This code generates a "reserved instruction" exception if the
1726 * Config5 NMS bit is set.
1727 */
1728static inline void check_nms(DisasContext *ctx)
1729{
1730 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3a4ef3b7 1731 gen_reserved_instruction(ctx);
fb32f8c8
DN
1732 }
1733}
1734
d046a9ea
DN
1735/*
1736 * This code generates a "reserved instruction" exception if the
1737 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1738 * Config2 TL, and Config5 L2C are unset.
1739 */
1740static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1741{
1f8929d2
AM
1742 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1743 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1744 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1745 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1746 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1747 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3a4ef3b7 1748 gen_reserved_instruction(ctx);
d046a9ea
DN
1749 }
1750}
1751
1752/*
1753 * This code generates a "reserved instruction" exception if the
1754 * Config5 EVA bit is NOT set.
1755 */
1756static inline void check_eva(DisasContext *ctx)
1757{
1758 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3a4ef3b7 1759 gen_reserved_instruction(ctx);
d046a9ea
DN
1760 }
1761}
1762
0b16dcd1 1763
7480515f
AM
1764/*
1765 * Define small wrappers for gen_load_fpr* so that we have a uniform
1766 * calling interface for 32 and 64-bit FPRs. No sense in changing
1767 * all callers for gen_load_fpr32 when we need the CTX parameter for
1768 * this one use.
1769 */
7c979afd 1770#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
1771#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1772#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1773static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1774 int ft, int fs, int cc) \
1775{ \
71375b59
AM
1776 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1777 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
8153667c
NF
1778 switch (ifmt) { \
1779 case FMT_PS: \
e29c9628 1780 check_ps(ctx); \
8153667c
NF
1781 break; \
1782 case FMT_D: \
1783 if (abs) { \
1784 check_cop1x(ctx); \
1785 } \
1786 check_cp1_registers(ctx, fs | ft); \
1787 break; \
1788 case FMT_S: \
1789 if (abs) { \
1790 check_cop1x(ctx); \
1791 } \
1792 break; \
1793 } \
71375b59
AM
1794 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1795 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
8153667c 1796 switch (n) { \
1f8929d2
AM
1797 case 0: \
1798 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1799 break; \
1800 case 1: \
1801 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1802 break; \
1803 case 2: \
1804 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1805 break; \
1806 case 3: \
1807 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1808 break; \
1809 case 4: \
1810 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1811 break; \
1812 case 5: \
1813 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1814 break; \
1815 case 6: \
1816 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1817 break; \
1818 case 7: \
1819 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1820 break; \
1821 case 8: \
1822 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1823 break; \
1824 case 9: \
1825 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1826 break; \
1827 case 10: \
1828 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1829 break; \
1830 case 11: \
1831 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1832 break; \
1833 case 12: \
1834 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1835 break; \
1836 case 13: \
1837 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1838 break; \
1839 case 14: \
1840 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1841 break; \
1842 case 15: \
1843 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1844 break; \
1845 default: \
1846 abort(); \
8153667c 1847 } \
8153667c
NF
1848}
1849
1850FOP_CONDS(, 0, d, FMT_D, 64)
1851FOP_CONDS(abs, 1, d, FMT_D, 64)
1852FOP_CONDS(, 0, s, FMT_S, 32)
1853FOP_CONDS(abs, 1, s, FMT_S, 32)
1854FOP_CONDS(, 0, ps, FMT_PS, 64)
1855FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1856#undef FOP_CONDS
3f493883
YK
1857
1858#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
71375b59 1859static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3f493883
YK
1860 int ft, int fs, int fd) \
1861{ \
1862 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1863 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 1864 if (ifmt == FMT_D) { \
3f493883 1865 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
1866 } \
1867 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1868 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1869 switch (n) { \
1870 case 0: \
ad75a51e 1871 gen_helper_r6_cmp_ ## fmt ## _af(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1872 break; \
1873 case 1: \
ad75a51e 1874 gen_helper_r6_cmp_ ## fmt ## _un(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1875 break; \
1876 case 2: \
ad75a51e 1877 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1878 break; \
1879 case 3: \
ad75a51e 1880 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1881 break; \
1882 case 4: \
ad75a51e 1883 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1884 break; \
1885 case 5: \
ad75a51e 1886 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1887 break; \
1888 case 6: \
ad75a51e 1889 gen_helper_r6_cmp_ ## fmt ## _le(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1890 break; \
1891 case 7: \
ad75a51e 1892 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1893 break; \
1894 case 8: \
ad75a51e 1895 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1896 break; \
1897 case 9: \
ad75a51e 1898 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1899 break; \
1900 case 10: \
ad75a51e 1901 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1902 break; \
1903 case 11: \
ad75a51e 1904 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1905 break; \
1906 case 12: \
ad75a51e 1907 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1908 break; \
1909 case 13: \
ad75a51e 1910 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1911 break; \
1912 case 14: \
ad75a51e 1913 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1914 break; \
1915 case 15: \
ad75a51e 1916 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1917 break; \
1918 case 17: \
ad75a51e 1919 gen_helper_r6_cmp_ ## fmt ## _or(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1920 break; \
1921 case 18: \
ad75a51e 1922 gen_helper_r6_cmp_ ## fmt ## _une(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1923 break; \
1924 case 19: \
ad75a51e 1925 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1926 break; \
1927 case 25: \
ad75a51e 1928 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1929 break; \
1930 case 26: \
ad75a51e 1931 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1932 break; \
1933 case 27: \
ad75a51e 1934 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, tcg_env, fp0, fp1); \
3f493883
YK
1935 break; \
1936 default: \
1937 abort(); \
1938 } \
1939 STORE; \
3f493883
YK
1940}
1941
1942FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 1943FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 1944#undef FOP_CONDNS
8153667c
NF
1945#undef gen_ldcmp_fpr32
1946#undef gen_ldcmp_fpr64
1947
958fb4a9 1948/* load/store instructions. */
e7139c44 1949#ifdef CONFIG_USER_ONLY
6d0cad12 1950#define OP_LD_ATOMIC(insn, memop) \
dd4096cd
JH
1951static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1952 DisasContext *ctx) \
d9bea114
AJ
1953{ \
1954 TCGv t0 = tcg_temp_new(); \
1955 tcg_gen_mov_tl(t0, arg1); \
6d0cad12 1956 tcg_gen_qemu_ld_tl(ret, arg1, ctx->mem_idx, memop); \
ad75a51e
RH
1957 tcg_gen_st_tl(t0, tcg_env, offsetof(CPUMIPSState, lladdr)); \
1958 tcg_gen_st_tl(ret, tcg_env, offsetof(CPUMIPSState, llval)); \
aaa9128a 1959}
e7139c44 1960#else
71375b59 1961#define OP_LD_ATOMIC(insn, fname) \
dd4096cd
JH
1962static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1963 DisasContext *ctx) \
e7139c44 1964{ \
ad75a51e 1965 gen_helper_##insn(ret, tcg_env, arg1, tcg_constant_i32(mem_idx)); \
e7139c44
AJ
1966}
1967#endif
6d0cad12 1968OP_LD_ATOMIC(ll, MO_TESL);
aaa9128a 1969#if defined(TARGET_MIPS64)
6d0cad12 1970OP_LD_ATOMIC(lld, MO_TEUQ);
aaa9128a
TS
1971#endif
1972#undef OP_LD_ATOMIC
1973
46c9e2b3 1974void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
662d7485
NF
1975{
1976 if (base == 0) {
1977 tcg_gen_movi_tl(addr, offset);
1978 } else if (offset == 0) {
1979 gen_load_gpr(addr, base);
1980 } else {
1981 tcg_gen_movi_tl(addr, offset);
1982 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1983 }
1984}
1985
235785e8 1986static target_ulong pc_relative_pc(DisasContext *ctx)
364d4831 1987{
eeb3bba8 1988 target_ulong pc = ctx->base.pc_next;
364d4831
NF
1989
1990 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1991 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1992
1993 pc -= branch_bytes;
1994 }
1995
1996 pc &= ~(target_ulong)3;
1997 return pc;
1998}
1999
990c162e
RH
2000/* LWL or LDL, depending on MemOp. */
2001static void gen_lxl(DisasContext *ctx, TCGv reg, TCGv addr,
2002 int mem_idx, MemOp mop)
2003{
2004 int sizem1 = memop_size(mop) - 1;
2005 TCGv t0 = tcg_temp_new();
2006 TCGv t1 = tcg_temp_new();
2007
2008 /*
2009 * Do a byte access to possibly trigger a page
2010 * fault with the unaligned address.
2011 */
2012 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
2013 tcg_gen_andi_tl(t1, addr, sizem1);
2014 if (!cpu_is_bigendian(ctx)) {
2015 tcg_gen_xori_tl(t1, t1, sizem1);
2016 }
2017 tcg_gen_shli_tl(t1, t1, 3);
2018 tcg_gen_andi_tl(t0, addr, ~sizem1);
2019 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
2020 tcg_gen_shl_tl(t0, t0, t1);
2021 tcg_gen_shl_tl(t1, tcg_constant_tl(-1), t1);
2022 tcg_gen_andc_tl(t1, reg, t1);
2023 tcg_gen_or_tl(reg, t0, t1);
2024}
2025
0694cd59
RH
2026/* LWR or LDR, depending on MemOp. */
2027static void gen_lxr(DisasContext *ctx, TCGv reg, TCGv addr,
2028 int mem_idx, MemOp mop)
2029{
2030 int size = memop_size(mop);
2031 int sizem1 = size - 1;
2032 TCGv t0 = tcg_temp_new();
2033 TCGv t1 = tcg_temp_new();
2034
2035 /*
2036 * Do a byte access to possibly trigger a page
2037 * fault with the unaligned address.
2038 */
2039 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
2040 tcg_gen_andi_tl(t1, addr, sizem1);
2041 if (cpu_is_bigendian(ctx)) {
2042 tcg_gen_xori_tl(t1, t1, sizem1);
2043 }
2044 tcg_gen_shli_tl(t1, t1, 3);
2045 tcg_gen_andi_tl(t0, addr, ~sizem1);
2046 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
2047 tcg_gen_shr_tl(t0, t0, t1);
2048 tcg_gen_xori_tl(t1, t1, size * 8 - 1);
2049 tcg_gen_shl_tl(t1, tcg_constant_tl(~1), t1);
2050 tcg_gen_and_tl(t1, reg, t1);
2051 tcg_gen_or_tl(reg, t0, t1);
2052}
2053
5c13fdfd 2054/* Load */
d75c135e 2055static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 2056 int rt, int base, int offset)
6af0bf9c 2057{
0694cd59 2058 TCGv t0, t1;
dd4096cd 2059 int mem_idx = ctx->mem_idx;
afa88c3a 2060
8e2d5831
JY
2061 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2062 INSN_LOONGSON3A)) {
7480515f
AM
2063 /*
2064 * Loongson CPU uses a load to zero register for prefetch.
2065 * We emulate it as a NOP. On other CPU we must perform the
2066 * actual memory access.
2067 */
afa88c3a
AJ
2068 return;
2069 }
6af0bf9c 2070
afa88c3a 2071 t0 = tcg_temp_new();
662d7485 2072 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 2073
6af0bf9c 2074 switch (opc) {
d26bc211 2075#if defined(TARGET_MIPS64)
6e473128 2076 case OPC_LWU:
dd4096cd 2077 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 2078 ctx->default_tcg_memop_mask);
78723684 2079 gen_store_gpr(t0, rt);
6e473128 2080 break;
6af0bf9c 2081 case OPC_LD:
fc313c64 2082 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ |
be3a8c53 2083 ctx->default_tcg_memop_mask);
78723684 2084 gen_store_gpr(t0, rt);
6af0bf9c 2085 break;
7a387fff 2086 case OPC_LLD:
bf7910c6 2087 case R6_OPC_LLD:
dd4096cd 2088 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 2089 gen_store_gpr(t0, rt);
7a387fff 2090 break;
6af0bf9c 2091 case OPC_LDL:
3cee3050 2092 t1 = tcg_temp_new();
78723684 2093 gen_load_gpr(t1, rt);
990c162e
RH
2094 gen_lxl(ctx, t1, t0, mem_idx, MO_TEUQ);
2095 gen_store_gpr(t1, rt);
6af0bf9c 2096 break;
6af0bf9c 2097 case OPC_LDR:
3cee3050 2098 t1 = tcg_temp_new();
78723684 2099 gen_load_gpr(t1, rt);
0694cd59
RH
2100 gen_lxr(ctx, t1, t0, mem_idx, MO_TEUQ);
2101 gen_store_gpr(t1, rt);
6af0bf9c 2102 break;
364d4831 2103 case OPC_LDPC:
c29e79af 2104 t1 = tcg_constant_tl(pc_relative_pc(ctx));
364d4831 2105 gen_op_addr_add(ctx, t0, t0, t1);
fc313c64 2106 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
364d4831
NF
2107 gen_store_gpr(t0, rt);
2108 break;
6af0bf9c 2109#endif
364d4831 2110 case OPC_LWPC:
c29e79af 2111 t1 = tcg_constant_tl(pc_relative_pc(ctx));
364d4831 2112 gen_op_addr_add(ctx, t0, t0, t1);
dd4096cd 2113 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
2114 gen_store_gpr(t0, rt);
2115 break;
76964147
JH
2116 case OPC_LWE:
2117 mem_idx = MIPS_HFLAG_UM;
2118 /* fall through */
6af0bf9c 2119 case OPC_LW:
dd4096cd 2120 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 2121 ctx->default_tcg_memop_mask);
78723684 2122 gen_store_gpr(t0, rt);
6af0bf9c 2123 break;
76964147
JH
2124 case OPC_LHE:
2125 mem_idx = MIPS_HFLAG_UM;
2126 /* fall through */
6af0bf9c 2127 case OPC_LH:
dd4096cd 2128 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 2129 ctx->default_tcg_memop_mask);
78723684 2130 gen_store_gpr(t0, rt);
6af0bf9c 2131 break;
76964147
JH
2132 case OPC_LHUE:
2133 mem_idx = MIPS_HFLAG_UM;
2134 /* fall through */
6af0bf9c 2135 case OPC_LHU:
dd4096cd 2136 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 2137 ctx->default_tcg_memop_mask);
78723684 2138 gen_store_gpr(t0, rt);
6af0bf9c 2139 break;
76964147
JH
2140 case OPC_LBE:
2141 mem_idx = MIPS_HFLAG_UM;
2142 /* fall through */
6af0bf9c 2143 case OPC_LB:
dd4096cd 2144 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 2145 gen_store_gpr(t0, rt);
6af0bf9c 2146 break;
76964147
JH
2147 case OPC_LBUE:
2148 mem_idx = MIPS_HFLAG_UM;
2149 /* fall through */
6af0bf9c 2150 case OPC_LBU:
dd4096cd 2151 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 2152 gen_store_gpr(t0, rt);
6af0bf9c 2153 break;
76964147
JH
2154 case OPC_LWLE:
2155 mem_idx = MIPS_HFLAG_UM;
2156 /* fall through */
6af0bf9c 2157 case OPC_LWL:
3cee3050 2158 t1 = tcg_temp_new();
6958549d 2159 gen_load_gpr(t1, rt);
990c162e
RH
2160 gen_lxl(ctx, t1, t0, mem_idx, MO_TEUL);
2161 tcg_gen_ext32s_tl(t1, t1);
2162 gen_store_gpr(t1, rt);
6af0bf9c 2163 break;
76964147
JH
2164 case OPC_LWRE:
2165 mem_idx = MIPS_HFLAG_UM;
2166 /* fall through */
6af0bf9c 2167 case OPC_LWR:
3cee3050 2168 t1 = tcg_temp_new();
6958549d 2169 gen_load_gpr(t1, rt);
0694cd59
RH
2170 gen_lxr(ctx, t1, t0, mem_idx, MO_TEUL);
2171 tcg_gen_ext32s_tl(t1, t1);
2172 gen_store_gpr(t1, rt);
6af0bf9c 2173 break;
76964147
JH
2174 case OPC_LLE:
2175 mem_idx = MIPS_HFLAG_UM;
2176 /* fall through */
6af0bf9c 2177 case OPC_LL:
4368b29a 2178 case R6_OPC_LL:
dd4096cd 2179 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 2180 gen_store_gpr(t0, rt);
6af0bf9c 2181 break;
d66c7132 2182 }
d66c7132
AJ
2183}
2184
5c13fdfd 2185/* Store */
235785e8
AM
2186static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2187 int base, int offset)
5c13fdfd 2188{
5c13fdfd
AJ
2189 TCGv t0 = tcg_temp_new();
2190 TCGv t1 = tcg_temp_new();
dd4096cd 2191 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
2192
2193 gen_base_offset_addr(ctx, t0, base, offset);
2194 gen_load_gpr(t1, rt);
2195 switch (opc) {
2196#if defined(TARGET_MIPS64)
2197 case OPC_SD:
fc313c64 2198 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUQ |
be3a8c53 2199 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
2200 break;
2201 case OPC_SDL:
dd4096cd 2202 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
2203 break;
2204 case OPC_SDR:
dd4096cd 2205 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
2206 break;
2207#endif
76964147
JH
2208 case OPC_SWE:
2209 mem_idx = MIPS_HFLAG_UM;
2210 /* fall through */
5c13fdfd 2211 case OPC_SW:
dd4096cd 2212 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 2213 ctx->default_tcg_memop_mask);
5c13fdfd 2214 break;
76964147
JH
2215 case OPC_SHE:
2216 mem_idx = MIPS_HFLAG_UM;
2217 /* fall through */
5c13fdfd 2218 case OPC_SH:
dd4096cd 2219 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 2220 ctx->default_tcg_memop_mask);
5c13fdfd 2221 break;
76964147
JH
2222 case OPC_SBE:
2223 mem_idx = MIPS_HFLAG_UM;
2224 /* fall through */
5c13fdfd 2225 case OPC_SB:
dd4096cd 2226 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 2227 break;
76964147
JH
2228 case OPC_SWLE:
2229 mem_idx = MIPS_HFLAG_UM;
2230 /* fall through */
5c13fdfd 2231 case OPC_SWL:
dd4096cd 2232 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 2233 break;
76964147
JH
2234 case OPC_SWRE:
2235 mem_idx = MIPS_HFLAG_UM;
2236 /* fall through */
5c13fdfd 2237 case OPC_SWR:
dd4096cd 2238 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
2239 break;
2240 }
5c13fdfd
AJ
2241}
2242
2243
d66c7132 2244/* Store conditional */
33a07fa2 2245static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
14776ab5 2246 MemOp tcg_mo, bool eva)
d66c7132 2247{
33a07fa2
LA
2248 TCGv addr, t0, val;
2249 TCGLabel *l1 = gen_new_label();
2250 TCGLabel *done = gen_new_label();
d66c7132 2251
2d2826b9 2252 t0 = tcg_temp_new();
33a07fa2 2253 addr = tcg_temp_new();
8cdf8869 2254 /* compare the address against that of the preceding LL */
33a07fa2
LA
2255 gen_base_offset_addr(ctx, addr, base, offset);
2256 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
33a07fa2
LA
2257 tcg_gen_movi_tl(t0, 0);
2258 gen_store_gpr(t0, rt);
2259 tcg_gen_br(done);
2260
2261 gen_set_label(l1);
2262 /* generate cmpxchg */
2263 val = tcg_temp_new();
2264 gen_load_gpr(val, rt);
2265 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2266 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2267 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2268 gen_store_gpr(t0, rt);
33a07fa2
LA
2269
2270 gen_set_label(done);
6af0bf9c
FB
2271}
2272
6ea83fed 2273/* Load and store */
235785e8
AM
2274static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2275 TCGv t0)
6ea83fed 2276{
7480515f
AM
2277 /*
2278 * Don't do NOP if destination is zero: we must perform the actual
2279 * memory access.
2280 */
6ea83fed
FB
2281 switch (opc) {
2282 case OPC_LWC1:
b6d96bed 2283 {
a7812ae4 2284 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
2285 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2286 ctx->default_tcg_memop_mask);
7c979afd 2287 gen_store_fpr32(ctx, fp0, ft);
b6d96bed 2288 }
6ea83fed
FB
2289 break;
2290 case OPC_SWC1:
b6d96bed 2291 {
a7812ae4 2292 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 2293 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
2294 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2295 ctx->default_tcg_memop_mask);
b6d96bed 2296 }
6ea83fed
FB
2297 break;
2298 case OPC_LDC1:
b6d96bed 2299 {
a7812ae4 2300 TCGv_i64 fp0 = tcg_temp_new_i64();
fc313c64 2301 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
be3a8c53 2302 ctx->default_tcg_memop_mask);
b6d96bed 2303 gen_store_fpr64(ctx, fp0, ft);
b6d96bed 2304 }
6ea83fed
FB
2305 break;
2306 case OPC_SDC1:
b6d96bed 2307 {
a7812ae4 2308 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2309 gen_load_fpr64(ctx, fp0, ft);
fc313c64 2310 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
be3a8c53 2311 ctx->default_tcg_memop_mask);
b6d96bed 2312 }
6ea83fed
FB
2313 break;
2314 default:
9d68ac14 2315 MIPS_INVAL("flt_ldst");
3a4ef3b7 2316 gen_reserved_instruction(ctx);
b52d3bfa 2317 break;
6ea83fed 2318 }
6ea83fed 2319}
6ea83fed 2320
5ab5c041
AJ
2321static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2322 int rs, int16_t imm)
26ebe468 2323{
b52d3bfa
YK
2324 TCGv t0 = tcg_temp_new();
2325
5ab5c041 2326 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 2327 check_cp1_enabled(ctx);
d9224450
MR
2328 switch (op) {
2329 case OPC_LDC1:
2330 case OPC_SDC1:
2331 check_insn(ctx, ISA_MIPS2);
2332 /* Fallthrough */
2333 default:
b52d3bfa
YK
2334 gen_base_offset_addr(ctx, t0, rs, imm);
2335 gen_flt_ldst(ctx, op, rt, t0);
d9224450 2336 }
26ebe468
NF
2337 } else {
2338 generate_exception_err(ctx, EXCP_CpU, 1);
2339 }
2340}
2341
6af0bf9c 2342/* Arithmetic with immediate operand */
d75c135e 2343static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 2344 int rt, int rs, int imm)
6af0bf9c 2345{
324d9e32 2346 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 2347
7a387fff 2348 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
7480515f
AM
2349 /*
2350 * If no destination, treat it as a NOP.
2351 * For addi, we must generate the overflow exception when needed.
2352 */
324d9e32 2353 return;
6af0bf9c
FB
2354 }
2355 switch (opc) {
2356 case OPC_ADDI:
48d38ca5 2357 {
6180cc40 2358 TCGv t0 = tcg_temp_new();
324d9e32
AJ
2359 TCGv t1 = tcg_temp_new();
2360 TCGv t2 = tcg_temp_new();
42a268c2 2361 TCGLabel *l1 = gen_new_label();
48d38ca5 2362
324d9e32
AJ
2363 gen_load_gpr(t1, rs);
2364 tcg_gen_addi_tl(t0, t1, uimm);
2365 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2366
324d9e32
AJ
2367 tcg_gen_xori_tl(t1, t1, ~uimm);
2368 tcg_gen_xori_tl(t2, t0, uimm);
2369 tcg_gen_and_tl(t1, t1, t2);
324d9e32 2370 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
48d38ca5
TS
2371 /* operands of same sign, result different sign */
2372 generate_exception(ctx, EXCP_OVERFLOW);
2373 gen_set_label(l1);
78723684 2374 tcg_gen_ext32s_tl(t0, t0);
324d9e32 2375 gen_store_gpr(t0, rt);
48d38ca5 2376 }
6af0bf9c
FB
2377 break;
2378 case OPC_ADDIU:
324d9e32
AJ
2379 if (rs != 0) {
2380 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2381 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2382 } else {
2383 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2384 }
6af0bf9c 2385 break;
d26bc211 2386#if defined(TARGET_MIPS64)
7a387fff 2387 case OPC_DADDI:
48d38ca5 2388 {
6180cc40 2389 TCGv t0 = tcg_temp_new();
324d9e32
AJ
2390 TCGv t1 = tcg_temp_new();
2391 TCGv t2 = tcg_temp_new();
42a268c2 2392 TCGLabel *l1 = gen_new_label();
48d38ca5 2393
324d9e32
AJ
2394 gen_load_gpr(t1, rs);
2395 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2396
324d9e32
AJ
2397 tcg_gen_xori_tl(t1, t1, ~uimm);
2398 tcg_gen_xori_tl(t2, t0, uimm);
2399 tcg_gen_and_tl(t1, t1, t2);
324d9e32 2400 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
48d38ca5
TS
2401 /* operands of same sign, result different sign */
2402 generate_exception(ctx, EXCP_OVERFLOW);
2403 gen_set_label(l1);
324d9e32 2404 gen_store_gpr(t0, rt);
48d38ca5 2405 }
7a387fff
TS
2406 break;
2407 case OPC_DADDIU:
324d9e32
AJ
2408 if (rs != 0) {
2409 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2410 } else {
2411 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2412 }
7a387fff
TS
2413 break;
2414#endif
324d9e32 2415 }
324d9e32
AJ
2416}
2417
2418/* Logic with immediate operand */
d75c135e 2419static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2420 int rt, int rs, int16_t imm)
324d9e32
AJ
2421{
2422 target_ulong uimm;
324d9e32
AJ
2423
2424 if (rt == 0) {
2425 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2426 return;
2427 }
2428 uimm = (uint16_t)imm;
2429 switch (opc) {
6af0bf9c 2430 case OPC_ANDI:
1f8929d2 2431 if (likely(rs != 0)) {
324d9e32 2432 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2433 } else {
324d9e32 2434 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1f8929d2 2435 }
6af0bf9c
FB
2436 break;
2437 case OPC_ORI:
1f8929d2 2438 if (rs != 0) {
324d9e32 2439 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2440 } else {
324d9e32 2441 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2442 }
6af0bf9c
FB
2443 break;
2444 case OPC_XORI:
1f8929d2 2445 if (likely(rs != 0)) {
324d9e32 2446 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1f8929d2 2447 } else {
324d9e32 2448 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1f8929d2 2449 }
6af0bf9c
FB
2450 break;
2451 case OPC_LUI:
2e211e0a 2452 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
d4ea6acd
LA
2453 /* OPC_AUI */
2454 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2455 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
2456 } else {
2457 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 2458 }
7c2c3ea3
EJ
2459 break;
2460
2461 default:
6af0bf9c 2462 break;
324d9e32 2463 }
324d9e32
AJ
2464}
2465
2466/* Set on less than with immediate operand */
d75c135e 2467static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2468 int rt, int rs, int16_t imm)
324d9e32
AJ
2469{
2470 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
2471 TCGv t0;
2472
2473 if (rt == 0) {
2474 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2475 return;
2476 }
2477 t0 = tcg_temp_new();
2478 gen_load_gpr(t0, rs);
2479 switch (opc) {
2480 case OPC_SLTI:
e68dd28f 2481 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2482 break;
2483 case OPC_SLTIU:
e68dd28f 2484 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2485 break;
2486 }
324d9e32
AJ
2487}
2488
2489/* Shifts with immediate operand */
d75c135e 2490static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
2491 int rt, int rs, int16_t imm)
2492{
2493 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
2494 TCGv t0;
2495
2496 if (rt == 0) {
2497 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2498 return;
2499 }
2500
2501 t0 = tcg_temp_new();
2502 gen_load_gpr(t0, rs);
2503 switch (opc) {
6af0bf9c 2504 case OPC_SLL:
78723684 2505 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 2506 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
2507 break;
2508 case OPC_SRA:
324d9e32 2509 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
2510 break;
2511 case OPC_SRL:
ea63e2c3
NF
2512 if (uimm != 0) {
2513 tcg_gen_ext32u_tl(t0, t0);
2514 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2515 } else {
2516 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 2517 }
ea63e2c3
NF
2518 break;
2519 case OPC_ROTR:
2520 if (uimm != 0) {
2521 TCGv_i32 t1 = tcg_temp_new_i32();
2522
2523 tcg_gen_trunc_tl_i32(t1, t0);
2524 tcg_gen_rotri_i32(t1, t1, uimm);
2525 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3399e30f
NF
2526 } else {
2527 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 2528 }
7a387fff 2529 break;
d26bc211 2530#if defined(TARGET_MIPS64)
7a387fff 2531 case OPC_DSLL:
324d9e32 2532 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2533 break;
2534 case OPC_DSRA:
324d9e32 2535 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2536 break;
2537 case OPC_DSRL:
ea63e2c3 2538 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
2539 break;
2540 case OPC_DROTR:
2541 if (uimm != 0) {
2542 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2543 } else {
2544 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2545 }
7a387fff
TS
2546 break;
2547 case OPC_DSLL32:
324d9e32 2548 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2549 break;
2550 case OPC_DSRA32:
324d9e32 2551 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2552 break;
2553 case OPC_DSRL32:
ea63e2c3 2554 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
2555 break;
2556 case OPC_DROTR32:
2557 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 2558 break;
7a387fff 2559#endif
6af0bf9c 2560 }
6af0bf9c
FB
2561}
2562
2563/* Arithmetic */
d75c135e
AJ
2564static void gen_arith(DisasContext *ctx, uint32_t opc,
2565 int rd, int rs, int rt)
6af0bf9c 2566{
7a387fff
TS
2567 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2568 && opc != OPC_DADD && opc != OPC_DSUB) {
7480515f
AM
2569 /*
2570 * If no destination, treat it as a NOP.
2571 * For add & sub, we must generate the overflow exception when needed.
2572 */
460f00c4 2573 return;
185f0762 2574 }
460f00c4 2575
6af0bf9c
FB
2576 switch (opc) {
2577 case OPC_ADD:
48d38ca5 2578 {
6180cc40 2579 TCGv t0 = tcg_temp_new();
460f00c4
AJ
2580 TCGv t1 = tcg_temp_new();
2581 TCGv t2 = tcg_temp_new();
42a268c2 2582 TCGLabel *l1 = gen_new_label();
48d38ca5 2583
460f00c4
AJ
2584 gen_load_gpr(t1, rs);
2585 gen_load_gpr(t2, rt);
2586 tcg_gen_add_tl(t0, t1, t2);
2587 tcg_gen_ext32s_tl(t0, t0);
2588 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2589 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2590 tcg_gen_andc_tl(t1, t2, t1);
460f00c4 2591 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
48d38ca5
TS
2592 /* operands of same sign, result different sign */
2593 generate_exception(ctx, EXCP_OVERFLOW);
2594 gen_set_label(l1);
460f00c4 2595 gen_store_gpr(t0, rd);
48d38ca5 2596 }
6af0bf9c
FB
2597 break;
2598 case OPC_ADDU:
460f00c4
AJ
2599 if (rs != 0 && rt != 0) {
2600 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2601 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2602 } else if (rs == 0 && rt != 0) {
2603 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2604 } else if (rs != 0 && rt == 0) {
2605 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2606 } else {
2607 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2608 }
6af0bf9c
FB
2609 break;
2610 case OPC_SUB:
48d38ca5 2611 {
6180cc40 2612 TCGv t0 = tcg_temp_new();
460f00c4
AJ
2613 TCGv t1 = tcg_temp_new();
2614 TCGv t2 = tcg_temp_new();
42a268c2 2615 TCGLabel *l1 = gen_new_label();
48d38ca5 2616
460f00c4
AJ
2617 gen_load_gpr(t1, rs);
2618 gen_load_gpr(t2, rt);
2619 tcg_gen_sub_tl(t0, t1, t2);
2620 tcg_gen_ext32s_tl(t0, t0);
2621 tcg_gen_xor_tl(t2, t1, t2);
2622 tcg_gen_xor_tl(t1, t0, t1);
2623 tcg_gen_and_tl(t1, t1, t2);
460f00c4 2624 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
7480515f
AM
2625 /*
2626 * operands of different sign, first operand and the result
2627 * of different sign
2628 */
48d38ca5
TS
2629 generate_exception(ctx, EXCP_OVERFLOW);
2630 gen_set_label(l1);
460f00c4 2631 gen_store_gpr(t0, rd);
48d38ca5 2632 }
6af0bf9c
FB
2633 break;
2634 case OPC_SUBU:
460f00c4
AJ
2635 if (rs != 0 && rt != 0) {
2636 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2637 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2638 } else if (rs == 0 && rt != 0) {
2639 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2640 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2641 } else if (rs != 0 && rt == 0) {
2642 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2643 } else {
2644 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2645 }
6af0bf9c 2646 break;
d26bc211 2647#if defined(TARGET_MIPS64)
7a387fff 2648 case OPC_DADD:
48d38ca5 2649 {
6180cc40 2650 TCGv t0 = tcg_temp_new();
460f00c4
AJ
2651 TCGv t1 = tcg_temp_new();
2652 TCGv t2 = tcg_temp_new();
42a268c2 2653 TCGLabel *l1 = gen_new_label();
48d38ca5 2654
460f00c4
AJ
2655 gen_load_gpr(t1, rs);
2656 gen_load_gpr(t2, rt);
2657 tcg_gen_add_tl(t0, t1, t2);
2658 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2659 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2660 tcg_gen_andc_tl(t1, t2, t1);
460f00c4 2661 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
48d38ca5
TS
2662 /* operands of same sign, result different sign */
2663 generate_exception(ctx, EXCP_OVERFLOW);
2664 gen_set_label(l1);
460f00c4 2665 gen_store_gpr(t0, rd);
48d38ca5 2666 }
7a387fff
TS
2667 break;
2668 case OPC_DADDU:
460f00c4
AJ
2669 if (rs != 0 && rt != 0) {
2670 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2671 } else if (rs == 0 && rt != 0) {
2672 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2673 } else if (rs != 0 && rt == 0) {
2674 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2675 } else {
2676 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2677 }
7a387fff
TS
2678 break;
2679 case OPC_DSUB:
48d38ca5 2680 {
6180cc40 2681 TCGv t0 = tcg_temp_new();
460f00c4
AJ
2682 TCGv t1 = tcg_temp_new();
2683 TCGv t2 = tcg_temp_new();
42a268c2 2684 TCGLabel *l1 = gen_new_label();
48d38ca5 2685
460f00c4
AJ
2686 gen_load_gpr(t1, rs);
2687 gen_load_gpr(t2, rt);
2688 tcg_gen_sub_tl(t0, t1, t2);
2689 tcg_gen_xor_tl(t2, t1, t2);
2690 tcg_gen_xor_tl(t1, t0, t1);
2691 tcg_gen_and_tl(t1, t1, t2);
460f00c4 2692 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
71375b59
AM
2693 /*
2694 * Operands of different sign, first operand and result different
2695 * sign.
2696 */
48d38ca5
TS
2697 generate_exception(ctx, EXCP_OVERFLOW);
2698 gen_set_label(l1);
460f00c4 2699 gen_store_gpr(t0, rd);
48d38ca5 2700 }
7a387fff
TS
2701 break;
2702 case OPC_DSUBU:
460f00c4
AJ
2703 if (rs != 0 && rt != 0) {
2704 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2705 } else if (rs == 0 && rt != 0) {
2706 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2707 } else if (rs != 0 && rt == 0) {
2708 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2709 } else {
2710 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2711 }
7a387fff
TS
2712 break;
2713#endif
460f00c4
AJ
2714 case OPC_MUL:
2715 if (likely(rs != 0 && rt != 0)) {
2716 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2717 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2718 } else {
2719 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2720 }
6af0bf9c 2721 break;
460f00c4 2722 }
460f00c4
AJ
2723}
2724
2725/* Conditional move */
d75c135e 2726static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 2727 int rd, int rs, int rt)
460f00c4 2728{
acf12465 2729 TCGv t0, t1, t2;
460f00c4
AJ
2730
2731 if (rd == 0) {
acf12465 2732 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2733 return;
2734 }
2735
acf12465
AJ
2736 t0 = tcg_temp_new();
2737 gen_load_gpr(t0, rt);
c29e79af 2738 t1 = tcg_constant_tl(0);
acf12465
AJ
2739 t2 = tcg_temp_new();
2740 gen_load_gpr(t2, rs);
460f00c4
AJ
2741 switch (opc) {
2742 case OPC_MOVN:
acf12465 2743 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 2744 break;
460f00c4 2745 case OPC_MOVZ:
acf12465 2746 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 2747 break;
b691d9d2
LA
2748 case OPC_SELNEZ:
2749 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
2750 break;
2751 case OPC_SELEQZ:
2752 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 2753 break;
460f00c4 2754 }
460f00c4
AJ
2755}
2756
2757/* Logic */
d75c135e 2758static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 2759 int rd, int rs, int rt)
460f00c4 2760{
460f00c4
AJ
2761 if (rd == 0) {
2762 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2763 return;
2764 }
2765
2766 switch (opc) {
6af0bf9c 2767 case OPC_AND:
460f00c4
AJ
2768 if (likely(rs != 0 && rt != 0)) {
2769 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2770 } else {
2771 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2772 }
6af0bf9c
FB
2773 break;
2774 case OPC_NOR:
460f00c4
AJ
2775 if (rs != 0 && rt != 0) {
2776 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2777 } else if (rs == 0 && rt != 0) {
2778 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2779 } else if (rs != 0 && rt == 0) {
2780 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2781 } else {
2782 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2783 }
6af0bf9c
FB
2784 break;
2785 case OPC_OR:
460f00c4
AJ
2786 if (likely(rs != 0 && rt != 0)) {
2787 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2788 } else if (rs == 0 && rt != 0) {
2789 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2790 } else if (rs != 0 && rt == 0) {
2791 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2792 } else {
2793 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2794 }
6af0bf9c
FB
2795 break;
2796 case OPC_XOR:
460f00c4
AJ
2797 if (likely(rs != 0 && rt != 0)) {
2798 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2799 } else if (rs == 0 && rt != 0) {
2800 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2801 } else if (rs != 0 && rt == 0) {
2802 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2803 } else {
2804 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2805 }
6af0bf9c 2806 break;
460f00c4 2807 }
460f00c4
AJ
2808}
2809
2810/* Set on lower than */
d75c135e 2811static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 2812 int rd, int rs, int rt)
460f00c4 2813{
460f00c4
AJ
2814 TCGv t0, t1;
2815
2816 if (rd == 0) {
2817 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2818 return;
2819 }
2820
2821 t0 = tcg_temp_new();
2822 t1 = tcg_temp_new();
2823 gen_load_gpr(t0, rs);
2824 gen_load_gpr(t1, rt);
2825 switch (opc) {
2826 case OPC_SLT:
e68dd28f 2827 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 2828 break;
460f00c4 2829 case OPC_SLTU:
e68dd28f 2830 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
2831 break;
2832 }
460f00c4 2833}
20c4c97c 2834
460f00c4 2835/* Shifts */
d75c135e
AJ
2836static void gen_shift(DisasContext *ctx, uint32_t opc,
2837 int rd, int rs, int rt)
460f00c4 2838{
460f00c4 2839 TCGv t0, t1;
20c4c97c 2840
460f00c4 2841 if (rd == 0) {
7480515f
AM
2842 /*
2843 * If no destination, treat it as a NOP.
2844 * For add & sub, we must generate the overflow exception when needed.
2845 */
460f00c4
AJ
2846 return;
2847 }
2848
2849 t0 = tcg_temp_new();
2850 t1 = tcg_temp_new();
2851 gen_load_gpr(t0, rs);
2852 gen_load_gpr(t1, rt);
2853 switch (opc) {
6af0bf9c 2854 case OPC_SLLV:
78723684
TS
2855 tcg_gen_andi_tl(t0, t0, 0x1f);
2856 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 2857 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
2858 break;
2859 case OPC_SRAV:
78723684 2860 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 2861 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
2862 break;
2863 case OPC_SRLV:
ea63e2c3
NF
2864 tcg_gen_ext32u_tl(t1, t1);
2865 tcg_gen_andi_tl(t0, t0, 0x1f);
2866 tcg_gen_shr_tl(t0, t1, t0);
2867 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
2868 break;
2869 case OPC_ROTRV:
2870 {
2871 TCGv_i32 t2 = tcg_temp_new_i32();
2872 TCGv_i32 t3 = tcg_temp_new_i32();
2873
2874 tcg_gen_trunc_tl_i32(t2, t0);
2875 tcg_gen_trunc_tl_i32(t3, t1);
2876 tcg_gen_andi_i32(t2, t2, 0x1f);
2877 tcg_gen_rotr_i32(t2, t3, t2);
2878 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5a63bcb2 2879 }
7a387fff 2880 break;
d26bc211 2881#if defined(TARGET_MIPS64)
7a387fff 2882 case OPC_DSLLV:
78723684 2883 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2884 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2885 break;
2886 case OPC_DSRAV:
78723684 2887 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2888 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2889 break;
2890 case OPC_DSRLV:
ea63e2c3
NF
2891 tcg_gen_andi_tl(t0, t0, 0x3f);
2892 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
2893 break;
2894 case OPC_DROTRV:
2895 tcg_gen_andi_tl(t0, t0, 0x3f);
2896 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 2897 break;
7a387fff 2898#endif
6af0bf9c 2899 }
6af0bf9c
FB
2900}
2901
2902/* Arithmetic on HI/LO registers */
26135ead 2903static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 2904{
86efbfb6 2905 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 2906 /* Treat as NOP. */
a1f6684d 2907 return;
6af0bf9c 2908 }
4133498f 2909
4133498f 2910 if (acc != 0) {
86efbfb6 2911 check_dsp(ctx);
4133498f
JL
2912 }
2913
6af0bf9c
FB
2914 switch (opc) {
2915 case OPC_MFHI:
4133498f
JL
2916#if defined(TARGET_MIPS64)
2917 if (acc != 0) {
2918 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2919 } else
2920#endif
2921 {
2922 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2923 }
6af0bf9c
FB
2924 break;
2925 case OPC_MFLO:
4133498f
JL
2926#if defined(TARGET_MIPS64)
2927 if (acc != 0) {
2928 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2929 } else
2930#endif
2931 {
2932 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2933 }
6af0bf9c
FB
2934 break;
2935 case OPC_MTHI:
4133498f
JL
2936 if (reg != 0) {
2937#if defined(TARGET_MIPS64)
2938 if (acc != 0) {
2939 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2940 } else
2941#endif
2942 {
2943 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2944 }
2945 } else {
2946 tcg_gen_movi_tl(cpu_HI[acc], 0);
2947 }
6af0bf9c
FB
2948 break;
2949 case OPC_MTLO:
4133498f
JL
2950 if (reg != 0) {
2951#if defined(TARGET_MIPS64)
2952 if (acc != 0) {
2953 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2954 } else
2955#endif
2956 {
2957 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2958 }
2959 } else {
2960 tcg_gen_movi_tl(cpu_LO[acc], 0);
2961 }
6af0bf9c 2962 break;
6af0bf9c 2963 }
6af0bf9c
FB
2964}
2965
d4ea6acd 2966static inline void gen_r6_ld(target_long addr, int reg, int memidx,
14776ab5 2967 MemOp memop)
d4ea6acd 2968{
0bcc6b4c
RH
2969 TCGv t0 = tcg_temp_new();
2970 tcg_gen_qemu_ld_tl(t0, tcg_constant_tl(addr), memidx, memop);
d4ea6acd 2971 gen_store_gpr(t0, reg);
d4ea6acd
LA
2972}
2973
ab39ee45
YK
2974static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
2975 int rs)
d4ea6acd
LA
2976{
2977 target_long offset;
2978 target_long addr;
2979
ab39ee45 2980 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
2981 case OPC_ADDIUPC:
2982 if (rs != 0) {
2983 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 2984 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
2985 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2986 }
2987 break;
2988 case R6_OPC_LWPC:
2989 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 2990 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
2991 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
2992 break;
2993#if defined(TARGET_MIPS64)
2994 case OPC_LWUPC:
2995 check_mips_64(ctx);
2996 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 2997 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
2998 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
2999 break;
3000#endif
3001 default:
ab39ee45 3002 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
3003 case OPC_AUIPC:
3004 if (rs != 0) {
ab39ee45
YK
3005 offset = sextract32(ctx->opcode, 0, 16) << 16;
3006 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3007 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3008 }
3009 break;
3010 case OPC_ALUIPC:
3011 if (rs != 0) {
ab39ee45
YK
3012 offset = sextract32(ctx->opcode, 0, 16) << 16;
3013 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
3014 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3015 }
3016 break;
3017#if defined(TARGET_MIPS64)
3018 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3019 case R6_OPC_LDPC + (1 << 16):
3020 case R6_OPC_LDPC + (2 << 16):
3021 case R6_OPC_LDPC + (3 << 16):
3022 check_mips_64(ctx);
3023 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 3024 addr = addr_add(ctx, (pc & ~0x7), offset);
fc313c64 3025 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUQ);
d4ea6acd
LA
3026 break;
3027#endif
3028 default:
3029 MIPS_INVAL("OPC_PCREL");
3a4ef3b7 3030 gen_reserved_instruction(ctx);
d4ea6acd
LA
3031 break;
3032 }
3033 break;
3034 }
3035}
3036
b42ee5e1
LA
3037static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3038{
b42ee5e1
LA
3039 TCGv t0, t1;
3040
3041 if (rd == 0) {
3042 /* Treat as NOP. */
b42ee5e1
LA
3043 return;
3044 }
3045
3046 t0 = tcg_temp_new();
3047 t1 = tcg_temp_new();
3048
3049 gen_load_gpr(t0, rs);
3050 gen_load_gpr(t1, rt);
3051
3052 switch (opc) {
3053 case R6_OPC_DIV:
3054 {
3055 TCGv t2 = tcg_temp_new();
3056 TCGv t3 = tcg_temp_new();
3057 tcg_gen_ext32s_tl(t0, t0);
3058 tcg_gen_ext32s_tl(t1, t1);
3059 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3060 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3061 tcg_gen_and_tl(t2, t2, t3);
3062 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3063 tcg_gen_or_tl(t2, t2, t3);
3064 tcg_gen_movi_tl(t3, 0);
3065 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3066 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3067 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
b42ee5e1 3068 }
b42ee5e1
LA
3069 break;
3070 case R6_OPC_MOD:
3071 {
3072 TCGv t2 = tcg_temp_new();
3073 TCGv t3 = tcg_temp_new();
3074 tcg_gen_ext32s_tl(t0, t0);
3075 tcg_gen_ext32s_tl(t1, t1);
3076 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3077 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3078 tcg_gen_and_tl(t2, t2, t3);
3079 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3080 tcg_gen_or_tl(t2, t2, t3);
3081 tcg_gen_movi_tl(t3, 0);
3082 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3083 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3084 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
b42ee5e1 3085 }
b42ee5e1
LA
3086 break;
3087 case R6_OPC_DIVU:
3088 {
c29e79af
RH
3089 TCGv t2 = tcg_constant_tl(0);
3090 TCGv t3 = tcg_constant_tl(1);
b42ee5e1
LA
3091 tcg_gen_ext32u_tl(t0, t0);
3092 tcg_gen_ext32u_tl(t1, t1);
3093 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3094 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3095 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
b42ee5e1 3096 }
b42ee5e1
LA
3097 break;
3098 case R6_OPC_MODU:
3099 {
c29e79af
RH
3100 TCGv t2 = tcg_constant_tl(0);
3101 TCGv t3 = tcg_constant_tl(1);
b42ee5e1
LA
3102 tcg_gen_ext32u_tl(t0, t0);
3103 tcg_gen_ext32u_tl(t1, t1);
3104 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3105 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3106 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
b42ee5e1 3107 }
b42ee5e1
LA
3108 break;
3109 case R6_OPC_MUL:
3110 {
3111 TCGv_i32 t2 = tcg_temp_new_i32();
3112 TCGv_i32 t3 = tcg_temp_new_i32();
3113 tcg_gen_trunc_tl_i32(t2, t0);
3114 tcg_gen_trunc_tl_i32(t3, t1);
3115 tcg_gen_mul_i32(t2, t2, t3);
3116 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
b42ee5e1 3117 }
b42ee5e1
LA
3118 break;
3119 case R6_OPC_MUH:
3120 {
3121 TCGv_i32 t2 = tcg_temp_new_i32();
3122 TCGv_i32 t3 = tcg_temp_new_i32();
3123 tcg_gen_trunc_tl_i32(t2, t0);
3124 tcg_gen_trunc_tl_i32(t3, t1);
3125 tcg_gen_muls2_i32(t2, t3, t2, t3);
3126 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
b42ee5e1 3127 }
b42ee5e1
LA
3128 break;
3129 case R6_OPC_MULU:
3130 {
3131 TCGv_i32 t2 = tcg_temp_new_i32();
3132 TCGv_i32 t3 = tcg_temp_new_i32();
3133 tcg_gen_trunc_tl_i32(t2, t0);
3134 tcg_gen_trunc_tl_i32(t3, t1);
3135 tcg_gen_mul_i32(t2, t2, t3);
3136 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
b42ee5e1 3137 }
b42ee5e1
LA
3138 break;
3139 case R6_OPC_MUHU:
3140 {
3141 TCGv_i32 t2 = tcg_temp_new_i32();
3142 TCGv_i32 t3 = tcg_temp_new_i32();
3143 tcg_gen_trunc_tl_i32(t2, t0);
3144 tcg_gen_trunc_tl_i32(t3, t1);
3145 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3146 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
b42ee5e1 3147 }
b42ee5e1
LA
3148 break;
3149#if defined(TARGET_MIPS64)
3150 case R6_OPC_DDIV:
3151 {
3152 TCGv t2 = tcg_temp_new();
3153 TCGv t3 = tcg_temp_new();
3154 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3155 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3156 tcg_gen_and_tl(t2, t2, t3);
3157 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3158 tcg_gen_or_tl(t2, t2, t3);
3159 tcg_gen_movi_tl(t3, 0);
3160 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3161 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
b42ee5e1 3162 }
b42ee5e1
LA
3163 break;
3164 case R6_OPC_DMOD:
3165 {
3166 TCGv t2 = tcg_temp_new();
3167 TCGv t3 = tcg_temp_new();
3168 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3169 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3170 tcg_gen_and_tl(t2, t2, t3);
3171 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3172 tcg_gen_or_tl(t2, t2, t3);
3173 tcg_gen_movi_tl(t3, 0);
3174 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3175 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
b42ee5e1 3176 }
b42ee5e1
LA
3177 break;
3178 case R6_OPC_DDIVU:
3179 {
c29e79af
RH
3180 TCGv t2 = tcg_constant_tl(0);
3181 TCGv t3 = tcg_constant_tl(1);
b42ee5e1
LA
3182 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3183 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
b42ee5e1 3184 }
b42ee5e1
LA
3185 break;
3186 case R6_OPC_DMODU:
3187 {
c29e79af
RH
3188 TCGv t2 = tcg_constant_tl(0);
3189 TCGv t3 = tcg_constant_tl(1);
b42ee5e1
LA
3190 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3191 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
b42ee5e1 3192 }
b42ee5e1
LA
3193 break;
3194 case R6_OPC_DMUL:
3195 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3196 break;
3197 case R6_OPC_DMUH:
3198 {
3199 TCGv t2 = tcg_temp_new();
3200 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
b42ee5e1 3201 }
b42ee5e1
LA
3202 break;
3203 case R6_OPC_DMULU:
3204 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3205 break;
3206 case R6_OPC_DMUHU:
3207 {
3208 TCGv t2 = tcg_temp_new();
3209 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
b42ee5e1 3210 }
b42ee5e1
LA
3211 break;
3212#endif
3213 default:
9d68ac14 3214 MIPS_INVAL("r6 mul/div");
3a4ef3b7 3215 gen_reserved_instruction(ctx);
74fda465 3216 break;
b42ee5e1 3217 }
b42ee5e1
LA
3218}
3219
37b9aae2 3220#if defined(TARGET_MIPS64)
c42171c3
FN
3221static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3222{
3223 TCGv t0, t1;
3224
3225 t0 = tcg_temp_new();
3226 t1 = tcg_temp_new();
3227
3228 gen_load_gpr(t0, rs);
3229 gen_load_gpr(t1, rt);
3230
3231 switch (opc) {
baa609db 3232 case MMI_OPC_DIV1:
c42171c3
FN
3233 {
3234 TCGv t2 = tcg_temp_new();
3235 TCGv t3 = tcg_temp_new();
3236 tcg_gen_ext32s_tl(t0, t0);
3237 tcg_gen_ext32s_tl(t1, t1);
3238 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3239 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3240 tcg_gen_and_tl(t2, t2, t3);
3241 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3242 tcg_gen_or_tl(t2, t2, t3);
3243 tcg_gen_movi_tl(t3, 0);
3244 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3245 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3246 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3247 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3248 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
c42171c3
FN
3249 }
3250 break;
baa609db 3251 case MMI_OPC_DIVU1:
c42171c3 3252 {
c29e79af
RH
3253 TCGv t2 = tcg_constant_tl(0);
3254 TCGv t3 = tcg_constant_tl(1);
c42171c3
FN
3255 tcg_gen_ext32u_tl(t0, t0);
3256 tcg_gen_ext32u_tl(t1, t1);
3257 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3258 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3259 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3260 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3261 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
c42171c3
FN
3262 }
3263 break;
3264 default:
3265 MIPS_INVAL("div1 TX79");
3a4ef3b7 3266 gen_reserved_instruction(ctx);
74fda465 3267 break;
c42171c3 3268 }
c42171c3 3269}
37b9aae2 3270#endif
c42171c3 3271
26135ead
RS
3272static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3273 int acc, int rs, int rt)
6af0bf9c 3274{
d45f89f4
AJ
3275 TCGv t0, t1;
3276
51127181
AJ
3277 t0 = tcg_temp_new();
3278 t1 = tcg_temp_new();
6af0bf9c 3279
78723684
TS
3280 gen_load_gpr(t0, rs);
3281 gen_load_gpr(t1, rt);
51127181 3282
26135ead 3283 if (acc != 0) {
c42171c3 3284 check_dsp(ctx);
26135ead
RS
3285 }
3286
6af0bf9c
FB
3287 switch (opc) {
3288 case OPC_DIV:
48d38ca5 3289 {
51127181
AJ
3290 TCGv t2 = tcg_temp_new();
3291 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3292 tcg_gen_ext32s_tl(t0, t0);
3293 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3294 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3295 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3296 tcg_gen_and_tl(t2, t2, t3);
3297 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3298 tcg_gen_or_tl(t2, t2, t3);
3299 tcg_gen_movi_tl(t3, 0);
3300 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3301 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3302 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3303 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3304 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
48d38ca5 3305 }
6af0bf9c
FB
3306 break;
3307 case OPC_DIVU:
48d38ca5 3308 {
c29e79af
RH
3309 TCGv t2 = tcg_constant_tl(0);
3310 TCGv t3 = tcg_constant_tl(1);
0c0ed03b
AJ
3311 tcg_gen_ext32u_tl(t0, t0);
3312 tcg_gen_ext32u_tl(t1, t1);
51127181 3313 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3314 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3315 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3316 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3317 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
48d38ca5 3318 }
6af0bf9c
FB
3319 break;
3320 case OPC_MULT:
214c465f 3321 {
ce1dd5d1
RH
3322 TCGv_i32 t2 = tcg_temp_new_i32();
3323 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3324 tcg_gen_trunc_tl_i32(t2, t0);
3325 tcg_gen_trunc_tl_i32(t3, t1);
3326 tcg_gen_muls2_i32(t2, t3, t2, t3);
3327 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3328 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
214c465f 3329 }
6af0bf9c
FB
3330 break;
3331 case OPC_MULTU:
214c465f 3332 {
ce1dd5d1
RH
3333 TCGv_i32 t2 = tcg_temp_new_i32();
3334 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3335 tcg_gen_trunc_tl_i32(t2, t0);
3336 tcg_gen_trunc_tl_i32(t3, t1);
3337 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3338 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3339 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
214c465f 3340 }
6af0bf9c 3341 break;
d26bc211 3342#if defined(TARGET_MIPS64)
7a387fff 3343 case OPC_DDIV:
48d38ca5 3344 {
51127181
AJ
3345 TCGv t2 = tcg_temp_new();
3346 TCGv t3 = tcg_temp_new();
3347 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3348 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3349 tcg_gen_and_tl(t2, t2, t3);
3350 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3351 tcg_gen_or_tl(t2, t2, t3);
3352 tcg_gen_movi_tl(t3, 0);
3353 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3354 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3355 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
48d38ca5 3356 }
7a387fff
TS
3357 break;
3358 case OPC_DDIVU:
48d38ca5 3359 {
c29e79af
RH
3360 TCGv t2 = tcg_constant_tl(0);
3361 TCGv t3 = tcg_constant_tl(1);
51127181 3362 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3363 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3364 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
48d38ca5 3365 }
7a387fff
TS
3366 break;
3367 case OPC_DMULT:
26135ead 3368 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3369 break;
3370 case OPC_DMULTU:
26135ead 3371 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3372 break;
3373#endif
6af0bf9c 3374 case OPC_MADD:
214c465f 3375 {
d45f89f4
AJ
3376 TCGv_i64 t2 = tcg_temp_new_i64();
3377 TCGv_i64 t3 = tcg_temp_new_i64();
3378
3379 tcg_gen_ext_tl_i64(t2, t0);
3380 tcg_gen_ext_tl_i64(t3, t1);
3381 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3382 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4 3383 tcg_gen_add_i64(t2, t2, t3);
71f303cd
RH
3384 gen_move_low32(cpu_LO[acc], t2);
3385 gen_move_high32(cpu_HI[acc], t2);
214c465f 3386 }
6af0bf9c
FB
3387 break;
3388 case OPC_MADDU:
4133498f 3389 {
d45f89f4
AJ
3390 TCGv_i64 t2 = tcg_temp_new_i64();
3391 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3392
78723684
TS
3393 tcg_gen_ext32u_tl(t0, t0);
3394 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3395 tcg_gen_extu_tl_i64(t2, t0);
3396 tcg_gen_extu_tl_i64(t3, t1);
3397 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3398 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4 3399 tcg_gen_add_i64(t2, t2, t3);
71f303cd
RH
3400 gen_move_low32(cpu_LO[acc], t2);
3401 gen_move_high32(cpu_HI[acc], t2);
214c465f 3402 }
6af0bf9c
FB
3403 break;
3404 case OPC_MSUB:
214c465f 3405 {
d45f89f4
AJ
3406 TCGv_i64 t2 = tcg_temp_new_i64();
3407 TCGv_i64 t3 = tcg_temp_new_i64();
3408
3409 tcg_gen_ext_tl_i64(t2, t0);
3410 tcg_gen_ext_tl_i64(t3, t1);
3411 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3412 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3413 tcg_gen_sub_i64(t2, t3, t2);
71f303cd
RH
3414 gen_move_low32(cpu_LO[acc], t2);
3415 gen_move_high32(cpu_HI[acc], t2);
214c465f 3416 }
6af0bf9c
FB
3417 break;
3418 case OPC_MSUBU:
214c465f 3419 {
d45f89f4
AJ
3420 TCGv_i64 t2 = tcg_temp_new_i64();
3421 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3422
78723684
TS
3423 tcg_gen_ext32u_tl(t0, t0);
3424 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3425 tcg_gen_extu_tl_i64(t2, t0);
3426 tcg_gen_extu_tl_i64(t3, t1);
3427 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3428 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3429 tcg_gen_sub_i64(t2, t3, t2);
71f303cd
RH
3430 gen_move_low32(cpu_LO[acc], t2);
3431 gen_move_high32(cpu_HI[acc], t2);
214c465f 3432 }
6af0bf9c
FB
3433 break;
3434 default:
9d68ac14 3435 MIPS_INVAL("mul/div");
3a4ef3b7 3436 gen_reserved_instruction(ctx);
74fda465 3437 break;
6af0bf9c 3438 }
6af0bf9c
FB
3439}
3440
21e8e8b2 3441/*
3b948f05
PMD
3442 * These MULT[U] and MADD[U] instructions implemented in for example
3443 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
3444 * architectures are special three-operand variants with the syntax
3445 *
06de726b 3446 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
3447 *
3448 * such that
3449 *
3450 * (rd, LO, HI) <- rs * rt
3451 *
3b948f05
PMD
3452 * and
3453 *
a95c4c26 3454 * MADD[U][1] rd, rs, rt
3b948f05
PMD
3455 *
3456 * such that
3457 *
3458 * (rd, LO, HI) <- (LO, HI) + rs * rt
3459 *
21e8e8b2
FN
3460 * where the low-order 32-bits of the result is placed into both the
3461 * GPR rd and the special register LO. The high-order 32-bits of the
3462 * result is placed into the special register HI.
3463 *
3464 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3465 * which is the zero register that always reads as 0.
3466 */
3467static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3468 int rd, int rs, int rt)
3469{
3470 TCGv t0 = tcg_temp_new();
3471 TCGv t1 = tcg_temp_new();
3472 int acc = 0;
3473
3474 gen_load_gpr(t0, rs);
3475 gen_load_gpr(t1, rt);
3476
3477 switch (opc) {
baa609db 3478 case MMI_OPC_MULT1:
06de726b
FN
3479 acc = 1;
3480 /* Fall through */
21e8e8b2
FN
3481 case OPC_MULT:
3482 {
3483 TCGv_i32 t2 = tcg_temp_new_i32();
3484 TCGv_i32 t3 = tcg_temp_new_i32();
3485 tcg_gen_trunc_tl_i32(t2, t0);
3486 tcg_gen_trunc_tl_i32(t3, t1);
3487 tcg_gen_muls2_i32(t2, t3, t2, t3);
3488 if (rd) {
3489 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3490 }
3491 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3492 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
21e8e8b2
FN
3493 }
3494 break;
baa609db 3495 case MMI_OPC_MULTU1:
06de726b
FN
3496 acc = 1;
3497 /* Fall through */
21e8e8b2
FN
3498 case OPC_MULTU:
3499 {
3500 TCGv_i32 t2 = tcg_temp_new_i32();
3501 TCGv_i32 t3 = tcg_temp_new_i32();
3502 tcg_gen_trunc_tl_i32(t2, t0);
3503 tcg_gen_trunc_tl_i32(t3, t1);
3504 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3505 if (rd) {
3506 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3507 }
3508 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3509 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
21e8e8b2
FN
3510 }
3511 break;
a95c4c26
FN
3512 case MMI_OPC_MADD1:
3513 acc = 1;
3514 /* Fall through */
3b948f05
PMD
3515 case MMI_OPC_MADD:
3516 {
3517 TCGv_i64 t2 = tcg_temp_new_i64();
3518 TCGv_i64 t3 = tcg_temp_new_i64();
3519
3520 tcg_gen_ext_tl_i64(t2, t0);
3521 tcg_gen_ext_tl_i64(t3, t1);
3522 tcg_gen_mul_i64(t2, t2, t3);
3523 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3524 tcg_gen_add_i64(t2, t2, t3);
3b948f05
PMD
3525 gen_move_low32(cpu_LO[acc], t2);
3526 gen_move_high32(cpu_HI[acc], t2);
3527 if (rd) {
3528 gen_move_low32(cpu_gpr[rd], t2);
3529 }
3b948f05
PMD
3530 }
3531 break;
a95c4c26
FN
3532 case MMI_OPC_MADDU1:
3533 acc = 1;
3534 /* Fall through */
3b948f05
PMD
3535 case MMI_OPC_MADDU:
3536 {
3537 TCGv_i64 t2 = tcg_temp_new_i64();
3538 TCGv_i64 t3 = tcg_temp_new_i64();
3539
3540 tcg_gen_ext32u_tl(t0, t0);
3541 tcg_gen_ext32u_tl(t1, t1);
3542 tcg_gen_extu_tl_i64(t2, t0);
3543 tcg_gen_extu_tl_i64(t3, t1);
3544 tcg_gen_mul_i64(t2, t2, t3);
3545 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3546 tcg_gen_add_i64(t2, t2, t3);
3b948f05
PMD
3547 gen_move_low32(cpu_LO[acc], t2);
3548 gen_move_high32(cpu_HI[acc], t2);
3549 if (rd) {
3550 gen_move_low32(cpu_gpr[rd], t2);
3551 }
3b948f05
PMD
3552 }
3553 break;
21e8e8b2 3554 default:
3b948f05 3555 MIPS_INVAL("mul/madd TXx9");
3a4ef3b7 3556 gen_reserved_instruction(ctx);
74fda465 3557 break;
21e8e8b2 3558 }
21e8e8b2
FN
3559}
3560
235785e8
AM
3561static void gen_cl(DisasContext *ctx, uint32_t opc,
3562 int rd, int rs)
6af0bf9c 3563{
20e1fb52 3564 TCGv t0;
6c5c1e20 3565
6af0bf9c 3566 if (rd == 0) {
ead9360e 3567 /* Treat as NOP. */
20e1fb52 3568 return;
6af0bf9c 3569 }
1a0196c5 3570 t0 = cpu_gpr[rd];
6c5c1e20 3571 gen_load_gpr(t0, rs);
1a0196c5 3572
6af0bf9c
FB
3573 switch (opc) {
3574 case OPC_CLO:
4267d3e6 3575 case R6_OPC_CLO:
1a0196c5
RH
3576#if defined(TARGET_MIPS64)
3577 case OPC_DCLO:
3578 case R6_OPC_DCLO:
3579#endif
3580 tcg_gen_not_tl(t0, t0);
6af0bf9c 3581 break;
1a0196c5
RH
3582 }
3583
3584 switch (opc) {
3585 case OPC_CLO:
3586 case R6_OPC_CLO:
6af0bf9c 3587 case OPC_CLZ:
4267d3e6 3588 case R6_OPC_CLZ:
1a0196c5
RH
3589 tcg_gen_ext32u_tl(t0, t0);
3590 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3591 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 3592 break;
d26bc211 3593#if defined(TARGET_MIPS64)
7a387fff 3594 case OPC_DCLO:
4267d3e6 3595 case R6_OPC_DCLO:
7a387fff 3596 case OPC_DCLZ:
4267d3e6 3597 case R6_OPC_DCLZ:
1a0196c5 3598 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
3599 break;
3600#endif
6af0bf9c 3601 }
6af0bf9c
FB
3602}
3603
161f85e6 3604/* Godson integer instructions */
bd277fa1
RH
3605static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3606 int rd, int rs, int rt)
161f85e6 3607{
161f85e6
AJ
3608 TCGv t0, t1;
3609
3610 if (rd == 0) {
3611 /* Treat as NOP. */
161f85e6
AJ
3612 return;
3613 }
3614
6180cc40
RH
3615 t0 = tcg_temp_new();
3616 t1 = tcg_temp_new();
161f85e6
AJ
3617 gen_load_gpr(t0, rs);
3618 gen_load_gpr(t1, rt);
3619
3620 switch (opc) {
3621 case OPC_MULT_G_2E:
3622 case OPC_MULT_G_2F:
3623 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3624 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3625 break;
3626 case OPC_MULTU_G_2E:
3627 case OPC_MULTU_G_2F:
3628 tcg_gen_ext32u_tl(t0, t0);
3629 tcg_gen_ext32u_tl(t1, t1);
3630 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3631 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3632 break;
3633 case OPC_DIV_G_2E:
3634 case OPC_DIV_G_2F:
3635 {
42a268c2
RH
3636 TCGLabel *l1 = gen_new_label();
3637 TCGLabel *l2 = gen_new_label();
3638 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3639 tcg_gen_ext32s_tl(t0, t0);
3640 tcg_gen_ext32s_tl(t1, t1);
3641 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3642 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3643 tcg_gen_br(l3);
3644 gen_set_label(l1);
3645 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3646 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3647 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3648 tcg_gen_br(l3);
3649 gen_set_label(l2);
3650 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3651 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3652 gen_set_label(l3);
3653 }
161f85e6
AJ
3654 break;
3655 case OPC_DIVU_G_2E:
3656 case OPC_DIVU_G_2F:
3657 {
42a268c2
RH
3658 TCGLabel *l1 = gen_new_label();
3659 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3660 tcg_gen_ext32u_tl(t0, t0);
3661 tcg_gen_ext32u_tl(t1, t1);
3662 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3663 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3664 tcg_gen_br(l2);
3665 gen_set_label(l1);
3666 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3667 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3668 gen_set_label(l2);
3669 }
161f85e6
AJ
3670 break;
3671 case OPC_MOD_G_2E:
3672 case OPC_MOD_G_2F:
3673 {
42a268c2
RH
3674 TCGLabel *l1 = gen_new_label();
3675 TCGLabel *l2 = gen_new_label();
3676 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3677 tcg_gen_ext32u_tl(t0, t0);
3678 tcg_gen_ext32u_tl(t1, t1);
3679 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3680 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3681 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3682 gen_set_label(l1);
3683 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3684 tcg_gen_br(l3);
3685 gen_set_label(l2);
3686 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3687 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3688 gen_set_label(l3);
3689 }
161f85e6
AJ
3690 break;
3691 case OPC_MODU_G_2E:
3692 case OPC_MODU_G_2F:
3693 {
42a268c2
RH
3694 TCGLabel *l1 = gen_new_label();
3695 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3696 tcg_gen_ext32u_tl(t0, t0);
3697 tcg_gen_ext32u_tl(t1, t1);
3698 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3699 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3700 tcg_gen_br(l2);
3701 gen_set_label(l1);
3702 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3703 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3704 gen_set_label(l2);
3705 }
161f85e6
AJ
3706 break;
3707#if defined(TARGET_MIPS64)
3708 case OPC_DMULT_G_2E:
3709 case OPC_DMULT_G_2F:
3710 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
3711 break;
3712 case OPC_DMULTU_G_2E:
3713 case OPC_DMULTU_G_2F:
3714 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
3715 break;
3716 case OPC_DDIV_G_2E:
3717 case OPC_DDIV_G_2F:
3718 {
42a268c2
RH
3719 TCGLabel *l1 = gen_new_label();
3720 TCGLabel *l2 = gen_new_label();
3721 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3722 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3723 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3724 tcg_gen_br(l3);
3725 gen_set_label(l1);
3726 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3727 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3728 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3729 tcg_gen_br(l3);
3730 gen_set_label(l2);
3731 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3732 gen_set_label(l3);
3733 }
161f85e6
AJ
3734 break;
3735 case OPC_DDIVU_G_2E:
3736 case OPC_DDIVU_G_2F:
3737 {
42a268c2
RH
3738 TCGLabel *l1 = gen_new_label();
3739 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3740 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3741 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3742 tcg_gen_br(l2);
3743 gen_set_label(l1);
3744 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3745 gen_set_label(l2);
3746 }
161f85e6
AJ
3747 break;
3748 case OPC_DMOD_G_2E:
3749 case OPC_DMOD_G_2F:
3750 {
42a268c2
RH
3751 TCGLabel *l1 = gen_new_label();
3752 TCGLabel *l2 = gen_new_label();
3753 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3754 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3755 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3756 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3757 gen_set_label(l1);
3758 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3759 tcg_gen_br(l3);
3760 gen_set_label(l2);
3761 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3762 gen_set_label(l3);
3763 }
161f85e6
AJ
3764 break;
3765 case OPC_DMODU_G_2E:
3766 case OPC_DMODU_G_2F:
3767 {
42a268c2
RH
3768 TCGLabel *l1 = gen_new_label();
3769 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3770 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3771 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3772 tcg_gen_br(l2);
3773 gen_set_label(l1);
3774 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3775 gen_set_label(l2);
3776 }
161f85e6
AJ
3777 break;
3778#endif
3779 }
161f85e6
AJ
3780}
3781
bd277fa1
RH
3782/* Loongson multimedia instructions */
3783static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3784{
bd277fa1
RH
3785 uint32_t opc, shift_max;
3786 TCGv_i64 t0, t1;
84878f4c 3787 TCGCond cond;
bd277fa1 3788
8e2d5831 3789 opc = MASK_LMMI(ctx->opcode);
b5a587b6 3790 check_cp1_enabled(ctx);
6180cc40
RH
3791
3792 t0 = tcg_temp_new_i64();
3793 t1 = tcg_temp_new_i64();
bd277fa1
RH
3794 gen_load_fpr64(ctx, t0, rs);
3795 gen_load_fpr64(ctx, t1, rt);
3796
bd277fa1 3797 switch (opc) {
b1cf82f0
AM
3798 case OPC_PADDSH:
3799 gen_helper_paddsh(t0, t0, t1);
3800 break;
3801 case OPC_PADDUSH:
3802 gen_helper_paddush(t0, t0, t1);
3803 break;
3804 case OPC_PADDH:
3805 gen_helper_paddh(t0, t0, t1);
3806 break;
3807 case OPC_PADDW:
3808 gen_helper_paddw(t0, t0, t1);
3809 break;
3810 case OPC_PADDSB:
3811 gen_helper_paddsb(t0, t0, t1);
3812 break;
3813 case OPC_PADDUSB:
3814 gen_helper_paddusb(t0, t0, t1);
3815 break;
3816 case OPC_PADDB:
3817 gen_helper_paddb(t0, t0, t1);
3818 break;
3819
3820 case OPC_PSUBSH:
3821 gen_helper_psubsh(t0, t0, t1);
3822 break;
3823 case OPC_PSUBUSH:
3824 gen_helper_psubush(t0, t0, t1);
3825 break;
3826 case OPC_PSUBH:
3827 gen_helper_psubh(t0, t0, t1);
3828 break;
3829 case OPC_PSUBW:
3830 gen_helper_psubw(t0, t0, t1);
3831 break;
3832 case OPC_PSUBSB:
3833 gen_helper_psubsb(t0, t0, t1);
3834 break;
3835 case OPC_PSUBUSB:
3836 gen_helper_psubusb(t0, t0, t1);
3837 break;
3838 case OPC_PSUBB:
3839 gen_helper_psubb(t0, t0, t1);
3840 break;
3841
3842 case OPC_PSHUFH:
3843 gen_helper_pshufh(t0, t0, t1);
3844 break;
3845 case OPC_PACKSSWH:
3846 gen_helper_packsswh(t0, t0, t1);
3847 break;
3848 case OPC_PACKSSHB:
3849 gen_helper_packsshb(t0, t0, t1);
3850 break;
3851 case OPC_PACKUSHB:
3852 gen_helper_packushb(t0, t0, t1);
3853 break;
3854
3855 case OPC_PUNPCKLHW:
3856 gen_helper_punpcklhw(t0, t0, t1);
3857 break;
3858 case OPC_PUNPCKHHW:
3859 gen_helper_punpckhhw(t0, t0, t1);
3860 break;
3861 case OPC_PUNPCKLBH:
3862 gen_helper_punpcklbh(t0, t0, t1);
3863 break;
3864 case OPC_PUNPCKHBH:
3865 gen_helper_punpckhbh(t0, t0, t1);
3866 break;
3867 case OPC_PUNPCKLWD:
3868 gen_helper_punpcklwd(t0, t0, t1);
3869 break;
3870 case OPC_PUNPCKHWD:
3871 gen_helper_punpckhwd(t0, t0, t1);
3872 break;
3873
3874 case OPC_PAVGH:
3875 gen_helper_pavgh(t0, t0, t1);
3876 break;
3877 case OPC_PAVGB:
3878 gen_helper_pavgb(t0, t0, t1);
3879 break;
3880 case OPC_PMAXSH:
3881 gen_helper_pmaxsh(t0, t0, t1);
3882 break;
3883 case OPC_PMINSH:
3884 gen_helper_pminsh(t0, t0, t1);
3885 break;
3886 case OPC_PMAXUB:
3887 gen_helper_pmaxub(t0, t0, t1);
3888 break;
3889 case OPC_PMINUB:
3890 gen_helper_pminub(t0, t0, t1);
3891 break;
3892
3893 case OPC_PCMPEQW:
3894 gen_helper_pcmpeqw(t0, t0, t1);
3895 break;
3896 case OPC_PCMPGTW:
3897 gen_helper_pcmpgtw(t0, t0, t1);
3898 break;
3899 case OPC_PCMPEQH:
3900 gen_helper_pcmpeqh(t0, t0, t1);
3901 break;
3902 case OPC_PCMPGTH:
3903 gen_helper_pcmpgth(t0, t0, t1);
3904 break;
3905 case OPC_PCMPEQB:
3906 gen_helper_pcmpeqb(t0, t0, t1);
3907 break;
3908 case OPC_PCMPGTB:
3909 gen_helper_pcmpgtb(t0, t0, t1);
3910 break;
3911
3912 case OPC_PSLLW:
3913 gen_helper_psllw(t0, t0, t1);
3914 break;
3915 case OPC_PSLLH:
3916 gen_helper_psllh(t0, t0, t1);
3917 break;
3918 case OPC_PSRLW:
3919 gen_helper_psrlw(t0, t0, t1);
3920 break;
3921 case OPC_PSRLH:
3922 gen_helper_psrlh(t0, t0, t1);
3923 break;
3924 case OPC_PSRAW:
3925 gen_helper_psraw(t0, t0, t1);
3926 break;
3927 case OPC_PSRAH:
3928 gen_helper_psrah(t0, t0, t1);
3929 break;
3930
3931 case OPC_PMULLH:
3932 gen_helper_pmullh(t0, t0, t1);
3933 break;
3934 case OPC_PMULHH:
3935 gen_helper_pmulhh(t0, t0, t1);
3936 break;
3937 case OPC_PMULHUH:
3938 gen_helper_pmulhuh(t0, t0, t1);
3939 break;
3940 case OPC_PMADDHW:
3941 gen_helper_pmaddhw(t0, t0, t1);
3942 break;
3943
3944 case OPC_PASUBUB:
3945 gen_helper_pasubub(t0, t0, t1);
3946 break;
3947 case OPC_BIADD:
3948 gen_helper_biadd(t0, t0);
3949 break;
3950 case OPC_PMOVMSKB:
3951 gen_helper_pmovmskb(t0, t0);
3952 break;
3953
3954 case OPC_PADDD:
3955 tcg_gen_add_i64(t0, t0, t1);
3956 break;
3957 case OPC_PSUBD:
3958 tcg_gen_sub_i64(t0, t0, t1);
3959 break;
3960 case OPC_XOR_CP2:
3961 tcg_gen_xor_i64(t0, t0, t1);
3962 break;
3963 case OPC_NOR_CP2:
3964 tcg_gen_nor_i64(t0, t0, t1);
3965 break;
3966 case OPC_AND_CP2:
3967 tcg_gen_and_i64(t0, t0, t1);
3968 break;
3969 case OPC_OR_CP2:
3970 tcg_gen_or_i64(t0, t0, t1);
3971 break;
bd277fa1 3972
9099a36b
H
3973 case OPC_PANDN:
3974 tcg_gen_andc_i64(t0, t1, t0);
3975 break;
3976
bd277fa1
RH
3977 case OPC_PINSRH_0:
3978 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
3979 break;
3980 case OPC_PINSRH_1:
3981 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
3982 break;
3983 case OPC_PINSRH_2:
3984 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
3985 break;
3986 case OPC_PINSRH_3:
3987 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
3988 break;
3989
3990 case OPC_PEXTRH:
3991 tcg_gen_andi_i64(t1, t1, 3);
3992 tcg_gen_shli_i64(t1, t1, 4);
3993 tcg_gen_shr_i64(t0, t0, t1);
3994 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
3995 break;
3996
3997 case OPC_ADDU_CP2:
3998 tcg_gen_add_i64(t0, t0, t1);
3999 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4000 break;
4001 case OPC_SUBU_CP2:
4002 tcg_gen_sub_i64(t0, t0, t1);
4003 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4004 break;
4005
4006 case OPC_SLL_CP2:
bd277fa1
RH
4007 shift_max = 32;
4008 goto do_shift;
4009 case OPC_SRL_CP2:
bd277fa1
RH
4010 shift_max = 32;
4011 goto do_shift;
4012 case OPC_SRA_CP2:
bd277fa1
RH
4013 shift_max = 32;
4014 goto do_shift;
4015 case OPC_DSLL_CP2:
bd277fa1
RH
4016 shift_max = 64;
4017 goto do_shift;
4018 case OPC_DSRL_CP2:
bd277fa1
RH
4019 shift_max = 64;
4020 goto do_shift;
4021 case OPC_DSRA_CP2:
bd277fa1
RH
4022 shift_max = 64;
4023 goto do_shift;
4024 do_shift:
4025 /* Make sure shift count isn't TCG undefined behaviour. */
4026 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4027
4028 switch (opc) {
4029 case OPC_SLL_CP2:
4030 case OPC_DSLL_CP2:
4031 tcg_gen_shl_i64(t0, t0, t1);
4032 break;
4033 case OPC_SRA_CP2:
4034 case OPC_DSRA_CP2:
7480515f
AM
4035 /*
4036 * Since SRA is UndefinedResult without sign-extended inputs,
4037 * we can treat SRA and DSRA the same.
4038 */
bd277fa1
RH
4039 tcg_gen_sar_i64(t0, t0, t1);
4040 break;
4041 case OPC_SRL_CP2:
4042 /* We want to shift in zeros for SRL; zero-extend first. */
4043 tcg_gen_ext32u_i64(t0, t0);
4044 /* FALLTHRU */
4045 case OPC_DSRL_CP2:
4046 tcg_gen_shr_i64(t0, t0, t1);
4047 break;
4048 }
4049
4050 if (shift_max == 32) {
4051 tcg_gen_ext32s_i64(t0, t0);
4052 }
4053
4054 /* Shifts larger than MAX produce zero. */
4055 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4056 tcg_gen_neg_i64(t1, t1);
4057 tcg_gen_and_i64(t0, t0, t1);
4058 break;
4059
4060 case OPC_ADD_CP2:
4061 case OPC_DADD_CP2:
4062 {
4063 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4064 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4065
4066 tcg_gen_mov_i64(t2, t0);
4067 tcg_gen_add_i64(t0, t1, t2);
4068 if (opc == OPC_ADD_CP2) {
4069 tcg_gen_ext32s_i64(t0, t0);
4070 }
4071 tcg_gen_xor_i64(t1, t1, t2);
4072 tcg_gen_xor_i64(t2, t2, t0);
4073 tcg_gen_andc_i64(t1, t2, t1);
bd277fa1
RH
4074 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4075 generate_exception(ctx, EXCP_OVERFLOW);
4076 gen_set_label(lab);
bd277fa1
RH
4077 break;
4078 }
4079
4080 case OPC_SUB_CP2:
4081 case OPC_DSUB_CP2:
4082 {
4083 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4084 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4085
4086 tcg_gen_mov_i64(t2, t0);
4087 tcg_gen_sub_i64(t0, t1, t2);
4088 if (opc == OPC_SUB_CP2) {
4089 tcg_gen_ext32s_i64(t0, t0);
4090 }
4091 tcg_gen_xor_i64(t1, t1, t2);
4092 tcg_gen_xor_i64(t2, t2, t0);
4093 tcg_gen_and_i64(t1, t1, t2);
bd277fa1
RH
4094 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4095 generate_exception(ctx, EXCP_OVERFLOW);
4096 gen_set_label(lab);
bd277fa1
RH
4097 break;
4098 }
4099
4100 case OPC_PMULUW:
4101 tcg_gen_ext32u_i64(t0, t0);
4102 tcg_gen_ext32u_i64(t1, t1);
4103 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
4104 break;
4105
4106 case OPC_SEQU_CP2:
4107 case OPC_SEQ_CP2:
84878f4c
JY
4108 cond = TCG_COND_EQ;
4109 goto do_cc_cond;
4110 break;
bd277fa1 4111 case OPC_SLTU_CP2:
84878f4c
JY
4112 cond = TCG_COND_LTU;
4113 goto do_cc_cond;
4114 break;
bd277fa1 4115 case OPC_SLT_CP2:
84878f4c
JY
4116 cond = TCG_COND_LT;
4117 goto do_cc_cond;
4118 break;
bd277fa1 4119 case OPC_SLEU_CP2:
84878f4c
JY
4120 cond = TCG_COND_LEU;
4121 goto do_cc_cond;
4122 break;
bd277fa1 4123 case OPC_SLE_CP2:
84878f4c
JY
4124 cond = TCG_COND_LE;
4125 do_cc_cond:
4126 {
4127 int cc = (ctx->opcode >> 8) & 0x7;
4128 TCGv_i64 t64 = tcg_temp_new_i64();
4129 TCGv_i32 t32 = tcg_temp_new_i32();
4130
4131 tcg_gen_setcond_i64(cond, t64, t0, t1);
4132 tcg_gen_extrl_i64_i32(t32, t64);
4133 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4134 get_fp_bit(cc), 1);
84878f4c 4135 }
74fda465 4136 return;
bd277fa1 4137 default:
9d68ac14 4138 MIPS_INVAL("loongson_cp2");
3a4ef3b7 4139 gen_reserved_instruction(ctx);
bd277fa1
RH
4140 return;
4141 }
4142
bd277fa1 4143 gen_store_fpr64(ctx, t0, rd);
bd277fa1
RH
4144}
4145
e10a0ca1
JY
4146static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4147 int rs, int rd)
4148{
0694cd59 4149 TCGv t0, t1;
fd723105 4150 TCGv_i32 fp0;
e10a0ca1 4151#if defined(TARGET_MIPS64)
e10a0ca1
JY
4152 int lsq_rt1 = ctx->opcode & 0x1f;
4153 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4154#endif
fd723105 4155 int shf_offset = sextract32(ctx->opcode, 6, 8);
e10a0ca1
JY
4156
4157 t0 = tcg_temp_new();
4158
4159 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4160#if defined(TARGET_MIPS64)
4161 case OPC_GSLQ:
4162 t1 = tcg_temp_new();
4163 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
fc313c64 4164 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4165 ctx->default_tcg_memop_mask);
4166 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
fc313c64 4167 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4168 ctx->default_tcg_memop_mask);
4169 gen_store_gpr(t1, rt);
4170 gen_store_gpr(t0, lsq_rt1);
e10a0ca1
JY
4171 break;
4172 case OPC_GSLQC1:
4173 check_cp1_enabled(ctx);
4174 t1 = tcg_temp_new();
4175 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
fc313c64 4176 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4177 ctx->default_tcg_memop_mask);
4178 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
fc313c64 4179 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4180 ctx->default_tcg_memop_mask);
4181 gen_store_fpr64(ctx, t1, rt);
4182 gen_store_fpr64(ctx, t0, lsq_rt1);
e10a0ca1
JY
4183 break;
4184 case OPC_GSSQ:
4185 t1 = tcg_temp_new();
4186 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4187 gen_load_gpr(t1, rt);
fc313c64 4188 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4189 ctx->default_tcg_memop_mask);
4190 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4191 gen_load_gpr(t1, lsq_rt1);
fc313c64 4192 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1 4193 ctx->default_tcg_memop_mask);
e10a0ca1
JY
4194 break;
4195 case OPC_GSSQC1:
4196 check_cp1_enabled(ctx);
4197 t1 = tcg_temp_new();
4198 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4199 gen_load_fpr64(ctx, t1, rt);
fc313c64 4200 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1
JY
4201 ctx->default_tcg_memop_mask);
4202 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4203 gen_load_fpr64(ctx, t1, lsq_rt1);
fc313c64 4204 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
e10a0ca1 4205 ctx->default_tcg_memop_mask);
e10a0ca1
JY
4206 break;
4207#endif
fd723105
JY
4208 case OPC_GSSHFL:
4209 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4210 case OPC_GSLWLC1:
4211 check_cp1_enabled(ctx);
4212 gen_base_offset_addr(ctx, t0, rs, shf_offset);
fd723105
JY
4213 fp0 = tcg_temp_new_i32();
4214 gen_load_fpr32(ctx, fp0, rt);
990c162e 4215 t1 = tcg_temp_new();
fd723105 4216 tcg_gen_ext_i32_tl(t1, fp0);
990c162e
RH
4217 gen_lxl(ctx, t1, t0, ctx->mem_idx, MO_TEUL);
4218 tcg_gen_trunc_tl_i32(fp0, t1);
fd723105 4219 gen_store_fpr32(ctx, fp0, rt);
fd723105
JY
4220 break;
4221 case OPC_GSLWRC1:
4222 check_cp1_enabled(ctx);
4223 gen_base_offset_addr(ctx, t0, rs, shf_offset);
fd723105
JY
4224 fp0 = tcg_temp_new_i32();
4225 gen_load_fpr32(ctx, fp0, rt);
0694cd59 4226 t1 = tcg_temp_new();
fd723105 4227 tcg_gen_ext_i32_tl(t1, fp0);
0694cd59
RH
4228 gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUL);
4229 tcg_gen_trunc_tl_i32(fp0, t1);
fd723105 4230 gen_store_fpr32(ctx, fp0, rt);
fd723105
JY
4231 break;
4232#if defined(TARGET_MIPS64)
4233 case OPC_GSLDLC1:
4234 check_cp1_enabled(ctx);
4235 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4236 t1 = tcg_temp_new();
fd723105 4237 gen_load_fpr64(ctx, t1, rt);
990c162e
RH
4238 gen_lxl(ctx, t1, t0, ctx->mem_idx, MO_TEUQ);
4239 gen_store_fpr64(ctx, t1, rt);
fd723105
JY
4240 break;
4241 case OPC_GSLDRC1:
4242 check_cp1_enabled(ctx);
4243 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4244 t1 = tcg_temp_new();
fd723105 4245 gen_load_fpr64(ctx, t1, rt);
0694cd59
RH
4246 gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUQ);
4247 gen_store_fpr64(ctx, t1, rt);
fd723105
JY
4248 break;
4249#endif
4250 default:
4251 MIPS_INVAL("loongson_gsshfl");
3a4ef3b7 4252 gen_reserved_instruction(ctx);
fd723105
JY
4253 break;
4254 }
4255 break;
4256 case OPC_GSSHFS:
4257 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4258 case OPC_GSSWLC1:
4259 check_cp1_enabled(ctx);
4260 t1 = tcg_temp_new();
4261 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4262 fp0 = tcg_temp_new_i32();
4263 gen_load_fpr32(ctx, fp0, rt);
4264 tcg_gen_ext_i32_tl(t1, fp0);
4265 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
fd723105
JY
4266 break;
4267 case OPC_GSSWRC1:
4268 check_cp1_enabled(ctx);
4269 t1 = tcg_temp_new();
4270 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4271 fp0 = tcg_temp_new_i32();
4272 gen_load_fpr32(ctx, fp0, rt);
4273 tcg_gen_ext_i32_tl(t1, fp0);
4274 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
fd723105
JY
4275 break;
4276#if defined(TARGET_MIPS64)
4277 case OPC_GSSDLC1:
4278 check_cp1_enabled(ctx);
4279 t1 = tcg_temp_new();
4280 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4281 gen_load_fpr64(ctx, t1, rt);
4282 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
fd723105
JY
4283 break;
4284 case OPC_GSSDRC1:
4285 check_cp1_enabled(ctx);
4286 t1 = tcg_temp_new();
4287 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4288 gen_load_fpr64(ctx, t1, rt);
4289 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
fd723105
JY
4290 break;
4291#endif
4292 default:
4293 MIPS_INVAL("loongson_gsshfs");
3a4ef3b7 4294 gen_reserved_instruction(ctx);
fd723105
JY
4295 break;
4296 }
4297 break;
e10a0ca1
JY
4298 default:
4299 MIPS_INVAL("loongson_gslsq");
3a4ef3b7 4300 gen_reserved_instruction(ctx);
e10a0ca1
JY
4301 break;
4302 }
e10a0ca1
JY
4303}
4304
90e22a57
JY
4305/* Loongson EXT LDC2/SDC2 */
4306static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4307 int rs, int rd)
4308{
4309 int offset = sextract32(ctx->opcode, 3, 8);
4310 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4311 TCGv t0, t1;
4312 TCGv_i32 fp0;
4313
4314 /* Pre-conditions */
4315 switch (opc) {
4316 case OPC_GSLBX:
4317 case OPC_GSLHX:
4318 case OPC_GSLWX:
4319 case OPC_GSLDX:
4320 /* prefetch, implement as NOP */
4321 if (rt == 0) {
4322 return;
4323 }
4324 break;
4325 case OPC_GSSBX:
4326 case OPC_GSSHX:
4327 case OPC_GSSWX:
4328 case OPC_GSSDX:
4329 break;
4330 case OPC_GSLWXC1:
4331#if defined(TARGET_MIPS64)
4332 case OPC_GSLDXC1:
4333#endif
4334 check_cp1_enabled(ctx);
4335 /* prefetch, implement as NOP */
4336 if (rt == 0) {
4337 return;
4338 }
4339 break;
4340 case OPC_GSSWXC1:
4341#if defined(TARGET_MIPS64)
4342 case OPC_GSSDXC1:
4343#endif
4344 check_cp1_enabled(ctx);
4345 break;
4346 default:
4347 MIPS_INVAL("loongson_lsdc2");
3a4ef3b7 4348 gen_reserved_instruction(ctx);
90e22a57
JY
4349 return;
4350 break;
4351 }
4352
4353 t0 = tcg_temp_new();
4354
4355 gen_base_offset_addr(ctx, t0, rs, offset);
4356 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4357
4358 switch (opc) {
4359 case OPC_GSLBX:
4360 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4361 gen_store_gpr(t0, rt);
4362 break;
4363 case OPC_GSLHX:
4364 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4365 ctx->default_tcg_memop_mask);
4366 gen_store_gpr(t0, rt);
4367 break;
4368 case OPC_GSLWX:
4369 gen_base_offset_addr(ctx, t0, rs, offset);
4370 if (rd) {
4371 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4372 }
4373 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4374 ctx->default_tcg_memop_mask);
4375 gen_store_gpr(t0, rt);
4376 break;
4377#if defined(TARGET_MIPS64)
4378 case OPC_GSLDX:
4379 gen_base_offset_addr(ctx, t0, rs, offset);
4380 if (rd) {
4381 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4382 }
fc313c64 4383 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
90e22a57
JY
4384 ctx->default_tcg_memop_mask);
4385 gen_store_gpr(t0, rt);
4386 break;
4387#endif
4388 case OPC_GSLWXC1:
90e22a57
JY
4389 gen_base_offset_addr(ctx, t0, rs, offset);
4390 if (rd) {
4391 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4392 }
4393 fp0 = tcg_temp_new_i32();
4394 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4395 ctx->default_tcg_memop_mask);
4396 gen_store_fpr32(ctx, fp0, rt);
90e22a57
JY
4397 break;
4398#if defined(TARGET_MIPS64)
4399 case OPC_GSLDXC1:
90e22a57
JY
4400 gen_base_offset_addr(ctx, t0, rs, offset);
4401 if (rd) {
4402 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4403 }
fc313c64 4404 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
90e22a57
JY
4405 ctx->default_tcg_memop_mask);
4406 gen_store_fpr64(ctx, t0, rt);
4407 break;
4408#endif
4409 case OPC_GSSBX:
4410 t1 = tcg_temp_new();
4411 gen_load_gpr(t1, rt);
4412 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
90e22a57
JY
4413 break;
4414 case OPC_GSSHX:
4415 t1 = tcg_temp_new();
4416 gen_load_gpr(t1, rt);
4417 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4418 ctx->default_tcg_memop_mask);
90e22a57
JY
4419 break;
4420 case OPC_GSSWX:
4421 t1 = tcg_temp_new();
4422 gen_load_gpr(t1, rt);
4423 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4424 ctx->default_tcg_memop_mask);
90e22a57
JY
4425 break;
4426#if defined(TARGET_MIPS64)
4427 case OPC_GSSDX:
4428 t1 = tcg_temp_new();
4429 gen_load_gpr(t1, rt);
fc313c64 4430 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
90e22a57 4431 ctx->default_tcg_memop_mask);
90e22a57
JY
4432 break;
4433#endif
4434 case OPC_GSSWXC1:
4435 fp0 = tcg_temp_new_i32();
4436 gen_load_fpr32(ctx, fp0, rt);
4437 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4438 ctx->default_tcg_memop_mask);
90e22a57
JY
4439 break;
4440#if defined(TARGET_MIPS64)
4441 case OPC_GSSDXC1:
4442 t1 = tcg_temp_new();
4443 gen_load_fpr64(ctx, t1, rt);
fc313c64 4444 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ |
90e22a57 4445 ctx->default_tcg_memop_mask);
90e22a57
JY
4446 break;
4447#endif
4448 default:
4449 break;
4450 }
90e22a57
JY
4451}
4452
6af0bf9c 4453/* Traps */
71375b59 4454static void gen_trap(DisasContext *ctx, uint32_t opc,
0a3336f6 4455 int rs, int rt, int16_t imm, int code)
6af0bf9c
FB
4456{
4457 int cond;
cdc0faa6 4458 TCGv t0 = tcg_temp_new();
1ba74fb8 4459 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4460
4461 cond = 0;
4462 /* Load needed operands */
4463 switch (opc) {
4464 case OPC_TEQ:
4465 case OPC_TGE:
4466 case OPC_TGEU:
4467 case OPC_TLT:
4468 case OPC_TLTU:
4469 case OPC_TNE:
4470 /* Compare two registers */
4471 if (rs != rt) {
be24bb4f
TS
4472 gen_load_gpr(t0, rs);
4473 gen_load_gpr(t1, rt);
6af0bf9c
FB
4474 cond = 1;
4475 }
179e32bb 4476 break;
6af0bf9c
FB
4477 case OPC_TEQI:
4478 case OPC_TGEI:
4479 case OPC_TGEIU:
4480 case OPC_TLTI:
4481 case OPC_TLTIU:
4482 case OPC_TNEI:
4483 /* Compare register to immediate */
4484 if (rs != 0 || imm != 0) {
be24bb4f
TS
4485 gen_load_gpr(t0, rs);
4486 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4487 cond = 1;
4488 }
4489 break;
4490 }
4491 if (cond == 0) {
4492 switch (opc) {
4493 case OPC_TEQ: /* rs == rs */
4494 case OPC_TEQI: /* r0 == 0 */
4495 case OPC_TGE: /* rs >= rs */
4496 case OPC_TGEI: /* r0 >= 0 */
4497 case OPC_TGEU: /* rs >= rs unsigned */
4498 case OPC_TGEIU: /* r0 >= 0 unsigned */
4499 /* Always trap */
0a3336f6
RH
4500#ifdef CONFIG_USER_ONLY
4501 /* Pass the break code along to cpu_loop. */
ad75a51e 4502 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
0a3336f6
RH
4503 offsetof(CPUMIPSState, error_code));
4504#endif
9c708c7f 4505 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
4506 break;
4507 case OPC_TLT: /* rs < rs */
4508 case OPC_TLTI: /* r0 < 0 */
4509 case OPC_TLTU: /* rs < rs unsigned */
4510 case OPC_TLTIU: /* r0 < 0 unsigned */
4511 case OPC_TNE: /* rs != rs */
4512 case OPC_TNEI: /* r0 != 0 */
ead9360e 4513 /* Never trap: treat as NOP. */
cdc0faa6 4514 break;
6af0bf9c
FB
4515 }
4516 } else {
42a268c2 4517 TCGLabel *l1 = gen_new_label();
cdc0faa6 4518
6af0bf9c
FB
4519 switch (opc) {
4520 case OPC_TEQ:
4521 case OPC_TEQI:
cdc0faa6 4522 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4523 break;
4524 case OPC_TGE:
4525 case OPC_TGEI:
cdc0faa6 4526 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4527 break;
4528 case OPC_TGEU:
4529 case OPC_TGEIU:
cdc0faa6 4530 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
4531 break;
4532 case OPC_TLT:
4533 case OPC_TLTI:
cdc0faa6 4534 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
4535 break;
4536 case OPC_TLTU:
4537 case OPC_TLTIU:
cdc0faa6 4538 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
4539 break;
4540 case OPC_TNE:
4541 case OPC_TNEI:
cdc0faa6 4542 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 4543 break;
6af0bf9c 4544 }
0a3336f6
RH
4545#ifdef CONFIG_USER_ONLY
4546 /* Pass the break code along to cpu_loop. */
ad75a51e 4547 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
0a3336f6
RH
4548 offsetof(CPUMIPSState, error_code));
4549#endif
4550 /* Like save_cpu_state, only don't update saved values. */
4551 if (ctx->base.pc_next != ctx->saved_pc) {
4552 gen_save_pc(ctx->base.pc_next);
4553 }
4554 if (ctx->hflags != ctx->saved_hflags) {
4555 tcg_gen_movi_i32(hflags, ctx->hflags);
4556 }
cdc0faa6 4557 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
4558 gen_set_label(l1);
4559 }
6af0bf9c
FB
4560}
4561
97eea3c1 4562static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
90aa39a1 4563{
97eea3c1 4564 if (translator_use_goto_tb(&ctx->base, dest)) {
57fec1fe 4565 tcg_gen_goto_tb(n);
9b9e4393 4566 gen_save_pc(dest);
07ea28b4 4567 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 4568 } else {
9b9e4393 4569 gen_save_pc(dest);
1a79c413 4570 tcg_gen_lookup_and_goto_ptr();
6e256c93 4571 }
c53be334
FB
4572}
4573
6af0bf9c 4574/* Branches (before delay slot) */
71375b59
AM
4575static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
4576 int insn_bytes,
4577 int rs, int rt, int32_t offset,
4578 int delayslot_size)
6af0bf9c 4579{
d077b6f7 4580 target_ulong btgt = -1;
3ad4bb2d 4581 int blink = 0;
2fdbad25 4582 int bcond_compute = 0;
1ba74fb8
AJ
4583 TCGv t0 = tcg_temp_new();
4584 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
4585
4586 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 4587#ifdef MIPS_DEBUG_DISAS
339cd2a8 4588 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 4589 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 4590#endif
3a4ef3b7 4591 gen_reserved_instruction(ctx);
6c5c1e20 4592 goto out;
3ad4bb2d 4593 }
6af0bf9c 4594
6af0bf9c
FB
4595 /* Load needed operands */
4596 switch (opc) {
4597 case OPC_BEQ:
4598 case OPC_BEQL:
4599 case OPC_BNE:
4600 case OPC_BNEL:
4601 /* Compare two registers */
4602 if (rs != rt) {
6c5c1e20
TS
4603 gen_load_gpr(t0, rs);
4604 gen_load_gpr(t1, rt);
2fdbad25 4605 bcond_compute = 1;
6af0bf9c 4606 }
eeb3bba8 4607 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
4608 break;
4609 case OPC_BGEZ:
4610 case OPC_BGEZAL:
4611 case OPC_BGEZALL:
4612 case OPC_BGEZL:
4613 case OPC_BGTZ:
4614 case OPC_BGTZL:
4615 case OPC_BLEZ:
4616 case OPC_BLEZL:
4617 case OPC_BLTZ:
4618 case OPC_BLTZAL:
4619 case OPC_BLTZALL:
4620 case OPC_BLTZL:
4621 /* Compare to zero */
4622 if (rs != 0) {
6c5c1e20 4623 gen_load_gpr(t0, rs);
2fdbad25 4624 bcond_compute = 1;
6af0bf9c 4625 }
eeb3bba8 4626 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 4627 break;
e45a93e2
JL
4628 case OPC_BPOSGE32:
4629#if defined(TARGET_MIPS64)
4630 case OPC_BPOSGE64:
4631 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4632#else
4633 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4634#endif
4635 bcond_compute = 1;
eeb3bba8 4636 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 4637 break;
6af0bf9c
FB
4638 case OPC_J:
4639 case OPC_JAL:
9055ffd7
MN
4640 {
4641 /* Jump to immediate */
4642 int jal_mask = ctx->hflags & MIPS_HFLAG_M16 ? 0xF8000000
4643 : 0xF0000000;
4644 btgt = ((ctx->base.pc_next + insn_bytes) & jal_mask)
4645 | (uint32_t)offset;
4646 break;
4647 }
364d4831 4648 case OPC_JALX:
6af0bf9c 4649 /* Jump to immediate */
eeb3bba8
EC
4650 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4651 (uint32_t)offset;
6af0bf9c
FB
4652 break;
4653 case OPC_JR:
4654 case OPC_JALR:
4655 /* Jump to register */
7a387fff 4656 if (offset != 0 && offset != 16) {
7480515f
AM
4657 /*
4658 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4659 * others are reserved.
4660 */
923617a3 4661 MIPS_INVAL("jump hint");
3a4ef3b7 4662 gen_reserved_instruction(ctx);
6c5c1e20 4663 goto out;
6af0bf9c 4664 }
d077b6f7 4665 gen_load_gpr(btarget, rs);
6af0bf9c
FB
4666 break;
4667 default:
4668 MIPS_INVAL("branch/jump");
3a4ef3b7 4669 gen_reserved_instruction(ctx);
6c5c1e20 4670 goto out;
6af0bf9c 4671 }
2fdbad25 4672 if (bcond_compute == 0) {
6af0bf9c
FB
4673 /* No condition to be computed */
4674 switch (opc) {
4675 case OPC_BEQ: /* rx == rx */
4676 case OPC_BEQL: /* rx == rx likely */
4677 case OPC_BGEZ: /* 0 >= 0 */
4678 case OPC_BGEZL: /* 0 >= 0 likely */
4679 case OPC_BLEZ: /* 0 <= 0 */
4680 case OPC_BLEZL: /* 0 <= 0 likely */
4681 /* Always take */
4ad40f36 4682 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4683 break;
4684 case OPC_BGEZAL: /* 0 >= 0 */
4685 case OPC_BGEZALL: /* 0 >= 0 likely */
4686 /* Always take and link */
4687 blink = 31;
4ad40f36 4688 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4689 break;
4690 case OPC_BNE: /* rx != rx */
4691 case OPC_BGTZ: /* 0 > 0 */
4692 case OPC_BLTZ: /* 0 < 0 */
ead9360e 4693 /* Treat as NOP. */
6c5c1e20 4694 goto out;
eeef26cd 4695 case OPC_BLTZAL: /* 0 < 0 */
7480515f
AM
4696 /*
4697 * Handle as an unconditional branch to get correct delay
4698 * slot checking.
4699 */
3c824109 4700 blink = 31;
eeb3bba8 4701 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 4702 ctx->hflags |= MIPS_HFLAG_B;
3c824109 4703 break;
eeef26cd 4704 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 4705 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 4706 /* Skip the instruction in the delay slot */
eeb3bba8 4707 ctx->base.pc_next += 4;
6c5c1e20 4708 goto out;
6af0bf9c
FB
4709 case OPC_BNEL: /* rx != rx likely */
4710 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
4711 case OPC_BLTZL: /* 0 < 0 likely */
4712 /* Skip the instruction in the delay slot */
eeb3bba8 4713 ctx->base.pc_next += 4;
6c5c1e20 4714 goto out;
6af0bf9c 4715 case OPC_J:
4ad40f36 4716 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 4717 break;
364d4831
NF
4718 case OPC_JALX:
4719 ctx->hflags |= MIPS_HFLAG_BX;
4720 /* Fallthrough */
6af0bf9c
FB
4721 case OPC_JAL:
4722 blink = 31;
4ad40f36 4723 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4724 break;
4725 case OPC_JR:
4ad40f36 4726 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4727 break;
4728 case OPC_JALR:
4729 blink = rt;
4ad40f36 4730 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4731 break;
4732 default:
4733 MIPS_INVAL("branch/jump");
3a4ef3b7 4734 gen_reserved_instruction(ctx);
6c5c1e20 4735 goto out;
6af0bf9c
FB
4736 }
4737 } else {
4738 switch (opc) {
4739 case OPC_BEQ:
e68dd28f 4740 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4741 goto not_likely;
4742 case OPC_BEQL:
e68dd28f 4743 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4744 goto likely;
4745 case OPC_BNE:
e68dd28f 4746 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4747 goto not_likely;
4748 case OPC_BNEL:
e68dd28f 4749 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4750 goto likely;
4751 case OPC_BGEZ:
e68dd28f 4752 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4753 goto not_likely;
4754 case OPC_BGEZL:
e68dd28f 4755 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4756 goto likely;
4757 case OPC_BGEZAL:
e68dd28f 4758 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4759 blink = 31;
4760 goto not_likely;
4761 case OPC_BGEZALL:
e68dd28f 4762 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 4763 blink = 31;
6af0bf9c
FB
4764 goto likely;
4765 case OPC_BGTZ:
e68dd28f 4766 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4767 goto not_likely;
4768 case OPC_BGTZL:
e68dd28f 4769 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4770 goto likely;
4771 case OPC_BLEZ:
e68dd28f 4772 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4773 goto not_likely;
4774 case OPC_BLEZL:
e68dd28f 4775 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4776 goto likely;
4777 case OPC_BLTZ:
e68dd28f 4778 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
4779 goto not_likely;
4780 case OPC_BLTZL:
e68dd28f 4781 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4782 goto likely;
e45a93e2
JL
4783 case OPC_BPOSGE32:
4784 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
4785 goto not_likely;
4786#if defined(TARGET_MIPS64)
4787 case OPC_BPOSGE64:
4788 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
4789 goto not_likely;
4790#endif
6af0bf9c 4791 case OPC_BLTZAL:
e68dd28f 4792 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4793 blink = 31;
6af0bf9c 4794 not_likely:
4ad40f36 4795 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
4796 break;
4797 case OPC_BLTZALL:
e68dd28f 4798 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4799 blink = 31;
6af0bf9c 4800 likely:
4ad40f36 4801 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 4802 break;
c53f4a62
TS
4803 default:
4804 MIPS_INVAL("conditional branch/jump");
3a4ef3b7 4805 gen_reserved_instruction(ctx);
6c5c1e20 4806 goto out;
6af0bf9c 4807 }
6af0bf9c 4808 }
9b9e4393 4809
d077b6f7 4810 ctx->btarget = btgt;
b231c103
YK
4811
4812 switch (delayslot_size) {
4813 case 2:
4814 ctx->hflags |= MIPS_HFLAG_BDS16;
4815 break;
4816 case 4:
4817 ctx->hflags |= MIPS_HFLAG_BDS32;
4818 break;
4819 }
4820
6af0bf9c 4821 if (blink > 0) {
b231c103 4822 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
4823 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4824
eeb3bba8
EC
4825 tcg_gen_movi_tl(cpu_gpr[blink],
4826 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 4827 }
6c5c1e20
TS
4828
4829 out:
1f8929d2 4830 if (insn_bytes == 2) {
364d4831 4831 ctx->hflags |= MIPS_HFLAG_B16;
1f8929d2 4832 }
6af0bf9c
FB
4833}
4834
764371d2 4835
7a387fff 4836/* special3 bitfield operations */
235785e8
AM
4837static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
4838 int rs, int lsb, int msb)
7a387fff 4839{
a7812ae4
PB
4840 TCGv t0 = tcg_temp_new();
4841 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
4842
4843 gen_load_gpr(t1, rs);
7a387fff
TS
4844 switch (opc) {
4845 case OPC_EXT:
b7f26e52 4846 if (lsb + msb > 31) {
7a387fff 4847 goto fail;
b7f26e52 4848 }
505ad7c2 4849 if (msb != 31) {
6eebb7a4 4850 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 4851 } else {
7480515f
AM
4852 /*
4853 * The two checks together imply that lsb == 0,
4854 * so this is a simple sign-extension.
4855 */
6eebb7a4 4856 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 4857 }
7a387fff 4858 break;
c6d6dd7c 4859#if defined(TARGET_MIPS64)
7a387fff 4860 case OPC_DEXTU:
b7f26e52
RH
4861 lsb += 32;
4862 goto do_dext;
4863 case OPC_DEXTM:
4864 msb += 32;
4865 goto do_dext;
7a387fff 4866 case OPC_DEXT:
b7f26e52
RH
4867 do_dext:
4868 if (lsb + msb > 63) {
4869 goto fail;
4870 }
6eebb7a4 4871 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 4872 break;
c6d6dd7c 4873#endif
7a387fff 4874 case OPC_INS:
b7f26e52 4875 if (lsb > msb) {
7a387fff 4876 goto fail;
b7f26e52 4877 }
6c5c1e20 4878 gen_load_gpr(t0, rt);
e0d002f1 4879 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 4880 tcg_gen_ext32s_tl(t0, t0);
7a387fff 4881 break;
c6d6dd7c 4882#if defined(TARGET_MIPS64)
7a387fff 4883 case OPC_DINSU:
b7f26e52
RH
4884 lsb += 32;
4885 /* FALLTHRU */
4886 case OPC_DINSM:
4887 msb += 32;
4888 /* FALLTHRU */
7a387fff 4889 case OPC_DINS:
b7f26e52
RH
4890 if (lsb > msb) {
4891 goto fail;
4892 }
6c5c1e20 4893 gen_load_gpr(t0, rt);
e0d002f1 4894 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 4895 break;
c6d6dd7c 4896#endif
7a387fff
TS
4897 default:
4898fail:
4899 MIPS_INVAL("bitops");
3a4ef3b7 4900 gen_reserved_instruction(ctx);
7a387fff
TS
4901 return;
4902 }
6c5c1e20 4903 gen_store_gpr(t0, rt);
7a387fff
TS
4904}
4905
235785e8 4906static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
49bcf33c 4907{
3a55fa47 4908 TCGv t0;
49bcf33c 4909
3a55fa47
AJ
4910 if (rd == 0) {
4911 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
4912 return;
4913 }
4914
4915 t0 = tcg_temp_new();
4916 gen_load_gpr(t0, rt);
49bcf33c
AJ
4917 switch (op2) {
4918 case OPC_WSBH:
3a55fa47
AJ
4919 {
4920 TCGv t1 = tcg_temp_new();
c29e79af 4921 TCGv t2 = tcg_constant_tl(0x00FF00FF);
3a55fa47
AJ
4922
4923 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
4924 tcg_gen_and_tl(t1, t1, t2);
4925 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4926 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 4927 tcg_gen_or_tl(t0, t0, t1);
3a55fa47
AJ
4928 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4929 }
49bcf33c
AJ
4930 break;
4931 case OPC_SEB:
3a55fa47 4932 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4933 break;
4934 case OPC_SEH:
3a55fa47 4935 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4936 break;
4937#if defined(TARGET_MIPS64)
4938 case OPC_DSBH:
3a55fa47
AJ
4939 {
4940 TCGv t1 = tcg_temp_new();
c29e79af 4941 TCGv t2 = tcg_constant_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
4942
4943 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
4944 tcg_gen_and_tl(t1, t1, t2);
4945 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4946 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 4947 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3a55fa47 4948 }
49bcf33c
AJ
4949 break;
4950 case OPC_DSHD:
3a55fa47
AJ
4951 {
4952 TCGv t1 = tcg_temp_new();
c29e79af 4953 TCGv t2 = tcg_constant_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
4954
4955 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
4956 tcg_gen_and_tl(t1, t1, t2);
4957 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4958 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
4959 tcg_gen_or_tl(t0, t0, t1);
4960 tcg_gen_shri_tl(t1, t0, 32);
4961 tcg_gen_shli_tl(t0, t0, 32);
4962 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3a55fa47 4963 }
49bcf33c
AJ
4964 break;
4965#endif
4966 default:
4967 MIPS_INVAL("bsfhl");
3a4ef3b7 4968 gen_reserved_instruction(ctx);
49bcf33c
AJ
4969 return;
4970 }
49bcf33c
AJ
4971}
4972
821f2008
JH
4973static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4974 int rt, int bits)
284b731a 4975{
1f1b4c00
YK
4976 TCGv t0;
4977 if (rd == 0) {
4978 /* Treat as NOP. */
4979 return;
4980 }
4981 t0 = tcg_temp_new();
821f2008
JH
4982 if (bits == 0 || bits == wordsz) {
4983 if (bits == 0) {
4984 gen_load_gpr(t0, rt);
4985 } else {
4986 gen_load_gpr(t0, rs);
4987 }
4988 switch (wordsz) {
4989 case 32:
51243852
MD
4990 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4991 break;
4992#if defined(TARGET_MIPS64)
821f2008 4993 case 64:
51243852
MD
4994 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4995 break;
4996#endif
4997 }
1f1b4c00
YK
4998 } else {
4999 TCGv t1 = tcg_temp_new();
821f2008 5000 gen_load_gpr(t0, rt);
1f1b4c00 5001 gen_load_gpr(t1, rs);
821f2008
JH
5002 switch (wordsz) {
5003 case 32:
1f1b4c00
YK
5004 {
5005 TCGv_i64 t2 = tcg_temp_new_i64();
5006 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 5007 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00 5008 gen_move_low32(cpu_gpr[rd], t2);
1f1b4c00
YK
5009 }
5010 break;
284b731a 5011#if defined(TARGET_MIPS64)
821f2008
JH
5012 case 64:
5013 tcg_gen_shli_tl(t0, t0, bits);
5014 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
5015 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5016 break;
284b731a 5017#endif
1f1b4c00 5018 }
1f1b4c00 5019 }
1f1b4c00
YK
5020}
5021
d5076631 5022void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
821f2008
JH
5023{
5024 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5025}
5026
1f1b4c00
YK
5027static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5028{
5029 TCGv t0;
5030 if (rd == 0) {
5031 /* Treat as NOP. */
5032 return;
5033 }
5034 t0 = tcg_temp_new();
5035 gen_load_gpr(t0, rt);
5036 switch (opc) {
5037 case OPC_BITSWAP:
5038 gen_helper_bitswap(cpu_gpr[rd], t0);
5039 break;
5040#if defined(TARGET_MIPS64)
5041 case OPC_DBITSWAP:
5042 gen_helper_dbitswap(cpu_gpr[rd], t0);
5043 break;
5044#endif
5045 }
284b731a
LA
5046}
5047
1f1b4c00
YK
5048#ifndef CONFIG_USER_ONLY
5049/* CP0 (MMU and control) */
5204ea79
LA
5050static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5051{
5052 TCGv_i64 t0 = tcg_temp_new_i64();
5053 TCGv_i64 t1 = tcg_temp_new_i64();
5054
5055 tcg_gen_ext_tl_i64(t0, arg);
ad75a51e 5056 tcg_gen_ld_i64(t1, tcg_env, off);
5204ea79
LA
5057#if defined(TARGET_MIPS64)
5058 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5059#else
5060 tcg_gen_concat32_i64(t1, t1, t0);
5061#endif
ad75a51e 5062 tcg_gen_st_i64(t1, tcg_env, off);
5204ea79
LA
5063}
5064
5065static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5066{
5067 TCGv_i64 t0 = tcg_temp_new_i64();
5068 TCGv_i64 t1 = tcg_temp_new_i64();
5069
5070 tcg_gen_ext_tl_i64(t0, arg);
ad75a51e 5071 tcg_gen_ld_i64(t1, tcg_env, off);
5204ea79 5072 tcg_gen_concat32_i64(t1, t1, t0);
ad75a51e 5073 tcg_gen_st_i64(t1, tcg_env, off);
5204ea79
LA
5074}
5075
5076static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5077{
5078 TCGv_i64 t0 = tcg_temp_new_i64();
5079
ad75a51e 5080 tcg_gen_ld_i64(t0, tcg_env, off);
5204ea79
LA
5081#if defined(TARGET_MIPS64)
5082 tcg_gen_shri_i64(t0, t0, 30);
5083#else
5084 tcg_gen_shri_i64(t0, t0, 32);
5085#endif
5086 gen_move_low32(arg, t0);
5204ea79
LA
5087}
5088
5089static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5090{
5091 TCGv_i64 t0 = tcg_temp_new_i64();
5092
ad75a51e 5093 tcg_gen_ld_i64(t0, tcg_env, off);
5204ea79
LA
5094 tcg_gen_shri_i64(t0, t0, 32 + shift);
5095 gen_move_low32(arg, t0);
5204ea79
LA
5096}
5097
235785e8 5098static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4f57689a 5099{
d9bea114 5100 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 5101
ad75a51e 5102 tcg_gen_ld_i32(t0, tcg_env, off);
d9bea114 5103 tcg_gen_ext_i32_tl(arg, t0);
4f57689a
TS
5104}
5105
235785e8 5106static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4f57689a 5107{
ad75a51e 5108 tcg_gen_ld_tl(arg, tcg_env, off);
d9bea114 5109 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
5110}
5111
235785e8 5112static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
f1aa6320 5113{
d9bea114 5114 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 5115
d9bea114 5116 tcg_gen_trunc_tl_i32(t0, arg);
ad75a51e 5117 tcg_gen_st_i32(t0, tcg_env, off);
f1aa6320
TS
5118}
5119
c98d3d79
YK
5120#define CP0_CHECK(c) \
5121 do { \
5122 if (!(c)) { \
5123 goto cp0_unimplemented; \
5124 } \
5125 } while (0)
5126
5204ea79
LA
5127static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5128{
294fc2ea 5129 const char *register_name = "invalid";
5204ea79 5130
5204ea79 5131 switch (reg) {
04992c8c 5132 case CP0_REGISTER_02:
5204ea79
LA
5133 switch (sel) {
5134 case 0:
59488dda 5135 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5136 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5137 register_name = "EntryLo0";
5204ea79
LA
5138 break;
5139 default:
c98d3d79 5140 goto cp0_unimplemented;
5204ea79
LA
5141 }
5142 break;
04992c8c 5143 case CP0_REGISTER_03:
5204ea79 5144 switch (sel) {
acd37316 5145 case CP0_REG03__ENTRYLO1:
59488dda 5146 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 5147 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5148 register_name = "EntryLo1";
5204ea79
LA
5149 break;
5150 default:
c98d3d79 5151 goto cp0_unimplemented;
5204ea79
LA
5152 }
5153 break;
04992c8c 5154 case CP0_REGISTER_09:
5fb2dcd1 5155 switch (sel) {
e5a98a72 5156 case CP0_REG09__SAAR:
5fb2dcd1 5157 CP0_CHECK(ctx->saar);
ad75a51e 5158 gen_helper_mfhc0_saar(arg, tcg_env);
294fc2ea 5159 register_name = "SAAR";
5fb2dcd1
YK
5160 break;
5161 default:
5162 goto cp0_unimplemented;
5163 }
5164 break;
04992c8c 5165 case CP0_REGISTER_17:
5204ea79 5166 switch (sel) {
706ce142 5167 case CP0_REG17__LLADDR:
c7c7e1e9 5168 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5204ea79 5169 ctx->CP0_LLAddr_shift);
294fc2ea 5170 register_name = "LLAddr";
5204ea79 5171 break;
706ce142 5172 case CP0_REG17__MAAR:
f6d4dd81 5173 CP0_CHECK(ctx->mrp);
ad75a51e 5174 gen_helper_mfhc0_maar(arg, tcg_env);
294fc2ea 5175 register_name = "MAAR";
f6d4dd81 5176 break;
5204ea79 5177 default:
c98d3d79 5178 goto cp0_unimplemented;
5204ea79
LA
5179 }
5180 break;
feafe82c
YK
5181 case CP0_REGISTER_19:
5182 switch (sel) {
5183 case CP0_REG19__WATCHHI0:
5184 case CP0_REG19__WATCHHI1:
5185 case CP0_REG19__WATCHHI2:
5186 case CP0_REG19__WATCHHI3:
5187 case CP0_REG19__WATCHHI4:
5188 case CP0_REG19__WATCHHI5:
5189 case CP0_REG19__WATCHHI6:
5190 case CP0_REG19__WATCHHI7:
5191 /* upper 32 bits are only available when Config5MI != 0 */
5192 CP0_CHECK(ctx->mi);
5193 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5194 register_name = "WatchHi";
5195 break;
5196 default:
5197 goto cp0_unimplemented;
5198 }
5199 break;
04992c8c 5200 case CP0_REGISTER_28:
5204ea79
LA
5201 switch (sel) {
5202 case 0:
5203 case 2:
5204 case 4:
5205 case 6:
5206 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 5207 register_name = "TagLo";
5204ea79
LA
5208 break;
5209 default:
c98d3d79 5210 goto cp0_unimplemented;
5204ea79
LA
5211 }
5212 break;
5213 default:
c98d3d79 5214 goto cp0_unimplemented;
5204ea79 5215 }
294fc2ea 5216 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
5217 return;
5218
c98d3d79 5219cp0_unimplemented:
294fc2ea
AM
5220 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5221 register_name, reg, sel);
5204ea79
LA
5222 tcg_gen_movi_tl(arg, 0);
5223}
5224
5225static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5226{
294fc2ea 5227 const char *register_name = "invalid";
5204ea79
LA
5228 uint64_t mask = ctx->PAMask >> 36;
5229
5204ea79 5230 switch (reg) {
04992c8c 5231 case CP0_REGISTER_02:
5204ea79
LA
5232 switch (sel) {
5233 case 0:
59488dda 5234 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5235 tcg_gen_andi_tl(arg, arg, mask);
5236 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 5237 register_name = "EntryLo0";
5204ea79
LA
5238 break;
5239 default:
c98d3d79 5240 goto cp0_unimplemented;
5204ea79
LA
5241 }
5242 break;
04992c8c 5243 case CP0_REGISTER_03:
5204ea79 5244 switch (sel) {
acd37316 5245 case CP0_REG03__ENTRYLO1:
59488dda 5246 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5247 tcg_gen_andi_tl(arg, arg, mask);
5248 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 5249 register_name = "EntryLo1";
5204ea79
LA
5250 break;
5251 default:
c98d3d79 5252 goto cp0_unimplemented;
5204ea79
LA
5253 }
5254 break;
04992c8c 5255 case CP0_REGISTER_09:
5fb2dcd1 5256 switch (sel) {
e5a98a72 5257 case CP0_REG09__SAAR:
5fb2dcd1 5258 CP0_CHECK(ctx->saar);
ad75a51e 5259 gen_helper_mthc0_saar(tcg_env, arg);
294fc2ea 5260 register_name = "SAAR";
5fb2dcd1
YK
5261 break;
5262 default:
5263 goto cp0_unimplemented;
5264 }
ab8c3410 5265 break;
04992c8c 5266 case CP0_REGISTER_17:
5204ea79 5267 switch (sel) {
706ce142 5268 case CP0_REG17__LLADDR:
7480515f
AM
5269 /*
5270 * LLAddr is read-only (the only exception is bit 0 if LLB is
5271 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5272 * relevant for modern MIPS cores supporting MTHC0, therefore
5273 * treating MTHC0 to LLAddr as NOP.
5274 */
294fc2ea 5275 register_name = "LLAddr";
5204ea79 5276 break;
706ce142 5277 case CP0_REG17__MAAR:
f6d4dd81 5278 CP0_CHECK(ctx->mrp);
ad75a51e 5279 gen_helper_mthc0_maar(tcg_env, arg);
294fc2ea 5280 register_name = "MAAR";
f6d4dd81 5281 break;
5204ea79 5282 default:
c98d3d79 5283 goto cp0_unimplemented;
5204ea79
LA
5284 }
5285 break;
feafe82c
YK
5286 case CP0_REGISTER_19:
5287 switch (sel) {
5288 case CP0_REG19__WATCHHI0:
5289 case CP0_REG19__WATCHHI1:
5290 case CP0_REG19__WATCHHI2:
5291 case CP0_REG19__WATCHHI3:
5292 case CP0_REG19__WATCHHI4:
5293 case CP0_REG19__WATCHHI5:
5294 case CP0_REG19__WATCHHI6:
5295 case CP0_REG19__WATCHHI7:
5296 /* upper 32 bits are only available when Config5MI != 0 */
5297 CP0_CHECK(ctx->mi);
5298 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5299 register_name = "WatchHi";
5300 break;
5301 default:
5302 goto cp0_unimplemented;
5303 }
5304 break;
04992c8c 5305 case CP0_REGISTER_28:
5204ea79
LA
5306 switch (sel) {
5307 case 0:
5308 case 2:
5309 case 4:
5310 case 6:
5311 tcg_gen_andi_tl(arg, arg, mask);
5312 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 5313 register_name = "TagLo";
5204ea79
LA
5314 break;
5315 default:
c98d3d79 5316 goto cp0_unimplemented;
5204ea79
LA
5317 }
5318 break;
5319 default:
c98d3d79 5320 goto cp0_unimplemented;
5204ea79 5321 }
294fc2ea 5322 trace_mips_translate_c0("mthc0", register_name, reg, sel);
bc2eb5ea 5323 return;
5204ea79 5324
c98d3d79 5325cp0_unimplemented:
294fc2ea
AM
5326 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5327 register_name, reg, sel);
5204ea79
LA
5328}
5329
e98c0d17
LA
5330static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5331{
2e211e0a 5332 if (ctx->insn_flags & ISA_MIPS_R6) {
e98c0d17
LA
5333 tcg_gen_movi_tl(arg, 0);
5334 } else {
5335 tcg_gen_movi_tl(arg, ~0);
5336 }
5337}
5338
d75c135e 5339static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 5340{
294fc2ea 5341 const char *register_name = "invalid";
873eb012 5342
1f8929d2 5343 if (sel != 0) {
bbd5e4a2 5344 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 5345 }
e189e748 5346
873eb012 5347 switch (reg) {
04992c8c 5348 case CP0_REGISTER_00:
7a387fff 5349 switch (sel) {
1b142da5 5350 case CP0_REG00__INDEX:
7db13fae 5351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 5352 register_name = "Index";
7a387fff 5353 break;
1b142da5 5354 case CP0_REG00__MVPCONTROL:
f31b035a 5355 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5356 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
294fc2ea 5357 register_name = "MVPControl";
ead9360e 5358 break;
1b142da5 5359 case CP0_REG00__MVPCONF0:
f31b035a 5360 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5361 gen_helper_mfc0_mvpconf0(arg, tcg_env);
294fc2ea 5362 register_name = "MVPConf0";
ead9360e 5363 break;
1b142da5 5364 case CP0_REG00__MVPCONF1:
f31b035a 5365 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5366 gen_helper_mfc0_mvpconf1(arg, tcg_env);
294fc2ea 5367 register_name = "MVPConf1";
ead9360e 5368 break;
1b142da5 5369 case CP0_REG00__VPCONTROL:
01bc435b
YK
5370 CP0_CHECK(ctx->vp);
5371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 5372 register_name = "VPControl";
01bc435b 5373 break;
7a387fff 5374 default:
f31b035a 5375 goto cp0_unimplemented;
7a387fff 5376 }
873eb012 5377 break;
04992c8c 5378 case CP0_REGISTER_01:
7a387fff 5379 switch (sel) {
30deb460 5380 case CP0_REG01__RANDOM:
2e211e0a 5381 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
ad75a51e 5382 gen_helper_mfc0_random(arg, tcg_env);
294fc2ea 5383 register_name = "Random";
2423f660 5384 break;
30deb460 5385 case CP0_REG01__VPECONTROL:
f31b035a 5386 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5387 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 5388 register_name = "VPEControl";
ead9360e 5389 break;
30deb460 5390 case CP0_REG01__VPECONF0:
f31b035a 5391 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 5393 register_name = "VPEConf0";
ead9360e 5394 break;
30deb460 5395 case CP0_REG01__VPECONF1:
f31b035a 5396 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 5398 register_name = "VPEConf1";
ead9360e 5399 break;
30deb460 5400 case CP0_REG01__YQMASK:
f31b035a 5401 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5402 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 5403 register_name = "YQMask";
ead9360e 5404 break;
30deb460 5405 case CP0_REG01__VPESCHEDULE:
f31b035a 5406 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5407 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 5408 register_name = "VPESchedule";
ead9360e 5409 break;
30deb460 5410 case CP0_REG01__VPESCHEFBACK:
f31b035a 5411 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5412 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 5413 register_name = "VPEScheFBack";
ead9360e 5414 break;
30deb460 5415 case CP0_REG01__VPEOPT:
f31b035a 5416 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 5418 register_name = "VPEOpt";
ead9360e 5419 break;
7a387fff 5420 default:
f31b035a 5421 goto cp0_unimplemented;
7a387fff 5422 }
873eb012 5423 break;
04992c8c 5424 case CP0_REGISTER_02:
7a387fff 5425 switch (sel) {
6d27d5bd 5426 case CP0_REG02__ENTRYLO0:
284b731a
LA
5427 {
5428 TCGv_i64 tmp = tcg_temp_new_i64();
ad75a51e 5429 tcg_gen_ld_i64(tmp, tcg_env,
284b731a 5430 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 5431#if defined(TARGET_MIPS64)
284b731a
LA
5432 if (ctx->rxi) {
5433 /* Move RI/XI fields to bits 31:30 */
5434 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5435 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5436 }
7207c7f9 5437#endif
284b731a 5438 gen_move_low32(arg, tmp);
284b731a 5439 }
294fc2ea 5440 register_name = "EntryLo0";
2423f660 5441 break;
6d27d5bd 5442 case CP0_REG02__TCSTATUS:
f31b035a 5443 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5444 gen_helper_mfc0_tcstatus(arg, tcg_env);
294fc2ea 5445 register_name = "TCStatus";
ead9360e 5446 break;
6d27d5bd 5447 case CP0_REG02__TCBIND:
f31b035a 5448 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5449 gen_helper_mfc0_tcbind(arg, tcg_env);
294fc2ea 5450 register_name = "TCBind";
ead9360e 5451 break;
6d27d5bd 5452 case CP0_REG02__TCRESTART:
f31b035a 5453 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5454 gen_helper_mfc0_tcrestart(arg, tcg_env);
294fc2ea 5455 register_name = "TCRestart";
ead9360e 5456 break;
6d27d5bd 5457 case CP0_REG02__TCHALT:
f31b035a 5458 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5459 gen_helper_mfc0_tchalt(arg, tcg_env);
294fc2ea 5460 register_name = "TCHalt";
ead9360e 5461 break;
6d27d5bd 5462 case CP0_REG02__TCCONTEXT:
f31b035a 5463 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5464 gen_helper_mfc0_tccontext(arg, tcg_env);
294fc2ea 5465 register_name = "TCContext";
ead9360e 5466 break;
6d27d5bd 5467 case CP0_REG02__TCSCHEDULE:
f31b035a 5468 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5469 gen_helper_mfc0_tcschedule(arg, tcg_env);
294fc2ea 5470 register_name = "TCSchedule";
ead9360e 5471 break;
6d27d5bd 5472 case CP0_REG02__TCSCHEFBACK:
f31b035a 5473 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 5474 gen_helper_mfc0_tcschefback(arg, tcg_env);
294fc2ea 5475 register_name = "TCScheFBack";
ead9360e 5476 break;
7a387fff 5477 default:
f31b035a 5478 goto cp0_unimplemented;
7a387fff 5479 }
873eb012 5480 break;
04992c8c 5481 case CP0_REGISTER_03:
7a387fff 5482 switch (sel) {
acd37316 5483 case CP0_REG03__ENTRYLO1:
284b731a
LA
5484 {
5485 TCGv_i64 tmp = tcg_temp_new_i64();
ad75a51e 5486 tcg_gen_ld_i64(tmp, tcg_env,
284b731a 5487 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 5488#if defined(TARGET_MIPS64)
284b731a
LA
5489 if (ctx->rxi) {
5490 /* Move RI/XI fields to bits 31:30 */
5491 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5492 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5493 }
7207c7f9 5494#endif
284b731a 5495 gen_move_low32(arg, tmp);
284b731a 5496 }
294fc2ea 5497 register_name = "EntryLo1";
2423f660 5498 break;
acd37316 5499 case CP0_REG03__GLOBALNUM:
01bc435b
YK
5500 CP0_CHECK(ctx->vp);
5501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 5502 register_name = "GlobalNumber";
01bc435b 5503 break;
7a387fff 5504 default:
f31b035a 5505 goto cp0_unimplemented;
1579a72e 5506 }
873eb012 5507 break;
04992c8c 5508 case CP0_REGISTER_04:
7a387fff 5509 switch (sel) {
020fe379 5510 case CP0_REG04__CONTEXT:
ad75a51e 5511 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 5512 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5513 register_name = "Context";
2423f660 5514 break;
020fe379
AM
5515 case CP0_REG04__CONTEXTCONFIG:
5516 /* SmartMIPS ASE */
5517 /* gen_helper_mfc0_contextconfig(arg); */
294fc2ea 5518 register_name = "ContextConfig";
f31b035a 5519 goto cp0_unimplemented;
020fe379 5520 case CP0_REG04__USERLOCAL:
f31b035a 5521 CP0_CHECK(ctx->ulri);
ad75a51e 5522 tcg_gen_ld_tl(arg, tcg_env,
e40df9a8
JH
5523 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5524 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5525 register_name = "UserLocal";
d279279e 5526 break;
99029be1
YK
5527 case CP0_REG04__MMID:
5528 CP0_CHECK(ctx->mi);
ad75a51e 5529 gen_helper_mtc0_memorymapid(tcg_env, arg);
99029be1
YK
5530 register_name = "MMID";
5531 break;
7a387fff 5532 default:
f31b035a 5533 goto cp0_unimplemented;
1579a72e 5534 }
873eb012 5535 break;
04992c8c 5536 case CP0_REGISTER_05:
7a387fff 5537 switch (sel) {
a1e76353 5538 case CP0_REG05__PAGEMASK:
7db13fae 5539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 5540 register_name = "PageMask";
2423f660 5541 break;
a1e76353 5542 case CP0_REG05__PAGEGRAIN:
7a47bae5 5543 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 5545 register_name = "PageGrain";
2423f660 5546 break;
a1e76353 5547 case CP0_REG05__SEGCTL0:
cec56a73 5548 CP0_CHECK(ctx->sc);
ad75a51e 5549 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
cec56a73 5550 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5551 register_name = "SegCtl0";
cec56a73 5552 break;
a1e76353 5553 case CP0_REG05__SEGCTL1:
cec56a73 5554 CP0_CHECK(ctx->sc);
ad75a51e 5555 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
cec56a73 5556 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5557 register_name = "SegCtl1";
cec56a73 5558 break;
a1e76353 5559 case CP0_REG05__SEGCTL2:
cec56a73 5560 CP0_CHECK(ctx->sc);
ad75a51e 5561 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
cec56a73 5562 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5563 register_name = "SegCtl2";
cec56a73 5564 break;
a1e76353 5565 case CP0_REG05__PWBASE:
5e31fdd5
YK
5566 check_pw(ctx);
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 5568 register_name = "PWBase";
5e31fdd5 5569 break;
a1e76353 5570 case CP0_REG05__PWFIELD:
fa75ad14
YK
5571 check_pw(ctx);
5572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 5573 register_name = "PWField";
fa75ad14 5574 break;
a1e76353 5575 case CP0_REG05__PWSIZE:
20b28ebc
YK
5576 check_pw(ctx);
5577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 5578 register_name = "PWSize";
20b28ebc 5579 break;
7a387fff 5580 default:
f31b035a 5581 goto cp0_unimplemented;
1579a72e 5582 }
873eb012 5583 break;
04992c8c 5584 case CP0_REGISTER_06:
7a387fff 5585 switch (sel) {
9023594b 5586 case CP0_REG06__WIRED:
7db13fae 5587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 5588 register_name = "Wired";
2423f660 5589 break;
9023594b 5590 case CP0_REG06__SRSCONF0:
7a47bae5 5591 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 5593 register_name = "SRSConf0";
ead9360e 5594 break;
9023594b 5595 case CP0_REG06__SRSCONF1:
7a47bae5 5596 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 5598 register_name = "SRSConf1";
ead9360e 5599 break;
9023594b 5600 case CP0_REG06__SRSCONF2:
7a47bae5 5601 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 5603 register_name = "SRSConf2";
ead9360e 5604 break;
9023594b 5605 case CP0_REG06__SRSCONF3:
7a47bae5 5606 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 5608 register_name = "SRSConf3";
ead9360e 5609 break;
9023594b 5610 case CP0_REG06__SRSCONF4:
7a47bae5 5611 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5612 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 5613 register_name = "SRSConf4";
ead9360e 5614 break;
9023594b 5615 case CP0_REG06__PWCTL:
103be64c
YK
5616 check_pw(ctx);
5617 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 5618 register_name = "PWCtl";
103be64c 5619 break;
7a387fff 5620 default:
f31b035a 5621 goto cp0_unimplemented;
1579a72e 5622 }
873eb012 5623 break;
04992c8c 5624 case CP0_REGISTER_07:
7a387fff 5625 switch (sel) {
143a9875 5626 case CP0_REG07__HWRENA:
7a47bae5 5627 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 5629 register_name = "HWREna";
2423f660 5630 break;
7a387fff 5631 default:
f31b035a 5632 goto cp0_unimplemented;
1579a72e 5633 }
8c0fdd85 5634 break;
04992c8c 5635 case CP0_REGISTER_08:
7a387fff 5636 switch (sel) {
67d167d2 5637 case CP0_REG08__BADVADDR:
ad75a51e 5638 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 5639 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5640 register_name = "BadVAddr";
2423f660 5641 break;
67d167d2 5642 case CP0_REG08__BADINSTR:
f31b035a
LA
5643 CP0_CHECK(ctx->bi);
5644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 5645 register_name = "BadInstr";
aea14095 5646 break;
67d167d2 5647 case CP0_REG08__BADINSTRP:
f31b035a
LA
5648 CP0_CHECK(ctx->bp);
5649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 5650 register_name = "BadInstrP";
aea14095 5651 break;
67d167d2 5652 case CP0_REG08__BADINSTRX:
25beba9b
SM
5653 CP0_CHECK(ctx->bi);
5654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5655 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 5656 register_name = "BadInstrX";
25beba9b 5657 break;
05aa7e93 5658 default:
f31b035a 5659 goto cp0_unimplemented;
aea14095 5660 }
873eb012 5661 break;
04992c8c 5662 case CP0_REGISTER_09:
7a387fff 5663 switch (sel) {
e5a98a72 5664 case CP0_REG09__COUNT:
2e70f6ef 5665 /* Mark as an IO operation because we read the time. */
dfd1b812
RH
5666 translator_io_start(&ctx->base);
5667
ad75a51e 5668 gen_helper_mfc0_count(arg, tcg_env);
7480515f
AM
5669 /*
5670 * Break the TB to be able to take timer interrupts immediately
5671 * after reading count. DISAS_STOP isn't sufficient, we need to
5672 * ensure we break completely out of translated code.
5673 */
eeb3bba8
EC
5674 gen_save_pc(ctx->base.pc_next + 4);
5675 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 5676 register_name = "Count";
2423f660 5677 break;
e5a98a72 5678 case CP0_REG09__SAARI:
5fb2dcd1
YK
5679 CP0_CHECK(ctx->saar);
5680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 5681 register_name = "SAARI";
5fb2dcd1 5682 break;
e5a98a72 5683 case CP0_REG09__SAAR:
5fb2dcd1 5684 CP0_CHECK(ctx->saar);
ad75a51e 5685 gen_helper_mfc0_saar(arg, tcg_env);
294fc2ea 5686 register_name = "SAAR";
5fb2dcd1 5687 break;
7a387fff 5688 default:
f31b035a 5689 goto cp0_unimplemented;
2423f660 5690 }
873eb012 5691 break;
04992c8c 5692 case CP0_REGISTER_10:
7a387fff 5693 switch (sel) {
860ffef0 5694 case CP0_REG10__ENTRYHI:
ad75a51e 5695 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 5696 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5697 register_name = "EntryHi";
2423f660 5698 break;
7a387fff 5699 default:
f31b035a 5700 goto cp0_unimplemented;
1579a72e 5701 }
873eb012 5702 break;
04992c8c 5703 case CP0_REGISTER_11:
7a387fff 5704 switch (sel) {
f5f3834f 5705 case CP0_REG11__COMPARE:
7db13fae 5706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 5707 register_name = "Compare";
2423f660
TS
5708 break;
5709 /* 6,7 are implementation dependent */
7a387fff 5710 default:
f31b035a 5711 goto cp0_unimplemented;
2423f660 5712 }
873eb012 5713 break;
04992c8c 5714 case CP0_REGISTER_12:
7a387fff 5715 switch (sel) {
2b084867 5716 case CP0_REG12__STATUS:
7db13fae 5717 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 5718 register_name = "Status";
2423f660 5719 break;
2b084867 5720 case CP0_REG12__INTCTL:
7a47bae5 5721 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 5723 register_name = "IntCtl";
2423f660 5724 break;
2b084867 5725 case CP0_REG12__SRSCTL:
7a47bae5 5726 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 5728 register_name = "SRSCtl";
2423f660 5729 break;
2b084867 5730 case CP0_REG12__SRSMAP:
7a47bae5 5731 check_insn(ctx, ISA_MIPS_R2);
7db13fae 5732 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 5733 register_name = "SRSMap";
fd88b6ab 5734 break;
7a387fff 5735 default:
f31b035a 5736 goto cp0_unimplemented;
7a387fff 5737 }
873eb012 5738 break;
04992c8c 5739 case CP0_REGISTER_13:
7a387fff 5740 switch (sel) {
e3c7559d 5741 case CP0_REG13__CAUSE:
7db13fae 5742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 5743 register_name = "Cause";
2423f660 5744 break;
7a387fff 5745 default:
f31b035a 5746 goto cp0_unimplemented;
7a387fff 5747 }
873eb012 5748 break;
04992c8c 5749 case CP0_REGISTER_14:
7a387fff 5750 switch (sel) {
35e4b54d 5751 case CP0_REG14__EPC:
ad75a51e 5752 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 5753 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5754 register_name = "EPC";
2423f660 5755 break;
7a387fff 5756 default:
f31b035a 5757 goto cp0_unimplemented;
1579a72e 5758 }
873eb012 5759 break;
04992c8c 5760 case CP0_REGISTER_15:
7a387fff 5761 switch (sel) {
4466cd49 5762 case CP0_REG15__PRID:
7db13fae 5763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 5764 register_name = "PRid";
2423f660 5765 break;
4466cd49 5766 case CP0_REG15__EBASE:
7a47bae5 5767 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 5768 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
74dbf824 5769 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5770 register_name = "EBase";
2423f660 5771 break;
4466cd49 5772 case CP0_REG15__CMGCRBASE:
7a47bae5 5773 check_insn(ctx, ISA_MIPS_R2);
c870e3f5 5774 CP0_CHECK(ctx->cmgcr);
ad75a51e 5775 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
c870e3f5 5776 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5777 register_name = "CMGCRBase";
c870e3f5 5778 break;
7a387fff 5779 default:
f31b035a 5780 goto cp0_unimplemented;
7a387fff 5781 }
873eb012 5782 break;
04992c8c 5783 case CP0_REGISTER_16:
873eb012 5784 switch (sel) {
433efb4c 5785 case CP0_REG16__CONFIG:
7db13fae 5786 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 5787 register_name = "Config";
873eb012 5788 break;
433efb4c 5789 case CP0_REG16__CONFIG1:
7db13fae 5790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 5791 register_name = "Config1";
873eb012 5792 break;
433efb4c 5793 case CP0_REG16__CONFIG2:
7db13fae 5794 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 5795 register_name = "Config2";
7a387fff 5796 break;
433efb4c 5797 case CP0_REG16__CONFIG3:
7db13fae 5798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 5799 register_name = "Config3";
7a387fff 5800 break;
433efb4c 5801 case CP0_REG16__CONFIG4:
b4160af1 5802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 5803 register_name = "Config4";
b4160af1 5804 break;
433efb4c 5805 case CP0_REG16__CONFIG5:
b4dd99a3 5806 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 5807 register_name = "Config5";
b4dd99a3 5808 break;
e397ee33 5809 /* 6,7 are implementation dependent */
433efb4c 5810 case CP0_REG16__CONFIG6:
7db13fae 5811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 5812 register_name = "Config6";
e397ee33 5813 break;
433efb4c 5814 case CP0_REG16__CONFIG7:
7db13fae 5815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 5816 register_name = "Config7";
e397ee33 5817 break;
873eb012 5818 default:
f31b035a 5819 goto cp0_unimplemented;
873eb012
TS
5820 }
5821 break;
04992c8c 5822 case CP0_REGISTER_17:
7a387fff 5823 switch (sel) {
706ce142 5824 case CP0_REG17__LLADDR:
ad75a51e 5825 gen_helper_mfc0_lladdr(arg, tcg_env);
294fc2ea 5826 register_name = "LLAddr";
2423f660 5827 break;
706ce142 5828 case CP0_REG17__MAAR:
f6d4dd81 5829 CP0_CHECK(ctx->mrp);
ad75a51e 5830 gen_helper_mfc0_maar(arg, tcg_env);
294fc2ea 5831 register_name = "MAAR";
f6d4dd81 5832 break;
706ce142 5833 case CP0_REG17__MAARI:
f6d4dd81
YK
5834 CP0_CHECK(ctx->mrp);
5835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 5836 register_name = "MAARI";
f6d4dd81 5837 break;
7a387fff 5838 default:
f31b035a 5839 goto cp0_unimplemented;
7a387fff 5840 }
873eb012 5841 break;
04992c8c 5842 case CP0_REGISTER_18:
7a387fff 5843 switch (sel) {
e8dcfe82
AM
5844 case CP0_REG18__WATCHLO0:
5845 case CP0_REG18__WATCHLO1:
5846 case CP0_REG18__WATCHLO2:
5847 case CP0_REG18__WATCHLO3:
5848 case CP0_REG18__WATCHLO4:
5849 case CP0_REG18__WATCHLO5:
5850 case CP0_REG18__WATCHLO6:
5851 case CP0_REG18__WATCHLO7:
fa192d49 5852 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 5853 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 5854 register_name = "WatchLo";
2423f660 5855 break;
7a387fff 5856 default:
f31b035a 5857 goto cp0_unimplemented;
7a387fff 5858 }
873eb012 5859 break;
04992c8c 5860 case CP0_REGISTER_19:
7a387fff 5861 switch (sel) {
be274dc1
AM
5862 case CP0_REG19__WATCHHI0:
5863 case CP0_REG19__WATCHHI1:
5864 case CP0_REG19__WATCHHI2:
5865 case CP0_REG19__WATCHHI3:
5866 case CP0_REG19__WATCHHI4:
5867 case CP0_REG19__WATCHHI5:
5868 case CP0_REG19__WATCHHI6:
5869 case CP0_REG19__WATCHHI7:
fa192d49 5870 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 5871 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 5872 register_name = "WatchHi";
2423f660 5873 break;
7a387fff 5874 default:
f31b035a 5875 goto cp0_unimplemented;
7a387fff 5876 }
873eb012 5877 break;
04992c8c 5878 case CP0_REGISTER_20:
7a387fff 5879 switch (sel) {
14f92b0b 5880 case CP0_REG20__XCONTEXT:
d26bc211 5881#if defined(TARGET_MIPS64)
d75c135e 5882 check_insn(ctx, ISA_MIPS3);
ad75a51e 5883 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 5884 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5885 register_name = "XContext";
2423f660 5886 break;
703eaf37 5887#endif
7a387fff 5888 default:
f31b035a 5889 goto cp0_unimplemented;
7a387fff 5890 }
8c0fdd85 5891 break;
04992c8c 5892 case CP0_REGISTER_21:
7a387fff 5893 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 5894 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
5895 switch (sel) {
5896 case 0:
7db13fae 5897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 5898 register_name = "Framemask";
2423f660 5899 break;
7a387fff 5900 default:
f31b035a 5901 goto cp0_unimplemented;
7a387fff 5902 }
8c0fdd85 5903 break;
04992c8c 5904 case CP0_REGISTER_22:
d9bea114 5905 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 5906 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 5907 break;
04992c8c 5908 case CP0_REGISTER_23:
7a387fff 5909 switch (sel) {
4cbf4b6d 5910 case CP0_REG23__DEBUG:
ad75a51e 5911 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
294fc2ea 5912 register_name = "Debug";
2423f660 5913 break;
4cbf4b6d
AM
5914 case CP0_REG23__TRACECONTROL:
5915 /* PDtrace support */
5916 /* gen_helper_mfc0_tracecontrol(arg); */
294fc2ea 5917 register_name = "TraceControl";
3570d7f6 5918 goto cp0_unimplemented;
4cbf4b6d
AM
5919 case CP0_REG23__TRACECONTROL2:
5920 /* PDtrace support */
5921 /* gen_helper_mfc0_tracecontrol2(arg); */
294fc2ea 5922 register_name = "TraceControl2";
3570d7f6 5923 goto cp0_unimplemented;
4cbf4b6d
AM
5924 case CP0_REG23__USERTRACEDATA1:
5925 /* PDtrace support */
5926 /* gen_helper_mfc0_usertracedata1(arg);*/
5927 register_name = "UserTraceData1";
3570d7f6 5928 goto cp0_unimplemented;
4cbf4b6d
AM
5929 case CP0_REG23__TRACEIBPC:
5930 /* PDtrace support */
5931 /* gen_helper_mfc0_traceibpc(arg); */
5932 register_name = "TraceIBPC";
5933 goto cp0_unimplemented;
5934 case CP0_REG23__TRACEDBPC:
5935 /* PDtrace support */
5936 /* gen_helper_mfc0_tracedbpc(arg); */
5937 register_name = "TraceDBPC";
3570d7f6 5938 goto cp0_unimplemented;
7a387fff 5939 default:
f31b035a 5940 goto cp0_unimplemented;
7a387fff 5941 }
873eb012 5942 break;
04992c8c 5943 case CP0_REGISTER_24:
7a387fff 5944 switch (sel) {
8d7b4b6e 5945 case CP0_REG24__DEPC:
f0b3f3ae 5946 /* EJTAG support */
ad75a51e 5947 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 5948 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 5949 register_name = "DEPC";
2423f660 5950 break;
7a387fff 5951 default:
f31b035a 5952 goto cp0_unimplemented;
7a387fff 5953 }
873eb012 5954 break;
04992c8c 5955 case CP0_REGISTER_25:
7a387fff 5956 switch (sel) {
1176b328 5957 case CP0_REG25__PERFCTL0:
7db13fae 5958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 5959 register_name = "Performance0";
7a387fff 5960 break;
1176b328 5961 case CP0_REG25__PERFCNT0:
7480515f 5962 /* gen_helper_mfc0_performance1(arg); */
294fc2ea 5963 register_name = "Performance1";
3570d7f6 5964 goto cp0_unimplemented;
1176b328 5965 case CP0_REG25__PERFCTL1:
7480515f 5966 /* gen_helper_mfc0_performance2(arg); */
294fc2ea 5967 register_name = "Performance2";
3570d7f6 5968 goto cp0_unimplemented;
1176b328 5969 case CP0_REG25__PERFCNT1:
7480515f 5970 /* gen_helper_mfc0_performance3(arg); */
294fc2ea 5971 register_name = "Performance3";
3570d7f6 5972 goto cp0_unimplemented;
1176b328 5973 case CP0_REG25__PERFCTL2:
7480515f 5974 /* gen_helper_mfc0_performance4(arg); */
294fc2ea 5975 register_name = "Performance4";
3570d7f6 5976 goto cp0_unimplemented;
1176b328 5977 case CP0_REG25__PERFCNT2:
7480515f 5978 /* gen_helper_mfc0_performance5(arg); */
294fc2ea 5979 register_name = "Performance5";
3570d7f6 5980 goto cp0_unimplemented;
1176b328 5981 case CP0_REG25__PERFCTL3:
7480515f 5982 /* gen_helper_mfc0_performance6(arg); */
294fc2ea 5983 register_name = "Performance6";
3570d7f6 5984 goto cp0_unimplemented;
1176b328 5985 case CP0_REG25__PERFCNT3:
7480515f 5986 /* gen_helper_mfc0_performance7(arg); */
294fc2ea 5987 register_name = "Performance7";
3570d7f6 5988 goto cp0_unimplemented;
7a387fff 5989 default:
f31b035a 5990 goto cp0_unimplemented;
7a387fff 5991 }
8c0fdd85 5992 break;
04992c8c 5993 case CP0_REGISTER_26:
0d74a222 5994 switch (sel) {
dbbf08b2 5995 case CP0_REG26__ERRCTL:
0d74a222 5996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 5997 register_name = "ErrCtl";
0d74a222
LA
5998 break;
5999 default:
6000 goto cp0_unimplemented;
6001 }
da80682b 6002 break;
04992c8c 6003 case CP0_REGISTER_27:
7a387fff 6004 switch (sel) {
5a10873d 6005 case CP0_REG27__CACHERR:
d9bea114 6006 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 6007 register_name = "CacheErr";
2423f660 6008 break;
7a387fff 6009 default:
f31b035a 6010 goto cp0_unimplemented;
7a387fff 6011 }
8c0fdd85 6012 break;
04992c8c 6013 case CP0_REGISTER_28:
873eb012 6014 switch (sel) {
a30e2f21
AM
6015 case CP0_REG28__TAGLO:
6016 case CP0_REG28__TAGLO1:
6017 case CP0_REG28__TAGLO2:
6018 case CP0_REG28__TAGLO3:
284b731a
LA
6019 {
6020 TCGv_i64 tmp = tcg_temp_new_i64();
ad75a51e 6021 tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUMIPSState, CP0_TagLo));
284b731a 6022 gen_move_low32(arg, tmp);
284b731a 6023 }
294fc2ea 6024 register_name = "TagLo";
873eb012 6025 break;
a30e2f21
AM
6026 case CP0_REG28__DATALO:
6027 case CP0_REG28__DATALO1:
6028 case CP0_REG28__DATALO2:
6029 case CP0_REG28__DATALO3:
7db13fae 6030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 6031 register_name = "DataLo";
873eb012
TS
6032 break;
6033 default:
f31b035a 6034 goto cp0_unimplemented;
873eb012
TS
6035 }
6036 break;
04992c8c 6037 case CP0_REGISTER_29:
7a387fff 6038 switch (sel) {
af4bb6da
AM
6039 case CP0_REG29__TAGHI:
6040 case CP0_REG29__TAGHI1:
6041 case CP0_REG29__TAGHI2:
6042 case CP0_REG29__TAGHI3:
7db13fae 6043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 6044 register_name = "TagHi";
7a387fff 6045 break;
af4bb6da
AM
6046 case CP0_REG29__DATAHI:
6047 case CP0_REG29__DATAHI1:
6048 case CP0_REG29__DATAHI2:
6049 case CP0_REG29__DATAHI3:
7db13fae 6050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 6051 register_name = "DataHi";
7a387fff
TS
6052 break;
6053 default:
f31b035a 6054 goto cp0_unimplemented;
7a387fff 6055 }
8c0fdd85 6056 break;
04992c8c 6057 case CP0_REGISTER_30:
7a387fff 6058 switch (sel) {
4bcf121e 6059 case CP0_REG30__ERROREPC:
ad75a51e 6060 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 6061 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6062 register_name = "ErrorEPC";
2423f660 6063 break;
7a387fff 6064 default:
f31b035a 6065 goto cp0_unimplemented;
7a387fff 6066 }
873eb012 6067 break;
04992c8c 6068 case CP0_REGISTER_31:
7a387fff 6069 switch (sel) {
14d92efd 6070 case CP0_REG31__DESAVE:
f0b3f3ae 6071 /* EJTAG support */
7db13fae 6072 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 6073 register_name = "DESAVE";
2423f660 6074 break;
14d92efd
AM
6075 case CP0_REG31__KSCRATCH1:
6076 case CP0_REG31__KSCRATCH2:
6077 case CP0_REG31__KSCRATCH3:
6078 case CP0_REG31__KSCRATCH4:
6079 case CP0_REG31__KSCRATCH5:
6080 case CP0_REG31__KSCRATCH6:
f31b035a 6081 CP0_CHECK(ctx->kscrexist & (1 << sel));
ad75a51e 6082 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 6083 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
f31b035a 6084 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6085 register_name = "KScratch";
e98c0d17 6086 break;
7a387fff 6087 default:
f31b035a 6088 goto cp0_unimplemented;
7a387fff 6089 }
873eb012
TS
6090 break;
6091 default:
f31b035a 6092 goto cp0_unimplemented;
873eb012 6093 }
294fc2ea 6094 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
6095 return;
6096
f31b035a 6097cp0_unimplemented:
294fc2ea
AM
6098 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6099 register_name, reg, sel);
f31b035a 6100 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
6101}
6102
d75c135e 6103static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 6104{
294fc2ea 6105 const char *register_name = "invalid";
dfd1b812 6106 bool icount;
7a387fff 6107
1f8929d2 6108 if (sel != 0) {
bbd5e4a2 6109 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 6110 }
e189e748 6111
dfd1b812 6112 icount = translator_io_start(&ctx->base);
2e70f6ef 6113
8c0fdd85 6114 switch (reg) {
04992c8c 6115 case CP0_REGISTER_00:
7a387fff 6116 switch (sel) {
1b142da5 6117 case CP0_REG00__INDEX:
ad75a51e 6118 gen_helper_mtc0_index(tcg_env, arg);
294fc2ea 6119 register_name = "Index";
7a387fff 6120 break;
1b142da5 6121 case CP0_REG00__MVPCONTROL:
f31b035a 6122 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6123 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
294fc2ea 6124 register_name = "MVPControl";
ead9360e 6125 break;
1b142da5 6126 case CP0_REG00__MVPCONF0:
f31b035a 6127 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6128 /* ignored */
294fc2ea 6129 register_name = "MVPConf0";
ead9360e 6130 break;
1b142da5 6131 case CP0_REG00__MVPCONF1:
f31b035a 6132 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6133 /* ignored */
294fc2ea 6134 register_name = "MVPConf1";
ead9360e 6135 break;
1b142da5 6136 case CP0_REG00__VPCONTROL:
01bc435b
YK
6137 CP0_CHECK(ctx->vp);
6138 /* ignored */
294fc2ea 6139 register_name = "VPControl";
01bc435b 6140 break;
7a387fff 6141 default:
f31b035a 6142 goto cp0_unimplemented;
7a387fff 6143 }
8c0fdd85 6144 break;
04992c8c 6145 case CP0_REGISTER_01:
7a387fff 6146 switch (sel) {
30deb460 6147 case CP0_REG01__RANDOM:
2423f660 6148 /* ignored */
294fc2ea 6149 register_name = "Random";
2423f660 6150 break;
30deb460 6151 case CP0_REG01__VPECONTROL:
f31b035a 6152 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6153 gen_helper_mtc0_vpecontrol(tcg_env, arg);
294fc2ea 6154 register_name = "VPEControl";
ead9360e 6155 break;
30deb460 6156 case CP0_REG01__VPECONF0:
f31b035a 6157 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6158 gen_helper_mtc0_vpeconf0(tcg_env, arg);
294fc2ea 6159 register_name = "VPEConf0";
ead9360e 6160 break;
30deb460 6161 case CP0_REG01__VPECONF1:
f31b035a 6162 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6163 gen_helper_mtc0_vpeconf1(tcg_env, arg);
294fc2ea 6164 register_name = "VPEConf1";
ead9360e 6165 break;
30deb460 6166 case CP0_REG01__YQMASK:
f31b035a 6167 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6168 gen_helper_mtc0_yqmask(tcg_env, arg);
294fc2ea 6169 register_name = "YQMask";
ead9360e 6170 break;
30deb460 6171 case CP0_REG01__VPESCHEDULE:
f31b035a 6172 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6173 tcg_gen_st_tl(arg, tcg_env,
d54a299b 6174 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6175 register_name = "VPESchedule";
ead9360e 6176 break;
30deb460 6177 case CP0_REG01__VPESCHEFBACK:
f31b035a 6178 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6179 tcg_gen_st_tl(arg, tcg_env,
d54a299b 6180 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6181 register_name = "VPEScheFBack";
ead9360e 6182 break;
30deb460 6183 case CP0_REG01__VPEOPT:
f31b035a 6184 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6185 gen_helper_mtc0_vpeopt(tcg_env, arg);
294fc2ea 6186 register_name = "VPEOpt";
ead9360e 6187 break;
7a387fff 6188 default:
f31b035a 6189 goto cp0_unimplemented;
7a387fff 6190 }
8c0fdd85 6191 break;
04992c8c 6192 case CP0_REGISTER_02:
7a387fff 6193 switch (sel) {
6d27d5bd 6194 case CP0_REG02__ENTRYLO0:
ad75a51e 6195 gen_helper_mtc0_entrylo0(tcg_env, arg);
294fc2ea 6196 register_name = "EntryLo0";
2423f660 6197 break;
6d27d5bd 6198 case CP0_REG02__TCSTATUS:
f31b035a 6199 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6200 gen_helper_mtc0_tcstatus(tcg_env, arg);
294fc2ea 6201 register_name = "TCStatus";
ead9360e 6202 break;
6d27d5bd 6203 case CP0_REG02__TCBIND:
f31b035a 6204 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6205 gen_helper_mtc0_tcbind(tcg_env, arg);
294fc2ea 6206 register_name = "TCBind";
ead9360e 6207 break;
6d27d5bd 6208 case CP0_REG02__TCRESTART:
f31b035a 6209 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6210 gen_helper_mtc0_tcrestart(tcg_env, arg);
294fc2ea 6211 register_name = "TCRestart";
ead9360e 6212 break;
6d27d5bd 6213 case CP0_REG02__TCHALT:
f31b035a 6214 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6215 gen_helper_mtc0_tchalt(tcg_env, arg);
294fc2ea 6216 register_name = "TCHalt";
ead9360e 6217 break;
6d27d5bd 6218 case CP0_REG02__TCCONTEXT:
f31b035a 6219 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6220 gen_helper_mtc0_tccontext(tcg_env, arg);
294fc2ea 6221 register_name = "TCContext";
ead9360e 6222 break;
6d27d5bd 6223 case CP0_REG02__TCSCHEDULE:
f31b035a 6224 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6225 gen_helper_mtc0_tcschedule(tcg_env, arg);
294fc2ea 6226 register_name = "TCSchedule";
ead9360e 6227 break;
6d27d5bd 6228 case CP0_REG02__TCSCHEFBACK:
f31b035a 6229 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6230 gen_helper_mtc0_tcschefback(tcg_env, arg);
294fc2ea 6231 register_name = "TCScheFBack";
ead9360e 6232 break;
7a387fff 6233 default:
f31b035a 6234 goto cp0_unimplemented;
7a387fff 6235 }
8c0fdd85 6236 break;
04992c8c 6237 case CP0_REGISTER_03:
7a387fff 6238 switch (sel) {
acd37316 6239 case CP0_REG03__ENTRYLO1:
ad75a51e 6240 gen_helper_mtc0_entrylo1(tcg_env, arg);
294fc2ea 6241 register_name = "EntryLo1";
2423f660 6242 break;
acd37316 6243 case CP0_REG03__GLOBALNUM:
01bc435b
YK
6244 CP0_CHECK(ctx->vp);
6245 /* ignored */
294fc2ea 6246 register_name = "GlobalNumber";
01bc435b 6247 break;
7a387fff 6248 default:
f31b035a 6249 goto cp0_unimplemented;
876d4b07 6250 }
8c0fdd85 6251 break;
04992c8c 6252 case CP0_REGISTER_04:
7a387fff 6253 switch (sel) {
020fe379 6254 case CP0_REG04__CONTEXT:
ad75a51e 6255 gen_helper_mtc0_context(tcg_env, arg);
294fc2ea 6256 register_name = "Context";
2423f660 6257 break;
020fe379
AM
6258 case CP0_REG04__CONTEXTCONFIG:
6259 /* SmartMIPS ASE */
6260 /* gen_helper_mtc0_contextconfig(arg); */
294fc2ea 6261 register_name = "ContextConfig";
f31b035a 6262 goto cp0_unimplemented;
020fe379 6263 case CP0_REG04__USERLOCAL:
f31b035a 6264 CP0_CHECK(ctx->ulri);
ad75a51e 6265 tcg_gen_st_tl(arg, tcg_env,
f31b035a 6266 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 6267 register_name = "UserLocal";
d279279e 6268 break;
99029be1
YK
6269 case CP0_REG04__MMID:
6270 CP0_CHECK(ctx->mi);
6271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6272 register_name = "MMID";
6273 break;
7a387fff 6274 default:
f31b035a 6275 goto cp0_unimplemented;
876d4b07 6276 }
8c0fdd85 6277 break;
04992c8c 6278 case CP0_REGISTER_05:
7a387fff 6279 switch (sel) {
a1e76353 6280 case CP0_REG05__PAGEMASK:
ad75a51e 6281 gen_helper_mtc0_pagemask(tcg_env, arg);
294fc2ea 6282 register_name = "PageMask";
2423f660 6283 break;
a1e76353 6284 case CP0_REG05__PAGEGRAIN:
7a47bae5 6285 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6286 gen_helper_mtc0_pagegrain(tcg_env, arg);
294fc2ea 6287 register_name = "PageGrain";
eeb3bba8 6288 ctx->base.is_jmp = DISAS_STOP;
2423f660 6289 break;
a1e76353 6290 case CP0_REG05__SEGCTL0:
cec56a73 6291 CP0_CHECK(ctx->sc);
ad75a51e 6292 gen_helper_mtc0_segctl0(tcg_env, arg);
294fc2ea 6293 register_name = "SegCtl0";
cec56a73 6294 break;
a1e76353 6295 case CP0_REG05__SEGCTL1:
cec56a73 6296 CP0_CHECK(ctx->sc);
ad75a51e 6297 gen_helper_mtc0_segctl1(tcg_env, arg);
294fc2ea 6298 register_name = "SegCtl1";
cec56a73 6299 break;
a1e76353 6300 case CP0_REG05__SEGCTL2:
cec56a73 6301 CP0_CHECK(ctx->sc);
ad75a51e 6302 gen_helper_mtc0_segctl2(tcg_env, arg);
294fc2ea 6303 register_name = "SegCtl2";
cec56a73 6304 break;
a1e76353 6305 case CP0_REG05__PWBASE:
5e31fdd5
YK
6306 check_pw(ctx);
6307 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6308 register_name = "PWBase";
5e31fdd5 6309 break;
a1e76353 6310 case CP0_REG05__PWFIELD:
fa75ad14 6311 check_pw(ctx);
ad75a51e 6312 gen_helper_mtc0_pwfield(tcg_env, arg);
294fc2ea 6313 register_name = "PWField";
fa75ad14 6314 break;
a1e76353 6315 case CP0_REG05__PWSIZE:
20b28ebc 6316 check_pw(ctx);
ad75a51e 6317 gen_helper_mtc0_pwsize(tcg_env, arg);
294fc2ea 6318 register_name = "PWSize";
20b28ebc 6319 break;
7a387fff 6320 default:
f31b035a 6321 goto cp0_unimplemented;
876d4b07 6322 }
8c0fdd85 6323 break;
04992c8c 6324 case CP0_REGISTER_06:
7a387fff 6325 switch (sel) {
9023594b 6326 case CP0_REG06__WIRED:
ad75a51e 6327 gen_helper_mtc0_wired(tcg_env, arg);
294fc2ea 6328 register_name = "Wired";
2423f660 6329 break;
9023594b 6330 case CP0_REG06__SRSCONF0:
7a47bae5 6331 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6332 gen_helper_mtc0_srsconf0(tcg_env, arg);
294fc2ea 6333 register_name = "SRSConf0";
ead9360e 6334 break;
9023594b 6335 case CP0_REG06__SRSCONF1:
7a47bae5 6336 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6337 gen_helper_mtc0_srsconf1(tcg_env, arg);
294fc2ea 6338 register_name = "SRSConf1";
ead9360e 6339 break;
9023594b 6340 case CP0_REG06__SRSCONF2:
7a47bae5 6341 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6342 gen_helper_mtc0_srsconf2(tcg_env, arg);
294fc2ea 6343 register_name = "SRSConf2";
ead9360e 6344 break;
9023594b 6345 case CP0_REG06__SRSCONF3:
7a47bae5 6346 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6347 gen_helper_mtc0_srsconf3(tcg_env, arg);
294fc2ea 6348 register_name = "SRSConf3";
ead9360e 6349 break;
9023594b 6350 case CP0_REG06__SRSCONF4:
7a47bae5 6351 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6352 gen_helper_mtc0_srsconf4(tcg_env, arg);
294fc2ea 6353 register_name = "SRSConf4";
ead9360e 6354 break;
9023594b 6355 case CP0_REG06__PWCTL:
103be64c 6356 check_pw(ctx);
ad75a51e 6357 gen_helper_mtc0_pwctl(tcg_env, arg);
294fc2ea 6358 register_name = "PWCtl";
103be64c 6359 break;
7a387fff 6360 default:
f31b035a 6361 goto cp0_unimplemented;
876d4b07 6362 }
8c0fdd85 6363 break;
04992c8c 6364 case CP0_REGISTER_07:
7a387fff 6365 switch (sel) {
143a9875 6366 case CP0_REG07__HWRENA:
7a47bae5 6367 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6368 gen_helper_mtc0_hwrena(tcg_env, arg);
eeb3bba8 6369 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 6370 register_name = "HWREna";
2423f660 6371 break;
7a387fff 6372 default:
f31b035a 6373 goto cp0_unimplemented;
876d4b07 6374 }
8c0fdd85 6375 break;
04992c8c 6376 case CP0_REGISTER_08:
aea14095 6377 switch (sel) {
67d167d2 6378 case CP0_REG08__BADVADDR:
aea14095 6379 /* ignored */
294fc2ea 6380 register_name = "BadVAddr";
aea14095 6381 break;
67d167d2 6382 case CP0_REG08__BADINSTR:
aea14095 6383 /* ignored */
294fc2ea 6384 register_name = "BadInstr";
aea14095 6385 break;
67d167d2 6386 case CP0_REG08__BADINSTRP:
aea14095 6387 /* ignored */
294fc2ea 6388 register_name = "BadInstrP";
aea14095 6389 break;
67d167d2 6390 case CP0_REG08__BADINSTRX:
25beba9b 6391 /* ignored */
294fc2ea 6392 register_name = "BadInstrX";
25beba9b 6393 break;
aea14095 6394 default:
f31b035a 6395 goto cp0_unimplemented;
aea14095 6396 }
8c0fdd85 6397 break;
04992c8c 6398 case CP0_REGISTER_09:
7a387fff 6399 switch (sel) {
e5a98a72 6400 case CP0_REG09__COUNT:
ad75a51e 6401 gen_helper_mtc0_count(tcg_env, arg);
294fc2ea 6402 register_name = "Count";
2423f660 6403 break;
e5a98a72 6404 case CP0_REG09__SAARI:
5fb2dcd1 6405 CP0_CHECK(ctx->saar);
ad75a51e 6406 gen_helper_mtc0_saari(tcg_env, arg);
294fc2ea 6407 register_name = "SAARI";
5fb2dcd1 6408 break;
e5a98a72 6409 case CP0_REG09__SAAR:
5fb2dcd1 6410 CP0_CHECK(ctx->saar);
ad75a51e 6411 gen_helper_mtc0_saar(tcg_env, arg);
294fc2ea 6412 register_name = "SAAR";
5fb2dcd1 6413 break;
7a387fff 6414 default:
f31b035a 6415 goto cp0_unimplemented;
876d4b07 6416 }
8c0fdd85 6417 break;
04992c8c 6418 case CP0_REGISTER_10:
7a387fff 6419 switch (sel) {
860ffef0 6420 case CP0_REG10__ENTRYHI:
ad75a51e 6421 gen_helper_mtc0_entryhi(tcg_env, arg);
294fc2ea 6422 register_name = "EntryHi";
2423f660 6423 break;
7a387fff 6424 default:
f31b035a 6425 goto cp0_unimplemented;
876d4b07 6426 }
8c0fdd85 6427 break;
04992c8c 6428 case CP0_REGISTER_11:
7a387fff 6429 switch (sel) {
f5f3834f 6430 case CP0_REG11__COMPARE:
ad75a51e 6431 gen_helper_mtc0_compare(tcg_env, arg);
294fc2ea 6432 register_name = "Compare";
2423f660
TS
6433 break;
6434 /* 6,7 are implementation dependent */
7a387fff 6435 default:
f31b035a 6436 goto cp0_unimplemented;
876d4b07 6437 }
8c0fdd85 6438 break;
04992c8c 6439 case CP0_REGISTER_12:
7a387fff 6440 switch (sel) {
2b084867 6441 case CP0_REG12__STATUS:
867abc7e 6442 save_cpu_state(ctx, 1);
ad75a51e 6443 gen_helper_mtc0_status(tcg_env, arg);
b28425ba 6444 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6445 gen_save_pc(ctx->base.pc_next + 4);
6446 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 6447 register_name = "Status";
2423f660 6448 break;
2b084867 6449 case CP0_REG12__INTCTL:
7a47bae5 6450 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6451 gen_helper_mtc0_intctl(tcg_env, arg);
8487327a 6452 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6453 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 6454 register_name = "IntCtl";
2423f660 6455 break;
2b084867 6456 case CP0_REG12__SRSCTL:
7a47bae5 6457 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6458 gen_helper_mtc0_srsctl(tcg_env, arg);
8487327a 6459 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6460 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 6461 register_name = "SRSCtl";
2423f660 6462 break;
2b084867 6463 case CP0_REG12__SRSMAP:
7a47bae5 6464 check_insn(ctx, ISA_MIPS_R2);
7db13fae 6465 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 6466 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6467 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 6468 register_name = "SRSMap";
fd88b6ab 6469 break;
7a387fff 6470 default:
f31b035a 6471 goto cp0_unimplemented;
876d4b07 6472 }
8c0fdd85 6473 break;
04992c8c 6474 case CP0_REGISTER_13:
7a387fff 6475 switch (sel) {
e3c7559d 6476 case CP0_REG13__CAUSE:
867abc7e 6477 save_cpu_state(ctx, 1);
ad75a51e 6478 gen_helper_mtc0_cause(tcg_env, arg);
7480515f
AM
6479 /*
6480 * Stop translation as we may have triggered an interrupt.
b28425ba 6481 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
6482 * translated code to check for pending interrupts.
6483 */
eeb3bba8
EC
6484 gen_save_pc(ctx->base.pc_next + 4);
6485 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 6486 register_name = "Cause";
2423f660 6487 break;
7a387fff 6488 default:
f31b035a 6489 goto cp0_unimplemented;
876d4b07 6490 }
8c0fdd85 6491 break;
04992c8c 6492 case CP0_REGISTER_14:
7a387fff 6493 switch (sel) {
35e4b54d 6494 case CP0_REG14__EPC:
ad75a51e 6495 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 6496 register_name = "EPC";
2423f660 6497 break;
7a387fff 6498 default:
f31b035a 6499 goto cp0_unimplemented;
876d4b07 6500 }
8c0fdd85 6501 break;
04992c8c 6502 case CP0_REGISTER_15:
7a387fff 6503 switch (sel) {
4466cd49 6504 case CP0_REG15__PRID:
2423f660 6505 /* ignored */
294fc2ea 6506 register_name = "PRid";
2423f660 6507 break;
4466cd49 6508 case CP0_REG15__EBASE:
7a47bae5 6509 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 6510 gen_helper_mtc0_ebase(tcg_env, arg);
294fc2ea 6511 register_name = "EBase";
2423f660 6512 break;
7a387fff 6513 default:
f31b035a 6514 goto cp0_unimplemented;
1579a72e 6515 }
8c0fdd85 6516 break;
04992c8c 6517 case CP0_REGISTER_16:
8c0fdd85 6518 switch (sel) {
433efb4c 6519 case CP0_REG16__CONFIG:
ad75a51e 6520 gen_helper_mtc0_config0(tcg_env, arg);
294fc2ea 6521 register_name = "Config";
2423f660 6522 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6523 ctx->base.is_jmp = DISAS_STOP;
7a387fff 6524 break;
433efb4c 6525 case CP0_REG16__CONFIG1:
e397ee33 6526 /* ignored, read only */
294fc2ea 6527 register_name = "Config1";
7a387fff 6528 break;
433efb4c 6529 case CP0_REG16__CONFIG2:
ad75a51e 6530 gen_helper_mtc0_config2(tcg_env, arg);
294fc2ea 6531 register_name = "Config2";
2423f660 6532 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6533 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 6534 break;
433efb4c 6535 case CP0_REG16__CONFIG3:
ad75a51e 6536 gen_helper_mtc0_config3(tcg_env, arg);
294fc2ea 6537 register_name = "Config3";
90f12d73 6538 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6539 ctx->base.is_jmp = DISAS_STOP;
7a387fff 6540 break;
433efb4c 6541 case CP0_REG16__CONFIG4:
ad75a51e 6542 gen_helper_mtc0_config4(tcg_env, arg);
294fc2ea 6543 register_name = "Config4";
eeb3bba8 6544 ctx->base.is_jmp = DISAS_STOP;
b4160af1 6545 break;
433efb4c 6546 case CP0_REG16__CONFIG5:
ad75a51e 6547 gen_helper_mtc0_config5(tcg_env, arg);
294fc2ea 6548 register_name = "Config5";
b4dd99a3 6549 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6550 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 6551 break;
e397ee33 6552 /* 6,7 are implementation dependent */
433efb4c 6553 case CP0_REG16__CONFIG6:
e397ee33 6554 /* ignored */
294fc2ea 6555 register_name = "Config6";
e397ee33 6556 break;
433efb4c 6557 case CP0_REG16__CONFIG7:
e397ee33 6558 /* ignored */
294fc2ea 6559 register_name = "Config7";
e397ee33 6560 break;
8c0fdd85 6561 default:
294fc2ea 6562 register_name = "Invalid config selector";
f31b035a 6563 goto cp0_unimplemented;
8c0fdd85
TS
6564 }
6565 break;
04992c8c 6566 case CP0_REGISTER_17:
7a387fff 6567 switch (sel) {
706ce142 6568 case CP0_REG17__LLADDR:
ad75a51e 6569 gen_helper_mtc0_lladdr(tcg_env, arg);
294fc2ea 6570 register_name = "LLAddr";
2423f660 6571 break;
706ce142 6572 case CP0_REG17__MAAR:
f6d4dd81 6573 CP0_CHECK(ctx->mrp);
ad75a51e 6574 gen_helper_mtc0_maar(tcg_env, arg);
294fc2ea 6575 register_name = "MAAR";
f6d4dd81 6576 break;
706ce142 6577 case CP0_REG17__MAARI:
f6d4dd81 6578 CP0_CHECK(ctx->mrp);
ad75a51e 6579 gen_helper_mtc0_maari(tcg_env, arg);
294fc2ea 6580 register_name = "MAARI";
f6d4dd81 6581 break;
7a387fff 6582 default:
f31b035a 6583 goto cp0_unimplemented;
7a387fff 6584 }
8c0fdd85 6585 break;
04992c8c 6586 case CP0_REGISTER_18:
7a387fff 6587 switch (sel) {
e8dcfe82
AM
6588 case CP0_REG18__WATCHLO0:
6589 case CP0_REG18__WATCHLO1:
6590 case CP0_REG18__WATCHLO2:
6591 case CP0_REG18__WATCHLO3:
6592 case CP0_REG18__WATCHLO4:
6593 case CP0_REG18__WATCHLO5:
6594 case CP0_REG18__WATCHLO6:
6595 case CP0_REG18__WATCHLO7:
fa192d49 6596 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6597 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 6598 register_name = "WatchLo";
2423f660 6599 break;
7a387fff 6600 default:
f31b035a 6601 goto cp0_unimplemented;
7a387fff 6602 }
8c0fdd85 6603 break;
04992c8c 6604 case CP0_REGISTER_19:
7a387fff 6605 switch (sel) {
be274dc1
AM
6606 case CP0_REG19__WATCHHI0:
6607 case CP0_REG19__WATCHHI1:
6608 case CP0_REG19__WATCHHI2:
6609 case CP0_REG19__WATCHHI3:
6610 case CP0_REG19__WATCHHI4:
6611 case CP0_REG19__WATCHHI5:
6612 case CP0_REG19__WATCHHI6:
6613 case CP0_REG19__WATCHHI7:
fa192d49 6614 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6615 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 6616 register_name = "WatchHi";
2423f660 6617 break;
7a387fff 6618 default:
f31b035a 6619 goto cp0_unimplemented;
7a387fff 6620 }
8c0fdd85 6621 break;
04992c8c 6622 case CP0_REGISTER_20:
7a387fff 6623 switch (sel) {
14f92b0b 6624 case CP0_REG20__XCONTEXT:
d26bc211 6625#if defined(TARGET_MIPS64)
d75c135e 6626 check_insn(ctx, ISA_MIPS3);
ad75a51e 6627 gen_helper_mtc0_xcontext(tcg_env, arg);
294fc2ea 6628 register_name = "XContext";
2423f660 6629 break;
703eaf37 6630#endif
7a387fff 6631 default:
f31b035a 6632 goto cp0_unimplemented;
7a387fff 6633 }
8c0fdd85 6634 break;
04992c8c 6635 case CP0_REGISTER_21:
7a387fff 6636 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 6637 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7a387fff
TS
6638 switch (sel) {
6639 case 0:
ad75a51e 6640 gen_helper_mtc0_framemask(tcg_env, arg);
294fc2ea 6641 register_name = "Framemask";
2423f660 6642 break;
7a387fff 6643 default:
f31b035a 6644 goto cp0_unimplemented;
7a387fff
TS
6645 }
6646 break;
04992c8c 6647 case CP0_REGISTER_22:
7a387fff 6648 /* ignored */
294fc2ea 6649 register_name = "Diagnostic"; /* implementation dependent */
2423f660 6650 break;
04992c8c 6651 case CP0_REGISTER_23:
7a387fff 6652 switch (sel) {
4cbf4b6d 6653 case CP0_REG23__DEBUG:
ad75a51e 6654 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
b28425ba 6655 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6656 gen_save_pc(ctx->base.pc_next + 4);
6657 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 6658 register_name = "Debug";
2423f660 6659 break;
4cbf4b6d
AM
6660 case CP0_REG23__TRACECONTROL:
6661 /* PDtrace support */
ad75a51e 6662 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
294fc2ea 6663 register_name = "TraceControl";
8487327a 6664 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6665 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6666 goto cp0_unimplemented;
4cbf4b6d
AM
6667 case CP0_REG23__TRACECONTROL2:
6668 /* PDtrace support */
ad75a51e 6669 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
294fc2ea 6670 register_name = "TraceControl2";
8487327a 6671 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6672 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6673 goto cp0_unimplemented;
4cbf4b6d 6674 case CP0_REG23__USERTRACEDATA1:
8487327a 6675 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6676 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 6677 /* PDtrace support */
ad75a51e 6678 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
294fc2ea 6679 register_name = "UserTraceData";
8487327a 6680 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6681 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6682 goto cp0_unimplemented;
4cbf4b6d
AM
6683 case CP0_REG23__TRACEIBPC:
6684 /* PDtrace support */
ad75a51e 6685 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
8487327a 6686 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6687 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d
AM
6688 register_name = "TraceIBPC";
6689 goto cp0_unimplemented;
6690 case CP0_REG23__TRACEDBPC:
6691 /* PDtrace support */
ad75a51e 6692 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
4cbf4b6d
AM
6693 /* Stop translation as we may have switched the execution mode */
6694 ctx->base.is_jmp = DISAS_STOP;
6695 register_name = "TraceDBPC";
3570d7f6 6696 goto cp0_unimplemented;
7a387fff 6697 default:
f31b035a 6698 goto cp0_unimplemented;
7a387fff 6699 }
8c0fdd85 6700 break;
04992c8c 6701 case CP0_REGISTER_24:
7a387fff 6702 switch (sel) {
8d7b4b6e 6703 case CP0_REG24__DEPC:
f1aa6320 6704 /* EJTAG support */
ad75a51e 6705 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 6706 register_name = "DEPC";
2423f660 6707 break;
7a387fff 6708 default:
f31b035a 6709 goto cp0_unimplemented;
7a387fff 6710 }
8c0fdd85 6711 break;
04992c8c 6712 case CP0_REGISTER_25:
7a387fff 6713 switch (sel) {
1176b328 6714 case CP0_REG25__PERFCTL0:
ad75a51e 6715 gen_helper_mtc0_performance0(tcg_env, arg);
294fc2ea 6716 register_name = "Performance0";
2423f660 6717 break;
1176b328 6718 case CP0_REG25__PERFCNT0:
7480515f 6719 /* gen_helper_mtc0_performance1(arg); */
294fc2ea 6720 register_name = "Performance1";
3570d7f6 6721 goto cp0_unimplemented;
1176b328 6722 case CP0_REG25__PERFCTL1:
7480515f 6723 /* gen_helper_mtc0_performance2(arg); */
294fc2ea 6724 register_name = "Performance2";
3570d7f6 6725 goto cp0_unimplemented;
1176b328 6726 case CP0_REG25__PERFCNT1:
7480515f 6727 /* gen_helper_mtc0_performance3(arg); */
294fc2ea 6728 register_name = "Performance3";
3570d7f6 6729 goto cp0_unimplemented;
1176b328 6730 case CP0_REG25__PERFCTL2:
7480515f 6731 /* gen_helper_mtc0_performance4(arg); */
294fc2ea 6732 register_name = "Performance4";
3570d7f6 6733 goto cp0_unimplemented;
1176b328 6734 case CP0_REG25__PERFCNT2:
7480515f 6735 /* gen_helper_mtc0_performance5(arg); */
294fc2ea 6736 register_name = "Performance5";
3570d7f6 6737 goto cp0_unimplemented;
1176b328 6738 case CP0_REG25__PERFCTL3:
7480515f 6739 /* gen_helper_mtc0_performance6(arg); */
294fc2ea 6740 register_name = "Performance6";
3570d7f6 6741 goto cp0_unimplemented;
1176b328 6742 case CP0_REG25__PERFCNT3:
7480515f 6743 /* gen_helper_mtc0_performance7(arg); */
294fc2ea 6744 register_name = "Performance7";
3570d7f6 6745 goto cp0_unimplemented;
7a387fff 6746 default:
f31b035a 6747 goto cp0_unimplemented;
7a387fff 6748 }
8c0fdd85 6749 break;
04992c8c 6750 case CP0_REGISTER_26:
0d74a222 6751 switch (sel) {
dbbf08b2 6752 case CP0_REG26__ERRCTL:
ad75a51e 6753 gen_helper_mtc0_errctl(tcg_env, arg);
eeb3bba8 6754 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 6755 register_name = "ErrCtl";
0d74a222
LA
6756 break;
6757 default:
6758 goto cp0_unimplemented;
6759 }
2423f660 6760 break;
04992c8c 6761 case CP0_REGISTER_27:
7a387fff 6762 switch (sel) {
5a10873d 6763 case CP0_REG27__CACHERR:
2423f660 6764 /* ignored */
294fc2ea 6765 register_name = "CacheErr";
2423f660 6766 break;
7a387fff 6767 default:
f31b035a 6768 goto cp0_unimplemented;
7a387fff 6769 }
8c0fdd85 6770 break;
04992c8c 6771 case CP0_REGISTER_28:
8c0fdd85 6772 switch (sel) {
a30e2f21
AM
6773 case CP0_REG28__TAGLO:
6774 case CP0_REG28__TAGLO1:
6775 case CP0_REG28__TAGLO2:
6776 case CP0_REG28__TAGLO3:
ad75a51e 6777 gen_helper_mtc0_taglo(tcg_env, arg);
294fc2ea 6778 register_name = "TagLo";
8c0fdd85 6779 break;
a30e2f21
AM
6780 case CP0_REG28__DATALO:
6781 case CP0_REG28__DATALO1:
6782 case CP0_REG28__DATALO2:
6783 case CP0_REG28__DATALO3:
ad75a51e 6784 gen_helper_mtc0_datalo(tcg_env, arg);
294fc2ea 6785 register_name = "DataLo";
7a387fff 6786 break;
8c0fdd85 6787 default:
f31b035a 6788 goto cp0_unimplemented;
8c0fdd85
TS
6789 }
6790 break;
04992c8c 6791 case CP0_REGISTER_29:
7a387fff 6792 switch (sel) {
af4bb6da
AM
6793 case CP0_REG29__TAGHI:
6794 case CP0_REG29__TAGHI1:
6795 case CP0_REG29__TAGHI2:
6796 case CP0_REG29__TAGHI3:
ad75a51e 6797 gen_helper_mtc0_taghi(tcg_env, arg);
294fc2ea 6798 register_name = "TagHi";
7a387fff 6799 break;
af4bb6da
AM
6800 case CP0_REG29__DATAHI:
6801 case CP0_REG29__DATAHI1:
6802 case CP0_REG29__DATAHI2:
6803 case CP0_REG29__DATAHI3:
ad75a51e 6804 gen_helper_mtc0_datahi(tcg_env, arg);
294fc2ea 6805 register_name = "DataHi";
7a387fff
TS
6806 break;
6807 default:
294fc2ea 6808 register_name = "invalid sel";
f31b035a 6809 goto cp0_unimplemented;
7a387fff 6810 }
8c0fdd85 6811 break;
04992c8c 6812 case CP0_REGISTER_30:
7a387fff 6813 switch (sel) {
4bcf121e 6814 case CP0_REG30__ERROREPC:
ad75a51e 6815 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 6816 register_name = "ErrorEPC";
2423f660 6817 break;
7a387fff 6818 default:
f31b035a 6819 goto cp0_unimplemented;
7a387fff 6820 }
8c0fdd85 6821 break;
04992c8c 6822 case CP0_REGISTER_31:
7a387fff 6823 switch (sel) {
14d92efd 6824 case CP0_REG31__DESAVE:
f1aa6320 6825 /* EJTAG support */
7db13fae 6826 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 6827 register_name = "DESAVE";
2423f660 6828 break;
14d92efd
AM
6829 case CP0_REG31__KSCRATCH1:
6830 case CP0_REG31__KSCRATCH2:
6831 case CP0_REG31__KSCRATCH3:
6832 case CP0_REG31__KSCRATCH4:
6833 case CP0_REG31__KSCRATCH5:
6834 case CP0_REG31__KSCRATCH6:
f31b035a 6835 CP0_CHECK(ctx->kscrexist & (1 << sel));
ad75a51e 6836 tcg_gen_st_tl(arg, tcg_env,
05aa7e93 6837 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 6838 register_name = "KScratch";
e98c0d17 6839 break;
7a387fff 6840 default:
f31b035a 6841 goto cp0_unimplemented;
7a387fff 6842 }
8c0fdd85
TS
6843 break;
6844 default:
f31b035a 6845 goto cp0_unimplemented;
8c0fdd85 6846 }
294fc2ea 6847 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 6848
bf20dc07 6849 /* For simplicity assume that all writes can cause interrupts. */
dfd1b812 6850 if (icount) {
7480515f
AM
6851 /*
6852 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6853 * translated code to check for pending interrupts.
6854 */
eeb3bba8
EC
6855 gen_save_pc(ctx->base.pc_next + 4);
6856 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 6857 }
8c0fdd85
TS
6858 return;
6859
f31b035a 6860cp0_unimplemented:
294fc2ea
AM
6861 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
6862 register_name, reg, sel);
8c0fdd85
TS
6863}
6864
d26bc211 6865#if defined(TARGET_MIPS64)
d75c135e 6866static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 6867{
294fc2ea 6868 const char *register_name = "invalid";
9c2149c8 6869
1f8929d2 6870 if (sel != 0) {
bbd5e4a2 6871 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 6872 }
e189e748 6873
9c2149c8 6874 switch (reg) {
04992c8c 6875 case CP0_REGISTER_00:
9c2149c8 6876 switch (sel) {
1b142da5 6877 case CP0_REG00__INDEX:
7db13fae 6878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6879 register_name = "Index";
9c2149c8 6880 break;
1b142da5 6881 case CP0_REG00__MVPCONTROL:
f31b035a 6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6883 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
294fc2ea 6884 register_name = "MVPControl";
ead9360e 6885 break;
1b142da5 6886 case CP0_REG00__MVPCONF0:
f31b035a 6887 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6888 gen_helper_mfc0_mvpconf0(arg, tcg_env);
294fc2ea 6889 register_name = "MVPConf0";
ead9360e 6890 break;
1b142da5 6891 case CP0_REG00__MVPCONF1:
f31b035a 6892 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6893 gen_helper_mfc0_mvpconf1(arg, tcg_env);
294fc2ea 6894 register_name = "MVPConf1";
ead9360e 6895 break;
1b142da5 6896 case CP0_REG00__VPCONTROL:
01bc435b
YK
6897 CP0_CHECK(ctx->vp);
6898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 6899 register_name = "VPControl";
01bc435b 6900 break;
9c2149c8 6901 default:
f31b035a 6902 goto cp0_unimplemented;
9c2149c8
TS
6903 }
6904 break;
04992c8c 6905 case CP0_REGISTER_01:
9c2149c8 6906 switch (sel) {
30deb460 6907 case CP0_REG01__RANDOM:
2e211e0a 6908 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
ad75a51e 6909 gen_helper_mfc0_random(arg, tcg_env);
294fc2ea 6910 register_name = "Random";
2423f660 6911 break;
30deb460 6912 case CP0_REG01__VPECONTROL:
f31b035a 6913 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6915 register_name = "VPEControl";
ead9360e 6916 break;
30deb460 6917 case CP0_REG01__VPECONF0:
f31b035a 6918 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6920 register_name = "VPEConf0";
ead9360e 6921 break;
30deb460 6922 case CP0_REG01__VPECONF1:
f31b035a 6923 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6925 register_name = "VPEConf1";
ead9360e 6926 break;
30deb460 6927 case CP0_REG01__YQMASK:
f31b035a 6928 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6929 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 6930 offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6931 register_name = "YQMask";
ead9360e 6932 break;
30deb460 6933 case CP0_REG01__VPESCHEDULE:
f31b035a 6934 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6935 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 6936 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6937 register_name = "VPESchedule";
ead9360e 6938 break;
30deb460 6939 case CP0_REG01__VPESCHEFBACK:
f31b035a 6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6941 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 6942 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6943 register_name = "VPEScheFBack";
ead9360e 6944 break;
30deb460 6945 case CP0_REG01__VPEOPT:
f31b035a 6946 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6948 register_name = "VPEOpt";
ead9360e 6949 break;
9c2149c8 6950 default:
f31b035a 6951 goto cp0_unimplemented;
9c2149c8
TS
6952 }
6953 break;
04992c8c 6954 case CP0_REGISTER_02:
9c2149c8 6955 switch (sel) {
6d27d5bd 6956 case CP0_REG02__ENTRYLO0:
ad75a51e 6957 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 6958 offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6959 register_name = "EntryLo0";
2423f660 6960 break;
6d27d5bd 6961 case CP0_REG02__TCSTATUS:
f31b035a 6962 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6963 gen_helper_mfc0_tcstatus(arg, tcg_env);
294fc2ea 6964 register_name = "TCStatus";
ead9360e 6965 break;
6d27d5bd 6966 case CP0_REG02__TCBIND:
f31b035a 6967 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6968 gen_helper_mfc0_tcbind(arg, tcg_env);
294fc2ea 6969 register_name = "TCBind";
ead9360e 6970 break;
6d27d5bd 6971 case CP0_REG02__TCRESTART:
f31b035a 6972 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6973 gen_helper_dmfc0_tcrestart(arg, tcg_env);
294fc2ea 6974 register_name = "TCRestart";
ead9360e 6975 break;
6d27d5bd 6976 case CP0_REG02__TCHALT:
f31b035a 6977 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6978 gen_helper_dmfc0_tchalt(arg, tcg_env);
294fc2ea 6979 register_name = "TCHalt";
ead9360e 6980 break;
6d27d5bd 6981 case CP0_REG02__TCCONTEXT:
f31b035a 6982 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6983 gen_helper_dmfc0_tccontext(arg, tcg_env);
294fc2ea 6984 register_name = "TCContext";
ead9360e 6985 break;
6d27d5bd 6986 case CP0_REG02__TCSCHEDULE:
f31b035a 6987 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6988 gen_helper_dmfc0_tcschedule(arg, tcg_env);
294fc2ea 6989 register_name = "TCSchedule";
ead9360e 6990 break;
6d27d5bd 6991 case CP0_REG02__TCSCHEFBACK:
f31b035a 6992 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 6993 gen_helper_dmfc0_tcschefback(arg, tcg_env);
294fc2ea 6994 register_name = "TCScheFBack";
ead9360e 6995 break;
9c2149c8 6996 default:
f31b035a 6997 goto cp0_unimplemented;
9c2149c8
TS
6998 }
6999 break;
04992c8c 7000 case CP0_REGISTER_03:
9c2149c8 7001 switch (sel) {
acd37316 7002 case CP0_REG03__ENTRYLO1:
ad75a51e 7003 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 7004 register_name = "EntryLo1";
2423f660 7005 break;
acd37316 7006 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7007 CP0_CHECK(ctx->vp);
7008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 7009 register_name = "GlobalNumber";
01bc435b 7010 break;
9c2149c8 7011 default:
f31b035a 7012 goto cp0_unimplemented;
1579a72e 7013 }
9c2149c8 7014 break;
04992c8c 7015 case CP0_REGISTER_04:
9c2149c8 7016 switch (sel) {
020fe379 7017 case CP0_REG04__CONTEXT:
ad75a51e 7018 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 7019 register_name = "Context";
2423f660 7020 break;
020fe379
AM
7021 case CP0_REG04__CONTEXTCONFIG:
7022 /* SmartMIPS ASE */
7023 /* gen_helper_dmfc0_contextconfig(arg); */
294fc2ea 7024 register_name = "ContextConfig";
f31b035a 7025 goto cp0_unimplemented;
020fe379 7026 case CP0_REG04__USERLOCAL:
f31b035a 7027 CP0_CHECK(ctx->ulri);
ad75a51e 7028 tcg_gen_ld_tl(arg, tcg_env,
f31b035a 7029 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7030 register_name = "UserLocal";
d279279e 7031 break;
99029be1
YK
7032 case CP0_REG04__MMID:
7033 CP0_CHECK(ctx->mi);
ad75a51e 7034 gen_helper_mtc0_memorymapid(tcg_env, arg);
99029be1
YK
7035 register_name = "MMID";
7036 break;
9c2149c8 7037 default:
f31b035a 7038 goto cp0_unimplemented;
876d4b07 7039 }
9c2149c8 7040 break;
04992c8c 7041 case CP0_REGISTER_05:
9c2149c8 7042 switch (sel) {
a1e76353 7043 case CP0_REG05__PAGEMASK:
7db13fae 7044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 7045 register_name = "PageMask";
2423f660 7046 break;
a1e76353 7047 case CP0_REG05__PAGEGRAIN:
7a47bae5 7048 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7049 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 7050 register_name = "PageGrain";
2423f660 7051 break;
a1e76353 7052 case CP0_REG05__SEGCTL0:
cec56a73 7053 CP0_CHECK(ctx->sc);
ad75a51e 7054 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 7055 register_name = "SegCtl0";
cec56a73 7056 break;
a1e76353 7057 case CP0_REG05__SEGCTL1:
cec56a73 7058 CP0_CHECK(ctx->sc);
ad75a51e 7059 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 7060 register_name = "SegCtl1";
cec56a73 7061 break;
a1e76353 7062 case CP0_REG05__SEGCTL2:
cec56a73 7063 CP0_CHECK(ctx->sc);
ad75a51e 7064 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 7065 register_name = "SegCtl2";
cec56a73 7066 break;
a1e76353 7067 case CP0_REG05__PWBASE:
5e31fdd5 7068 check_pw(ctx);
ad75a51e 7069 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7070 register_name = "PWBase";
5e31fdd5 7071 break;
a1e76353 7072 case CP0_REG05__PWFIELD:
fa75ad14 7073 check_pw(ctx);
ad75a51e 7074 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 7075 register_name = "PWField";
fa75ad14 7076 break;
a1e76353 7077 case CP0_REG05__PWSIZE:
20b28ebc 7078 check_pw(ctx);
ad75a51e 7079 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 7080 register_name = "PWSize";
20b28ebc 7081 break;
9c2149c8 7082 default:
f31b035a 7083 goto cp0_unimplemented;
876d4b07 7084 }
9c2149c8 7085 break;
04992c8c 7086 case CP0_REGISTER_06:
9c2149c8 7087 switch (sel) {
9023594b 7088 case CP0_REG06__WIRED:
7db13fae 7089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 7090 register_name = "Wired";
2423f660 7091 break;
9023594b 7092 case CP0_REG06__SRSCONF0:
7a47bae5 7093 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 7095 register_name = "SRSConf0";
ead9360e 7096 break;
9023594b 7097 case CP0_REG06__SRSCONF1:
7a47bae5 7098 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7099 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 7100 register_name = "SRSConf1";
ead9360e 7101 break;
9023594b 7102 case CP0_REG06__SRSCONF2:
7a47bae5 7103 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7105 register_name = "SRSConf2";
ead9360e 7106 break;
9023594b 7107 case CP0_REG06__SRSCONF3:
7a47bae5 7108 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7110 register_name = "SRSConf3";
ead9360e 7111 break;
9023594b 7112 case CP0_REG06__SRSCONF4:
7a47bae5 7113 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7114 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7115 register_name = "SRSConf4";
ead9360e 7116 break;
9023594b 7117 case CP0_REG06__PWCTL:
103be64c
YK
7118 check_pw(ctx);
7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7120 register_name = "PWCtl";
103be64c 7121 break;
9c2149c8 7122 default:
f31b035a 7123 goto cp0_unimplemented;
876d4b07 7124 }
9c2149c8 7125 break;
04992c8c 7126 case CP0_REGISTER_07:
9c2149c8 7127 switch (sel) {
143a9875 7128 case CP0_REG07__HWRENA:
7a47bae5 7129 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7131 register_name = "HWREna";
2423f660 7132 break;
9c2149c8 7133 default:
f31b035a 7134 goto cp0_unimplemented;
876d4b07 7135 }
9c2149c8 7136 break;
04992c8c 7137 case CP0_REGISTER_08:
9c2149c8 7138 switch (sel) {
67d167d2 7139 case CP0_REG08__BADVADDR:
ad75a51e 7140 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 7141 register_name = "BadVAddr";
2423f660 7142 break;
67d167d2 7143 case CP0_REG08__BADINSTR:
f31b035a
LA
7144 CP0_CHECK(ctx->bi);
7145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7146 register_name = "BadInstr";
aea14095 7147 break;
67d167d2 7148 case CP0_REG08__BADINSTRP:
f31b035a
LA
7149 CP0_CHECK(ctx->bp);
7150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7151 register_name = "BadInstrP";
aea14095 7152 break;
67d167d2 7153 case CP0_REG08__BADINSTRX:
25beba9b
SM
7154 CP0_CHECK(ctx->bi);
7155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7156 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7157 register_name = "BadInstrX";
25beba9b 7158 break;
9c2149c8 7159 default:
f31b035a 7160 goto cp0_unimplemented;
876d4b07 7161 }
9c2149c8 7162 break;
04992c8c 7163 case CP0_REGISTER_09:
9c2149c8 7164 switch (sel) {
e5a98a72 7165 case CP0_REG09__COUNT:
2e70f6ef 7166 /* Mark as an IO operation because we read the time. */
dfd1b812 7167 translator_io_start(&ctx->base);
ad75a51e 7168 gen_helper_mfc0_count(arg, tcg_env);
7480515f
AM
7169 /*
7170 * Break the TB to be able to take timer interrupts immediately
7171 * after reading count. DISAS_STOP isn't sufficient, we need to
7172 * ensure we break completely out of translated code.
7173 */
eeb3bba8
EC
7174 gen_save_pc(ctx->base.pc_next + 4);
7175 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7176 register_name = "Count";
2423f660 7177 break;
e5a98a72 7178 case CP0_REG09__SAARI:
5fb2dcd1
YK
7179 CP0_CHECK(ctx->saar);
7180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7181 register_name = "SAARI";
5fb2dcd1 7182 break;
e5a98a72 7183 case CP0_REG09__SAAR:
5fb2dcd1 7184 CP0_CHECK(ctx->saar);
ad75a51e 7185 gen_helper_dmfc0_saar(arg, tcg_env);
294fc2ea 7186 register_name = "SAAR";
5fb2dcd1 7187 break;
9c2149c8 7188 default:
f31b035a 7189 goto cp0_unimplemented;
876d4b07 7190 }
9c2149c8 7191 break;
04992c8c 7192 case CP0_REGISTER_10:
9c2149c8 7193 switch (sel) {
860ffef0 7194 case CP0_REG10__ENTRYHI:
ad75a51e 7195 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 7196 register_name = "EntryHi";
2423f660 7197 break;
9c2149c8 7198 default:
f31b035a 7199 goto cp0_unimplemented;
876d4b07 7200 }
9c2149c8 7201 break;
04992c8c 7202 case CP0_REGISTER_11:
9c2149c8 7203 switch (sel) {
f5f3834f 7204 case CP0_REG11__COMPARE:
7db13fae 7205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7206 register_name = "Compare";
2423f660 7207 break;
876d4b07 7208 /* 6,7 are implementation dependent */
9c2149c8 7209 default:
f31b035a 7210 goto cp0_unimplemented;
876d4b07 7211 }
9c2149c8 7212 break;
04992c8c 7213 case CP0_REGISTER_12:
9c2149c8 7214 switch (sel) {
2b084867 7215 case CP0_REG12__STATUS:
7db13fae 7216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7217 register_name = "Status";
2423f660 7218 break;
2b084867 7219 case CP0_REG12__INTCTL:
7a47bae5 7220 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7222 register_name = "IntCtl";
2423f660 7223 break;
2b084867 7224 case CP0_REG12__SRSCTL:
7a47bae5 7225 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7227 register_name = "SRSCtl";
2423f660 7228 break;
2b084867 7229 case CP0_REG12__SRSMAP:
7a47bae5 7230 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7232 register_name = "SRSMap";
2423f660 7233 break;
9c2149c8 7234 default:
f31b035a 7235 goto cp0_unimplemented;
876d4b07 7236 }
9c2149c8 7237 break;
04992c8c 7238 case CP0_REGISTER_13:
9c2149c8 7239 switch (sel) {
e3c7559d 7240 case CP0_REG13__CAUSE:
7db13fae 7241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7242 register_name = "Cause";
2423f660 7243 break;
9c2149c8 7244 default:
f31b035a 7245 goto cp0_unimplemented;
876d4b07 7246 }
9c2149c8 7247 break;
04992c8c 7248 case CP0_REGISTER_14:
9c2149c8 7249 switch (sel) {
35e4b54d 7250 case CP0_REG14__EPC:
ad75a51e 7251 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7252 register_name = "EPC";
2423f660 7253 break;
9c2149c8 7254 default:
f31b035a 7255 goto cp0_unimplemented;
876d4b07 7256 }
9c2149c8 7257 break;
04992c8c 7258 case CP0_REGISTER_15:
9c2149c8 7259 switch (sel) {
4466cd49 7260 case CP0_REG15__PRID:
7db13fae 7261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7262 register_name = "PRid";
2423f660 7263 break;
4466cd49 7264 case CP0_REG15__EBASE:
7a47bae5 7265 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7266 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 7267 register_name = "EBase";
2423f660 7268 break;
4466cd49 7269 case CP0_REG15__CMGCRBASE:
7a47bae5 7270 check_insn(ctx, ISA_MIPS_R2);
c870e3f5 7271 CP0_CHECK(ctx->cmgcr);
ad75a51e 7272 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 7273 register_name = "CMGCRBase";
c870e3f5 7274 break;
9c2149c8 7275 default:
f31b035a 7276 goto cp0_unimplemented;
876d4b07 7277 }
9c2149c8 7278 break;
04992c8c 7279 case CP0_REGISTER_16:
9c2149c8 7280 switch (sel) {
433efb4c 7281 case CP0_REG16__CONFIG:
7db13fae 7282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7283 register_name = "Config";
9c2149c8 7284 break;
433efb4c 7285 case CP0_REG16__CONFIG1:
7db13fae 7286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7287 register_name = "Config1";
9c2149c8 7288 break;
433efb4c 7289 case CP0_REG16__CONFIG2:
7db13fae 7290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7291 register_name = "Config2";
9c2149c8 7292 break;
433efb4c 7293 case CP0_REG16__CONFIG3:
7db13fae 7294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7295 register_name = "Config3";
9c2149c8 7296 break;
433efb4c 7297 case CP0_REG16__CONFIG4:
faf1f68b 7298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7299 register_name = "Config4";
faf1f68b 7300 break;
433efb4c 7301 case CP0_REG16__CONFIG5:
faf1f68b 7302 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7303 register_name = "Config5";
faf1f68b 7304 break;
05aa7e93 7305 /* 6,7 are implementation dependent */
433efb4c 7306 case CP0_REG16__CONFIG6:
7db13fae 7307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7308 register_name = "Config6";
f0b3f3ae 7309 break;
433efb4c 7310 case CP0_REG16__CONFIG7:
7db13fae 7311 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7312 register_name = "Config7";
f0b3f3ae 7313 break;
9c2149c8 7314 default:
f31b035a 7315 goto cp0_unimplemented;
9c2149c8
TS
7316 }
7317 break;
04992c8c 7318 case CP0_REGISTER_17:
9c2149c8 7319 switch (sel) {
706ce142 7320 case CP0_REG17__LLADDR:
ad75a51e 7321 gen_helper_dmfc0_lladdr(arg, tcg_env);
294fc2ea 7322 register_name = "LLAddr";
2423f660 7323 break;
706ce142 7324 case CP0_REG17__MAAR:
f6d4dd81 7325 CP0_CHECK(ctx->mrp);
ad75a51e 7326 gen_helper_dmfc0_maar(arg, tcg_env);
294fc2ea 7327 register_name = "MAAR";
f6d4dd81 7328 break;
706ce142 7329 case CP0_REG17__MAARI:
f6d4dd81
YK
7330 CP0_CHECK(ctx->mrp);
7331 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7332 register_name = "MAARI";
f6d4dd81 7333 break;
9c2149c8 7334 default:
f31b035a 7335 goto cp0_unimplemented;
9c2149c8
TS
7336 }
7337 break;
04992c8c 7338 case CP0_REGISTER_18:
9c2149c8 7339 switch (sel) {
e8dcfe82
AM
7340 case CP0_REG18__WATCHLO0:
7341 case CP0_REG18__WATCHLO1:
7342 case CP0_REG18__WATCHLO2:
7343 case CP0_REG18__WATCHLO3:
7344 case CP0_REG18__WATCHLO4:
7345 case CP0_REG18__WATCHLO5:
7346 case CP0_REG18__WATCHLO6:
7347 case CP0_REG18__WATCHLO7:
fa192d49 7348 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7349 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 7350 register_name = "WatchLo";
2423f660 7351 break;
9c2149c8 7352 default:
f31b035a 7353 goto cp0_unimplemented;
9c2149c8
TS
7354 }
7355 break;
04992c8c 7356 case CP0_REGISTER_19:
9c2149c8 7357 switch (sel) {
be274dc1
AM
7358 case CP0_REG19__WATCHHI0:
7359 case CP0_REG19__WATCHHI1:
7360 case CP0_REG19__WATCHHI2:
7361 case CP0_REG19__WATCHHI3:
7362 case CP0_REG19__WATCHHI4:
7363 case CP0_REG19__WATCHHI5:
7364 case CP0_REG19__WATCHHI6:
7365 case CP0_REG19__WATCHHI7:
fa192d49 7366 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
feafe82c 7367 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
294fc2ea 7368 register_name = "WatchHi";
2423f660 7369 break;
9c2149c8 7370 default:
f31b035a 7371 goto cp0_unimplemented;
9c2149c8
TS
7372 }
7373 break;
04992c8c 7374 case CP0_REGISTER_20:
9c2149c8 7375 switch (sel) {
14f92b0b 7376 case CP0_REG20__XCONTEXT:
d75c135e 7377 check_insn(ctx, ISA_MIPS3);
ad75a51e 7378 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 7379 register_name = "XContext";
2423f660 7380 break;
9c2149c8 7381 default:
f31b035a 7382 goto cp0_unimplemented;
9c2149c8
TS
7383 }
7384 break;
04992c8c 7385 case CP0_REGISTER_21:
05aa7e93 7386 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 7387 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
7388 switch (sel) {
7389 case 0:
7db13fae 7390 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7391 register_name = "Framemask";
2423f660 7392 break;
9c2149c8 7393 default:
f31b035a 7394 goto cp0_unimplemented;
9c2149c8
TS
7395 }
7396 break;
04992c8c 7397 case CP0_REGISTER_22:
d9bea114 7398 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7399 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7400 break;
04992c8c 7401 case CP0_REGISTER_23:
9c2149c8 7402 switch (sel) {
4cbf4b6d 7403 case CP0_REG23__DEBUG:
ad75a51e 7404 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
294fc2ea 7405 register_name = "Debug";
2423f660 7406 break;
4cbf4b6d
AM
7407 case CP0_REG23__TRACECONTROL:
7408 /* PDtrace support */
ad75a51e 7409 /* gen_helper_dmfc0_tracecontrol(arg, tcg_env); */
294fc2ea 7410 register_name = "TraceControl";
3570d7f6 7411 goto cp0_unimplemented;
4cbf4b6d
AM
7412 case CP0_REG23__TRACECONTROL2:
7413 /* PDtrace support */
ad75a51e 7414 /* gen_helper_dmfc0_tracecontrol2(arg, tcg_env); */
294fc2ea 7415 register_name = "TraceControl2";
3570d7f6 7416 goto cp0_unimplemented;
4cbf4b6d
AM
7417 case CP0_REG23__USERTRACEDATA1:
7418 /* PDtrace support */
ad75a51e 7419 /* gen_helper_dmfc0_usertracedata1(arg, tcg_env);*/
4cbf4b6d 7420 register_name = "UserTraceData1";
3570d7f6 7421 goto cp0_unimplemented;
4cbf4b6d
AM
7422 case CP0_REG23__TRACEIBPC:
7423 /* PDtrace support */
ad75a51e 7424 /* gen_helper_dmfc0_traceibpc(arg, tcg_env); */
4cbf4b6d
AM
7425 register_name = "TraceIBPC";
7426 goto cp0_unimplemented;
7427 case CP0_REG23__TRACEDBPC:
7428 /* PDtrace support */
ad75a51e 7429 /* gen_helper_dmfc0_tracedbpc(arg, tcg_env); */
4cbf4b6d 7430 register_name = "TraceDBPC";
3570d7f6 7431 goto cp0_unimplemented;
9c2149c8 7432 default:
f31b035a 7433 goto cp0_unimplemented;
9c2149c8
TS
7434 }
7435 break;
04992c8c 7436 case CP0_REGISTER_24:
9c2149c8 7437 switch (sel) {
8d7b4b6e 7438 case CP0_REG24__DEPC:
f0b3f3ae 7439 /* EJTAG support */
ad75a51e 7440 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 7441 register_name = "DEPC";
2423f660 7442 break;
9c2149c8 7443 default:
f31b035a 7444 goto cp0_unimplemented;
9c2149c8
TS
7445 }
7446 break;
04992c8c 7447 case CP0_REGISTER_25:
9c2149c8 7448 switch (sel) {
1176b328 7449 case CP0_REG25__PERFCTL0:
7db13fae 7450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7451 register_name = "Performance0";
9c2149c8 7452 break;
1176b328 7453 case CP0_REG25__PERFCNT0:
7480515f 7454 /* gen_helper_dmfc0_performance1(arg); */
294fc2ea 7455 register_name = "Performance1";
3570d7f6 7456 goto cp0_unimplemented;
1176b328 7457 case CP0_REG25__PERFCTL1:
7480515f 7458 /* gen_helper_dmfc0_performance2(arg); */
294fc2ea 7459 register_name = "Performance2";
3570d7f6 7460 goto cp0_unimplemented;
1176b328 7461 case CP0_REG25__PERFCNT1:
7480515f 7462 /* gen_helper_dmfc0_performance3(arg); */
294fc2ea 7463 register_name = "Performance3";
3570d7f6 7464 goto cp0_unimplemented;
1176b328 7465 case CP0_REG25__PERFCTL2:
7480515f 7466 /* gen_helper_dmfc0_performance4(arg); */
294fc2ea 7467 register_name = "Performance4";
3570d7f6 7468 goto cp0_unimplemented;
1176b328 7469 case CP0_REG25__PERFCNT2:
7480515f 7470 /* gen_helper_dmfc0_performance5(arg); */
294fc2ea 7471 register_name = "Performance5";
3570d7f6 7472 goto cp0_unimplemented;
1176b328 7473 case CP0_REG25__PERFCTL3:
7480515f 7474 /* gen_helper_dmfc0_performance6(arg); */
294fc2ea 7475 register_name = "Performance6";
3570d7f6 7476 goto cp0_unimplemented;
1176b328 7477 case CP0_REG25__PERFCNT3:
7480515f 7478 /* gen_helper_dmfc0_performance7(arg); */
294fc2ea 7479 register_name = "Performance7";
3570d7f6 7480 goto cp0_unimplemented;
9c2149c8 7481 default:
f31b035a 7482 goto cp0_unimplemented;
9c2149c8
TS
7483 }
7484 break;
04992c8c 7485 case CP0_REGISTER_26:
0d74a222 7486 switch (sel) {
dbbf08b2 7487 case CP0_REG26__ERRCTL:
0d74a222 7488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7489 register_name = "ErrCtl";
0d74a222
LA
7490 break;
7491 default:
7492 goto cp0_unimplemented;
7493 }
da80682b 7494 break;
04992c8c 7495 case CP0_REGISTER_27:
9c2149c8
TS
7496 switch (sel) {
7497 /* ignored */
5a10873d 7498 case CP0_REG27__CACHERR:
d9bea114 7499 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7500 register_name = "CacheErr";
2423f660 7501 break;
9c2149c8 7502 default:
f31b035a 7503 goto cp0_unimplemented;
9c2149c8
TS
7504 }
7505 break;
04992c8c 7506 case CP0_REGISTER_28:
9c2149c8 7507 switch (sel) {
a30e2f21
AM
7508 case CP0_REG28__TAGLO:
7509 case CP0_REG28__TAGLO1:
7510 case CP0_REG28__TAGLO2:
7511 case CP0_REG28__TAGLO3:
7db13fae 7512 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 7513 register_name = "TagLo";
9c2149c8 7514 break;
a30e2f21
AM
7515 case CP0_REG28__DATALO:
7516 case CP0_REG28__DATALO1:
7517 case CP0_REG28__DATALO2:
7518 case CP0_REG28__DATALO3:
7db13fae 7519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7520 register_name = "DataLo";
9c2149c8
TS
7521 break;
7522 default:
f31b035a 7523 goto cp0_unimplemented;
9c2149c8
TS
7524 }
7525 break;
04992c8c 7526 case CP0_REGISTER_29:
9c2149c8 7527 switch (sel) {
af4bb6da
AM
7528 case CP0_REG29__TAGHI:
7529 case CP0_REG29__TAGHI1:
7530 case CP0_REG29__TAGHI2:
7531 case CP0_REG29__TAGHI3:
7db13fae 7532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7533 register_name = "TagHi";
9c2149c8 7534 break;
af4bb6da
AM
7535 case CP0_REG29__DATAHI:
7536 case CP0_REG29__DATAHI1:
7537 case CP0_REG29__DATAHI2:
7538 case CP0_REG29__DATAHI3:
7db13fae 7539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7540 register_name = "DataHi";
9c2149c8
TS
7541 break;
7542 default:
f31b035a 7543 goto cp0_unimplemented;
9c2149c8
TS
7544 }
7545 break;
04992c8c 7546 case CP0_REGISTER_30:
9c2149c8 7547 switch (sel) {
4bcf121e 7548 case CP0_REG30__ERROREPC:
ad75a51e 7549 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 7550 register_name = "ErrorEPC";
2423f660 7551 break;
9c2149c8 7552 default:
f31b035a 7553 goto cp0_unimplemented;
9c2149c8
TS
7554 }
7555 break;
04992c8c 7556 case CP0_REGISTER_31:
9c2149c8 7557 switch (sel) {
14d92efd 7558 case CP0_REG31__DESAVE:
f0b3f3ae 7559 /* EJTAG support */
7db13fae 7560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7561 register_name = "DESAVE";
2423f660 7562 break;
14d92efd
AM
7563 case CP0_REG31__KSCRATCH1:
7564 case CP0_REG31__KSCRATCH2:
7565 case CP0_REG31__KSCRATCH3:
7566 case CP0_REG31__KSCRATCH4:
7567 case CP0_REG31__KSCRATCH5:
7568 case CP0_REG31__KSCRATCH6:
f31b035a 7569 CP0_CHECK(ctx->kscrexist & (1 << sel));
ad75a51e 7570 tcg_gen_ld_tl(arg, tcg_env,
05aa7e93 7571 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 7572 register_name = "KScratch";
e98c0d17 7573 break;
9c2149c8 7574 default:
f31b035a 7575 goto cp0_unimplemented;
9c2149c8
TS
7576 }
7577 break;
7578 default:
f31b035a 7579 goto cp0_unimplemented;
9c2149c8 7580 }
294fc2ea 7581 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
7582 return;
7583
f31b035a 7584cp0_unimplemented:
294fc2ea
AM
7585 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
7586 register_name, reg, sel);
f31b035a 7587 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
7588}
7589
d75c135e 7590static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 7591{
294fc2ea 7592 const char *register_name = "invalid";
dfd1b812 7593 bool icount;
9c2149c8 7594
1f8929d2 7595 if (sel != 0) {
bbd5e4a2 7596 check_insn(ctx, ISA_MIPS_R1);
1f8929d2 7597 }
e189e748 7598
dfd1b812 7599 icount = translator_io_start(&ctx->base);
2e70f6ef 7600
9c2149c8 7601 switch (reg) {
04992c8c 7602 case CP0_REGISTER_00:
9c2149c8 7603 switch (sel) {
1b142da5 7604 case CP0_REG00__INDEX:
ad75a51e 7605 gen_helper_mtc0_index(tcg_env, arg);
294fc2ea 7606 register_name = "Index";
9c2149c8 7607 break;
1b142da5 7608 case CP0_REG00__MVPCONTROL:
f31b035a 7609 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7610 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
294fc2ea 7611 register_name = "MVPControl";
ead9360e 7612 break;
1b142da5 7613 case CP0_REG00__MVPCONF0:
f31b035a 7614 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7615 /* ignored */
294fc2ea 7616 register_name = "MVPConf0";
ead9360e 7617 break;
1b142da5 7618 case CP0_REG00__MVPCONF1:
f31b035a 7619 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7620 /* ignored */
294fc2ea 7621 register_name = "MVPConf1";
ead9360e 7622 break;
1b142da5 7623 case CP0_REG00__VPCONTROL:
01bc435b
YK
7624 CP0_CHECK(ctx->vp);
7625 /* ignored */
294fc2ea 7626 register_name = "VPControl";
01bc435b 7627 break;
9c2149c8 7628 default:
f31b035a 7629 goto cp0_unimplemented;
9c2149c8
TS
7630 }
7631 break;
04992c8c 7632 case CP0_REGISTER_01:
9c2149c8 7633 switch (sel) {
30deb460 7634 case CP0_REG01__RANDOM:
2423f660 7635 /* ignored */
294fc2ea 7636 register_name = "Random";
2423f660 7637 break;
30deb460 7638 case CP0_REG01__VPECONTROL:
f31b035a 7639 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7640 gen_helper_mtc0_vpecontrol(tcg_env, arg);
294fc2ea 7641 register_name = "VPEControl";
ead9360e 7642 break;
30deb460 7643 case CP0_REG01__VPECONF0:
f31b035a 7644 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7645 gen_helper_mtc0_vpeconf0(tcg_env, arg);
294fc2ea 7646 register_name = "VPEConf0";
ead9360e 7647 break;
30deb460 7648 case CP0_REG01__VPECONF1:
f31b035a 7649 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7650 gen_helper_mtc0_vpeconf1(tcg_env, arg);
294fc2ea 7651 register_name = "VPEConf1";
ead9360e 7652 break;
30deb460 7653 case CP0_REG01__YQMASK:
f31b035a 7654 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7655 gen_helper_mtc0_yqmask(tcg_env, arg);
294fc2ea 7656 register_name = "YQMask";
ead9360e 7657 break;
30deb460 7658 case CP0_REG01__VPESCHEDULE:
f31b035a 7659 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7660 tcg_gen_st_tl(arg, tcg_env,
05aa7e93 7661 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7662 register_name = "VPESchedule";
ead9360e 7663 break;
30deb460 7664 case CP0_REG01__VPESCHEFBACK:
f31b035a 7665 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7666 tcg_gen_st_tl(arg, tcg_env,
05aa7e93 7667 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7668 register_name = "VPEScheFBack";
ead9360e 7669 break;
30deb460 7670 case CP0_REG01__VPEOPT:
f31b035a 7671 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7672 gen_helper_mtc0_vpeopt(tcg_env, arg);
294fc2ea 7673 register_name = "VPEOpt";
ead9360e 7674 break;
9c2149c8 7675 default:
f31b035a 7676 goto cp0_unimplemented;
9c2149c8
TS
7677 }
7678 break;
04992c8c 7679 case CP0_REGISTER_02:
9c2149c8 7680 switch (sel) {
6d27d5bd 7681 case CP0_REG02__ENTRYLO0:
ad75a51e 7682 gen_helper_dmtc0_entrylo0(tcg_env, arg);
294fc2ea 7683 register_name = "EntryLo0";
2423f660 7684 break;
6d27d5bd 7685 case CP0_REG02__TCSTATUS:
f31b035a 7686 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7687 gen_helper_mtc0_tcstatus(tcg_env, arg);
294fc2ea 7688 register_name = "TCStatus";
ead9360e 7689 break;
6d27d5bd 7690 case CP0_REG02__TCBIND:
f31b035a 7691 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7692 gen_helper_mtc0_tcbind(tcg_env, arg);
294fc2ea 7693 register_name = "TCBind";
ead9360e 7694 break;
6d27d5bd 7695 case CP0_REG02__TCRESTART:
f31b035a 7696 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7697 gen_helper_mtc0_tcrestart(tcg_env, arg);
294fc2ea 7698 register_name = "TCRestart";
ead9360e 7699 break;
6d27d5bd 7700 case CP0_REG02__TCHALT:
f31b035a 7701 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7702 gen_helper_mtc0_tchalt(tcg_env, arg);
294fc2ea 7703 register_name = "TCHalt";
ead9360e 7704 break;
6d27d5bd 7705 case CP0_REG02__TCCONTEXT:
f31b035a 7706 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7707 gen_helper_mtc0_tccontext(tcg_env, arg);
294fc2ea 7708 register_name = "TCContext";
ead9360e 7709 break;
6d27d5bd 7710 case CP0_REG02__TCSCHEDULE:
f31b035a 7711 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7712 gen_helper_mtc0_tcschedule(tcg_env, arg);
294fc2ea 7713 register_name = "TCSchedule";
ead9360e 7714 break;
6d27d5bd 7715 case CP0_REG02__TCSCHEFBACK:
f31b035a 7716 CP0_CHECK(ctx->insn_flags & ASE_MT);
ad75a51e 7717 gen_helper_mtc0_tcschefback(tcg_env, arg);
294fc2ea 7718 register_name = "TCScheFBack";
ead9360e 7719 break;
9c2149c8 7720 default:
f31b035a 7721 goto cp0_unimplemented;
9c2149c8
TS
7722 }
7723 break;
04992c8c 7724 case CP0_REGISTER_03:
9c2149c8 7725 switch (sel) {
acd37316 7726 case CP0_REG03__ENTRYLO1:
ad75a51e 7727 gen_helper_dmtc0_entrylo1(tcg_env, arg);
294fc2ea 7728 register_name = "EntryLo1";
2423f660 7729 break;
acd37316 7730 case CP0_REG03__GLOBALNUM:
01bc435b
YK
7731 CP0_CHECK(ctx->vp);
7732 /* ignored */
294fc2ea 7733 register_name = "GlobalNumber";
01bc435b 7734 break;
9c2149c8 7735 default:
f31b035a 7736 goto cp0_unimplemented;
876d4b07 7737 }
9c2149c8 7738 break;
04992c8c 7739 case CP0_REGISTER_04:
9c2149c8 7740 switch (sel) {
020fe379 7741 case CP0_REG04__CONTEXT:
ad75a51e 7742 gen_helper_mtc0_context(tcg_env, arg);
294fc2ea 7743 register_name = "Context";
2423f660 7744 break;
020fe379
AM
7745 case CP0_REG04__CONTEXTCONFIG:
7746 /* SmartMIPS ASE */
7747 /* gen_helper_dmtc0_contextconfig(arg); */
294fc2ea 7748 register_name = "ContextConfig";
f31b035a 7749 goto cp0_unimplemented;
020fe379 7750 case CP0_REG04__USERLOCAL:
f31b035a 7751 CP0_CHECK(ctx->ulri);
ad75a51e 7752 tcg_gen_st_tl(arg, tcg_env,
f31b035a 7753 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7754 register_name = "UserLocal";
d279279e 7755 break;
99029be1
YK
7756 case CP0_REG04__MMID:
7757 CP0_CHECK(ctx->mi);
7758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7759 register_name = "MMID";
7760 break;
9c2149c8 7761 default:
f31b035a 7762 goto cp0_unimplemented;
876d4b07 7763 }
9c2149c8 7764 break;
04992c8c 7765 case CP0_REGISTER_05:
9c2149c8 7766 switch (sel) {
a1e76353 7767 case CP0_REG05__PAGEMASK:
ad75a51e 7768 gen_helper_mtc0_pagemask(tcg_env, arg);
294fc2ea 7769 register_name = "PageMask";
2423f660 7770 break;
a1e76353 7771 case CP0_REG05__PAGEGRAIN:
7a47bae5 7772 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7773 gen_helper_mtc0_pagegrain(tcg_env, arg);
294fc2ea 7774 register_name = "PageGrain";
2423f660 7775 break;
a1e76353 7776 case CP0_REG05__SEGCTL0:
cec56a73 7777 CP0_CHECK(ctx->sc);
ad75a51e 7778 gen_helper_mtc0_segctl0(tcg_env, arg);
294fc2ea 7779 register_name = "SegCtl0";
cec56a73 7780 break;
a1e76353 7781 case CP0_REG05__SEGCTL1:
cec56a73 7782 CP0_CHECK(ctx->sc);
ad75a51e 7783 gen_helper_mtc0_segctl1(tcg_env, arg);
294fc2ea 7784 register_name = "SegCtl1";
cec56a73 7785 break;
a1e76353 7786 case CP0_REG05__SEGCTL2:
cec56a73 7787 CP0_CHECK(ctx->sc);
ad75a51e 7788 gen_helper_mtc0_segctl2(tcg_env, arg);
294fc2ea 7789 register_name = "SegCtl2";
cec56a73 7790 break;
a1e76353 7791 case CP0_REG05__PWBASE:
5e31fdd5 7792 check_pw(ctx);
ad75a51e 7793 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7794 register_name = "PWBase";
5e31fdd5 7795 break;
a1e76353 7796 case CP0_REG05__PWFIELD:
fa75ad14 7797 check_pw(ctx);
ad75a51e 7798 gen_helper_mtc0_pwfield(tcg_env, arg);
294fc2ea 7799 register_name = "PWField";
fa75ad14 7800 break;
a1e76353 7801 case CP0_REG05__PWSIZE:
20b28ebc 7802 check_pw(ctx);
ad75a51e 7803 gen_helper_mtc0_pwsize(tcg_env, arg);
294fc2ea 7804 register_name = "PWSize";
20b28ebc 7805 break;
9c2149c8 7806 default:
f31b035a 7807 goto cp0_unimplemented;
876d4b07 7808 }
9c2149c8 7809 break;
04992c8c 7810 case CP0_REGISTER_06:
9c2149c8 7811 switch (sel) {
9023594b 7812 case CP0_REG06__WIRED:
ad75a51e 7813 gen_helper_mtc0_wired(tcg_env, arg);
294fc2ea 7814 register_name = "Wired";
2423f660 7815 break;
9023594b 7816 case CP0_REG06__SRSCONF0:
7a47bae5 7817 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7818 gen_helper_mtc0_srsconf0(tcg_env, arg);
294fc2ea 7819 register_name = "SRSConf0";
ead9360e 7820 break;
9023594b 7821 case CP0_REG06__SRSCONF1:
7a47bae5 7822 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7823 gen_helper_mtc0_srsconf1(tcg_env, arg);
294fc2ea 7824 register_name = "SRSConf1";
ead9360e 7825 break;
9023594b 7826 case CP0_REG06__SRSCONF2:
7a47bae5 7827 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7828 gen_helper_mtc0_srsconf2(tcg_env, arg);
294fc2ea 7829 register_name = "SRSConf2";
ead9360e 7830 break;
9023594b 7831 case CP0_REG06__SRSCONF3:
7a47bae5 7832 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7833 gen_helper_mtc0_srsconf3(tcg_env, arg);
294fc2ea 7834 register_name = "SRSConf3";
ead9360e 7835 break;
9023594b 7836 case CP0_REG06__SRSCONF4:
7a47bae5 7837 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7838 gen_helper_mtc0_srsconf4(tcg_env, arg);
294fc2ea 7839 register_name = "SRSConf4";
ead9360e 7840 break;
9023594b 7841 case CP0_REG06__PWCTL:
103be64c 7842 check_pw(ctx);
ad75a51e 7843 gen_helper_mtc0_pwctl(tcg_env, arg);
294fc2ea 7844 register_name = "PWCtl";
103be64c 7845 break;
9c2149c8 7846 default:
f31b035a 7847 goto cp0_unimplemented;
876d4b07 7848 }
9c2149c8 7849 break;
04992c8c 7850 case CP0_REGISTER_07:
9c2149c8 7851 switch (sel) {
143a9875 7852 case CP0_REG07__HWRENA:
7a47bae5 7853 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7854 gen_helper_mtc0_hwrena(tcg_env, arg);
eeb3bba8 7855 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7856 register_name = "HWREna";
2423f660 7857 break;
9c2149c8 7858 default:
f31b035a 7859 goto cp0_unimplemented;
876d4b07 7860 }
9c2149c8 7861 break;
04992c8c 7862 case CP0_REGISTER_08:
aea14095 7863 switch (sel) {
67d167d2 7864 case CP0_REG08__BADVADDR:
aea14095 7865 /* ignored */
294fc2ea 7866 register_name = "BadVAddr";
aea14095 7867 break;
67d167d2 7868 case CP0_REG08__BADINSTR:
aea14095 7869 /* ignored */
294fc2ea 7870 register_name = "BadInstr";
aea14095 7871 break;
67d167d2 7872 case CP0_REG08__BADINSTRP:
aea14095 7873 /* ignored */
294fc2ea 7874 register_name = "BadInstrP";
aea14095 7875 break;
67d167d2 7876 case CP0_REG08__BADINSTRX:
25beba9b 7877 /* ignored */
294fc2ea 7878 register_name = "BadInstrX";
25beba9b 7879 break;
aea14095 7880 default:
f31b035a 7881 goto cp0_unimplemented;
aea14095 7882 }
9c2149c8 7883 break;
04992c8c 7884 case CP0_REGISTER_09:
9c2149c8 7885 switch (sel) {
e5a98a72 7886 case CP0_REG09__COUNT:
ad75a51e 7887 gen_helper_mtc0_count(tcg_env, arg);
294fc2ea 7888 register_name = "Count";
2423f660 7889 break;
e5a98a72 7890 case CP0_REG09__SAARI:
5fb2dcd1 7891 CP0_CHECK(ctx->saar);
ad75a51e 7892 gen_helper_mtc0_saari(tcg_env, arg);
294fc2ea 7893 register_name = "SAARI";
5fb2dcd1 7894 break;
e5a98a72 7895 case CP0_REG09__SAAR:
5fb2dcd1 7896 CP0_CHECK(ctx->saar);
ad75a51e 7897 gen_helper_mtc0_saar(tcg_env, arg);
294fc2ea 7898 register_name = "SAAR";
5fb2dcd1 7899 break;
9c2149c8 7900 default:
f31b035a 7901 goto cp0_unimplemented;
876d4b07
TS
7902 }
7903 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7904 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 7905 break;
04992c8c 7906 case CP0_REGISTER_10:
9c2149c8 7907 switch (sel) {
860ffef0 7908 case CP0_REG10__ENTRYHI:
ad75a51e 7909 gen_helper_mtc0_entryhi(tcg_env, arg);
294fc2ea 7910 register_name = "EntryHi";
2423f660 7911 break;
9c2149c8 7912 default:
f31b035a 7913 goto cp0_unimplemented;
876d4b07 7914 }
9c2149c8 7915 break;
04992c8c 7916 case CP0_REGISTER_11:
9c2149c8 7917 switch (sel) {
f5f3834f 7918 case CP0_REG11__COMPARE:
ad75a51e 7919 gen_helper_mtc0_compare(tcg_env, arg);
294fc2ea 7920 register_name = "Compare";
2423f660 7921 break;
876d4b07 7922 /* 6,7 are implementation dependent */
9c2149c8 7923 default:
f31b035a 7924 goto cp0_unimplemented;
876d4b07 7925 }
de9a95f0 7926 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7927 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 7928 break;
04992c8c 7929 case CP0_REGISTER_12:
9c2149c8 7930 switch (sel) {
2b084867 7931 case CP0_REG12__STATUS:
867abc7e 7932 save_cpu_state(ctx, 1);
ad75a51e 7933 gen_helper_mtc0_status(tcg_env, arg);
b28425ba 7934 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7935 gen_save_pc(ctx->base.pc_next + 4);
7936 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7937 register_name = "Status";
2423f660 7938 break;
2b084867 7939 case CP0_REG12__INTCTL:
7a47bae5 7940 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7941 gen_helper_mtc0_intctl(tcg_env, arg);
8487327a 7942 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7943 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7944 register_name = "IntCtl";
2423f660 7945 break;
2b084867 7946 case CP0_REG12__SRSCTL:
7a47bae5 7947 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 7948 gen_helper_mtc0_srsctl(tcg_env, arg);
8487327a 7949 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7950 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7951 register_name = "SRSCtl";
2423f660 7952 break;
2b084867 7953 case CP0_REG12__SRSMAP:
7a47bae5 7954 check_insn(ctx, ISA_MIPS_R2);
7db13fae 7955 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7956 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7957 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7958 register_name = "SRSMap";
2423f660
TS
7959 break;
7960 default:
f31b035a 7961 goto cp0_unimplemented;
876d4b07 7962 }
9c2149c8 7963 break;
04992c8c 7964 case CP0_REGISTER_13:
9c2149c8 7965 switch (sel) {
e3c7559d 7966 case CP0_REG13__CAUSE:
867abc7e 7967 save_cpu_state(ctx, 1);
ad75a51e 7968 gen_helper_mtc0_cause(tcg_env, arg);
7480515f
AM
7969 /*
7970 * Stop translation as we may have triggered an interrupt.
b28425ba 7971 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7480515f
AM
7972 * translated code to check for pending interrupts.
7973 */
eeb3bba8
EC
7974 gen_save_pc(ctx->base.pc_next + 4);
7975 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7976 register_name = "Cause";
2423f660 7977 break;
9c2149c8 7978 default:
f31b035a 7979 goto cp0_unimplemented;
876d4b07 7980 }
9c2149c8 7981 break;
04992c8c 7982 case CP0_REGISTER_14:
9c2149c8 7983 switch (sel) {
35e4b54d 7984 case CP0_REG14__EPC:
ad75a51e 7985 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7986 register_name = "EPC";
2423f660 7987 break;
9c2149c8 7988 default:
f31b035a 7989 goto cp0_unimplemented;
876d4b07 7990 }
9c2149c8 7991 break;
04992c8c 7992 case CP0_REGISTER_15:
9c2149c8 7993 switch (sel) {
4466cd49 7994 case CP0_REG15__PRID:
2423f660 7995 /* ignored */
294fc2ea 7996 register_name = "PRid";
2423f660 7997 break;
4466cd49 7998 case CP0_REG15__EBASE:
7a47bae5 7999 check_insn(ctx, ISA_MIPS_R2);
ad75a51e 8000 gen_helper_mtc0_ebase(tcg_env, arg);
294fc2ea 8001 register_name = "EBase";
2423f660 8002 break;
9c2149c8 8003 default:
f31b035a 8004 goto cp0_unimplemented;
876d4b07 8005 }
9c2149c8 8006 break;
04992c8c 8007 case CP0_REGISTER_16:
9c2149c8 8008 switch (sel) {
433efb4c 8009 case CP0_REG16__CONFIG:
ad75a51e 8010 gen_helper_mtc0_config0(tcg_env, arg);
294fc2ea 8011 register_name = "Config";
2423f660 8012 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8013 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8014 break;
433efb4c 8015 case CP0_REG16__CONFIG1:
1fc7bf6e 8016 /* ignored, read only */
294fc2ea 8017 register_name = "Config1";
9c2149c8 8018 break;
433efb4c 8019 case CP0_REG16__CONFIG2:
ad75a51e 8020 gen_helper_mtc0_config2(tcg_env, arg);
294fc2ea 8021 register_name = "Config2";
2423f660 8022 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8023 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8024 break;
433efb4c 8025 case CP0_REG16__CONFIG3:
ad75a51e 8026 gen_helper_mtc0_config3(tcg_env, arg);
294fc2ea 8027 register_name = "Config3";
90f12d73 8028 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8029 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8030 break;
433efb4c 8031 case CP0_REG16__CONFIG4:
faf1f68b 8032 /* currently ignored */
294fc2ea 8033 register_name = "Config4";
faf1f68b 8034 break;
433efb4c 8035 case CP0_REG16__CONFIG5:
ad75a51e 8036 gen_helper_mtc0_config5(tcg_env, arg);
294fc2ea 8037 register_name = "Config5";
faf1f68b 8038 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8039 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 8040 break;
9c2149c8
TS
8041 /* 6,7 are implementation dependent */
8042 default:
294fc2ea 8043 register_name = "Invalid config selector";
f31b035a 8044 goto cp0_unimplemented;
9c2149c8 8045 }
9c2149c8 8046 break;
04992c8c 8047 case CP0_REGISTER_17:
9c2149c8 8048 switch (sel) {
706ce142 8049 case CP0_REG17__LLADDR:
ad75a51e 8050 gen_helper_mtc0_lladdr(tcg_env, arg);
294fc2ea 8051 register_name = "LLAddr";
2423f660 8052 break;
706ce142 8053 case CP0_REG17__MAAR:
f6d4dd81 8054 CP0_CHECK(ctx->mrp);
ad75a51e 8055 gen_helper_mtc0_maar(tcg_env, arg);
294fc2ea 8056 register_name = "MAAR";
f6d4dd81 8057 break;
706ce142 8058 case CP0_REG17__MAARI:
f6d4dd81 8059 CP0_CHECK(ctx->mrp);
ad75a51e 8060 gen_helper_mtc0_maari(tcg_env, arg);
294fc2ea 8061 register_name = "MAARI";
f6d4dd81 8062 break;
9c2149c8 8063 default:
f31b035a 8064 goto cp0_unimplemented;
9c2149c8
TS
8065 }
8066 break;
04992c8c 8067 case CP0_REGISTER_18:
9c2149c8 8068 switch (sel) {
e8dcfe82
AM
8069 case CP0_REG18__WATCHLO0:
8070 case CP0_REG18__WATCHLO1:
8071 case CP0_REG18__WATCHLO2:
8072 case CP0_REG18__WATCHLO3:
8073 case CP0_REG18__WATCHLO4:
8074 case CP0_REG18__WATCHLO5:
8075 case CP0_REG18__WATCHLO6:
8076 case CP0_REG18__WATCHLO7:
fa192d49 8077 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8078 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 8079 register_name = "WatchLo";
2423f660 8080 break;
9c2149c8 8081 default:
f31b035a 8082 goto cp0_unimplemented;
9c2149c8
TS
8083 }
8084 break;
04992c8c 8085 case CP0_REGISTER_19:
9c2149c8 8086 switch (sel) {
be274dc1
AM
8087 case CP0_REG19__WATCHHI0:
8088 case CP0_REG19__WATCHHI1:
8089 case CP0_REG19__WATCHHI2:
8090 case CP0_REG19__WATCHHI3:
8091 case CP0_REG19__WATCHHI4:
8092 case CP0_REG19__WATCHHI5:
8093 case CP0_REG19__WATCHHI6:
8094 case CP0_REG19__WATCHHI7:
fa192d49 8095 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8096 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8097 register_name = "WatchHi";
2423f660 8098 break;
9c2149c8 8099 default:
f31b035a 8100 goto cp0_unimplemented;
9c2149c8
TS
8101 }
8102 break;
04992c8c 8103 case CP0_REGISTER_20:
9c2149c8 8104 switch (sel) {
14f92b0b 8105 case CP0_REG20__XCONTEXT:
d75c135e 8106 check_insn(ctx, ISA_MIPS3);
ad75a51e 8107 gen_helper_mtc0_xcontext(tcg_env, arg);
294fc2ea 8108 register_name = "XContext";
2423f660 8109 break;
9c2149c8 8110 default:
f31b035a 8111 goto cp0_unimplemented;
9c2149c8
TS
8112 }
8113 break;
04992c8c 8114 case CP0_REGISTER_21:
9c2149c8 8115 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2e211e0a 8116 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9c2149c8
TS
8117 switch (sel) {
8118 case 0:
ad75a51e 8119 gen_helper_mtc0_framemask(tcg_env, arg);
294fc2ea 8120 register_name = "Framemask";
2423f660 8121 break;
9c2149c8 8122 default:
f31b035a 8123 goto cp0_unimplemented;
9c2149c8
TS
8124 }
8125 break;
04992c8c 8126 case CP0_REGISTER_22:
9c2149c8 8127 /* ignored */
294fc2ea 8128 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 8129 break;
04992c8c 8130 case CP0_REGISTER_23:
9c2149c8 8131 switch (sel) {
4cbf4b6d 8132 case CP0_REG23__DEBUG:
ad75a51e 8133 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
b28425ba 8134 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8135 gen_save_pc(ctx->base.pc_next + 4);
8136 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8137 register_name = "Debug";
2423f660 8138 break;
4cbf4b6d
AM
8139 case CP0_REG23__TRACECONTROL:
8140 /* PDtrace support */
ad75a51e 8141 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
8487327a 8142 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8143 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8144 register_name = "TraceControl";
3570d7f6 8145 goto cp0_unimplemented;
4cbf4b6d
AM
8146 case CP0_REG23__TRACECONTROL2:
8147 /* PDtrace support */
ad75a51e 8148 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
8487327a 8149 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8150 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8151 register_name = "TraceControl2";
3570d7f6 8152 goto cp0_unimplemented;
4cbf4b6d
AM
8153 case CP0_REG23__USERTRACEDATA1:
8154 /* PDtrace support */
ad75a51e 8155 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
8487327a 8156 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8157 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8158 register_name = "UserTraceData1";
3570d7f6 8159 goto cp0_unimplemented;
4cbf4b6d
AM
8160 case CP0_REG23__TRACEIBPC:
8161 /* PDtrace support */
ad75a51e 8162 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
4cbf4b6d
AM
8163 /* Stop translation as we may have switched the execution mode */
8164 ctx->base.is_jmp = DISAS_STOP;
8165 register_name = "TraceIBPC";
8166 goto cp0_unimplemented;
8167 case CP0_REG23__TRACEDBPC:
8168 /* PDtrace support */
ad75a51e 8169 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
8487327a 8170 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8171 ctx->base.is_jmp = DISAS_STOP;
4cbf4b6d 8172 register_name = "TraceDBPC";
3570d7f6 8173 goto cp0_unimplemented;
9c2149c8 8174 default:
f31b035a 8175 goto cp0_unimplemented;
9c2149c8 8176 }
9c2149c8 8177 break;
04992c8c 8178 case CP0_REGISTER_24:
9c2149c8 8179 switch (sel) {
8d7b4b6e 8180 case CP0_REG24__DEPC:
f1aa6320 8181 /* EJTAG support */
ad75a51e 8182 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8183 register_name = "DEPC";
2423f660 8184 break;
9c2149c8 8185 default:
f31b035a 8186 goto cp0_unimplemented;
9c2149c8
TS
8187 }
8188 break;
04992c8c 8189 case CP0_REGISTER_25:
9c2149c8 8190 switch (sel) {
1176b328 8191 case CP0_REG25__PERFCTL0:
ad75a51e 8192 gen_helper_mtc0_performance0(tcg_env, arg);
294fc2ea 8193 register_name = "Performance0";
2423f660 8194 break;
1176b328 8195 case CP0_REG25__PERFCNT0:
ad75a51e 8196 /* gen_helper_mtc0_performance1(tcg_env, arg); */
294fc2ea 8197 register_name = "Performance1";
3570d7f6 8198 goto cp0_unimplemented;
1176b328 8199 case CP0_REG25__PERFCTL1:
ad75a51e 8200 /* gen_helper_mtc0_performance2(tcg_env, arg); */
294fc2ea 8201 register_name = "Performance2";
3570d7f6 8202 goto cp0_unimplemented;
1176b328 8203 case CP0_REG25__PERFCNT1:
ad75a51e 8204 /* gen_helper_mtc0_performance3(tcg_env, arg); */
294fc2ea 8205 register_name = "Performance3";
3570d7f6 8206 goto cp0_unimplemented;
1176b328 8207 case CP0_REG25__PERFCTL2:
ad75a51e 8208 /* gen_helper_mtc0_performance4(tcg_env, arg); */
294fc2ea 8209 register_name = "Performance4";
3570d7f6 8210 goto cp0_unimplemented;
1176b328 8211 case CP0_REG25__PERFCNT2:
ad75a51e 8212 /* gen_helper_mtc0_performance5(tcg_env, arg); */
294fc2ea 8213 register_name = "Performance5";
3570d7f6 8214 goto cp0_unimplemented;
1176b328 8215 case CP0_REG25__PERFCTL3:
ad75a51e 8216 /* gen_helper_mtc0_performance6(tcg_env, arg); */
294fc2ea 8217 register_name = "Performance6";
3570d7f6 8218 goto cp0_unimplemented;
1176b328 8219 case CP0_REG25__PERFCNT3:
ad75a51e 8220 /* gen_helper_mtc0_performance7(tcg_env, arg); */
294fc2ea 8221 register_name = "Performance7";
3570d7f6 8222 goto cp0_unimplemented;
9c2149c8 8223 default:
f31b035a 8224 goto cp0_unimplemented;
9c2149c8 8225 }
876d4b07 8226 break;
04992c8c 8227 case CP0_REGISTER_26:
0d74a222 8228 switch (sel) {
dbbf08b2 8229 case CP0_REG26__ERRCTL:
ad75a51e 8230 gen_helper_mtc0_errctl(tcg_env, arg);
eeb3bba8 8231 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8232 register_name = "ErrCtl";
0d74a222
LA
8233 break;
8234 default:
8235 goto cp0_unimplemented;
8236 }
876d4b07 8237 break;
04992c8c 8238 case CP0_REGISTER_27:
9c2149c8 8239 switch (sel) {
5a10873d 8240 case CP0_REG27__CACHERR:
2423f660 8241 /* ignored */
294fc2ea 8242 register_name = "CacheErr";
2423f660 8243 break;
9c2149c8 8244 default:
f31b035a 8245 goto cp0_unimplemented;
9c2149c8 8246 }
876d4b07 8247 break;
04992c8c 8248 case CP0_REGISTER_28:
9c2149c8 8249 switch (sel) {
a30e2f21
AM
8250 case CP0_REG28__TAGLO:
8251 case CP0_REG28__TAGLO1:
8252 case CP0_REG28__TAGLO2:
8253 case CP0_REG28__TAGLO3:
ad75a51e 8254 gen_helper_mtc0_taglo(tcg_env, arg);
294fc2ea 8255 register_name = "TagLo";
9c2149c8 8256 break;
a30e2f21
AM
8257 case CP0_REG28__DATALO:
8258 case CP0_REG28__DATALO1:
8259 case CP0_REG28__DATALO2:
8260 case CP0_REG28__DATALO3:
ad75a51e 8261 gen_helper_mtc0_datalo(tcg_env, arg);
294fc2ea 8262 register_name = "DataLo";
9c2149c8
TS
8263 break;
8264 default:
f31b035a 8265 goto cp0_unimplemented;
9c2149c8
TS
8266 }
8267 break;
04992c8c 8268 case CP0_REGISTER_29:
9c2149c8 8269 switch (sel) {
af4bb6da
AM
8270 case CP0_REG29__TAGHI:
8271 case CP0_REG29__TAGHI1:
8272 case CP0_REG29__TAGHI2:
8273 case CP0_REG29__TAGHI3:
ad75a51e 8274 gen_helper_mtc0_taghi(tcg_env, arg);
294fc2ea 8275 register_name = "TagHi";
9c2149c8 8276 break;
af4bb6da
AM
8277 case CP0_REG29__DATAHI:
8278 case CP0_REG29__DATAHI1:
8279 case CP0_REG29__DATAHI2:
8280 case CP0_REG29__DATAHI3:
ad75a51e 8281 gen_helper_mtc0_datahi(tcg_env, arg);
294fc2ea 8282 register_name = "DataHi";
9c2149c8
TS
8283 break;
8284 default:
294fc2ea 8285 register_name = "invalid sel";
f31b035a 8286 goto cp0_unimplemented;
9c2149c8 8287 }
876d4b07 8288 break;
04992c8c 8289 case CP0_REGISTER_30:
9c2149c8 8290 switch (sel) {
4bcf121e 8291 case CP0_REG30__ERROREPC:
ad75a51e 8292 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8293 register_name = "ErrorEPC";
2423f660 8294 break;
9c2149c8 8295 default:
f31b035a 8296 goto cp0_unimplemented;
9c2149c8
TS
8297 }
8298 break;
04992c8c 8299 case CP0_REGISTER_31:
9c2149c8 8300 switch (sel) {
14d92efd 8301 case CP0_REG31__DESAVE:
f1aa6320 8302 /* EJTAG support */
7db13fae 8303 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8304 register_name = "DESAVE";
2423f660 8305 break;
14d92efd
AM
8306 case CP0_REG31__KSCRATCH1:
8307 case CP0_REG31__KSCRATCH2:
8308 case CP0_REG31__KSCRATCH3:
8309 case CP0_REG31__KSCRATCH4:
8310 case CP0_REG31__KSCRATCH5:
8311 case CP0_REG31__KSCRATCH6:
f31b035a 8312 CP0_CHECK(ctx->kscrexist & (1 << sel));
ad75a51e 8313 tcg_gen_st_tl(arg, tcg_env,
71375b59 8314 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
294fc2ea 8315 register_name = "KScratch";
e98c0d17 8316 break;
9c2149c8 8317 default:
f31b035a 8318 goto cp0_unimplemented;
9c2149c8 8319 }
9c2149c8
TS
8320 break;
8321 default:
f31b035a 8322 goto cp0_unimplemented;
9c2149c8 8323 }
294fc2ea 8324 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 8325
bf20dc07 8326 /* For simplicity assume that all writes can cause interrupts. */
dfd1b812 8327 if (icount) {
7480515f
AM
8328 /*
8329 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8330 * translated code to check for pending interrupts.
8331 */
eeb3bba8
EC
8332 gen_save_pc(ctx->base.pc_next + 4);
8333 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8334 }
9c2149c8
TS
8335 return;
8336
f31b035a 8337cp0_unimplemented:
294fc2ea
AM
8338 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8339 register_name, reg, sel);
9c2149c8 8340}
d26bc211 8341#endif /* TARGET_MIPS64 */
9c2149c8 8342
7db13fae 8343static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
8344 int u, int sel, int h)
8345{
8346 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6180cc40 8347 TCGv t0 = tcg_temp_new();
ead9360e
TS
8348
8349 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 8350 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 8351 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
1a3fd9c3 8352 tcg_gen_movi_tl(t0, -1);
1f8929d2
AM
8353 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8354 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
1a3fd9c3 8355 tcg_gen_movi_tl(t0, -1);
1f8929d2 8356 } else if (u == 0) {
ead9360e 8357 switch (rt) {
5a25ce94
EI
8358 case 1:
8359 switch (sel) {
8360 case 1:
ad75a51e 8361 gen_helper_mftc0_vpecontrol(t0, tcg_env);
5a25ce94
EI
8362 break;
8363 case 2:
ad75a51e 8364 gen_helper_mftc0_vpeconf0(t0, tcg_env);
5a25ce94
EI
8365 break;
8366 default:
8367 goto die;
8368 break;
8369 }
8370 break;
ead9360e
TS
8371 case 2:
8372 switch (sel) {
8373 case 1:
ad75a51e 8374 gen_helper_mftc0_tcstatus(t0, tcg_env);
ead9360e
TS
8375 break;
8376 case 2:
ad75a51e 8377 gen_helper_mftc0_tcbind(t0, tcg_env);
ead9360e
TS
8378 break;
8379 case 3:
ad75a51e 8380 gen_helper_mftc0_tcrestart(t0, tcg_env);
ead9360e
TS
8381 break;
8382 case 4:
ad75a51e 8383 gen_helper_mftc0_tchalt(t0, tcg_env);
ead9360e
TS
8384 break;
8385 case 5:
ad75a51e 8386 gen_helper_mftc0_tccontext(t0, tcg_env);
ead9360e
TS
8387 break;
8388 case 6:
ad75a51e 8389 gen_helper_mftc0_tcschedule(t0, tcg_env);
ead9360e
TS
8390 break;
8391 case 7:
ad75a51e 8392 gen_helper_mftc0_tcschefback(t0, tcg_env);
ead9360e
TS
8393 break;
8394 default:
d75c135e 8395 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8396 break;
8397 }
8398 break;
8399 case 10:
8400 switch (sel) {
8401 case 0:
ad75a51e 8402 gen_helper_mftc0_entryhi(t0, tcg_env);
ead9360e
TS
8403 break;
8404 default:
d75c135e 8405 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8406 break;
8407 }
f1fadbb2 8408 break;
ead9360e
TS
8409 case 12:
8410 switch (sel) {
8411 case 0:
ad75a51e 8412 gen_helper_mftc0_status(t0, tcg_env);
ead9360e
TS
8413 break;
8414 default:
d75c135e 8415 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8416 break;
8417 }
f1fadbb2 8418 break;
5a25ce94
EI
8419 case 13:
8420 switch (sel) {
8421 case 0:
ad75a51e 8422 gen_helper_mftc0_cause(t0, tcg_env);
5a25ce94
EI
8423 break;
8424 default:
8425 goto die;
8426 break;
8427 }
8428 break;
8429 case 14:
8430 switch (sel) {
8431 case 0:
ad75a51e 8432 gen_helper_mftc0_epc(t0, tcg_env);
5a25ce94
EI
8433 break;
8434 default:
8435 goto die;
8436 break;
8437 }
8438 break;
8439 case 15:
8440 switch (sel) {
8441 case 1:
ad75a51e 8442 gen_helper_mftc0_ebase(t0, tcg_env);
5a25ce94
EI
8443 break;
8444 default:
8445 goto die;
8446 break;
8447 }
8448 break;
8449 case 16:
8450 switch (sel) {
c2e19f3c
AM
8451 case 0:
8452 case 1:
8453 case 2:
8454 case 3:
8455 case 4:
8456 case 5:
8457 case 6:
8458 case 7:
ad75a51e 8459 gen_helper_mftc0_configx(t0, tcg_env, tcg_constant_tl(sel));
5a25ce94
EI
8460 break;
8461 default:
8462 goto die;
8463 break;
8464 }
8465 break;
ead9360e
TS
8466 case 23:
8467 switch (sel) {
8468 case 0:
ad75a51e 8469 gen_helper_mftc0_debug(t0, tcg_env);
ead9360e
TS
8470 break;
8471 default:
d75c135e 8472 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8473 break;
8474 }
8475 break;
8476 default:
d75c135e 8477 gen_mfc0(ctx, t0, rt, sel);
ead9360e 8478 }
71375b59
AM
8479 } else {
8480 switch (sel) {
8481 /* GPR registers. */
ead9360e 8482 case 0:
71375b59 8483 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e 8484 break;
71375b59 8485 /* Auxiliary CPU registers */
ead9360e 8486 case 1:
71375b59
AM
8487 switch (rt) {
8488 case 0:
8489 gen_helper_1e0i(mftlo, t0, 0);
8490 break;
8491 case 1:
8492 gen_helper_1e0i(mfthi, t0, 0);
8493 break;
8494 case 2:
8495 gen_helper_1e0i(mftacx, t0, 0);
8496 break;
8497 case 4:
8498 gen_helper_1e0i(mftlo, t0, 1);
8499 break;
8500 case 5:
8501 gen_helper_1e0i(mfthi, t0, 1);
8502 break;
8503 case 6:
8504 gen_helper_1e0i(mftacx, t0, 1);
8505 break;
8506 case 8:
8507 gen_helper_1e0i(mftlo, t0, 2);
8508 break;
8509 case 9:
8510 gen_helper_1e0i(mfthi, t0, 2);
8511 break;
8512 case 10:
8513 gen_helper_1e0i(mftacx, t0, 2);
8514 break;
8515 case 12:
8516 gen_helper_1e0i(mftlo, t0, 3);
8517 break;
8518 case 13:
8519 gen_helper_1e0i(mfthi, t0, 3);
8520 break;
8521 case 14:
8522 gen_helper_1e0i(mftacx, t0, 3);
8523 break;
8524 case 16:
ad75a51e 8525 gen_helper_mftdsp(t0, tcg_env);
71375b59
AM
8526 break;
8527 default:
8528 goto die;
8529 }
ead9360e 8530 break;
71375b59 8531 /* Floating point (COP1). */
ead9360e 8532 case 2:
71375b59
AM
8533 /* XXX: For now we support only a single FPU context. */
8534 if (h == 0) {
8535 TCGv_i32 fp0 = tcg_temp_new_i32();
8536
8537 gen_load_fpr32(ctx, fp0, rt);
8538 tcg_gen_ext_i32_tl(t0, fp0);
71375b59
AM
8539 } else {
8540 TCGv_i32 fp0 = tcg_temp_new_i32();
8541
8542 gen_load_fpr32h(ctx, fp0, rt);
8543 tcg_gen_ext_i32_tl(t0, fp0);
71375b59 8544 }
ead9360e 8545 break;
71375b59
AM
8546 case 3:
8547 /* XXX: For now we support only a single FPU context. */
8548 gen_helper_1e0i(cfc1, t0, rt);
ead9360e 8549 break;
71375b59
AM
8550 /* COP2: Not implemented. */
8551 case 4:
ead9360e 8552 case 5:
71375b59 8553 /* fall through */
ead9360e
TS
8554 default:
8555 goto die;
8556 }
ead9360e 8557 }
b44a7fb1 8558 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3 8559 gen_store_gpr(t0, rd);
ead9360e
TS
8560 return;
8561
8562die:
d12d51d5 8563 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
3a4ef3b7 8564 gen_reserved_instruction(ctx);
ead9360e
TS
8565}
8566
7db13fae 8567static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
8568 int u, int sel, int h)
8569{
8570 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6180cc40 8571 TCGv t0 = tcg_temp_new();
ead9360e 8572
1a3fd9c3 8573 gen_load_gpr(t0, rt);
ead9360e 8574 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732 8575 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
1f8929d2 8576 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
7480515f
AM
8577 /* NOP */
8578 ;
1f8929d2
AM
8579 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8580 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
7480515f
AM
8581 /* NOP */
8582 ;
1f8929d2 8583 } else if (u == 0) {
ead9360e 8584 switch (rd) {
5a25ce94
EI
8585 case 1:
8586 switch (sel) {
8587 case 1:
ad75a51e 8588 gen_helper_mttc0_vpecontrol(tcg_env, t0);
5a25ce94
EI
8589 break;
8590 case 2:
ad75a51e 8591 gen_helper_mttc0_vpeconf0(tcg_env, t0);
5a25ce94
EI
8592 break;
8593 default:
8594 goto die;
8595 break;
8596 }
8597 break;
ead9360e
TS
8598 case 2:
8599 switch (sel) {
8600 case 1:
ad75a51e 8601 gen_helper_mttc0_tcstatus(tcg_env, t0);
ead9360e
TS
8602 break;
8603 case 2:
ad75a51e 8604 gen_helper_mttc0_tcbind(tcg_env, t0);
ead9360e
TS
8605 break;
8606 case 3:
ad75a51e 8607 gen_helper_mttc0_tcrestart(tcg_env, t0);
ead9360e
TS
8608 break;
8609 case 4:
ad75a51e 8610 gen_helper_mttc0_tchalt(tcg_env, t0);
ead9360e
TS
8611 break;
8612 case 5:
ad75a51e 8613 gen_helper_mttc0_tccontext(tcg_env, t0);
ead9360e
TS
8614 break;
8615 case 6:
ad75a51e 8616 gen_helper_mttc0_tcschedule(tcg_env, t0);
ead9360e
TS
8617 break;
8618 case 7:
ad75a51e 8619 gen_helper_mttc0_tcschefback(tcg_env, t0);
ead9360e
TS
8620 break;
8621 default:
d75c135e 8622 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8623 break;
8624 }
8625 break;
8626 case 10:
8627 switch (sel) {
8628 case 0:
ad75a51e 8629 gen_helper_mttc0_entryhi(tcg_env, t0);
ead9360e
TS
8630 break;
8631 default:
d75c135e 8632 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8633 break;
8634 }
0d0304f2 8635 break;
ead9360e
TS
8636 case 12:
8637 switch (sel) {
8638 case 0:
ad75a51e 8639 gen_helper_mttc0_status(tcg_env, t0);
ead9360e
TS
8640 break;
8641 default:
d75c135e 8642 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8643 break;
8644 }
0d0304f2 8645 break;
5a25ce94
EI
8646 case 13:
8647 switch (sel) {
8648 case 0:
ad75a51e 8649 gen_helper_mttc0_cause(tcg_env, t0);
5a25ce94
EI
8650 break;
8651 default:
8652 goto die;
8653 break;
8654 }
8655 break;
8656 case 15:
8657 switch (sel) {
8658 case 1:
ad75a51e 8659 gen_helper_mttc0_ebase(tcg_env, t0);
5a25ce94
EI
8660 break;
8661 default:
8662 goto die;
8663 break;
8664 }
8665 break;
ead9360e
TS
8666 case 23:
8667 switch (sel) {
8668 case 0:
ad75a51e 8669 gen_helper_mttc0_debug(tcg_env, t0);
ead9360e
TS
8670 break;
8671 default:
d75c135e 8672 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8673 break;
8674 }
8675 break;
8676 default:
d75c135e 8677 gen_mtc0(ctx, t0, rd, sel);
ead9360e 8678 }
71375b59
AM
8679 } else {
8680 switch (sel) {
8681 /* GPR registers. */
ead9360e 8682 case 0:
71375b59 8683 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e 8684 break;
71375b59 8685 /* Auxiliary CPU registers */
ead9360e 8686 case 1:
71375b59
AM
8687 switch (rd) {
8688 case 0:
8689 gen_helper_0e1i(mttlo, t0, 0);
8690 break;
8691 case 1:
8692 gen_helper_0e1i(mtthi, t0, 0);
8693 break;
8694 case 2:
8695 gen_helper_0e1i(mttacx, t0, 0);
8696 break;
8697 case 4:
8698 gen_helper_0e1i(mttlo, t0, 1);
8699 break;
8700 case 5:
8701 gen_helper_0e1i(mtthi, t0, 1);
8702 break;
8703 case 6:
8704 gen_helper_0e1i(mttacx, t0, 1);
8705 break;
8706 case 8:
8707 gen_helper_0e1i(mttlo, t0, 2);
8708 break;
8709 case 9:
8710 gen_helper_0e1i(mtthi, t0, 2);
8711 break;
8712 case 10:
8713 gen_helper_0e1i(mttacx, t0, 2);
8714 break;
8715 case 12:
8716 gen_helper_0e1i(mttlo, t0, 3);
8717 break;
8718 case 13:
8719 gen_helper_0e1i(mtthi, t0, 3);
8720 break;
8721 case 14:
8722 gen_helper_0e1i(mttacx, t0, 3);
8723 break;
8724 case 16:
ad75a51e 8725 gen_helper_mttdsp(tcg_env, t0);
71375b59
AM
8726 break;
8727 default:
8728 goto die;
8729 }
ead9360e 8730 break;
71375b59 8731 /* Floating point (COP1). */
ead9360e 8732 case 2:
71375b59
AM
8733 /* XXX: For now we support only a single FPU context. */
8734 if (h == 0) {
8735 TCGv_i32 fp0 = tcg_temp_new_i32();
8736
8737 tcg_gen_trunc_tl_i32(fp0, t0);
8738 gen_store_fpr32(ctx, fp0, rd);
71375b59
AM
8739 } else {
8740 TCGv_i32 fp0 = tcg_temp_new_i32();
8741
8742 tcg_gen_trunc_tl_i32(fp0, t0);
8743 gen_store_fpr32h(ctx, fp0, rd);
71375b59 8744 }
ead9360e 8745 break;
71375b59
AM
8746 case 3:
8747 /* XXX: For now we support only a single FPU context. */
78bdd388 8748 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(rd), rt);
71375b59
AM
8749 /* Stop translation as we may have changed hflags */
8750 ctx->base.is_jmp = DISAS_STOP;
ead9360e 8751 break;
71375b59
AM
8752 /* COP2: Not implemented. */
8753 case 4:
ead9360e 8754 case 5:
71375b59 8755 /* fall through */
ead9360e
TS
8756 default:
8757 goto die;
8758 }
ead9360e 8759 }
b44a7fb1 8760 trace_mips_translate_tr("mttr", rd, u, sel, h);
ead9360e
TS
8761 return;
8762
8763die:
d12d51d5 8764 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
3a4ef3b7 8765 gen_reserved_instruction(ctx);
ead9360e
TS
8766}
8767
235785e8
AM
8768static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
8769 int rt, int rd)
6af0bf9c 8770{
287c4b84 8771 const char *opn = "ldst";
6af0bf9c 8772
2e15497c 8773 check_cp0_enabled(ctx);
6af0bf9c
FB
8774 switch (opc) {
8775 case OPC_MFC0:
8776 if (rt == 0) {
ead9360e 8777 /* Treat as NOP. */
6af0bf9c
FB
8778 return;
8779 }
d75c135e 8780 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
8781 opn = "mfc0";
8782 break;
8783 case OPC_MTC0:
1a3fd9c3 8784 {
1fc7bf6e 8785 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8786
8787 gen_load_gpr(t0, rt);
d75c135e 8788 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3 8789 }
6af0bf9c
FB
8790 opn = "mtc0";
8791 break;
d26bc211 8792#if defined(TARGET_MIPS64)
9c2149c8 8793 case OPC_DMFC0:
d75c135e 8794 check_insn(ctx, ISA_MIPS3);
9c2149c8 8795 if (rt == 0) {
ead9360e 8796 /* Treat as NOP. */
9c2149c8
TS
8797 return;
8798 }
d75c135e 8799 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
8800 opn = "dmfc0";
8801 break;
8802 case OPC_DMTC0:
d75c135e 8803 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 8804 {
1fc7bf6e 8805 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8806
8807 gen_load_gpr(t0, rt);
d75c135e 8808 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3 8809 }
9c2149c8
TS
8810 opn = "dmtc0";
8811 break;
534ce69f 8812#endif
5204ea79
LA
8813 case OPC_MFHC0:
8814 check_mvh(ctx);
8815 if (rt == 0) {
8816 /* Treat as NOP. */
8817 return;
8818 }
8819 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8820 opn = "mfhc0";
8821 break;
8822 case OPC_MTHC0:
8823 check_mvh(ctx);
8824 {
8825 TCGv t0 = tcg_temp_new();
8826 gen_load_gpr(t0, rt);
8827 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
5204ea79
LA
8828 }
8829 opn = "mthc0";
8830 break;
ead9360e 8831 case OPC_MFTR:
9affc1c5 8832 check_cp0_enabled(ctx);
ead9360e
TS
8833 if (rd == 0) {
8834 /* Treat as NOP. */
8835 return;
8836 }
6c5c1e20 8837 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 8838 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
8839 opn = "mftr";
8840 break;
8841 case OPC_MTTR:
9affc1c5 8842 check_cp0_enabled(ctx);
6c5c1e20 8843 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
8844 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8845 opn = "mttr";
8846 break;
6af0bf9c 8847 case OPC_TLBWI:
6af0bf9c 8848 opn = "tlbwi";
1f8929d2 8849 if (!env->tlb->helper_tlbwi) {
29929e34 8850 goto die;
1f8929d2 8851 }
ad75a51e 8852 gen_helper_tlbwi(tcg_env);
6af0bf9c 8853 break;
9456c2fb
LA
8854 case OPC_TLBINV:
8855 opn = "tlbinv";
8856 if (ctx->ie >= 2) {
8857 if (!env->tlb->helper_tlbinv) {
8858 goto die;
8859 }
ad75a51e 8860 gen_helper_tlbinv(tcg_env);
9456c2fb
LA
8861 } /* treat as nop if TLBINV not supported */
8862 break;
8863 case OPC_TLBINVF:
8864 opn = "tlbinvf";
8865 if (ctx->ie >= 2) {
8866 if (!env->tlb->helper_tlbinvf) {
8867 goto die;
8868 }
ad75a51e 8869 gen_helper_tlbinvf(tcg_env);
9456c2fb
LA
8870 } /* treat as nop if TLBINV not supported */
8871 break;
6af0bf9c 8872 case OPC_TLBWR:
6af0bf9c 8873 opn = "tlbwr";
1f8929d2 8874 if (!env->tlb->helper_tlbwr) {
29929e34 8875 goto die;
1f8929d2 8876 }
ad75a51e 8877 gen_helper_tlbwr(tcg_env);
6af0bf9c
FB
8878 break;
8879 case OPC_TLBP:
6af0bf9c 8880 opn = "tlbp";
1f8929d2 8881 if (!env->tlb->helper_tlbp) {
29929e34 8882 goto die;
1f8929d2 8883 }
ad75a51e 8884 gen_helper_tlbp(tcg_env);
6af0bf9c
FB
8885 break;
8886 case OPC_TLBR:
6af0bf9c 8887 opn = "tlbr";
1f8929d2 8888 if (!env->tlb->helper_tlbr) {
29929e34 8889 goto die;
1f8929d2 8890 }
ad75a51e 8891 gen_helper_tlbr(tcg_env);
6af0bf9c 8892 break;
ce9782f4 8893 case OPC_ERET: /* OPC_ERETNC */
2e211e0a 8894 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 8895 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 8896 goto die;
ce9782f4
LA
8897 } else {
8898 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8899 if (ctx->opcode & (1 << bit_shift)) {
8900 /* OPC_ERETNC */
8901 opn = "eretnc";
5f89ce4f 8902 check_insn(ctx, ISA_MIPS_R5);
ad75a51e 8903 gen_helper_eretnc(tcg_env);
ce9782f4
LA
8904 } else {
8905 /* OPC_ERET */
8906 opn = "eret";
8907 check_insn(ctx, ISA_MIPS2);
ad75a51e 8908 gen_helper_eret(tcg_env);
ce9782f4 8909 }
eeb3bba8 8910 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 8911 }
6af0bf9c
FB
8912 break;
8913 case OPC_DERET:
8914 opn = "deret";
bbd5e4a2 8915 check_insn(ctx, ISA_MIPS_R1);
2e211e0a 8916 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 8917 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8918 goto die;
8919 }
6af0bf9c 8920 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 8921 MIPS_INVAL(opn);
3a4ef3b7 8922 gen_reserved_instruction(ctx);
6af0bf9c 8923 } else {
ad75a51e 8924 gen_helper_deret(tcg_env);
eeb3bba8 8925 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
8926 }
8927 break;
4ad40f36
FB
8928 case OPC_WAIT:
8929 opn = "wait";
bbd5e4a2 8930 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
2e211e0a 8931 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 8932 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8933 goto die;
8934 }
4ad40f36 8935 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 8936 ctx->base.pc_next += 4;
4ad40f36 8937 save_cpu_state(ctx, 1);
eeb3bba8 8938 ctx->base.pc_next -= 4;
ad75a51e 8939 gen_helper_wait(tcg_env);
eeb3bba8 8940 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 8941 break;
6af0bf9c 8942 default:
29929e34 8943 die:
923617a3 8944 MIPS_INVAL(opn);
3a4ef3b7 8945 gen_reserved_instruction(ctx);
6af0bf9c
FB
8946 return;
8947 }
2abf314d 8948 (void)opn; /* avoid a compiler warning */
6af0bf9c 8949}
f1aa6320 8950#endif /* !CONFIG_USER_ONLY */
6af0bf9c 8951
6ea83fed 8952/* CP1 Branches (before delay slot) */
d75c135e
AJ
8953static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8954 int32_t cc, int32_t offset)
6ea83fed
FB
8955{
8956 target_ulong btarget;
a7812ae4 8957 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 8958
2e211e0a 8959 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 8960 gen_reserved_instruction(ctx);
74fda465 8961 return;
339cd2a8
LA
8962 }
8963
1f8929d2 8964 if (cc != 0) {
bbd5e4a2 8965 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
1f8929d2 8966 }
e189e748 8967
eeb3bba8 8968 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 8969
7a387fff
TS
8970 switch (op) {
8971 case OPC_BC1F:
d94536f4
AJ
8972 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8973 tcg_gen_not_i32(t0, t0);
8974 tcg_gen_andi_i32(t0, t0, 1);
8975 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 8976 goto not_likely;
7a387fff 8977 case OPC_BC1FL:
d94536f4
AJ
8978 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8979 tcg_gen_not_i32(t0, t0);
8980 tcg_gen_andi_i32(t0, t0, 1);
8981 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 8982 goto likely;
7a387fff 8983 case OPC_BC1T:
d94536f4
AJ
8984 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8985 tcg_gen_andi_i32(t0, t0, 1);
8986 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 8987 goto not_likely;
7a387fff 8988 case OPC_BC1TL:
d94536f4
AJ
8989 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8990 tcg_gen_andi_i32(t0, t0, 1);
8991 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
8992 likely:
8993 ctx->hflags |= MIPS_HFLAG_BL;
8994 break;
5a5012ec 8995 case OPC_BC1FANY2:
a16336e4 8996 {
d94536f4
AJ
8997 TCGv_i32 t1 = tcg_temp_new_i32();
8998 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 8999 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9000 tcg_gen_nand_i32(t0, t0, t1);
d94536f4
AJ
9001 tcg_gen_andi_i32(t0, t0, 1);
9002 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9003 }
5a5012ec
TS
9004 goto not_likely;
9005 case OPC_BC1TANY2:
a16336e4 9006 {
d94536f4
AJ
9007 TCGv_i32 t1 = tcg_temp_new_i32();
9008 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9009 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 9010 tcg_gen_or_i32(t0, t0, t1);
d94536f4
AJ
9011 tcg_gen_andi_i32(t0, t0, 1);
9012 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9013 }
5a5012ec
TS
9014 goto not_likely;
9015 case OPC_BC1FANY4:
a16336e4 9016 {
d94536f4
AJ
9017 TCGv_i32 t1 = tcg_temp_new_i32();
9018 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9019 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d7f66b52 9020 tcg_gen_and_i32(t0, t0, t1);
71375b59 9021 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d7f66b52 9022 tcg_gen_and_i32(t0, t0, t1);
71375b59 9023 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d7f66b52 9024 tcg_gen_nand_i32(t0, t0, t1);
d94536f4
AJ
9025 tcg_gen_andi_i32(t0, t0, 1);
9026 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9027 }
5a5012ec
TS
9028 goto not_likely;
9029 case OPC_BC1TANY4:
a16336e4 9030 {
d94536f4
AJ
9031 TCGv_i32 t1 = tcg_temp_new_i32();
9032 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
71375b59 9033 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
d94536f4 9034 tcg_gen_or_i32(t0, t0, t1);
71375b59 9035 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
d94536f4 9036 tcg_gen_or_i32(t0, t0, t1);
71375b59 9037 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
d94536f4 9038 tcg_gen_or_i32(t0, t0, t1);
d94536f4
AJ
9039 tcg_gen_andi_i32(t0, t0, 1);
9040 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9041 }
5a5012ec
TS
9042 not_likely:
9043 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
9044 break;
9045 default:
9d68ac14 9046 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9047 gen_reserved_instruction(ctx);
74fda465 9048 return;
6ea83fed 9049 }
6ea83fed 9050 ctx->btarget = btarget;
b231c103 9051 ctx->hflags |= MIPS_HFLAG_BDS32;
6ea83fed
FB
9052}
9053
31837be3
YK
9054/* R6 CP1 Branches */
9055static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
9056 int32_t ft, int32_t offset,
9057 int delayslot_size)
31837be3
YK
9058{
9059 target_ulong btarget;
31837be3
YK
9060 TCGv_i64 t0 = tcg_temp_new_i64();
9061
9062 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9063#ifdef MIPS_DEBUG_DISAS
339cd2a8 9064 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 9065 "\n", ctx->base.pc_next);
31837be3 9066#endif
3a4ef3b7 9067 gen_reserved_instruction(ctx);
74fda465 9068 return;
31837be3
YK
9069 }
9070
9071 gen_load_fpr64(ctx, t0, ft);
9072 tcg_gen_andi_i64(t0, t0, 1);
9073
eeb3bba8 9074 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
9075
9076 switch (op) {
9077 case OPC_BC1EQZ:
9078 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
9079 ctx->hflags |= MIPS_HFLAG_BC;
9080 break;
9081 case OPC_BC1NEZ:
9082 /* t0 already set */
31837be3
YK
9083 ctx->hflags |= MIPS_HFLAG_BC;
9084 break;
9085 default:
9d68ac14 9086 MIPS_INVAL("cp1 cond branch");
3a4ef3b7 9087 gen_reserved_instruction(ctx);
74fda465 9088 return;
31837be3
YK
9089 }
9090
9091 tcg_gen_trunc_i64_tl(bcond, t0);
9092
31837be3 9093 ctx->btarget = btarget;
65935f07
YK
9094
9095 switch (delayslot_size) {
9096 case 2:
9097 ctx->hflags |= MIPS_HFLAG_BDS16;
9098 break;
9099 case 4:
9100 ctx->hflags |= MIPS_HFLAG_BDS32;
9101 break;
9102 }
31837be3
YK
9103}
9104
6af0bf9c 9105/* Coprocessor 1 (FPU) */
5a5012ec 9106
5a5012ec
TS
9107#define FOP(func, fmt) (((fmt) << 21) | (func))
9108
bf4120ad
NF
9109enum fopcode {
9110 OPC_ADD_S = FOP(0, FMT_S),
9111 OPC_SUB_S = FOP(1, FMT_S),
9112 OPC_MUL_S = FOP(2, FMT_S),
9113 OPC_DIV_S = FOP(3, FMT_S),
9114 OPC_SQRT_S = FOP(4, FMT_S),
9115 OPC_ABS_S = FOP(5, FMT_S),
9116 OPC_MOV_S = FOP(6, FMT_S),
9117 OPC_NEG_S = FOP(7, FMT_S),
9118 OPC_ROUND_L_S = FOP(8, FMT_S),
9119 OPC_TRUNC_L_S = FOP(9, FMT_S),
9120 OPC_CEIL_L_S = FOP(10, FMT_S),
9121 OPC_FLOOR_L_S = FOP(11, FMT_S),
9122 OPC_ROUND_W_S = FOP(12, FMT_S),
9123 OPC_TRUNC_W_S = FOP(13, FMT_S),
9124 OPC_CEIL_W_S = FOP(14, FMT_S),
9125 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 9126 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
9127 OPC_MOVCF_S = FOP(17, FMT_S),
9128 OPC_MOVZ_S = FOP(18, FMT_S),
9129 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 9130 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
9131 OPC_RECIP_S = FOP(21, FMT_S),
9132 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
9133 OPC_SELNEZ_S = FOP(23, FMT_S),
9134 OPC_MADDF_S = FOP(24, FMT_S),
9135 OPC_MSUBF_S = FOP(25, FMT_S),
9136 OPC_RINT_S = FOP(26, FMT_S),
9137 OPC_CLASS_S = FOP(27, FMT_S),
9138 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 9139 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 9140 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 9141 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 9142 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 9143 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 9144 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
9145 OPC_RSQRT2_S = FOP(31, FMT_S),
9146 OPC_CVT_D_S = FOP(33, FMT_S),
9147 OPC_CVT_W_S = FOP(36, FMT_S),
9148 OPC_CVT_L_S = FOP(37, FMT_S),
9149 OPC_CVT_PS_S = FOP(38, FMT_S),
235785e8
AM
9150 OPC_CMP_F_S = FOP(48, FMT_S),
9151 OPC_CMP_UN_S = FOP(49, FMT_S),
9152 OPC_CMP_EQ_S = FOP(50, FMT_S),
9153 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9154 OPC_CMP_OLT_S = FOP(52, FMT_S),
9155 OPC_CMP_ULT_S = FOP(53, FMT_S),
9156 OPC_CMP_OLE_S = FOP(54, FMT_S),
9157 OPC_CMP_ULE_S = FOP(55, FMT_S),
9158 OPC_CMP_SF_S = FOP(56, FMT_S),
9159 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9160 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9161 OPC_CMP_NGL_S = FOP(59, FMT_S),
9162 OPC_CMP_LT_S = FOP(60, FMT_S),
9163 OPC_CMP_NGE_S = FOP(61, FMT_S),
9164 OPC_CMP_LE_S = FOP(62, FMT_S),
9165 OPC_CMP_NGT_S = FOP(63, FMT_S),
bf4120ad
NF
9166
9167 OPC_ADD_D = FOP(0, FMT_D),
9168 OPC_SUB_D = FOP(1, FMT_D),
9169 OPC_MUL_D = FOP(2, FMT_D),
9170 OPC_DIV_D = FOP(3, FMT_D),
9171 OPC_SQRT_D = FOP(4, FMT_D),
9172 OPC_ABS_D = FOP(5, FMT_D),
9173 OPC_MOV_D = FOP(6, FMT_D),
9174 OPC_NEG_D = FOP(7, FMT_D),
9175 OPC_ROUND_L_D = FOP(8, FMT_D),
9176 OPC_TRUNC_L_D = FOP(9, FMT_D),
9177 OPC_CEIL_L_D = FOP(10, FMT_D),
9178 OPC_FLOOR_L_D = FOP(11, FMT_D),
9179 OPC_ROUND_W_D = FOP(12, FMT_D),
9180 OPC_TRUNC_W_D = FOP(13, FMT_D),
9181 OPC_CEIL_W_D = FOP(14, FMT_D),
9182 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 9183 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
9184 OPC_MOVCF_D = FOP(17, FMT_D),
9185 OPC_MOVZ_D = FOP(18, FMT_D),
9186 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 9187 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
9188 OPC_RECIP_D = FOP(21, FMT_D),
9189 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
9190 OPC_SELNEZ_D = FOP(23, FMT_D),
9191 OPC_MADDF_D = FOP(24, FMT_D),
9192 OPC_MSUBF_D = FOP(25, FMT_D),
9193 OPC_RINT_D = FOP(26, FMT_D),
9194 OPC_CLASS_D = FOP(27, FMT_D),
9195 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 9196 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 9197 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 9198 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 9199 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 9200 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 9201 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
9202 OPC_RSQRT2_D = FOP(31, FMT_D),
9203 OPC_CVT_S_D = FOP(32, FMT_D),
9204 OPC_CVT_W_D = FOP(36, FMT_D),
9205 OPC_CVT_L_D = FOP(37, FMT_D),
235785e8
AM
9206 OPC_CMP_F_D = FOP(48, FMT_D),
9207 OPC_CMP_UN_D = FOP(49, FMT_D),
9208 OPC_CMP_EQ_D = FOP(50, FMT_D),
9209 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9210 OPC_CMP_OLT_D = FOP(52, FMT_D),
9211 OPC_CMP_ULT_D = FOP(53, FMT_D),
9212 OPC_CMP_OLE_D = FOP(54, FMT_D),
9213 OPC_CMP_ULE_D = FOP(55, FMT_D),
9214 OPC_CMP_SF_D = FOP(56, FMT_D),
9215 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9216 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9217 OPC_CMP_NGL_D = FOP(59, FMT_D),
9218 OPC_CMP_LT_D = FOP(60, FMT_D),
9219 OPC_CMP_NGE_D = FOP(61, FMT_D),
9220 OPC_CMP_LE_D = FOP(62, FMT_D),
9221 OPC_CMP_NGT_D = FOP(63, FMT_D),
bf4120ad
NF
9222
9223 OPC_CVT_S_W = FOP(32, FMT_W),
9224 OPC_CVT_D_W = FOP(33, FMT_W),
9225 OPC_CVT_S_L = FOP(32, FMT_L),
9226 OPC_CVT_D_L = FOP(33, FMT_L),
9227 OPC_CVT_PS_PW = FOP(38, FMT_W),
9228
9229 OPC_ADD_PS = FOP(0, FMT_PS),
9230 OPC_SUB_PS = FOP(1, FMT_PS),
9231 OPC_MUL_PS = FOP(2, FMT_PS),
9232 OPC_DIV_PS = FOP(3, FMT_PS),
9233 OPC_ABS_PS = FOP(5, FMT_PS),
9234 OPC_MOV_PS = FOP(6, FMT_PS),
9235 OPC_NEG_PS = FOP(7, FMT_PS),
9236 OPC_MOVCF_PS = FOP(17, FMT_PS),
9237 OPC_MOVZ_PS = FOP(18, FMT_PS),
9238 OPC_MOVN_PS = FOP(19, FMT_PS),
9239 OPC_ADDR_PS = FOP(24, FMT_PS),
9240 OPC_MULR_PS = FOP(26, FMT_PS),
9241 OPC_RECIP2_PS = FOP(28, FMT_PS),
9242 OPC_RECIP1_PS = FOP(29, FMT_PS),
9243 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9244 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9245
9246 OPC_CVT_S_PU = FOP(32, FMT_PS),
9247 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9248 OPC_CVT_S_PL = FOP(40, FMT_PS),
9249 OPC_PLL_PS = FOP(44, FMT_PS),
9250 OPC_PLU_PS = FOP(45, FMT_PS),
9251 OPC_PUL_PS = FOP(46, FMT_PS),
9252 OPC_PUU_PS = FOP(47, FMT_PS),
235785e8
AM
9253 OPC_CMP_F_PS = FOP(48, FMT_PS),
9254 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9255 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9256 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9257 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9258 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9259 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9260 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9261 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9262 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9263 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9264 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9265 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9266 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9267 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9268 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
bf4120ad
NF
9269};
9270
3f493883
YK
9271enum r6_f_cmp_op {
9272 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9273 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9274 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9275 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9276 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9277 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9278 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9279 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9280 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9281 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9282 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9283 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9284 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9285 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9286 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9287 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9288 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9289 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9290 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9291 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9292 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9293 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9294
9295 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9296 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9297 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9298 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9299 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9300 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9301 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9302 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9303 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9304 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9305 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9306 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9307 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9308 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9309 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9310 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9311 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9312 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9313 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9314 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9315 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9316 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9317};
235785e8
AM
9318
9319static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 9320{
72c3a3ee 9321 TCGv t0 = tcg_temp_new();
6ea83fed
FB
9322
9323 switch (opc) {
9324 case OPC_MFC1:
b6d96bed 9325 {
a7812ae4 9326 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9327
7c979afd 9328 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 9329 tcg_gen_ext_i32_tl(t0, fp0);
6958549d 9330 }
6c5c1e20 9331 gen_store_gpr(t0, rt);
6ea83fed
FB
9332 break;
9333 case OPC_MTC1:
6c5c1e20 9334 gen_load_gpr(t0, rt);
b6d96bed 9335 {
a7812ae4 9336 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9337
9338 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 9339 gen_store_fpr32(ctx, fp0, fs);
6958549d 9340 }
6ea83fed
FB
9341 break;
9342 case OPC_CFC1:
895c2d04 9343 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 9344 gen_store_gpr(t0, rt);
6ea83fed
FB
9345 break;
9346 case OPC_CTC1:
6c5c1e20 9347 gen_load_gpr(t0, rt);
9c708c7f 9348 save_cpu_state(ctx, 0);
78bdd388 9349 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(fs), rt);
4cf8a45f 9350 /* Stop translation as we may have changed hflags */
eeb3bba8 9351 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 9352 break;
72c3a3ee 9353#if defined(TARGET_MIPS64)
9c2149c8 9354 case OPC_DMFC1:
72c3a3ee 9355 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 9356 gen_store_gpr(t0, rt);
5a5012ec 9357 break;
9c2149c8 9358 case OPC_DMTC1:
6c5c1e20 9359 gen_load_gpr(t0, rt);
72c3a3ee 9360 gen_store_fpr64(ctx, t0, fs);
5a5012ec 9361 break;
72c3a3ee 9362#endif
5a5012ec 9363 case OPC_MFHC1:
b6d96bed 9364 {
a7812ae4 9365 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9366
7f6613ce 9367 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 9368 tcg_gen_ext_i32_tl(t0, fp0);
6958549d 9369 }
6c5c1e20 9370 gen_store_gpr(t0, rt);
5a5012ec
TS
9371 break;
9372 case OPC_MTHC1:
6c5c1e20 9373 gen_load_gpr(t0, rt);
b6d96bed 9374 {
a7812ae4 9375 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9376
9377 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 9378 gen_store_fpr32h(ctx, fp0, fs);
6958549d 9379 }
5a5012ec 9380 break;
6ea83fed 9381 default:
9d68ac14 9382 MIPS_INVAL("cp1 move");
3a4ef3b7 9383 gen_reserved_instruction(ctx);
74fda465 9384 return;
6ea83fed 9385 }
6ea83fed
FB
9386}
9387
235785e8 9388static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
5a5012ec 9389{
42a268c2 9390 TCGLabel *l1;
e214b9bb 9391 TCGCond cond;
af58f9ca
AJ
9392 TCGv_i32 t0;
9393
9394 if (rd == 0) {
9395 /* Treat as NOP. */
9396 return;
9397 }
6ea83fed 9398
1f8929d2 9399 if (tf) {
e214b9bb 9400 cond = TCG_COND_EQ;
1f8929d2 9401 } else {
27848470 9402 cond = TCG_COND_NE;
1f8929d2 9403 }
27848470 9404
af58f9ca
AJ
9405 l1 = gen_new_label();
9406 t0 = tcg_temp_new_i32();
fa31af0e 9407 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 9408 tcg_gen_brcondi_i32(cond, t0, 0, l1);
c27b4579 9409 gen_load_gpr(cpu_gpr[rd], rs);
e214b9bb 9410 gen_set_label(l1);
5a5012ec
TS
9411}
9412
7c979afd
LA
9413static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9414 int tf)
a16336e4 9415{
a16336e4 9416 int cond;
cbc37b28 9417 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 9418 TCGLabel *l1 = gen_new_label();
a16336e4 9419
1f8929d2 9420 if (tf) {
a16336e4 9421 cond = TCG_COND_EQ;
1f8929d2 9422 } else {
a16336e4 9423 cond = TCG_COND_NE;
1f8929d2 9424 }
a16336e4 9425
fa31af0e 9426 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9427 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9428 gen_load_fpr32(ctx, t0, fs);
9429 gen_store_fpr32(ctx, t0, fd);
a16336e4 9430 gen_set_label(l1);
5a5012ec 9431}
a16336e4 9432
235785e8
AM
9433static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
9434 int tf)
a16336e4 9435{
a16336e4 9436 int cond;
cbc37b28
AJ
9437 TCGv_i32 t0 = tcg_temp_new_i32();
9438 TCGv_i64 fp0;
42a268c2 9439 TCGLabel *l1 = gen_new_label();
a16336e4 9440
1f8929d2 9441 if (tf) {
a16336e4 9442 cond = TCG_COND_EQ;
1f8929d2 9443 } else {
a16336e4 9444 cond = TCG_COND_NE;
1f8929d2 9445 }
a16336e4 9446
fa31af0e 9447 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9448 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11f94258 9449 fp0 = tcg_temp_new_i64();
9bf3eb2c 9450 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 9451 gen_store_fpr64(ctx, fp0, fd);
cbc37b28 9452 gen_set_label(l1);
a16336e4
TS
9453}
9454
7f6613ce
PJ
9455static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9456 int cc, int tf)
a16336e4
TS
9457{
9458 int cond;
cbc37b28 9459 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
9460 TCGLabel *l1 = gen_new_label();
9461 TCGLabel *l2 = gen_new_label();
a16336e4 9462
1f8929d2 9463 if (tf) {
a16336e4 9464 cond = TCG_COND_EQ;
1f8929d2 9465 } else {
a16336e4 9466 cond = TCG_COND_NE;
1f8929d2 9467 }
a16336e4 9468
fa31af0e 9469 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9470 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9471 gen_load_fpr32(ctx, t0, fs);
9472 gen_store_fpr32(ctx, t0, fd);
a16336e4 9473 gen_set_label(l1);
9bf3eb2c 9474
71375b59 9475 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
cbc37b28 9476 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
9477 gen_load_fpr32h(ctx, t0, fs);
9478 gen_store_fpr32h(ctx, t0, fd);
a16336e4 9479 gen_set_label(l2);
a16336e4
TS
9480}
9481
e7f16abb
LA
9482static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9483 int fs)
9484{
c29e79af 9485 TCGv_i32 t1 = tcg_constant_i32(0);
e7f16abb
LA
9486 TCGv_i32 fp0 = tcg_temp_new_i32();
9487 TCGv_i32 fp1 = tcg_temp_new_i32();
9488 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9489 gen_load_fpr32(ctx, fp0, fd);
9490 gen_load_fpr32(ctx, fp1, ft);
9491 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
9492
9493 switch (op1) {
9494 case OPC_SEL_S:
9495 tcg_gen_andi_i32(fp0, fp0, 1);
9496 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9497 break;
9498 case OPC_SELEQZ_S:
9499 tcg_gen_andi_i32(fp1, fp1, 1);
9500 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9501 break;
9502 case OPC_SELNEZ_S:
9503 tcg_gen_andi_i32(fp1, fp1, 1);
9504 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9505 break;
9506 default:
9507 MIPS_INVAL("gen_sel_s");
3a4ef3b7 9508 gen_reserved_instruction(ctx);
e7f16abb
LA
9509 break;
9510 }
9511
7c979afd 9512 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9513}
9514
9515static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9516 int fs)
9517{
c29e79af 9518 TCGv_i64 t1 = tcg_constant_i64(0);
e7f16abb
LA
9519 TCGv_i64 fp0 = tcg_temp_new_i64();
9520 TCGv_i64 fp1 = tcg_temp_new_i64();
9521 TCGv_i64 fp2 = tcg_temp_new_i64();
9522 gen_load_fpr64(ctx, fp0, fd);
9523 gen_load_fpr64(ctx, fp1, ft);
9524 gen_load_fpr64(ctx, fp2, fs);
9525
9526 switch (op1) {
9527 case OPC_SEL_D:
9528 tcg_gen_andi_i64(fp0, fp0, 1);
9529 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9530 break;
9531 case OPC_SELEQZ_D:
9532 tcg_gen_andi_i64(fp1, fp1, 1);
9533 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9534 break;
9535 case OPC_SELNEZ_D:
9536 tcg_gen_andi_i64(fp1, fp1, 1);
9537 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9538 break;
9539 default:
9540 MIPS_INVAL("gen_sel_d");
3a4ef3b7 9541 gen_reserved_instruction(ctx);
e7f16abb
LA
9542 break;
9543 }
9544
9545 gen_store_fpr64(ctx, fp0, fd);
e7f16abb 9546}
6ea83fed 9547
235785e8
AM
9548static void gen_farith(DisasContext *ctx, enum fopcode op1,
9549 int ft, int fs, int fd, int cc)
6ea83fed 9550{
7a387fff 9551 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
9552 switch (op1) {
9553 case OPC_ADD_S:
b6d96bed 9554 {
a7812ae4
PB
9555 TCGv_i32 fp0 = tcg_temp_new_i32();
9556 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9557
7c979afd
LA
9558 gen_load_fpr32(ctx, fp0, fs);
9559 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9560 gen_helper_float_add_s(fp0, tcg_env, fp0, fp1);
7c979afd 9561 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9562 }
5a5012ec 9563 break;
bf4120ad 9564 case OPC_SUB_S:
b6d96bed 9565 {
a7812ae4
PB
9566 TCGv_i32 fp0 = tcg_temp_new_i32();
9567 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9568
7c979afd
LA
9569 gen_load_fpr32(ctx, fp0, fs);
9570 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9571 gen_helper_float_sub_s(fp0, tcg_env, fp0, fp1);
7c979afd 9572 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9573 }
5a5012ec 9574 break;
bf4120ad 9575 case OPC_MUL_S:
b6d96bed 9576 {
a7812ae4
PB
9577 TCGv_i32 fp0 = tcg_temp_new_i32();
9578 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9579
7c979afd
LA
9580 gen_load_fpr32(ctx, fp0, fs);
9581 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9582 gen_helper_float_mul_s(fp0, tcg_env, fp0, fp1);
7c979afd 9583 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9584 }
5a5012ec 9585 break;
bf4120ad 9586 case OPC_DIV_S:
b6d96bed 9587 {
a7812ae4
PB
9588 TCGv_i32 fp0 = tcg_temp_new_i32();
9589 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9590
7c979afd
LA
9591 gen_load_fpr32(ctx, fp0, fs);
9592 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9593 gen_helper_float_div_s(fp0, tcg_env, fp0, fp1);
7c979afd 9594 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9595 }
5a5012ec 9596 break;
bf4120ad 9597 case OPC_SQRT_S:
b6d96bed 9598 {
a7812ae4 9599 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9600
7c979afd 9601 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9602 gen_helper_float_sqrt_s(fp0, tcg_env, fp0);
7c979afd 9603 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9604 }
5a5012ec 9605 break;
bf4120ad 9606 case OPC_ABS_S:
b6d96bed 9607 {
a7812ae4 9608 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9609
7c979afd 9610 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9611 if (ctx->abs2008) {
9612 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9613 } else {
9614 gen_helper_float_abs_s(fp0, fp0);
9615 }
7c979afd 9616 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9617 }
5a5012ec 9618 break;
bf4120ad 9619 case OPC_MOV_S:
b6d96bed 9620 {
a7812ae4 9621 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9622
7c979afd
LA
9623 gen_load_fpr32(ctx, fp0, fs);
9624 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9625 }
5a5012ec 9626 break;
bf4120ad 9627 case OPC_NEG_S:
b6d96bed 9628 {
a7812ae4 9629 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9630
7c979afd 9631 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9632 if (ctx->abs2008) {
9633 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9634 } else {
9635 gen_helper_float_chs_s(fp0, fp0);
9636 }
7c979afd 9637 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9638 }
5a5012ec 9639 break;
bf4120ad 9640 case OPC_ROUND_L_S:
5e755519 9641 check_cp1_64bitmode(ctx);
b6d96bed 9642 {
a7812ae4
PB
9643 TCGv_i32 fp32 = tcg_temp_new_i32();
9644 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9645
7c979afd 9646 gen_load_fpr32(ctx, fp32, fs);
87552089 9647 if (ctx->nan2008) {
ad75a51e 9648 gen_helper_float_round_2008_l_s(fp64, tcg_env, fp32);
87552089 9649 } else {
ad75a51e 9650 gen_helper_float_round_l_s(fp64, tcg_env, fp32);
87552089 9651 }
b6d96bed 9652 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9653 }
5a5012ec 9654 break;
bf4120ad 9655 case OPC_TRUNC_L_S:
5e755519 9656 check_cp1_64bitmode(ctx);
b6d96bed 9657 {
a7812ae4
PB
9658 TCGv_i32 fp32 = tcg_temp_new_i32();
9659 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9660
7c979afd 9661 gen_load_fpr32(ctx, fp32, fs);
87552089 9662 if (ctx->nan2008) {
ad75a51e 9663 gen_helper_float_trunc_2008_l_s(fp64, tcg_env, fp32);
87552089 9664 } else {
ad75a51e 9665 gen_helper_float_trunc_l_s(fp64, tcg_env, fp32);
87552089 9666 }
b6d96bed 9667 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9668 }
5a5012ec 9669 break;
bf4120ad 9670 case OPC_CEIL_L_S:
5e755519 9671 check_cp1_64bitmode(ctx);
b6d96bed 9672 {
a7812ae4
PB
9673 TCGv_i32 fp32 = tcg_temp_new_i32();
9674 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9675
7c979afd 9676 gen_load_fpr32(ctx, fp32, fs);
87552089 9677 if (ctx->nan2008) {
ad75a51e 9678 gen_helper_float_ceil_2008_l_s(fp64, tcg_env, fp32);
87552089 9679 } else {
ad75a51e 9680 gen_helper_float_ceil_l_s(fp64, tcg_env, fp32);
87552089 9681 }
b6d96bed 9682 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9683 }
5a5012ec 9684 break;
bf4120ad 9685 case OPC_FLOOR_L_S:
5e755519 9686 check_cp1_64bitmode(ctx);
b6d96bed 9687 {
a7812ae4
PB
9688 TCGv_i32 fp32 = tcg_temp_new_i32();
9689 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9690
7c979afd 9691 gen_load_fpr32(ctx, fp32, fs);
87552089 9692 if (ctx->nan2008) {
ad75a51e 9693 gen_helper_float_floor_2008_l_s(fp64, tcg_env, fp32);
87552089 9694 } else {
ad75a51e 9695 gen_helper_float_floor_l_s(fp64, tcg_env, fp32);
87552089 9696 }
b6d96bed 9697 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9698 }
5a5012ec 9699 break;
bf4120ad 9700 case OPC_ROUND_W_S:
b6d96bed 9701 {
a7812ae4 9702 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9703
7c979afd 9704 gen_load_fpr32(ctx, fp0, fs);
87552089 9705 if (ctx->nan2008) {
ad75a51e 9706 gen_helper_float_round_2008_w_s(fp0, tcg_env, fp0);
87552089 9707 } else {
ad75a51e 9708 gen_helper_float_round_w_s(fp0, tcg_env, fp0);
87552089 9709 }
7c979afd 9710 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9711 }
5a5012ec 9712 break;
bf4120ad 9713 case OPC_TRUNC_W_S:
b6d96bed 9714 {
a7812ae4 9715 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9716
7c979afd 9717 gen_load_fpr32(ctx, fp0, fs);
87552089 9718 if (ctx->nan2008) {
ad75a51e 9719 gen_helper_float_trunc_2008_w_s(fp0, tcg_env, fp0);
87552089 9720 } else {
ad75a51e 9721 gen_helper_float_trunc_w_s(fp0, tcg_env, fp0);
87552089 9722 }
7c979afd 9723 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9724 }
5a5012ec 9725 break;
bf4120ad 9726 case OPC_CEIL_W_S:
b6d96bed 9727 {
a7812ae4 9728 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9729
7c979afd 9730 gen_load_fpr32(ctx, fp0, fs);
87552089 9731 if (ctx->nan2008) {
ad75a51e 9732 gen_helper_float_ceil_2008_w_s(fp0, tcg_env, fp0);
87552089 9733 } else {
ad75a51e 9734 gen_helper_float_ceil_w_s(fp0, tcg_env, fp0);
87552089 9735 }
7c979afd 9736 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9737 }
5a5012ec 9738 break;
bf4120ad 9739 case OPC_FLOOR_W_S:
b6d96bed 9740 {
a7812ae4 9741 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9742
7c979afd 9743 gen_load_fpr32(ctx, fp0, fs);
87552089 9744 if (ctx->nan2008) {
ad75a51e 9745 gen_helper_float_floor_2008_w_s(fp0, tcg_env, fp0);
87552089 9746 } else {
ad75a51e 9747 gen_helper_float_floor_w_s(fp0, tcg_env, fp0);
87552089 9748 }
7c979afd 9749 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9750 }
5a5012ec 9751 break;
e7f16abb 9752 case OPC_SEL_S:
2e211e0a 9753 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 9754 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9755 break;
9756 case OPC_SELEQZ_S:
2e211e0a 9757 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 9758 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9759 break;
9760 case OPC_SELNEZ_S:
2e211e0a 9761 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 9762 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 9763 break;
bf4120ad 9764 case OPC_MOVCF_S:
2e211e0a 9765 check_insn_opc_removed(ctx, ISA_MIPS_R6);
7c979afd 9766 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 9767 break;
bf4120ad 9768 case OPC_MOVZ_S:
2e211e0a 9769 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 9770 {
42a268c2 9771 TCGLabel *l1 = gen_new_label();
c9297f4d 9772 TCGv_i32 fp0;
a16336e4 9773
c9297f4d
AJ
9774 if (ft != 0) {
9775 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9776 }
9777 fp0 = tcg_temp_new_i32();
7c979afd
LA
9778 gen_load_fpr32(ctx, fp0, fs);
9779 gen_store_fpr32(ctx, fp0, fd);
a16336e4
TS
9780 gen_set_label(l1);
9781 }
5a5012ec 9782 break;
bf4120ad 9783 case OPC_MOVN_S:
2e211e0a 9784 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 9785 {
42a268c2 9786 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
9787 TCGv_i32 fp0;
9788
9789 if (ft != 0) {
9790 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9791 fp0 = tcg_temp_new_i32();
7c979afd
LA
9792 gen_load_fpr32(ctx, fp0, fs);
9793 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
9794 gen_set_label(l1);
9795 }
a16336e4 9796 }
5a5012ec 9797 break;
bf4120ad 9798 case OPC_RECIP_S:
b6d96bed 9799 {
a7812ae4 9800 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9801
7c979afd 9802 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9803 gen_helper_float_recip_s(fp0, tcg_env, fp0);
7c979afd 9804 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9805 }
57fa1fb3 9806 break;
bf4120ad 9807 case OPC_RSQRT_S:
b6d96bed 9808 {
a7812ae4 9809 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9810
7c979afd 9811 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9812 gen_helper_float_rsqrt_s(fp0, tcg_env, fp0);
7c979afd 9813 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9814 }
57fa1fb3 9815 break;
e7f16abb 9816 case OPC_MADDF_S:
2e211e0a 9817 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 9818 {
a7812ae4
PB
9819 TCGv_i32 fp0 = tcg_temp_new_i32();
9820 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9821 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9822 gen_load_fpr32(ctx, fp0, fs);
9823 gen_load_fpr32(ctx, fp1, ft);
9824 gen_load_fpr32(ctx, fp2, fd);
ad75a51e 9825 gen_helper_float_maddf_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 9826 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 9827 }
57fa1fb3 9828 break;
e7f16abb 9829 case OPC_MSUBF_S:
2e211e0a 9830 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 9831 {
a7812ae4 9832 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
9833 TCGv_i32 fp1 = tcg_temp_new_i32();
9834 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9835 gen_load_fpr32(ctx, fp0, fs);
9836 gen_load_fpr32(ctx, fp1, ft);
9837 gen_load_fpr32(ctx, fp2, fd);
ad75a51e 9838 gen_helper_float_msubf_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 9839 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 9840 }
57fa1fb3 9841 break;
e7f16abb 9842 case OPC_RINT_S:
2e211e0a 9843 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 9844 {
a7812ae4 9845 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9846 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9847 gen_helper_float_rint_s(fp0, tcg_env, fp0);
7c979afd 9848 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9849 }
57fa1fb3 9850 break;
e7f16abb 9851 case OPC_CLASS_S:
2e211e0a 9852 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 9853 {
e7f16abb 9854 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9855 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9856 gen_helper_float_class_s(fp0, tcg_env, fp0);
7c979afd 9857 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9858 }
9859 break;
9860 case OPC_MIN_S: /* OPC_RECIP2_S */
2e211e0a 9861 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 9862 /* OPC_MIN_S */
a7812ae4
PB
9863 TCGv_i32 fp0 = tcg_temp_new_i32();
9864 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9865 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9866 gen_load_fpr32(ctx, fp0, fs);
9867 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9868 gen_helper_float_min_s(fp2, tcg_env, fp0, fp1);
7c979afd 9869 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9870 } else {
9871 /* OPC_RECIP2_S */
9872 check_cp1_64bitmode(ctx);
9873 {
9874 TCGv_i32 fp0 = tcg_temp_new_i32();
9875 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9876
7c979afd
LA
9877 gen_load_fpr32(ctx, fp0, fs);
9878 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9879 gen_helper_float_recip2_s(fp0, tcg_env, fp0, fp1);
7c979afd 9880 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9881 }
e7f16abb
LA
9882 }
9883 break;
9884 case OPC_MINA_S: /* OPC_RECIP1_S */
2e211e0a 9885 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
9886 /* OPC_MINA_S */
9887 TCGv_i32 fp0 = tcg_temp_new_i32();
9888 TCGv_i32 fp1 = tcg_temp_new_i32();
9889 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9890 gen_load_fpr32(ctx, fp0, fs);
9891 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9892 gen_helper_float_mina_s(fp2, tcg_env, fp0, fp1);
7c979afd 9893 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9894 } else {
9895 /* OPC_RECIP1_S */
9896 check_cp1_64bitmode(ctx);
9897 {
9898 TCGv_i32 fp0 = tcg_temp_new_i32();
9899
7c979afd 9900 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9901 gen_helper_float_recip1_s(fp0, tcg_env, fp0);
7c979afd 9902 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9903 }
e7f16abb
LA
9904 }
9905 break;
9906 case OPC_MAX_S: /* OPC_RSQRT1_S */
2e211e0a 9907 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
9908 /* OPC_MAX_S */
9909 TCGv_i32 fp0 = tcg_temp_new_i32();
9910 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
9911 gen_load_fpr32(ctx, fp0, fs);
9912 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9913 gen_helper_float_max_s(fp1, tcg_env, fp0, fp1);
7c979afd 9914 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
9915 } else {
9916 /* OPC_RSQRT1_S */
9917 check_cp1_64bitmode(ctx);
9918 {
9919 TCGv_i32 fp0 = tcg_temp_new_i32();
9920
7c979afd 9921 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 9922 gen_helper_float_rsqrt1_s(fp0, tcg_env, fp0);
7c979afd 9923 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9924 }
e7f16abb
LA
9925 }
9926 break;
9927 case OPC_MAXA_S: /* OPC_RSQRT2_S */
2e211e0a 9928 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
9929 /* OPC_MAXA_S */
9930 TCGv_i32 fp0 = tcg_temp_new_i32();
9931 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
9932 gen_load_fpr32(ctx, fp0, fs);
9933 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9934 gen_helper_float_maxa_s(fp1, tcg_env, fp0, fp1);
7c979afd 9935 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
9936 } else {
9937 /* OPC_RSQRT2_S */
9938 check_cp1_64bitmode(ctx);
9939 {
9940 TCGv_i32 fp0 = tcg_temp_new_i32();
9941 TCGv_i32 fp1 = tcg_temp_new_i32();
9942
7c979afd
LA
9943 gen_load_fpr32(ctx, fp0, fs);
9944 gen_load_fpr32(ctx, fp1, ft);
ad75a51e 9945 gen_helper_float_rsqrt2_s(fp0, tcg_env, fp0, fp1);
7c979afd 9946 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9947 }
b6d96bed 9948 }
57fa1fb3 9949 break;
bf4120ad 9950 case OPC_CVT_D_S:
5e755519 9951 check_cp1_registers(ctx, fd);
b6d96bed 9952 {
a7812ae4
PB
9953 TCGv_i32 fp32 = tcg_temp_new_i32();
9954 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9955
7c979afd 9956 gen_load_fpr32(ctx, fp32, fs);
ad75a51e 9957 gen_helper_float_cvtd_s(fp64, tcg_env, fp32);
b6d96bed 9958 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9959 }
5a5012ec 9960 break;
bf4120ad 9961 case OPC_CVT_W_S:
b6d96bed 9962 {
a7812ae4 9963 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9964
7c979afd 9965 gen_load_fpr32(ctx, fp0, fs);
87552089 9966 if (ctx->nan2008) {
ad75a51e 9967 gen_helper_float_cvt_2008_w_s(fp0, tcg_env, fp0);
87552089 9968 } else {
ad75a51e 9969 gen_helper_float_cvt_w_s(fp0, tcg_env, fp0);
87552089 9970 }
7c979afd 9971 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 9972 }
5a5012ec 9973 break;
bf4120ad 9974 case OPC_CVT_L_S:
5e755519 9975 check_cp1_64bitmode(ctx);
b6d96bed 9976 {
a7812ae4
PB
9977 TCGv_i32 fp32 = tcg_temp_new_i32();
9978 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9979
7c979afd 9980 gen_load_fpr32(ctx, fp32, fs);
87552089 9981 if (ctx->nan2008) {
ad75a51e 9982 gen_helper_float_cvt_2008_l_s(fp64, tcg_env, fp32);
87552089 9983 } else {
ad75a51e 9984 gen_helper_float_cvt_l_s(fp64, tcg_env, fp32);
87552089 9985 }
b6d96bed 9986 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 9987 }
5a5012ec 9988 break;
bf4120ad 9989 case OPC_CVT_PS_S:
e29c9628 9990 check_ps(ctx);
b6d96bed 9991 {
a7812ae4
PB
9992 TCGv_i64 fp64 = tcg_temp_new_i64();
9993 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9994 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 9995
7c979afd
LA
9996 gen_load_fpr32(ctx, fp32_0, fs);
9997 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 9998 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
36aa55dc 9999 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 10000 }
5a5012ec 10001 break;
bf4120ad
NF
10002 case OPC_CMP_F_S:
10003 case OPC_CMP_UN_S:
10004 case OPC_CMP_EQ_S:
10005 case OPC_CMP_UEQ_S:
10006 case OPC_CMP_OLT_S:
10007 case OPC_CMP_ULT_S:
10008 case OPC_CMP_OLE_S:
10009 case OPC_CMP_ULE_S:
10010 case OPC_CMP_SF_S:
10011 case OPC_CMP_NGLE_S:
10012 case OPC_CMP_SEQ_S:
10013 case OPC_CMP_NGL_S:
10014 case OPC_CMP_LT_S:
10015 case OPC_CMP_NGE_S:
10016 case OPC_CMP_LE_S:
10017 case OPC_CMP_NGT_S:
2e211e0a 10018 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 10019 if (ctx->opcode & (1 << 6)) {
71375b59 10020 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
8153667c 10021 } else {
71375b59 10022 gen_cmp_s(ctx, func - 48, ft, fs, cc);
5a1e8ffb 10023 }
5a5012ec 10024 break;
bf4120ad 10025 case OPC_ADD_D:
5e755519 10026 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10027 {
a7812ae4
PB
10028 TCGv_i64 fp0 = tcg_temp_new_i64();
10029 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10030
10031 gen_load_fpr64(ctx, fp0, fs);
10032 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10033 gen_helper_float_add_d(fp0, tcg_env, fp0, fp1);
b6d96bed 10034 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10035 }
6ea83fed 10036 break;
bf4120ad 10037 case OPC_SUB_D:
5e755519 10038 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10039 {
a7812ae4
PB
10040 TCGv_i64 fp0 = tcg_temp_new_i64();
10041 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10042
10043 gen_load_fpr64(ctx, fp0, fs);
10044 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10045 gen_helper_float_sub_d(fp0, tcg_env, fp0, fp1);
b6d96bed 10046 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10047 }
6ea83fed 10048 break;
bf4120ad 10049 case OPC_MUL_D:
5e755519 10050 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10051 {
a7812ae4
PB
10052 TCGv_i64 fp0 = tcg_temp_new_i64();
10053 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10054
10055 gen_load_fpr64(ctx, fp0, fs);
10056 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10057 gen_helper_float_mul_d(fp0, tcg_env, fp0, fp1);
b6d96bed 10058 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10059 }
6ea83fed 10060 break;
bf4120ad 10061 case OPC_DIV_D:
5e755519 10062 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10063 {
a7812ae4
PB
10064 TCGv_i64 fp0 = tcg_temp_new_i64();
10065 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10066
10067 gen_load_fpr64(ctx, fp0, fs);
10068 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10069 gen_helper_float_div_d(fp0, tcg_env, fp0, fp1);
b6d96bed 10070 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10071 }
6ea83fed 10072 break;
bf4120ad 10073 case OPC_SQRT_D:
5e755519 10074 check_cp1_registers(ctx, fs | fd);
b6d96bed 10075 {
a7812ae4 10076 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10077
10078 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10079 gen_helper_float_sqrt_d(fp0, tcg_env, fp0);
b6d96bed 10080 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10081 }
6ea83fed 10082 break;
bf4120ad 10083 case OPC_ABS_D:
5e755519 10084 check_cp1_registers(ctx, fs | fd);
b6d96bed 10085 {
a7812ae4 10086 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10087
10088 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10089 if (ctx->abs2008) {
10090 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10091 } else {
10092 gen_helper_float_abs_d(fp0, fp0);
10093 }
b6d96bed 10094 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10095 }
6ea83fed 10096 break;
bf4120ad 10097 case OPC_MOV_D:
5e755519 10098 check_cp1_registers(ctx, fs | fd);
b6d96bed 10099 {
a7812ae4 10100 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10101
10102 gen_load_fpr64(ctx, fp0, fs);
10103 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10104 }
6ea83fed 10105 break;
bf4120ad 10106 case OPC_NEG_D:
5e755519 10107 check_cp1_registers(ctx, fs | fd);
b6d96bed 10108 {
a7812ae4 10109 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10110
10111 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10112 if (ctx->abs2008) {
10113 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10114 } else {
10115 gen_helper_float_chs_d(fp0, fp0);
10116 }
b6d96bed 10117 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10118 }
6ea83fed 10119 break;
bf4120ad 10120 case OPC_ROUND_L_D:
5e755519 10121 check_cp1_64bitmode(ctx);
b6d96bed 10122 {
a7812ae4 10123 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10124
10125 gen_load_fpr64(ctx, fp0, fs);
87552089 10126 if (ctx->nan2008) {
ad75a51e 10127 gen_helper_float_round_2008_l_d(fp0, tcg_env, fp0);
87552089 10128 } else {
ad75a51e 10129 gen_helper_float_round_l_d(fp0, tcg_env, fp0);
87552089 10130 }
b6d96bed 10131 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10132 }
5a5012ec 10133 break;
bf4120ad 10134 case OPC_TRUNC_L_D:
5e755519 10135 check_cp1_64bitmode(ctx);
b6d96bed 10136 {
a7812ae4 10137 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10138
10139 gen_load_fpr64(ctx, fp0, fs);
87552089 10140 if (ctx->nan2008) {
ad75a51e 10141 gen_helper_float_trunc_2008_l_d(fp0, tcg_env, fp0);
87552089 10142 } else {
ad75a51e 10143 gen_helper_float_trunc_l_d(fp0, tcg_env, fp0);
87552089 10144 }
b6d96bed 10145 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10146 }
5a5012ec 10147 break;
bf4120ad 10148 case OPC_CEIL_L_D:
5e755519 10149 check_cp1_64bitmode(ctx);
b6d96bed 10150 {
a7812ae4 10151 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10152
10153 gen_load_fpr64(ctx, fp0, fs);
87552089 10154 if (ctx->nan2008) {
ad75a51e 10155 gen_helper_float_ceil_2008_l_d(fp0, tcg_env, fp0);
87552089 10156 } else {
ad75a51e 10157 gen_helper_float_ceil_l_d(fp0, tcg_env, fp0);
87552089 10158 }
b6d96bed 10159 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10160 }
5a5012ec 10161 break;
bf4120ad 10162 case OPC_FLOOR_L_D:
5e755519 10163 check_cp1_64bitmode(ctx);
b6d96bed 10164 {
a7812ae4 10165 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10166
10167 gen_load_fpr64(ctx, fp0, fs);
87552089 10168 if (ctx->nan2008) {
ad75a51e 10169 gen_helper_float_floor_2008_l_d(fp0, tcg_env, fp0);
87552089 10170 } else {
ad75a51e 10171 gen_helper_float_floor_l_d(fp0, tcg_env, fp0);
87552089 10172 }
b6d96bed 10173 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10174 }
5a5012ec 10175 break;
bf4120ad 10176 case OPC_ROUND_W_D:
5e755519 10177 check_cp1_registers(ctx, fs);
b6d96bed 10178 {
a7812ae4
PB
10179 TCGv_i32 fp32 = tcg_temp_new_i32();
10180 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10181
10182 gen_load_fpr64(ctx, fp64, fs);
87552089 10183 if (ctx->nan2008) {
ad75a51e 10184 gen_helper_float_round_2008_w_d(fp32, tcg_env, fp64);
87552089 10185 } else {
ad75a51e 10186 gen_helper_float_round_w_d(fp32, tcg_env, fp64);
87552089 10187 }
7c979afd 10188 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10189 }
6ea83fed 10190 break;
bf4120ad 10191 case OPC_TRUNC_W_D:
5e755519 10192 check_cp1_registers(ctx, fs);
b6d96bed 10193 {
a7812ae4
PB
10194 TCGv_i32 fp32 = tcg_temp_new_i32();
10195 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10196
10197 gen_load_fpr64(ctx, fp64, fs);
87552089 10198 if (ctx->nan2008) {
ad75a51e 10199 gen_helper_float_trunc_2008_w_d(fp32, tcg_env, fp64);
87552089 10200 } else {
ad75a51e 10201 gen_helper_float_trunc_w_d(fp32, tcg_env, fp64);
87552089 10202 }
7c979afd 10203 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10204 }
6ea83fed 10205 break;
bf4120ad 10206 case OPC_CEIL_W_D:
5e755519 10207 check_cp1_registers(ctx, fs);
b6d96bed 10208 {
a7812ae4
PB
10209 TCGv_i32 fp32 = tcg_temp_new_i32();
10210 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10211
10212 gen_load_fpr64(ctx, fp64, fs);
87552089 10213 if (ctx->nan2008) {
ad75a51e 10214 gen_helper_float_ceil_2008_w_d(fp32, tcg_env, fp64);
87552089 10215 } else {
ad75a51e 10216 gen_helper_float_ceil_w_d(fp32, tcg_env, fp64);
87552089 10217 }
7c979afd 10218 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10219 }
6ea83fed 10220 break;
bf4120ad 10221 case OPC_FLOOR_W_D:
5e755519 10222 check_cp1_registers(ctx, fs);
b6d96bed 10223 {
a7812ae4
PB
10224 TCGv_i32 fp32 = tcg_temp_new_i32();
10225 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10226
10227 gen_load_fpr64(ctx, fp64, fs);
87552089 10228 if (ctx->nan2008) {
ad75a51e 10229 gen_helper_float_floor_2008_w_d(fp32, tcg_env, fp64);
87552089 10230 } else {
ad75a51e 10231 gen_helper_float_floor_w_d(fp32, tcg_env, fp64);
87552089 10232 }
7c979afd 10233 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10234 }
6ea83fed 10235 break;
e7f16abb 10236 case OPC_SEL_D:
2e211e0a 10237 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10238 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10239 break;
10240 case OPC_SELEQZ_D:
2e211e0a 10241 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10242 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10243 break;
10244 case OPC_SELNEZ_D:
2e211e0a 10245 check_insn(ctx, ISA_MIPS_R6);
e7f16abb 10246 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 10247 break;
bf4120ad 10248 case OPC_MOVCF_D:
2e211e0a 10249 check_insn_opc_removed(ctx, ISA_MIPS_R6);
b6d96bed 10250 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 10251 break;
bf4120ad 10252 case OPC_MOVZ_D:
2e211e0a 10253 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10254 {
42a268c2 10255 TCGLabel *l1 = gen_new_label();
c9297f4d 10256 TCGv_i64 fp0;
a16336e4 10257
c9297f4d
AJ
10258 if (ft != 0) {
10259 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10260 }
10261 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10262 gen_load_fpr64(ctx, fp0, fs);
10263 gen_store_fpr64(ctx, fp0, fd);
a16336e4
TS
10264 gen_set_label(l1);
10265 }
5a5012ec 10266 break;
bf4120ad 10267 case OPC_MOVN_D:
2e211e0a 10268 check_insn_opc_removed(ctx, ISA_MIPS_R6);
a16336e4 10269 {
42a268c2 10270 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10271 TCGv_i64 fp0;
10272
10273 if (ft != 0) {
10274 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10275 fp0 = tcg_temp_new_i64();
10276 gen_load_fpr64(ctx, fp0, fs);
10277 gen_store_fpr64(ctx, fp0, fd);
c9297f4d
AJ
10278 gen_set_label(l1);
10279 }
a16336e4 10280 }
6ea83fed 10281 break;
bf4120ad 10282 case OPC_RECIP_D:
ca6c7803 10283 check_cp1_registers(ctx, fs | fd);
b6d96bed 10284 {
a7812ae4 10285 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10286
10287 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10288 gen_helper_float_recip_d(fp0, tcg_env, fp0);
b6d96bed 10289 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10290 }
57fa1fb3 10291 break;
bf4120ad 10292 case OPC_RSQRT_D:
ca6c7803 10293 check_cp1_registers(ctx, fs | fd);
b6d96bed 10294 {
a7812ae4 10295 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10296
10297 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10298 gen_helper_float_rsqrt_d(fp0, tcg_env, fp0);
b6d96bed 10299 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10300 }
57fa1fb3 10301 break;
e7f16abb 10302 case OPC_MADDF_D:
2e211e0a 10303 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10304 {
a7812ae4
PB
10305 TCGv_i64 fp0 = tcg_temp_new_i64();
10306 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 10307 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10308 gen_load_fpr64(ctx, fp0, fs);
10309 gen_load_fpr64(ctx, fp1, ft);
e7f16abb 10310 gen_load_fpr64(ctx, fp2, fd);
ad75a51e 10311 gen_helper_float_maddf_d(fp2, tcg_env, fp0, fp1, fp2);
e7f16abb 10312 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 10313 }
57fa1fb3 10314 break;
e7f16abb 10315 case OPC_MSUBF_D:
2e211e0a 10316 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10317 {
a7812ae4 10318 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
10319 TCGv_i64 fp1 = tcg_temp_new_i64();
10320 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 10321 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
10322 gen_load_fpr64(ctx, fp1, ft);
10323 gen_load_fpr64(ctx, fp2, fd);
ad75a51e 10324 gen_helper_float_msubf_d(fp2, tcg_env, fp0, fp1, fp2);
e7f16abb 10325 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 10326 }
57fa1fb3 10327 break;
e7f16abb 10328 case OPC_RINT_D:
2e211e0a 10329 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10330 {
a7812ae4 10331 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10332 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10333 gen_helper_float_rint_d(fp0, tcg_env, fp0);
b6d96bed 10334 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10335 }
57fa1fb3 10336 break;
e7f16abb 10337 case OPC_CLASS_D:
2e211e0a 10338 check_insn(ctx, ISA_MIPS_R6);
b6d96bed 10339 {
e7f16abb
LA
10340 TCGv_i64 fp0 = tcg_temp_new_i64();
10341 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10342 gen_helper_float_class_d(fp0, tcg_env, fp0);
e7f16abb 10343 gen_store_fpr64(ctx, fp0, fd);
e7f16abb
LA
10344 }
10345 break;
10346 case OPC_MIN_D: /* OPC_RECIP2_D */
2e211e0a 10347 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb 10348 /* OPC_MIN_D */
a7812ae4
PB
10349 TCGv_i64 fp0 = tcg_temp_new_i64();
10350 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
10351 gen_load_fpr64(ctx, fp0, fs);
10352 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10353 gen_helper_float_min_d(fp1, tcg_env, fp0, fp1);
e7f16abb 10354 gen_store_fpr64(ctx, fp1, fd);
e7f16abb
LA
10355 } else {
10356 /* OPC_RECIP2_D */
10357 check_cp1_64bitmode(ctx);
10358 {
10359 TCGv_i64 fp0 = tcg_temp_new_i64();
10360 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 10361
e7f16abb
LA
10362 gen_load_fpr64(ctx, fp0, fs);
10363 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10364 gen_helper_float_recip2_d(fp0, tcg_env, fp0, fp1);
e7f16abb 10365 gen_store_fpr64(ctx, fp0, fd);
e7f16abb 10366 }
e7f16abb
LA
10367 }
10368 break;
10369 case OPC_MINA_D: /* OPC_RECIP1_D */
2e211e0a 10370 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10371 /* OPC_MINA_D */
10372 TCGv_i64 fp0 = tcg_temp_new_i64();
10373 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10374 gen_load_fpr64(ctx, fp0, fs);
10375 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10376 gen_helper_float_mina_d(fp1, tcg_env, fp0, fp1);
e7f16abb 10377 gen_store_fpr64(ctx, fp1, fd);
e7f16abb
LA
10378 } else {
10379 /* OPC_RECIP1_D */
10380 check_cp1_64bitmode(ctx);
10381 {
10382 TCGv_i64 fp0 = tcg_temp_new_i64();
10383
10384 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10385 gen_helper_float_recip1_d(fp0, tcg_env, fp0);
e7f16abb 10386 gen_store_fpr64(ctx, fp0, fd);
e7f16abb 10387 }
e7f16abb
LA
10388 }
10389 break;
10390 case OPC_MAX_D: /* OPC_RSQRT1_D */
2e211e0a 10391 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10392 /* OPC_MAX_D */
10393 TCGv_i64 fp0 = tcg_temp_new_i64();
10394 TCGv_i64 fp1 = tcg_temp_new_i64();
10395 gen_load_fpr64(ctx, fp0, fs);
10396 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10397 gen_helper_float_max_d(fp1, tcg_env, fp0, fp1);
e7f16abb 10398 gen_store_fpr64(ctx, fp1, fd);
e7f16abb
LA
10399 } else {
10400 /* OPC_RSQRT1_D */
10401 check_cp1_64bitmode(ctx);
10402 {
10403 TCGv_i64 fp0 = tcg_temp_new_i64();
10404
10405 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10406 gen_helper_float_rsqrt1_d(fp0, tcg_env, fp0);
e7f16abb 10407 gen_store_fpr64(ctx, fp0, fd);
e7f16abb 10408 }
e7f16abb
LA
10409 }
10410 break;
10411 case OPC_MAXA_D: /* OPC_RSQRT2_D */
2e211e0a 10412 if (ctx->insn_flags & ISA_MIPS_R6) {
e7f16abb
LA
10413 /* OPC_MAXA_D */
10414 TCGv_i64 fp0 = tcg_temp_new_i64();
10415 TCGv_i64 fp1 = tcg_temp_new_i64();
10416 gen_load_fpr64(ctx, fp0, fs);
10417 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10418 gen_helper_float_maxa_d(fp1, tcg_env, fp0, fp1);
e7f16abb 10419 gen_store_fpr64(ctx, fp1, fd);
e7f16abb
LA
10420 } else {
10421 /* OPC_RSQRT2_D */
10422 check_cp1_64bitmode(ctx);
10423 {
10424 TCGv_i64 fp0 = tcg_temp_new_i64();
10425 TCGv_i64 fp1 = tcg_temp_new_i64();
10426
10427 gen_load_fpr64(ctx, fp0, fs);
10428 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10429 gen_helper_float_rsqrt2_d(fp0, tcg_env, fp0, fp1);
e7f16abb 10430 gen_store_fpr64(ctx, fp0, fd);
e7f16abb 10431 }
b6d96bed 10432 }
57fa1fb3 10433 break;
bf4120ad
NF
10434 case OPC_CMP_F_D:
10435 case OPC_CMP_UN_D:
10436 case OPC_CMP_EQ_D:
10437 case OPC_CMP_UEQ_D:
10438 case OPC_CMP_OLT_D:
10439 case OPC_CMP_ULT_D:
10440 case OPC_CMP_OLE_D:
10441 case OPC_CMP_ULE_D:
10442 case OPC_CMP_SF_D:
10443 case OPC_CMP_NGLE_D:
10444 case OPC_CMP_SEQ_D:
10445 case OPC_CMP_NGL_D:
10446 case OPC_CMP_LT_D:
10447 case OPC_CMP_NGE_D:
10448 case OPC_CMP_LE_D:
10449 case OPC_CMP_NGT_D:
2e211e0a 10450 check_insn_opc_removed(ctx, ISA_MIPS_R6);
8153667c 10451 if (ctx->opcode & (1 << 6)) {
71375b59 10452 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
8153667c 10453 } else {
71375b59 10454 gen_cmp_d(ctx, func - 48, ft, fs, cc);
5a1e8ffb 10455 }
6ea83fed 10456 break;
bf4120ad 10457 case OPC_CVT_S_D:
5e755519 10458 check_cp1_registers(ctx, fs);
b6d96bed 10459 {
a7812ae4
PB
10460 TCGv_i32 fp32 = tcg_temp_new_i32();
10461 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10462
10463 gen_load_fpr64(ctx, fp64, fs);
ad75a51e 10464 gen_helper_float_cvts_d(fp32, tcg_env, fp64);
7c979afd 10465 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10466 }
5a5012ec 10467 break;
bf4120ad 10468 case OPC_CVT_W_D:
5e755519 10469 check_cp1_registers(ctx, fs);
b6d96bed 10470 {
a7812ae4
PB
10471 TCGv_i32 fp32 = tcg_temp_new_i32();
10472 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10473
10474 gen_load_fpr64(ctx, fp64, fs);
87552089 10475 if (ctx->nan2008) {
ad75a51e 10476 gen_helper_float_cvt_2008_w_d(fp32, tcg_env, fp64);
87552089 10477 } else {
ad75a51e 10478 gen_helper_float_cvt_w_d(fp32, tcg_env, fp64);
87552089 10479 }
7c979afd 10480 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10481 }
5a5012ec 10482 break;
bf4120ad 10483 case OPC_CVT_L_D:
5e755519 10484 check_cp1_64bitmode(ctx);
b6d96bed 10485 {
a7812ae4 10486 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10487
10488 gen_load_fpr64(ctx, fp0, fs);
87552089 10489 if (ctx->nan2008) {
ad75a51e 10490 gen_helper_float_cvt_2008_l_d(fp0, tcg_env, fp0);
87552089 10491 } else {
ad75a51e 10492 gen_helper_float_cvt_l_d(fp0, tcg_env, fp0);
87552089 10493 }
b6d96bed 10494 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10495 }
5a5012ec 10496 break;
bf4120ad 10497 case OPC_CVT_S_W:
b6d96bed 10498 {
a7812ae4 10499 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10500
7c979afd 10501 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 10502 gen_helper_float_cvts_w(fp0, tcg_env, fp0);
7c979afd 10503 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 10504 }
6ea83fed 10505 break;
bf4120ad 10506 case OPC_CVT_D_W:
5e755519 10507 check_cp1_registers(ctx, fd);
b6d96bed 10508 {
a7812ae4
PB
10509 TCGv_i32 fp32 = tcg_temp_new_i32();
10510 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10511
7c979afd 10512 gen_load_fpr32(ctx, fp32, fs);
ad75a51e 10513 gen_helper_float_cvtd_w(fp64, tcg_env, fp32);
b6d96bed 10514 gen_store_fpr64(ctx, fp64, fd);
b6d96bed 10515 }
5a5012ec 10516 break;
bf4120ad 10517 case OPC_CVT_S_L:
5e755519 10518 check_cp1_64bitmode(ctx);
b6d96bed 10519 {
a7812ae4
PB
10520 TCGv_i32 fp32 = tcg_temp_new_i32();
10521 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10522
10523 gen_load_fpr64(ctx, fp64, fs);
ad75a51e 10524 gen_helper_float_cvts_l(fp32, tcg_env, fp64);
7c979afd 10525 gen_store_fpr32(ctx, fp32, fd);
b6d96bed 10526 }
5a5012ec 10527 break;
bf4120ad 10528 case OPC_CVT_D_L:
5e755519 10529 check_cp1_64bitmode(ctx);
b6d96bed 10530 {
a7812ae4 10531 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10532
10533 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10534 gen_helper_float_cvtd_l(fp0, tcg_env, fp0);
b6d96bed 10535 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10536 }
5a5012ec 10537 break;
bf4120ad 10538 case OPC_CVT_PS_PW:
e29c9628 10539 check_ps(ctx);
b6d96bed 10540 {
a7812ae4 10541 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10542
10543 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10544 gen_helper_float_cvtps_pw(fp0, tcg_env, fp0);
b6d96bed 10545 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10546 }
5a5012ec 10547 break;
bf4120ad 10548 case OPC_ADD_PS:
e29c9628 10549 check_ps(ctx);
b6d96bed 10550 {
a7812ae4
PB
10551 TCGv_i64 fp0 = tcg_temp_new_i64();
10552 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10553
10554 gen_load_fpr64(ctx, fp0, fs);
10555 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10556 gen_helper_float_add_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10557 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10558 }
6ea83fed 10559 break;
bf4120ad 10560 case OPC_SUB_PS:
e29c9628 10561 check_ps(ctx);
b6d96bed 10562 {
a7812ae4
PB
10563 TCGv_i64 fp0 = tcg_temp_new_i64();
10564 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10565
10566 gen_load_fpr64(ctx, fp0, fs);
10567 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10568 gen_helper_float_sub_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10569 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10570 }
6ea83fed 10571 break;
bf4120ad 10572 case OPC_MUL_PS:
e29c9628 10573 check_ps(ctx);
b6d96bed 10574 {
a7812ae4
PB
10575 TCGv_i64 fp0 = tcg_temp_new_i64();
10576 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10577
10578 gen_load_fpr64(ctx, fp0, fs);
10579 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10580 gen_helper_float_mul_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10581 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10582 }
6ea83fed 10583 break;
bf4120ad 10584 case OPC_ABS_PS:
e29c9628 10585 check_ps(ctx);
b6d96bed 10586 {
a7812ae4 10587 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10588
10589 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10590 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 10591 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10592 }
6ea83fed 10593 break;
bf4120ad 10594 case OPC_MOV_PS:
e29c9628 10595 check_ps(ctx);
b6d96bed 10596 {
a7812ae4 10597 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10598
10599 gen_load_fpr64(ctx, fp0, fs);
10600 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10601 }
6ea83fed 10602 break;
bf4120ad 10603 case OPC_NEG_PS:
e29c9628 10604 check_ps(ctx);
b6d96bed 10605 {
a7812ae4 10606 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10607
10608 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10609 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 10610 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10611 }
6ea83fed 10612 break;
bf4120ad 10613 case OPC_MOVCF_PS:
e29c9628 10614 check_ps(ctx);
7f6613ce 10615 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 10616 break;
bf4120ad 10617 case OPC_MOVZ_PS:
e29c9628 10618 check_ps(ctx);
a16336e4 10619 {
42a268c2 10620 TCGLabel *l1 = gen_new_label();
30a3848b 10621 TCGv_i64 fp0;
a16336e4 10622
1f8929d2 10623 if (ft != 0) {
c9297f4d 10624 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
1f8929d2 10625 }
c9297f4d
AJ
10626 fp0 = tcg_temp_new_i64();
10627 gen_load_fpr64(ctx, fp0, fs);
10628 gen_store_fpr64(ctx, fp0, fd);
a16336e4
TS
10629 gen_set_label(l1);
10630 }
6ea83fed 10631 break;
bf4120ad 10632 case OPC_MOVN_PS:
e29c9628 10633 check_ps(ctx);
a16336e4 10634 {
42a268c2 10635 TCGLabel *l1 = gen_new_label();
30a3848b 10636 TCGv_i64 fp0;
c9297f4d
AJ
10637
10638 if (ft != 0) {
10639 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10640 fp0 = tcg_temp_new_i64();
10641 gen_load_fpr64(ctx, fp0, fs);
10642 gen_store_fpr64(ctx, fp0, fd);
c9297f4d
AJ
10643 gen_set_label(l1);
10644 }
a16336e4 10645 }
6ea83fed 10646 break;
bf4120ad 10647 case OPC_ADDR_PS:
e29c9628 10648 check_ps(ctx);
b6d96bed 10649 {
a7812ae4
PB
10650 TCGv_i64 fp0 = tcg_temp_new_i64();
10651 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10652
10653 gen_load_fpr64(ctx, fp0, ft);
10654 gen_load_fpr64(ctx, fp1, fs);
ad75a51e 10655 gen_helper_float_addr_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10656 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10657 }
fbcc6828 10658 break;
bf4120ad 10659 case OPC_MULR_PS:
e29c9628 10660 check_ps(ctx);
b6d96bed 10661 {
a7812ae4
PB
10662 TCGv_i64 fp0 = tcg_temp_new_i64();
10663 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10664
10665 gen_load_fpr64(ctx, fp0, ft);
10666 gen_load_fpr64(ctx, fp1, fs);
ad75a51e 10667 gen_helper_float_mulr_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10668 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10669 }
57fa1fb3 10670 break;
bf4120ad 10671 case OPC_RECIP2_PS:
e29c9628 10672 check_ps(ctx);
b6d96bed 10673 {
a7812ae4
PB
10674 TCGv_i64 fp0 = tcg_temp_new_i64();
10675 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10676
10677 gen_load_fpr64(ctx, fp0, fs);
d22d7289 10678 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10679 gen_helper_float_recip2_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10680 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10681 }
57fa1fb3 10682 break;
bf4120ad 10683 case OPC_RECIP1_PS:
e29c9628 10684 check_ps(ctx);
b6d96bed 10685 {
a7812ae4 10686 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10687
10688 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10689 gen_helper_float_recip1_ps(fp0, tcg_env, fp0);
b6d96bed 10690 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10691 }
57fa1fb3 10692 break;
bf4120ad 10693 case OPC_RSQRT1_PS:
e29c9628 10694 check_ps(ctx);
b6d96bed 10695 {
a7812ae4 10696 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10697
10698 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10699 gen_helper_float_rsqrt1_ps(fp0, tcg_env, fp0);
b6d96bed 10700 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10701 }
57fa1fb3 10702 break;
bf4120ad 10703 case OPC_RSQRT2_PS:
e29c9628 10704 check_ps(ctx);
b6d96bed 10705 {
a7812ae4
PB
10706 TCGv_i64 fp0 = tcg_temp_new_i64();
10707 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10708
10709 gen_load_fpr64(ctx, fp0, fs);
10710 gen_load_fpr64(ctx, fp1, ft);
ad75a51e 10711 gen_helper_float_rsqrt2_ps(fp0, tcg_env, fp0, fp1);
b6d96bed 10712 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10713 }
57fa1fb3 10714 break;
bf4120ad 10715 case OPC_CVT_S_PU:
5e755519 10716 check_cp1_64bitmode(ctx);
b6d96bed 10717 {
a7812ae4 10718 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10719
7f6613ce 10720 gen_load_fpr32h(ctx, fp0, fs);
ad75a51e 10721 gen_helper_float_cvts_pu(fp0, tcg_env, fp0);
7c979afd 10722 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 10723 }
dd016883 10724 break;
bf4120ad 10725 case OPC_CVT_PW_PS:
e29c9628 10726 check_ps(ctx);
b6d96bed 10727 {
a7812ae4 10728 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10729
10730 gen_load_fpr64(ctx, fp0, fs);
ad75a51e 10731 gen_helper_float_cvtpw_ps(fp0, tcg_env, fp0);
b6d96bed 10732 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10733 }
6ea83fed 10734 break;
bf4120ad 10735 case OPC_CVT_S_PL:
5e755519 10736 check_cp1_64bitmode(ctx);
b6d96bed 10737 {
a7812ae4 10738 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10739
7c979afd 10740 gen_load_fpr32(ctx, fp0, fs);
ad75a51e 10741 gen_helper_float_cvts_pl(fp0, tcg_env, fp0);
7c979afd 10742 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 10743 }
6ea83fed 10744 break;
bf4120ad 10745 case OPC_PLL_PS:
e29c9628 10746 check_ps(ctx);
b6d96bed 10747 {
a7812ae4
PB
10748 TCGv_i32 fp0 = tcg_temp_new_i32();
10749 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10750
7c979afd
LA
10751 gen_load_fpr32(ctx, fp0, fs);
10752 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 10753 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 10754 gen_store_fpr32(ctx, fp1, fd);
b6d96bed 10755 }
6ea83fed 10756 break;
bf4120ad 10757 case OPC_PLU_PS:
e29c9628 10758 check_ps(ctx);
b6d96bed 10759 {
a7812ae4
PB
10760 TCGv_i32 fp0 = tcg_temp_new_i32();
10761 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10762
7c979afd 10763 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 10764 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 10765 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10766 gen_store_fpr32h(ctx, fp0, fd);
b6d96bed 10767 }
5a5012ec 10768 break;
bf4120ad 10769 case OPC_PUL_PS:
e29c9628 10770 check_ps(ctx);
b6d96bed 10771 {
a7812ae4
PB
10772 TCGv_i32 fp0 = tcg_temp_new_i32();
10773 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10774
7f6613ce 10775 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
10776 gen_load_fpr32(ctx, fp1, ft);
10777 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10778 gen_store_fpr32h(ctx, fp0, fd);
b6d96bed 10779 }
5a5012ec 10780 break;
bf4120ad 10781 case OPC_PUU_PS:
e29c9628 10782 check_ps(ctx);
b6d96bed 10783 {
a7812ae4
PB
10784 TCGv_i32 fp0 = tcg_temp_new_i32();
10785 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10786
7f6613ce
PJ
10787 gen_load_fpr32h(ctx, fp0, fs);
10788 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 10789 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10790 gen_store_fpr32h(ctx, fp0, fd);
b6d96bed 10791 }
5a5012ec 10792 break;
bf4120ad
NF
10793 case OPC_CMP_F_PS:
10794 case OPC_CMP_UN_PS:
10795 case OPC_CMP_EQ_PS:
10796 case OPC_CMP_UEQ_PS:
10797 case OPC_CMP_OLT_PS:
10798 case OPC_CMP_ULT_PS:
10799 case OPC_CMP_OLE_PS:
10800 case OPC_CMP_ULE_PS:
10801 case OPC_CMP_SF_PS:
10802 case OPC_CMP_NGLE_PS:
10803 case OPC_CMP_SEQ_PS:
10804 case OPC_CMP_NGL_PS:
10805 case OPC_CMP_LT_PS:
10806 case OPC_CMP_NGE_PS:
10807 case OPC_CMP_LE_PS:
10808 case OPC_CMP_NGT_PS:
8153667c 10809 if (ctx->opcode & (1 << 6)) {
71375b59 10810 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
8153667c 10811 } else {
71375b59 10812 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
5a1e8ffb 10813 }
6ea83fed 10814 break;
5a5012ec 10815 default:
9d68ac14 10816 MIPS_INVAL("farith");
3a4ef3b7 10817 gen_reserved_instruction(ctx);
6ea83fed
FB
10818 return;
10819 }
6ea83fed 10820}
6af0bf9c 10821
5a5012ec 10822/* Coprocessor 3 (FPU) */
235785e8
AM
10823static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
10824 int fd, int fs, int base, int index)
7a387fff 10825{
4e2474d6 10826 TCGv t0 = tcg_temp_new();
7a387fff 10827
93b12ccc 10828 if (base == 0) {
6c5c1e20 10829 gen_load_gpr(t0, index);
93b12ccc 10830 } else if (index == 0) {
6c5c1e20 10831 gen_load_gpr(t0, base);
93b12ccc 10832 } else {
05168674 10833 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 10834 }
7480515f
AM
10835 /*
10836 * Don't do NOP if destination is zero: we must perform the actual
10837 * memory access.
10838 */
5a5012ec
TS
10839 switch (opc) {
10840 case OPC_LWXC1:
8c0ab41f 10841 check_cop1x(ctx);
b6d96bed 10842 {
a7812ae4 10843 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10844
5f68f5ae 10845 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 10846 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10847 gen_store_fpr32(ctx, fp0, fd);
b6d96bed 10848 }
5a5012ec
TS
10849 break;
10850 case OPC_LDXC1:
8c0ab41f
AJ
10851 check_cop1x(ctx);
10852 check_cp1_registers(ctx, fd);
b6d96bed 10853 {
a7812ae4 10854 TCGv_i64 fp0 = tcg_temp_new_i64();
fc313c64 10855 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
b6d96bed 10856 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10857 }
5a5012ec
TS
10858 break;
10859 case OPC_LUXC1:
8c0ab41f 10860 check_cp1_64bitmode(ctx);
6c5c1e20 10861 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 10862 {
a7812ae4 10863 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10864
fc313c64 10865 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
b6d96bed 10866 gen_store_fpr64(ctx, fp0, fd);
b6d96bed 10867 }
5a5012ec
TS
10868 break;
10869 case OPC_SWXC1:
8c0ab41f 10870 check_cop1x(ctx);
b6d96bed 10871 {
a7812ae4 10872 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10873 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 10874 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
b6d96bed 10875 }
5a5012ec
TS
10876 break;
10877 case OPC_SDXC1:
8c0ab41f
AJ
10878 check_cop1x(ctx);
10879 check_cp1_registers(ctx, fs);
b6d96bed 10880 {
a7812ae4 10881 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10882 gen_load_fpr64(ctx, fp0, fs);
fc313c64 10883 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
b6d96bed 10884 }
5a5012ec
TS
10885 break;
10886 case OPC_SUXC1:
8c0ab41f 10887 check_cp1_64bitmode(ctx);
6c5c1e20 10888 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 10889 {
a7812ae4 10890 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10891 gen_load_fpr64(ctx, fp0, fs);
fc313c64 10892 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
b6d96bed 10893 }
5a5012ec 10894 break;
5a5012ec 10895 }
5a5012ec
TS
10896}
10897
235785e8
AM
10898static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
10899 int fd, int fr, int fs, int ft)
5a5012ec 10900{
5a5012ec
TS
10901 switch (opc) {
10902 case OPC_ALNV_PS:
e29c9628 10903 check_ps(ctx);
a16336e4 10904 {
6180cc40 10905 TCGv t0 = tcg_temp_new();
c905fdac
AJ
10906 TCGv_i32 fp = tcg_temp_new_i32();
10907 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
10908 TCGLabel *l1 = gen_new_label();
10909 TCGLabel *l2 = gen_new_label();
a16336e4 10910
6c5c1e20
TS
10911 gen_load_gpr(t0, fr);
10912 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
10913
10914 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 10915 gen_load_fpr32(ctx, fp, fs);
7f6613ce 10916 gen_load_fpr32h(ctx, fph, fs);
7c979afd 10917 gen_store_fpr32(ctx, fp, fd);
7f6613ce 10918 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
10919 tcg_gen_br(l2);
10920 gen_set_label(l1);
6c5c1e20 10921 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
bf78469c
PMD
10922 if (cpu_is_bigendian(ctx)) {
10923 gen_load_fpr32(ctx, fp, fs);
10924 gen_load_fpr32h(ctx, fph, ft);
10925 gen_store_fpr32h(ctx, fp, fd);
10926 gen_store_fpr32(ctx, fph, fd);
10927 } else {
10928 gen_load_fpr32h(ctx, fph, fs);
10929 gen_load_fpr32(ctx, fp, ft);
10930 gen_store_fpr32(ctx, fph, fd);
10931 gen_store_fpr32h(ctx, fp, fd);
10932 }
a16336e4
TS
10933 gen_set_label(l2);
10934 }
5a5012ec
TS
10935 break;
10936 case OPC_MADD_S:
b8aa4598 10937 check_cop1x(ctx);
b6d96bed 10938 {
a7812ae4
PB
10939 TCGv_i32 fp0 = tcg_temp_new_i32();
10940 TCGv_i32 fp1 = tcg_temp_new_i32();
10941 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 10942
7c979afd
LA
10943 gen_load_fpr32(ctx, fp0, fs);
10944 gen_load_fpr32(ctx, fp1, ft);
10945 gen_load_fpr32(ctx, fp2, fr);
ad75a51e 10946 gen_helper_float_madd_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 10947 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 10948 }
5a5012ec
TS
10949 break;
10950 case OPC_MADD_D:
b8aa4598
TS
10951 check_cop1x(ctx);
10952 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10953 {
a7812ae4
PB
10954 TCGv_i64 fp0 = tcg_temp_new_i64();
10955 TCGv_i64 fp1 = tcg_temp_new_i64();
10956 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10957
10958 gen_load_fpr64(ctx, fp0, fs);
10959 gen_load_fpr64(ctx, fp1, ft);
10960 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 10961 gen_helper_float_madd_d(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 10962 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 10963 }
5a5012ec
TS
10964 break;
10965 case OPC_MADD_PS:
e29c9628 10966 check_ps(ctx);
b6d96bed 10967 {
a7812ae4
PB
10968 TCGv_i64 fp0 = tcg_temp_new_i64();
10969 TCGv_i64 fp1 = tcg_temp_new_i64();
10970 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10971
10972 gen_load_fpr64(ctx, fp0, fs);
10973 gen_load_fpr64(ctx, fp1, ft);
10974 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 10975 gen_helper_float_madd_ps(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 10976 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 10977 }
5a5012ec
TS
10978 break;
10979 case OPC_MSUB_S:
b8aa4598 10980 check_cop1x(ctx);
b6d96bed 10981 {
a7812ae4
PB
10982 TCGv_i32 fp0 = tcg_temp_new_i32();
10983 TCGv_i32 fp1 = tcg_temp_new_i32();
10984 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 10985
7c979afd
LA
10986 gen_load_fpr32(ctx, fp0, fs);
10987 gen_load_fpr32(ctx, fp1, ft);
10988 gen_load_fpr32(ctx, fp2, fr);
ad75a51e 10989 gen_helper_float_msub_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 10990 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 10991 }
5a5012ec
TS
10992 break;
10993 case OPC_MSUB_D:
b8aa4598
TS
10994 check_cop1x(ctx);
10995 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10996 {
a7812ae4
PB
10997 TCGv_i64 fp0 = tcg_temp_new_i64();
10998 TCGv_i64 fp1 = tcg_temp_new_i64();
10999 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11000
11001 gen_load_fpr64(ctx, fp0, fs);
11002 gen_load_fpr64(ctx, fp1, ft);
11003 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11004 gen_helper_float_msub_d(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11005 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11006 }
5a5012ec
TS
11007 break;
11008 case OPC_MSUB_PS:
e29c9628 11009 check_ps(ctx);
b6d96bed 11010 {
a7812ae4
PB
11011 TCGv_i64 fp0 = tcg_temp_new_i64();
11012 TCGv_i64 fp1 = tcg_temp_new_i64();
11013 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11014
11015 gen_load_fpr64(ctx, fp0, fs);
11016 gen_load_fpr64(ctx, fp1, ft);
11017 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11018 gen_helper_float_msub_ps(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11019 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11020 }
5a5012ec
TS
11021 break;
11022 case OPC_NMADD_S:
b8aa4598 11023 check_cop1x(ctx);
b6d96bed 11024 {
a7812ae4
PB
11025 TCGv_i32 fp0 = tcg_temp_new_i32();
11026 TCGv_i32 fp1 = tcg_temp_new_i32();
11027 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11028
7c979afd
LA
11029 gen_load_fpr32(ctx, fp0, fs);
11030 gen_load_fpr32(ctx, fp1, ft);
11031 gen_load_fpr32(ctx, fp2, fr);
ad75a51e 11032 gen_helper_float_nmadd_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 11033 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 11034 }
5a5012ec
TS
11035 break;
11036 case OPC_NMADD_D:
b8aa4598
TS
11037 check_cop1x(ctx);
11038 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11039 {
a7812ae4
PB
11040 TCGv_i64 fp0 = tcg_temp_new_i64();
11041 TCGv_i64 fp1 = tcg_temp_new_i64();
11042 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11043
11044 gen_load_fpr64(ctx, fp0, fs);
11045 gen_load_fpr64(ctx, fp1, ft);
11046 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11047 gen_helper_float_nmadd_d(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11048 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11049 }
5a5012ec
TS
11050 break;
11051 case OPC_NMADD_PS:
e29c9628 11052 check_ps(ctx);
b6d96bed 11053 {
a7812ae4
PB
11054 TCGv_i64 fp0 = tcg_temp_new_i64();
11055 TCGv_i64 fp1 = tcg_temp_new_i64();
11056 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11057
11058 gen_load_fpr64(ctx, fp0, fs);
11059 gen_load_fpr64(ctx, fp1, ft);
11060 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11061 gen_helper_float_nmadd_ps(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11062 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11063 }
5a5012ec
TS
11064 break;
11065 case OPC_NMSUB_S:
b8aa4598 11066 check_cop1x(ctx);
b6d96bed 11067 {
a7812ae4
PB
11068 TCGv_i32 fp0 = tcg_temp_new_i32();
11069 TCGv_i32 fp1 = tcg_temp_new_i32();
11070 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11071
7c979afd
LA
11072 gen_load_fpr32(ctx, fp0, fs);
11073 gen_load_fpr32(ctx, fp1, ft);
11074 gen_load_fpr32(ctx, fp2, fr);
ad75a51e 11075 gen_helper_float_nmsub_s(fp2, tcg_env, fp0, fp1, fp2);
7c979afd 11076 gen_store_fpr32(ctx, fp2, fd);
b6d96bed 11077 }
5a5012ec
TS
11078 break;
11079 case OPC_NMSUB_D:
b8aa4598
TS
11080 check_cop1x(ctx);
11081 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11082 {
a7812ae4
PB
11083 TCGv_i64 fp0 = tcg_temp_new_i64();
11084 TCGv_i64 fp1 = tcg_temp_new_i64();
11085 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11086
11087 gen_load_fpr64(ctx, fp0, fs);
11088 gen_load_fpr64(ctx, fp1, ft);
11089 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11090 gen_helper_float_nmsub_d(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11091 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11092 }
5a5012ec
TS
11093 break;
11094 case OPC_NMSUB_PS:
e29c9628 11095 check_ps(ctx);
b6d96bed 11096 {
a7812ae4
PB
11097 TCGv_i64 fp0 = tcg_temp_new_i64();
11098 TCGv_i64 fp1 = tcg_temp_new_i64();
11099 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11100
11101 gen_load_fpr64(ctx, fp0, fs);
11102 gen_load_fpr64(ctx, fp1, ft);
11103 gen_load_fpr64(ctx, fp2, fr);
ad75a51e 11104 gen_helper_float_nmsub_ps(fp2, tcg_env, fp0, fp1, fp2);
b6d96bed 11105 gen_store_fpr64(ctx, fp2, fd);
b6d96bed 11106 }
5a5012ec 11107 break;
923617a3 11108 default:
9d68ac14 11109 MIPS_INVAL("flt3_arith");
3a4ef3b7 11110 gen_reserved_instruction(ctx);
5a5012ec
TS
11111 return;
11112 }
7a387fff
TS
11113}
11114
f9fa53f1 11115void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
11116{
11117 TCGv t0;
11118
b3167288 11119#if !defined(CONFIG_USER_ONLY)
7480515f
AM
11120 /*
11121 * The Linux kernel will emulate rdhwr if it's not supported natively.
11122 * Therefore only check the ISA in system mode.
11123 */
7a47bae5 11124 check_insn(ctx, ISA_MIPS_R2);
b3167288 11125#endif
26ebe468
NF
11126 t0 = tcg_temp_new();
11127
11128 switch (rd) {
11129 case 0:
ad75a51e 11130 gen_helper_rdhwr_cpunum(t0, tcg_env);
26ebe468
NF
11131 gen_store_gpr(t0, rt);
11132 break;
11133 case 1:
ad75a51e 11134 gen_helper_rdhwr_synci_step(t0, tcg_env);
26ebe468
NF
11135 gen_store_gpr(t0, rt);
11136 break;
11137 case 2:
dfd1b812 11138 translator_io_start(&ctx->base);
ad75a51e 11139 gen_helper_rdhwr_cc(t0, tcg_env);
26ebe468 11140 gen_store_gpr(t0, rt);
7480515f
AM
11141 /*
11142 * Break the TB to be able to take timer interrupts immediately
11143 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
11144 * we break completely out of translated code.
11145 */
eeb3bba8
EC
11146 gen_save_pc(ctx->base.pc_next + 4);
11147 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
11148 break;
11149 case 3:
ad75a51e 11150 gen_helper_rdhwr_ccres(t0, tcg_env);
26ebe468
NF
11151 gen_store_gpr(t0, rt);
11152 break;
b00c7218 11153 case 4:
2e211e0a 11154 check_insn(ctx, ISA_MIPS_R6);
b00c7218 11155 if (sel != 0) {
7480515f
AM
11156 /*
11157 * Performance counter registers are not implemented other than
b00c7218
YK
11158 * control register 0.
11159 */
11160 generate_exception(ctx, EXCP_RI);
11161 }
ad75a51e 11162 gen_helper_rdhwr_performance(t0, tcg_env);
b00c7218
YK
11163 gen_store_gpr(t0, rt);
11164 break;
11165 case 5:
2e211e0a 11166 check_insn(ctx, ISA_MIPS_R6);
ad75a51e 11167 gen_helper_rdhwr_xnp(t0, tcg_env);
b00c7218
YK
11168 gen_store_gpr(t0, rt);
11169 break;
26ebe468
NF
11170 case 29:
11171#if defined(CONFIG_USER_ONLY)
ad75a51e 11172 tcg_gen_ld_tl(t0, tcg_env,
d279279e 11173 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
11174 gen_store_gpr(t0, rt);
11175 break;
11176#else
d279279e
PJ
11177 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11178 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
ad75a51e 11179 tcg_gen_ld_tl(t0, tcg_env,
d279279e
PJ
11180 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11181 gen_store_gpr(t0, rt);
11182 } else {
3a4ef3b7 11183 gen_reserved_instruction(ctx);
d279279e
PJ
11184 }
11185 break;
26ebe468
NF
11186#endif
11187 default: /* Invalid */
11188 MIPS_INVAL("rdhwr");
3a4ef3b7 11189 gen_reserved_instruction(ctx);
26ebe468
NF
11190 break;
11191 }
26ebe468
NF
11192}
11193
a5f53390
LA
11194static inline void clear_branch_hflags(DisasContext *ctx)
11195{
11196 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 11197 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
11198 save_cpu_state(ctx, 0);
11199 } else {
7480515f
AM
11200 /*
11201 * It is not safe to save ctx->hflags as hflags may be changed
11202 * in execution time by the instruction in delay / forbidden slot.
11203 */
a5f53390
LA
11204 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11205 }
11206}
11207
31837be3 11208static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
11209{
11210 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 11211 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 11212 /* Branches completion */
a5f53390 11213 clear_branch_hflags(ctx);
eeb3bba8 11214 ctx->base.is_jmp = DISAS_NORETURN;
364d4831 11215 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 11216 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 11217 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 11218 break;
c9602061
NF
11219 case MIPS_HFLAG_B:
11220 /* unconditional branch */
364d4831
NF
11221 if (proc_hflags & MIPS_HFLAG_BX) {
11222 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11223 }
c9602061
NF
11224 gen_goto_tb(ctx, 0, ctx->btarget);
11225 break;
11226 case MIPS_HFLAG_BL:
11227 /* blikely taken case */
c9602061
NF
11228 gen_goto_tb(ctx, 0, ctx->btarget);
11229 break;
11230 case MIPS_HFLAG_BC:
11231 /* Conditional branch */
c9602061 11232 {
42a268c2 11233 TCGLabel *l1 = gen_new_label();
c9602061
NF
11234
11235 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 11236 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
11237 gen_set_label(l1);
11238 gen_goto_tb(ctx, 0, ctx->btarget);
11239 }
11240 break;
11241 case MIPS_HFLAG_BR:
11242 /* unconditional branch to register */
d75c135e 11243 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
11244 TCGv t0 = tcg_temp_new();
11245 TCGv_i32 t1 = tcg_temp_new_i32();
11246
11247 tcg_gen_andi_tl(t0, btarget, 0x1);
11248 tcg_gen_trunc_tl_i32(t1, t0);
364d4831
NF
11249 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11250 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11251 tcg_gen_or_i32(hflags, hflags, t1);
364d4831
NF
11252
11253 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11254 } else {
11255 tcg_gen_mov_tl(cpu_PC, btarget);
11256 }
7f11636d 11257 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
11258 break;
11259 default:
05d9d035
PMD
11260 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
11261 gen_reserved_instruction(ctx);
c9602061
NF
11262 }
11263 }
11264}
11265
6893f074
YK
11266/* Compact Branches */
11267static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11268 int rs, int rt, int32_t offset)
11269{
11270 int bcond_compute = 0;
11271 TCGv t0 = tcg_temp_new();
11272 TCGv t1 = tcg_temp_new();
65935f07 11273 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
11274
11275 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11276#ifdef MIPS_DEBUG_DISAS
11277 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 11278 "\n", ctx->base.pc_next);
6893f074 11279#endif
3a4ef3b7 11280 gen_reserved_instruction(ctx);
74fda465 11281 return;
6893f074
YK
11282 }
11283
11284 /* Load needed operands and calculate btarget */
11285 switch (opc) {
11286 /* compact branch */
11287 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11288 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11289 gen_load_gpr(t0, rs);
11290 gen_load_gpr(t1, rt);
11291 bcond_compute = 1;
eeb3bba8 11292 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11293 if (rs <= rt && rs == 0) {
11294 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 11295 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11296 }
11297 break;
11298 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11299 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11300 gen_load_gpr(t0, rs);
11301 gen_load_gpr(t1, rt);
11302 bcond_compute = 1;
eeb3bba8 11303 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11304 break;
11305 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11306 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11307 if (rs == 0 || rs == rt) {
11308 /* OPC_BLEZALC, OPC_BGEZALC */
11309 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 11310 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11311 }
11312 gen_load_gpr(t0, rs);
11313 gen_load_gpr(t1, rt);
11314 bcond_compute = 1;
eeb3bba8 11315 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11316 break;
11317 case OPC_BC:
11318 case OPC_BALC:
eeb3bba8 11319 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11320 break;
11321 case OPC_BEQZC:
11322 case OPC_BNEZC:
11323 if (rs != 0) {
11324 /* OPC_BEQZC, OPC_BNEZC */
11325 gen_load_gpr(t0, rs);
11326 bcond_compute = 1;
eeb3bba8 11327 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11328 } else {
11329 /* OPC_JIC, OPC_JIALC */
11330 TCGv tbase = tcg_temp_new();
d2db0f72 11331 TCGv toffset = tcg_constant_tl(offset);
6893f074
YK
11332
11333 gen_load_gpr(tbase, rt);
6893f074 11334 gen_op_addr_add(ctx, btarget, tbase, toffset);
6893f074
YK
11335 }
11336 break;
11337 default:
11338 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 11339 gen_reserved_instruction(ctx);
74fda465 11340 return;
6893f074
YK
11341 }
11342
11343 if (bcond_compute == 0) {
63978560 11344 /* Unconditional compact branch */
6893f074
YK
11345 switch (opc) {
11346 case OPC_JIALC:
eeb3bba8 11347 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11348 /* Fallthrough */
11349 case OPC_JIC:
11350 ctx->hflags |= MIPS_HFLAG_BR;
11351 break;
11352 case OPC_BALC:
eeb3bba8 11353 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11354 /* Fallthrough */
11355 case OPC_BC:
11356 ctx->hflags |= MIPS_HFLAG_B;
11357 break;
11358 default:
11359 MIPS_INVAL("Compact branch/jump");
3a4ef3b7 11360 gen_reserved_instruction(ctx);
74fda465 11361 return;
6893f074
YK
11362 }
11363
11364 /* Generating branch here as compact branches don't have delay slot */
11365 gen_branch(ctx, 4);
11366 } else {
11367 /* Conditional compact branch */
11368 TCGLabel *fs = gen_new_label();
11369 save_cpu_state(ctx, 0);
11370
11371 switch (opc) {
11372 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11373 if (rs == 0 && rt != 0) {
11374 /* OPC_BLEZALC */
11375 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11376 } else if (rs != 0 && rt != 0 && rs == rt) {
11377 /* OPC_BGEZALC */
11378 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11379 } else {
11380 /* OPC_BGEUC */
11381 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11382 }
11383 break;
11384 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11385 if (rs == 0 && rt != 0) {
11386 /* OPC_BGTZALC */
11387 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11388 } else if (rs != 0 && rt != 0 && rs == rt) {
11389 /* OPC_BLTZALC */
11390 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11391 } else {
11392 /* OPC_BLTUC */
11393 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11394 }
11395 break;
11396 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11397 if (rs == 0 && rt != 0) {
11398 /* OPC_BLEZC */
11399 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11400 } else if (rs != 0 && rt != 0 && rs == rt) {
11401 /* OPC_BGEZC */
11402 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11403 } else {
11404 /* OPC_BGEC */
11405 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11406 }
11407 break;
11408 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11409 if (rs == 0 && rt != 0) {
11410 /* OPC_BGTZC */
11411 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11412 } else if (rs != 0 && rt != 0 && rs == rt) {
11413 /* OPC_BLTZC */
11414 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11415 } else {
11416 /* OPC_BLTC */
11417 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11418 }
11419 break;
11420 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11421 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11422 if (rs >= rt) {
11423 /* OPC_BOVC, OPC_BNVC */
11424 TCGv t2 = tcg_temp_new();
11425 TCGv t3 = tcg_temp_new();
11426 TCGv t4 = tcg_temp_new();
11427 TCGv input_overflow = tcg_temp_new();
11428
11429 gen_load_gpr(t0, rs);
11430 gen_load_gpr(t1, rt);
11431 tcg_gen_ext32s_tl(t2, t0);
11432 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11433 tcg_gen_ext32s_tl(t3, t1);
11434 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11435 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11436
11437 tcg_gen_add_tl(t4, t2, t3);
11438 tcg_gen_ext32s_tl(t4, t4);
11439 tcg_gen_xor_tl(t2, t2, t3);
11440 tcg_gen_xor_tl(t3, t4, t3);
11441 tcg_gen_andc_tl(t2, t3, t2);
11442 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11443 tcg_gen_or_tl(t4, t4, input_overflow);
11444 if (opc == OPC_BOVC) {
11445 /* OPC_BOVC */
11446 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11447 } else {
11448 /* OPC_BNVC */
11449 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11450 }
6893f074
YK
11451 } else if (rs < rt && rs == 0) {
11452 /* OPC_BEQZALC, OPC_BNEZALC */
11453 if (opc == OPC_BEQZALC) {
11454 /* OPC_BEQZALC */
11455 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11456 } else {
11457 /* OPC_BNEZALC */
11458 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11459 }
11460 } else {
11461 /* OPC_BEQC, OPC_BNEC */
11462 if (opc == OPC_BEQC) {
11463 /* OPC_BEQC */
11464 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11465 } else {
11466 /* OPC_BNEC */
11467 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11468 }
11469 }
11470 break;
11471 case OPC_BEQZC:
11472 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11473 break;
11474 case OPC_BNEZC:
11475 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11476 break;
11477 default:
11478 MIPS_INVAL("Compact conditional branch/jump");
3a4ef3b7 11479 gen_reserved_instruction(ctx);
74fda465 11480 return;
6893f074
YK
11481 }
11482
11483 /* Generating branch here as compact branches don't have delay slot */
11484 gen_goto_tb(ctx, 1, ctx->btarget);
11485 gen_set_label(fs);
11486
11487 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074 11488 }
6893f074
YK
11489}
11490
d5076631
PMD
11491void gen_addiupc(DisasContext *ctx, int rx, int imm,
11492 int is_64_bit, int extended)
364d4831
NF
11493{
11494 TCGv t0;
11495
11496 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 11497 gen_reserved_instruction(ctx);
364d4831
NF
11498 return;
11499 }
11500
11501 t0 = tcg_temp_new();
11502
11503 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11504 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11505 if (!is_64_bit) {
11506 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11507 }
364d4831
NF
11508}
11509
0d74a222
LA
11510static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11511 int16_t offset)
11512{
c29e79af 11513 TCGv_i32 t0 = tcg_constant_i32(op);
0d74a222
LA
11514 TCGv t1 = tcg_temp_new();
11515 gen_base_offset_addr(ctx, t1, base, offset);
ad75a51e 11516 gen_helper_cache(tcg_env, t1, t0);
0d74a222
LA
11517}
11518
b35d7401 11519static inline bool is_uhi(DisasContext *ctx, int sdbbp_code)
3b3c1694
LA
11520{
11521#ifdef CONFIG_USER_ONLY
11522 return false;
11523#else
b35d7401
PM
11524 bool is_user = (ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM;
11525 return semihosting_enabled(is_user) && sdbbp_code == 1;
3b3c1694
LA
11526#endif
11527}
11528
d5076631 11529void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
3c824109
NF
11530{
11531 TCGv t0 = tcg_temp_new();
11532 TCGv t1 = tcg_temp_new();
11533
11534 gen_load_gpr(t0, base);
11535
11536 if (index != 0) {
11537 gen_load_gpr(t1, index);
11538 tcg_gen_shli_tl(t1, t1, 2);
11539 gen_op_addr_add(ctx, t0, t1, t0);
11540 }
11541
5f68f5ae 11542 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109 11543 gen_store_gpr(t1, rd);
3c824109
NF
11544}
11545
d208ac0c
LA
11546static void gen_sync(int stype)
11547{
11548 TCGBar tcg_mo = TCG_BAR_SC;
11549
11550 switch (stype) {
11551 case 0x4: /* SYNC_WMB */
11552 tcg_mo |= TCG_MO_ST_ST;
11553 break;
11554 case 0x10: /* SYNC_MB */
11555 tcg_mo |= TCG_MO_ALL;
11556 break;
11557 case 0x11: /* SYNC_ACQUIRE */
11558 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
11559 break;
11560 case 0x12: /* SYNC_RELEASE */
11561 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
11562 break;
11563 case 0x13: /* SYNC_RMB */
11564 tcg_mo |= TCG_MO_LD_LD;
11565 break;
11566 default:
11567 tcg_mo |= TCG_MO_ALL;
11568 break;
11569 }
11570
11571 tcg_gen_mb(tcg_mo);
11572}
11573
bf52c45a 11574/* ISA extensions (ASEs) */
3c824109 11575
bf52c45a
PMD
11576/* MIPS16 extension to MIPS32 */
11577#include "mips16e_translate.c.inc"
3c824109 11578
bf52c45a 11579/* microMIPS extension to MIPS32/MIPS64 */
3c824109 11580
7480515f
AM
11581/*
11582 * Values for microMIPS fmt field. Variable-width, depending on which
11583 * formats the instruction supports.
11584 */
3c824109
NF
11585enum {
11586 FMT_SD_S = 0,
11587 FMT_SD_D = 1,
11588
11589 FMT_SDPS_S = 0,
11590 FMT_SDPS_D = 1,
11591 FMT_SDPS_PS = 2,
11592
11593 FMT_SWL_S = 0,
11594 FMT_SWL_W = 1,
11595 FMT_SWL_L = 2,
11596
11597 FMT_DWL_D = 0,
11598 FMT_DWL_W = 1,
11599 FMT_DWL_L = 2
11600};
11601
bf52c45a 11602#include "micromips_translate.c.inc"
3230bad9 11603
3f178b8d 11604#include "nanomips_translate.c.inc"
c533c0f4 11605
9b1a1d68 11606/* MIPSDSP functions. */
4525ea7e
PD
11607
11608/* Indexed load is not for DSP only */
11609static void gen_mips_lx(DisasContext *ctx, uint32_t opc,
11610 int rd, int base, int offset)
9b1a1d68 11611{
9b1a1d68
JL
11612 TCGv t0;
11613
4525ea7e
PD
11614 if (!(ctx->insn_flags & INSN_OCTEON)) {
11615 check_dsp(ctx);
11616 }
9b1a1d68
JL
11617 t0 = tcg_temp_new();
11618
11619 if (base == 0) {
11620 gen_load_gpr(t0, offset);
11621 } else if (offset == 0) {
11622 gen_load_gpr(t0, base);
11623 } else {
11624 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
11625 }
11626
9b1a1d68
JL
11627 switch (opc) {
11628 case OPC_LBUX:
5f68f5ae 11629 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 11630 gen_store_gpr(t0, rd);
9b1a1d68
JL
11631 break;
11632 case OPC_LHX:
5f68f5ae 11633 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 11634 gen_store_gpr(t0, rd);
9b1a1d68
JL
11635 break;
11636 case OPC_LWX:
5f68f5ae 11637 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 11638 gen_store_gpr(t0, rd);
9b1a1d68
JL
11639 break;
11640#if defined(TARGET_MIPS64)
11641 case OPC_LDX:
fc313c64 11642 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
9b1a1d68 11643 gen_store_gpr(t0, rd);
9b1a1d68
JL
11644 break;
11645#endif
11646 }
9b1a1d68
JL
11647}
11648
461c08df
JL
11649static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
11650 int ret, int v1, int v2)
11651{
461c08df
JL
11652 TCGv v1_t;
11653 TCGv v2_t;
11654
11655 if (ret == 0) {
11656 /* Treat as NOP. */
461c08df
JL
11657 return;
11658 }
11659
11660 v1_t = tcg_temp_new();
11661 v2_t = tcg_temp_new();
11662
11663 gen_load_gpr(v1_t, v1);
11664 gen_load_gpr(v2_t, v2);
11665
11666 switch (op1) {
11667 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
11668 case OPC_MULT_G_2E:
908f6be1 11669 check_dsp_r2(ctx);
461c08df
JL
11670 switch (op2) {
11671 case OPC_ADDUH_QB:
11672 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
11673 break;
11674 case OPC_ADDUH_R_QB:
11675 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11676 break;
11677 case OPC_ADDQH_PH:
11678 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
11679 break;
11680 case OPC_ADDQH_R_PH:
11681 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11682 break;
11683 case OPC_ADDQH_W:
11684 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
11685 break;
11686 case OPC_ADDQH_R_W:
11687 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11688 break;
11689 case OPC_SUBUH_QB:
11690 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
11691 break;
11692 case OPC_SUBUH_R_QB:
11693 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11694 break;
11695 case OPC_SUBQH_PH:
11696 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
11697 break;
11698 case OPC_SUBQH_R_PH:
11699 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11700 break;
11701 case OPC_SUBQH_W:
11702 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
11703 break;
11704 case OPC_SUBQH_R_W:
11705 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11706 break;
11707 }
11708 break;
11709 case OPC_ABSQ_S_PH_DSP:
11710 switch (op2) {
11711 case OPC_ABSQ_S_QB:
908f6be1 11712 check_dsp_r2(ctx);
ad75a51e 11713 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11714 break;
11715 case OPC_ABSQ_S_PH:
11716 check_dsp(ctx);
ad75a51e 11717 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11718 break;
11719 case OPC_ABSQ_S_W:
11720 check_dsp(ctx);
ad75a51e 11721 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11722 break;
11723 case OPC_PRECEQ_W_PHL:
11724 check_dsp(ctx);
11725 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
11726 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11727 break;
11728 case OPC_PRECEQ_W_PHR:
11729 check_dsp(ctx);
11730 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
11731 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
11732 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11733 break;
11734 case OPC_PRECEQU_PH_QBL:
11735 check_dsp(ctx);
11736 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
11737 break;
11738 case OPC_PRECEQU_PH_QBR:
11739 check_dsp(ctx);
11740 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
11741 break;
11742 case OPC_PRECEQU_PH_QBLA:
11743 check_dsp(ctx);
11744 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
11745 break;
11746 case OPC_PRECEQU_PH_QBRA:
11747 check_dsp(ctx);
11748 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
11749 break;
11750 case OPC_PRECEU_PH_QBL:
11751 check_dsp(ctx);
11752 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
11753 break;
11754 case OPC_PRECEU_PH_QBR:
11755 check_dsp(ctx);
11756 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
11757 break;
11758 case OPC_PRECEU_PH_QBLA:
11759 check_dsp(ctx);
11760 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
11761 break;
11762 case OPC_PRECEU_PH_QBRA:
11763 check_dsp(ctx);
11764 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
11765 break;
11766 }
11767 break;
11768 case OPC_ADDU_QB_DSP:
11769 switch (op2) {
11770 case OPC_ADDQ_PH:
11771 check_dsp(ctx);
ad75a51e 11772 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11773 break;
11774 case OPC_ADDQ_S_PH:
11775 check_dsp(ctx);
ad75a51e 11776 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11777 break;
11778 case OPC_ADDQ_S_W:
11779 check_dsp(ctx);
ad75a51e 11780 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11781 break;
11782 case OPC_ADDU_QB:
11783 check_dsp(ctx);
ad75a51e 11784 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11785 break;
11786 case OPC_ADDU_S_QB:
11787 check_dsp(ctx);
ad75a51e 11788 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11789 break;
11790 case OPC_ADDU_PH:
908f6be1 11791 check_dsp_r2(ctx);
ad75a51e 11792 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11793 break;
11794 case OPC_ADDU_S_PH:
908f6be1 11795 check_dsp_r2(ctx);
ad75a51e 11796 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11797 break;
11798 case OPC_SUBQ_PH:
11799 check_dsp(ctx);
ad75a51e 11800 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11801 break;
11802 case OPC_SUBQ_S_PH:
11803 check_dsp(ctx);
ad75a51e 11804 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11805 break;
11806 case OPC_SUBQ_S_W:
11807 check_dsp(ctx);
ad75a51e 11808 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11809 break;
11810 case OPC_SUBU_QB:
11811 check_dsp(ctx);
ad75a51e 11812 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11813 break;
11814 case OPC_SUBU_S_QB:
11815 check_dsp(ctx);
ad75a51e 11816 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11817 break;
11818 case OPC_SUBU_PH:
908f6be1 11819 check_dsp_r2(ctx);
ad75a51e 11820 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11821 break;
11822 case OPC_SUBU_S_PH:
908f6be1 11823 check_dsp_r2(ctx);
ad75a51e 11824 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11825 break;
11826 case OPC_ADDSC:
11827 check_dsp(ctx);
ad75a51e 11828 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11829 break;
11830 case OPC_ADDWC:
11831 check_dsp(ctx);
ad75a51e 11832 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11833 break;
11834 case OPC_MODSUB:
11835 check_dsp(ctx);
11836 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
11837 break;
11838 case OPC_RADDU_W_QB:
11839 check_dsp(ctx);
11840 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
11841 break;
11842 }
11843 break;
11844 case OPC_CMPU_EQ_QB_DSP:
11845 switch (op2) {
11846 case OPC_PRECR_QB_PH:
908f6be1 11847 check_dsp_r2(ctx);
461c08df
JL
11848 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11849 break;
11850 case OPC_PRECRQ_QB_PH:
11851 check_dsp(ctx);
11852 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11853 break;
11854 case OPC_PRECR_SRA_PH_W:
908f6be1 11855 check_dsp_r2(ctx);
461c08df 11856 {
c29e79af 11857 TCGv_i32 sa_t = tcg_constant_i32(v2);
461c08df
JL
11858 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
11859 cpu_gpr[ret]);
461c08df
JL
11860 break;
11861 }
11862 case OPC_PRECR_SRA_R_PH_W:
908f6be1 11863 check_dsp_r2(ctx);
461c08df 11864 {
c29e79af 11865 TCGv_i32 sa_t = tcg_constant_i32(v2);
461c08df
JL
11866 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
11867 cpu_gpr[ret]);
461c08df
JL
11868 break;
11869 }
11870 case OPC_PRECRQ_PH_W:
11871 check_dsp(ctx);
11872 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
11873 break;
11874 case OPC_PRECRQ_RS_PH_W:
11875 check_dsp(ctx);
ad75a51e 11876 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11877 break;
11878 case OPC_PRECRQU_S_QB_PH:
11879 check_dsp(ctx);
ad75a51e 11880 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11881 break;
11882 }
11883 break;
11884#ifdef TARGET_MIPS64
11885 case OPC_ABSQ_S_QH_DSP:
11886 switch (op2) {
11887 case OPC_PRECEQ_L_PWL:
11888 check_dsp(ctx);
11889 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
11890 break;
11891 case OPC_PRECEQ_L_PWR:
11892 check_dsp(ctx);
11893 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
11894 break;
11895 case OPC_PRECEQ_PW_QHL:
11896 check_dsp(ctx);
11897 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
11898 break;
11899 case OPC_PRECEQ_PW_QHR:
11900 check_dsp(ctx);
11901 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
11902 break;
11903 case OPC_PRECEQ_PW_QHLA:
11904 check_dsp(ctx);
11905 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
11906 break;
11907 case OPC_PRECEQ_PW_QHRA:
11908 check_dsp(ctx);
11909 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
11910 break;
11911 case OPC_PRECEQU_QH_OBL:
11912 check_dsp(ctx);
11913 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
11914 break;
11915 case OPC_PRECEQU_QH_OBR:
11916 check_dsp(ctx);
11917 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
11918 break;
11919 case OPC_PRECEQU_QH_OBLA:
11920 check_dsp(ctx);
11921 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
11922 break;
11923 case OPC_PRECEQU_QH_OBRA:
11924 check_dsp(ctx);
11925 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
11926 break;
11927 case OPC_PRECEU_QH_OBL:
11928 check_dsp(ctx);
11929 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
11930 break;
11931 case OPC_PRECEU_QH_OBR:
11932 check_dsp(ctx);
11933 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
11934 break;
11935 case OPC_PRECEU_QH_OBLA:
11936 check_dsp(ctx);
11937 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
11938 break;
11939 case OPC_PRECEU_QH_OBRA:
11940 check_dsp(ctx);
11941 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
11942 break;
11943 case OPC_ABSQ_S_OB:
908f6be1 11944 check_dsp_r2(ctx);
ad75a51e 11945 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11946 break;
11947 case OPC_ABSQ_S_PW:
11948 check_dsp(ctx);
ad75a51e 11949 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11950 break;
11951 case OPC_ABSQ_S_QH:
11952 check_dsp(ctx);
ad75a51e 11953 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, tcg_env);
461c08df
JL
11954 break;
11955 }
11956 break;
11957 case OPC_ADDU_OB_DSP:
11958 switch (op2) {
11959 case OPC_RADDU_L_OB:
11960 check_dsp(ctx);
11961 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
11962 break;
11963 case OPC_SUBQ_PW:
11964 check_dsp(ctx);
ad75a51e 11965 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11966 break;
11967 case OPC_SUBQ_S_PW:
11968 check_dsp(ctx);
ad75a51e 11969 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11970 break;
11971 case OPC_SUBQ_QH:
11972 check_dsp(ctx);
ad75a51e 11973 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11974 break;
11975 case OPC_SUBQ_S_QH:
11976 check_dsp(ctx);
ad75a51e 11977 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11978 break;
11979 case OPC_SUBU_OB:
11980 check_dsp(ctx);
ad75a51e 11981 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11982 break;
11983 case OPC_SUBU_S_OB:
11984 check_dsp(ctx);
ad75a51e 11985 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11986 break;
11987 case OPC_SUBU_QH:
908f6be1 11988 check_dsp_r2(ctx);
ad75a51e 11989 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11990 break;
11991 case OPC_SUBU_S_QH:
908f6be1 11992 check_dsp_r2(ctx);
ad75a51e 11993 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
11994 break;
11995 case OPC_SUBUH_OB:
908f6be1 11996 check_dsp_r2(ctx);
461c08df
JL
11997 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
11998 break;
11999 case OPC_SUBUH_R_OB:
908f6be1 12000 check_dsp_r2(ctx);
461c08df
JL
12001 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12002 break;
12003 case OPC_ADDQ_PW:
12004 check_dsp(ctx);
ad75a51e 12005 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12006 break;
12007 case OPC_ADDQ_S_PW:
12008 check_dsp(ctx);
ad75a51e 12009 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12010 break;
12011 case OPC_ADDQ_QH:
12012 check_dsp(ctx);
ad75a51e 12013 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12014 break;
12015 case OPC_ADDQ_S_QH:
12016 check_dsp(ctx);
ad75a51e 12017 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12018 break;
12019 case OPC_ADDU_OB:
12020 check_dsp(ctx);
ad75a51e 12021 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12022 break;
12023 case OPC_ADDU_S_OB:
12024 check_dsp(ctx);
ad75a51e 12025 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12026 break;
12027 case OPC_ADDU_QH:
908f6be1 12028 check_dsp_r2(ctx);
ad75a51e 12029 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12030 break;
12031 case OPC_ADDU_S_QH:
908f6be1 12032 check_dsp_r2(ctx);
ad75a51e 12033 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12034 break;
12035 case OPC_ADDUH_OB:
908f6be1 12036 check_dsp_r2(ctx);
461c08df
JL
12037 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
12038 break;
12039 case OPC_ADDUH_R_OB:
908f6be1 12040 check_dsp_r2(ctx);
461c08df
JL
12041 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12042 break;
12043 }
12044 break;
12045 case OPC_CMPU_EQ_OB_DSP:
12046 switch (op2) {
12047 case OPC_PRECR_OB_QH:
908f6be1 12048 check_dsp_r2(ctx);
461c08df
JL
12049 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12050 break;
12051 case OPC_PRECR_SRA_QH_PW:
908f6be1 12052 check_dsp_r2(ctx);
461c08df 12053 {
c29e79af 12054 TCGv_i32 ret_t = tcg_constant_i32(ret);
461c08df 12055 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
461c08df
JL
12056 break;
12057 }
12058 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 12059 check_dsp_r2(ctx);
461c08df 12060 {
c29e79af 12061 TCGv_i32 sa_v = tcg_constant_i32(ret);
461c08df 12062 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
461c08df
JL
12063 break;
12064 }
12065 case OPC_PRECRQ_OB_QH:
12066 check_dsp(ctx);
12067 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12068 break;
12069 case OPC_PRECRQ_PW_L:
12070 check_dsp(ctx);
12071 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
12072 break;
12073 case OPC_PRECRQ_QH_PW:
12074 check_dsp(ctx);
12075 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
12076 break;
12077 case OPC_PRECRQ_RS_QH_PW:
12078 check_dsp(ctx);
ad75a51e 12079 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12080 break;
12081 case OPC_PRECRQU_S_OB_QH:
12082 check_dsp(ctx);
ad75a51e 12083 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
461c08df
JL
12084 break;
12085 }
12086 break;
12087#endif
12088 }
461c08df 12089}
9b1a1d68 12090
77c5fa8b
JL
12091static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
12092 int ret, int v1, int v2)
12093{
12094 uint32_t op2;
77c5fa8b
JL
12095 TCGv t0;
12096 TCGv v1_t;
12097 TCGv v2_t;
12098
12099 if (ret == 0) {
12100 /* Treat as NOP. */
77c5fa8b
JL
12101 return;
12102 }
12103
12104 t0 = tcg_temp_new();
12105 v1_t = tcg_temp_new();
12106 v2_t = tcg_temp_new();
12107
12108 tcg_gen_movi_tl(t0, v1);
12109 gen_load_gpr(v1_t, v1);
12110 gen_load_gpr(v2_t, v2);
12111
12112 switch (opc) {
12113 case OPC_SHLL_QB_DSP:
12114 {
12115 op2 = MASK_SHLL_QB(ctx->opcode);
12116 switch (op2) {
12117 case OPC_SHLL_QB:
12118 check_dsp(ctx);
ad75a51e 12119 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, tcg_env);
77c5fa8b
JL
12120 break;
12121 case OPC_SHLLV_QB:
12122 check_dsp(ctx);
ad75a51e 12123 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
77c5fa8b
JL
12124 break;
12125 case OPC_SHLL_PH:
12126 check_dsp(ctx);
ad75a51e 12127 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
77c5fa8b
JL
12128 break;
12129 case OPC_SHLLV_PH:
12130 check_dsp(ctx);
ad75a51e 12131 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
77c5fa8b
JL
12132 break;
12133 case OPC_SHLL_S_PH:
12134 check_dsp(ctx);
ad75a51e 12135 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
77c5fa8b
JL
12136 break;
12137 case OPC_SHLLV_S_PH:
12138 check_dsp(ctx);
ad75a51e 12139 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
77c5fa8b
JL
12140 break;
12141 case OPC_SHLL_S_W:
12142 check_dsp(ctx);
ad75a51e 12143 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, tcg_env);
77c5fa8b
JL
12144 break;
12145 case OPC_SHLLV_S_W:
12146 check_dsp(ctx);
ad75a51e 12147 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
77c5fa8b
JL
12148 break;
12149 case OPC_SHRL_QB:
12150 check_dsp(ctx);
12151 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
12152 break;
12153 case OPC_SHRLV_QB:
12154 check_dsp(ctx);
12155 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
12156 break;
12157 case OPC_SHRL_PH:
908f6be1 12158 check_dsp_r2(ctx);
77c5fa8b
JL
12159 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
12160 break;
12161 case OPC_SHRLV_PH:
908f6be1 12162 check_dsp_r2(ctx);
77c5fa8b
JL
12163 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
12164 break;
12165 case OPC_SHRA_QB:
908f6be1 12166 check_dsp_r2(ctx);
77c5fa8b
JL
12167 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
12168 break;
12169 case OPC_SHRA_R_QB:
908f6be1 12170 check_dsp_r2(ctx);
77c5fa8b
JL
12171 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
12172 break;
12173 case OPC_SHRAV_QB:
908f6be1 12174 check_dsp_r2(ctx);
77c5fa8b
JL
12175 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
12176 break;
12177 case OPC_SHRAV_R_QB:
908f6be1 12178 check_dsp_r2(ctx);
77c5fa8b
JL
12179 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
12180 break;
12181 case OPC_SHRA_PH:
12182 check_dsp(ctx);
12183 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
12184 break;
12185 case OPC_SHRA_R_PH:
12186 check_dsp(ctx);
12187 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
12188 break;
12189 case OPC_SHRAV_PH:
12190 check_dsp(ctx);
12191 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
12192 break;
12193 case OPC_SHRAV_R_PH:
12194 check_dsp(ctx);
12195 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
12196 break;
12197 case OPC_SHRA_R_W:
12198 check_dsp(ctx);
12199 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
12200 break;
12201 case OPC_SHRAV_R_W:
12202 check_dsp(ctx);
12203 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
12204 break;
12205 default: /* Invalid */
12206 MIPS_INVAL("MASK SHLL.QB");
3a4ef3b7 12207 gen_reserved_instruction(ctx);
77c5fa8b
JL
12208 break;
12209 }
12210 break;
12211 }
12212#ifdef TARGET_MIPS64
12213 case OPC_SHLL_OB_DSP:
12214 op2 = MASK_SHLL_OB(ctx->opcode);
12215 switch (op2) {
12216 case OPC_SHLL_PW:
12217 check_dsp(ctx);
ad75a51e 12218 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
77c5fa8b
JL
12219 break;
12220 case OPC_SHLLV_PW:
12221 check_dsp(ctx);
ad75a51e 12222 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
77c5fa8b
JL
12223 break;
12224 case OPC_SHLL_S_PW:
12225 check_dsp(ctx);
ad75a51e 12226 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
77c5fa8b
JL
12227 break;
12228 case OPC_SHLLV_S_PW:
12229 check_dsp(ctx);
ad75a51e 12230 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
77c5fa8b
JL
12231 break;
12232 case OPC_SHLL_OB:
12233 check_dsp(ctx);
ad75a51e 12234 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, tcg_env);
77c5fa8b
JL
12235 break;
12236 case OPC_SHLLV_OB:
12237 check_dsp(ctx);
ad75a51e 12238 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, tcg_env);
77c5fa8b
JL
12239 break;
12240 case OPC_SHLL_QH:
12241 check_dsp(ctx);
ad75a51e 12242 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
77c5fa8b
JL
12243 break;
12244 case OPC_SHLLV_QH:
12245 check_dsp(ctx);
ad75a51e 12246 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
77c5fa8b
JL
12247 break;
12248 case OPC_SHLL_S_QH:
12249 check_dsp(ctx);
ad75a51e 12250 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
77c5fa8b
JL
12251 break;
12252 case OPC_SHLLV_S_QH:
12253 check_dsp(ctx);
ad75a51e 12254 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
77c5fa8b
JL
12255 break;
12256 case OPC_SHRA_OB:
908f6be1 12257 check_dsp_r2(ctx);
77c5fa8b
JL
12258 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
12259 break;
12260 case OPC_SHRAV_OB:
908f6be1 12261 check_dsp_r2(ctx);
77c5fa8b
JL
12262 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
12263 break;
12264 case OPC_SHRA_R_OB:
908f6be1 12265 check_dsp_r2(ctx);
77c5fa8b
JL
12266 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
12267 break;
12268 case OPC_SHRAV_R_OB:
908f6be1 12269 check_dsp_r2(ctx);
77c5fa8b
JL
12270 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
12271 break;
12272 case OPC_SHRA_PW:
12273 check_dsp(ctx);
12274 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
12275 break;
12276 case OPC_SHRAV_PW:
12277 check_dsp(ctx);
12278 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
12279 break;
12280 case OPC_SHRA_R_PW:
12281 check_dsp(ctx);
12282 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
12283 break;
12284 case OPC_SHRAV_R_PW:
12285 check_dsp(ctx);
12286 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
12287 break;
12288 case OPC_SHRA_QH:
12289 check_dsp(ctx);
12290 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
12291 break;
12292 case OPC_SHRAV_QH:
12293 check_dsp(ctx);
12294 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
12295 break;
12296 case OPC_SHRA_R_QH:
12297 check_dsp(ctx);
12298 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
12299 break;
12300 case OPC_SHRAV_R_QH:
12301 check_dsp(ctx);
12302 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
12303 break;
12304 case OPC_SHRL_OB:
12305 check_dsp(ctx);
12306 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
12307 break;
12308 case OPC_SHRLV_OB:
12309 check_dsp(ctx);
12310 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
12311 break;
12312 case OPC_SHRL_QH:
908f6be1 12313 check_dsp_r2(ctx);
77c5fa8b
JL
12314 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
12315 break;
12316 case OPC_SHRLV_QH:
908f6be1 12317 check_dsp_r2(ctx);
77c5fa8b
JL
12318 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
12319 break;
12320 default: /* Invalid */
12321 MIPS_INVAL("MASK SHLL.OB");
3a4ef3b7 12322 gen_reserved_instruction(ctx);
77c5fa8b
JL
12323 break;
12324 }
12325 break;
12326#endif
12327 }
77c5fa8b
JL
12328}
12329
a22260ae
JL
12330static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
12331 int ret, int v1, int v2, int check_ret)
12332{
a22260ae
JL
12333 TCGv_i32 t0;
12334 TCGv v1_t;
12335 TCGv v2_t;
12336
12337 if ((ret == 0) && (check_ret == 1)) {
12338 /* Treat as NOP. */
a22260ae
JL
12339 return;
12340 }
12341
12342 t0 = tcg_temp_new_i32();
12343 v1_t = tcg_temp_new();
12344 v2_t = tcg_temp_new();
12345
12346 tcg_gen_movi_i32(t0, ret);
12347 gen_load_gpr(v1_t, v1);
12348 gen_load_gpr(v2_t, v2);
12349
12350 switch (op1) {
7480515f
AM
12351 /*
12352 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
12353 * the same mask and op1.
12354 */
a22260ae 12355 case OPC_MULT_G_2E:
908f6be1 12356 check_dsp_r2(ctx);
a22260ae
JL
12357 switch (op2) {
12358 case OPC_MUL_PH:
ad75a51e 12359 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12360 break;
12361 case OPC_MUL_S_PH:
ad75a51e 12362 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12363 break;
12364 case OPC_MULQ_S_W:
ad75a51e 12365 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12366 break;
12367 case OPC_MULQ_RS_W:
ad75a51e 12368 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12369 break;
12370 }
12371 break;
12372 case OPC_DPA_W_PH_DSP:
12373 switch (op2) {
12374 case OPC_DPAU_H_QBL:
12375 check_dsp(ctx);
ad75a51e 12376 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12377 break;
12378 case OPC_DPAU_H_QBR:
12379 check_dsp(ctx);
ad75a51e 12380 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12381 break;
12382 case OPC_DPSU_H_QBL:
12383 check_dsp(ctx);
ad75a51e 12384 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12385 break;
12386 case OPC_DPSU_H_QBR:
12387 check_dsp(ctx);
ad75a51e 12388 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12389 break;
12390 case OPC_DPA_W_PH:
908f6be1 12391 check_dsp_r2(ctx);
ad75a51e 12392 gen_helper_dpa_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12393 break;
12394 case OPC_DPAX_W_PH:
908f6be1 12395 check_dsp_r2(ctx);
ad75a51e 12396 gen_helper_dpax_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12397 break;
12398 case OPC_DPAQ_S_W_PH:
12399 check_dsp(ctx);
ad75a51e 12400 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12401 break;
12402 case OPC_DPAQX_S_W_PH:
908f6be1 12403 check_dsp_r2(ctx);
ad75a51e 12404 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12405 break;
12406 case OPC_DPAQX_SA_W_PH:
908f6be1 12407 check_dsp_r2(ctx);
ad75a51e 12408 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12409 break;
12410 case OPC_DPS_W_PH:
908f6be1 12411 check_dsp_r2(ctx);
ad75a51e 12412 gen_helper_dps_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12413 break;
12414 case OPC_DPSX_W_PH:
908f6be1 12415 check_dsp_r2(ctx);
ad75a51e 12416 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12417 break;
12418 case OPC_DPSQ_S_W_PH:
12419 check_dsp(ctx);
ad75a51e 12420 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12421 break;
12422 case OPC_DPSQX_S_W_PH:
908f6be1 12423 check_dsp_r2(ctx);
ad75a51e 12424 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12425 break;
12426 case OPC_DPSQX_SA_W_PH:
908f6be1 12427 check_dsp_r2(ctx);
ad75a51e 12428 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12429 break;
12430 case OPC_MULSAQ_S_W_PH:
12431 check_dsp(ctx);
ad75a51e 12432 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12433 break;
12434 case OPC_DPAQ_SA_L_W:
12435 check_dsp(ctx);
ad75a51e 12436 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12437 break;
12438 case OPC_DPSQ_SA_L_W:
12439 check_dsp(ctx);
ad75a51e 12440 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12441 break;
12442 case OPC_MAQ_S_W_PHL:
12443 check_dsp(ctx);
ad75a51e 12444 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12445 break;
12446 case OPC_MAQ_S_W_PHR:
12447 check_dsp(ctx);
ad75a51e 12448 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12449 break;
12450 case OPC_MAQ_SA_W_PHL:
12451 check_dsp(ctx);
ad75a51e 12452 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12453 break;
12454 case OPC_MAQ_SA_W_PHR:
12455 check_dsp(ctx);
ad75a51e 12456 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12457 break;
12458 case OPC_MULSA_W_PH:
908f6be1 12459 check_dsp_r2(ctx);
ad75a51e 12460 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, tcg_env);
a22260ae
JL
12461 break;
12462 }
12463 break;
12464#ifdef TARGET_MIPS64
12465 case OPC_DPAQ_W_QH_DSP:
12466 {
12467 int ac = ret & 0x03;
12468 tcg_gen_movi_i32(t0, ac);
12469
12470 switch (op2) {
12471 case OPC_DMADD:
12472 check_dsp(ctx);
ad75a51e 12473 gen_helper_dmadd(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12474 break;
12475 case OPC_DMADDU:
12476 check_dsp(ctx);
ad75a51e 12477 gen_helper_dmaddu(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12478 break;
12479 case OPC_DMSUB:
12480 check_dsp(ctx);
ad75a51e 12481 gen_helper_dmsub(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12482 break;
12483 case OPC_DMSUBU:
12484 check_dsp(ctx);
ad75a51e 12485 gen_helper_dmsubu(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12486 break;
12487 case OPC_DPA_W_QH:
908f6be1 12488 check_dsp_r2(ctx);
ad75a51e 12489 gen_helper_dpa_w_qh(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12490 break;
12491 case OPC_DPAQ_S_W_QH:
12492 check_dsp(ctx);
ad75a51e 12493 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12494 break;
12495 case OPC_DPAQ_SA_L_PW:
12496 check_dsp(ctx);
ad75a51e 12497 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12498 break;
12499 case OPC_DPAU_H_OBL:
12500 check_dsp(ctx);
ad75a51e 12501 gen_helper_dpau_h_obl(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12502 break;
12503 case OPC_DPAU_H_OBR:
12504 check_dsp(ctx);
ad75a51e 12505 gen_helper_dpau_h_obr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12506 break;
12507 case OPC_DPS_W_QH:
908f6be1 12508 check_dsp_r2(ctx);
ad75a51e 12509 gen_helper_dps_w_qh(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12510 break;
12511 case OPC_DPSQ_S_W_QH:
12512 check_dsp(ctx);
ad75a51e 12513 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12514 break;
12515 case OPC_DPSQ_SA_L_PW:
12516 check_dsp(ctx);
ad75a51e 12517 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12518 break;
12519 case OPC_DPSU_H_OBL:
12520 check_dsp(ctx);
ad75a51e 12521 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12522 break;
12523 case OPC_DPSU_H_OBR:
12524 check_dsp(ctx);
ad75a51e 12525 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12526 break;
12527 case OPC_MAQ_S_L_PWL:
12528 check_dsp(ctx);
ad75a51e 12529 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12530 break;
12531 case OPC_MAQ_S_L_PWR:
12532 check_dsp(ctx);
ad75a51e 12533 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12534 break;
12535 case OPC_MAQ_S_W_QHLL:
12536 check_dsp(ctx);
ad75a51e 12537 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12538 break;
12539 case OPC_MAQ_SA_W_QHLL:
12540 check_dsp(ctx);
ad75a51e 12541 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12542 break;
12543 case OPC_MAQ_S_W_QHLR:
12544 check_dsp(ctx);
ad75a51e 12545 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12546 break;
12547 case OPC_MAQ_SA_W_QHLR:
12548 check_dsp(ctx);
ad75a51e 12549 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12550 break;
12551 case OPC_MAQ_S_W_QHRL:
12552 check_dsp(ctx);
ad75a51e 12553 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12554 break;
12555 case OPC_MAQ_SA_W_QHRL:
12556 check_dsp(ctx);
ad75a51e 12557 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12558 break;
12559 case OPC_MAQ_S_W_QHRR:
12560 check_dsp(ctx);
ad75a51e 12561 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12562 break;
12563 case OPC_MAQ_SA_W_QHRR:
12564 check_dsp(ctx);
ad75a51e 12565 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12566 break;
12567 case OPC_MULSAQ_S_L_PW:
12568 check_dsp(ctx);
ad75a51e 12569 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12570 break;
12571 case OPC_MULSAQ_S_W_QH:
12572 check_dsp(ctx);
ad75a51e 12573 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
a22260ae
JL
12574 break;
12575 }
12576 }
12577 break;
12578#endif
12579 case OPC_ADDU_QB_DSP:
12580 switch (op2) {
12581 case OPC_MULEU_S_PH_QBL:
12582 check_dsp(ctx);
ad75a51e 12583 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12584 break;
12585 case OPC_MULEU_S_PH_QBR:
12586 check_dsp(ctx);
ad75a51e 12587 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12588 break;
12589 case OPC_MULQ_RS_PH:
12590 check_dsp(ctx);
ad75a51e 12591 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12592 break;
12593 case OPC_MULEQ_S_W_PHL:
12594 check_dsp(ctx);
ad75a51e 12595 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12596 break;
12597 case OPC_MULEQ_S_W_PHR:
12598 check_dsp(ctx);
ad75a51e 12599 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12600 break;
12601 case OPC_MULQ_S_PH:
908f6be1 12602 check_dsp_r2(ctx);
ad75a51e 12603 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12604 break;
12605 }
12606 break;
12607#ifdef TARGET_MIPS64
12608 case OPC_ADDU_OB_DSP:
12609 switch (op2) {
12610 case OPC_MULEQ_S_PW_QHL:
12611 check_dsp(ctx);
ad75a51e 12612 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12613 break;
12614 case OPC_MULEQ_S_PW_QHR:
12615 check_dsp(ctx);
ad75a51e 12616 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12617 break;
12618 case OPC_MULEU_S_QH_OBL:
12619 check_dsp(ctx);
ad75a51e 12620 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12621 break;
12622 case OPC_MULEU_S_QH_OBR:
12623 check_dsp(ctx);
ad75a51e 12624 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12625 break;
12626 case OPC_MULQ_RS_QH:
12627 check_dsp(ctx);
ad75a51e 12628 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
a22260ae
JL
12629 break;
12630 }
12631 break;
12632#endif
12633 }
a22260ae
JL
12634}
12635
d75c135e 12636static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
12637 int ret, int val)
12638{
1cb6686c
JL
12639 int16_t imm;
12640 TCGv t0;
12641 TCGv val_t;
12642
12643 if (ret == 0) {
12644 /* Treat as NOP. */
1cb6686c
JL
12645 return;
12646 }
12647
12648 t0 = tcg_temp_new();
12649 val_t = tcg_temp_new();
12650 gen_load_gpr(val_t, val);
12651
12652 switch (op1) {
12653 case OPC_ABSQ_S_PH_DSP:
12654 switch (op2) {
12655 case OPC_BITREV:
12656 check_dsp(ctx);
12657 gen_helper_bitrev(cpu_gpr[ret], val_t);
12658 break;
12659 case OPC_REPL_QB:
12660 check_dsp(ctx);
12661 {
12662 target_long result;
12663 imm = (ctx->opcode >> 16) & 0xFF;
12664 result = (uint32_t)imm << 24 |
12665 (uint32_t)imm << 16 |
12666 (uint32_t)imm << 8 |
12667 (uint32_t)imm;
12668 result = (int32_t)result;
12669 tcg_gen_movi_tl(cpu_gpr[ret], result);
12670 }
12671 break;
12672 case OPC_REPLV_QB:
12673 check_dsp(ctx);
12674 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12675 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12676 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12677 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12678 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12679 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12680 break;
12681 case OPC_REPL_PH:
12682 check_dsp(ctx);
12683 {
12684 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 12685 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
12686 tcg_gen_movi_tl(cpu_gpr[ret], \
12687 (target_long)((int32_t)imm << 16 | \
c4aaba92 12688 (uint16_t)imm));
1cb6686c
JL
12689 }
12690 break;
12691 case OPC_REPLV_PH:
12692 check_dsp(ctx);
12693 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12694 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12695 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12696 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12697 break;
12698 }
12699 break;
12700#ifdef TARGET_MIPS64
12701 case OPC_ABSQ_S_QH_DSP:
12702 switch (op2) {
12703 case OPC_REPL_OB:
12704 check_dsp(ctx);
12705 {
12706 target_long temp;
12707
12708 imm = (ctx->opcode >> 16) & 0xFF;
12709 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
12710 temp = (temp << 16) | temp;
12711 temp = (temp << 32) | temp;
12712 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12713 break;
12714 }
12715 case OPC_REPL_PW:
12716 check_dsp(ctx);
12717 {
12718 target_long temp;
12719
12720 imm = (ctx->opcode >> 16) & 0x03FF;
12721 imm = (int16_t)(imm << 6) >> 6;
12722 temp = ((target_long)imm << 32) \
12723 | ((target_long)imm & 0xFFFFFFFF);
12724 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12725 break;
12726 }
12727 case OPC_REPL_QH:
12728 check_dsp(ctx);
12729 {
12730 target_long temp;
12731
12732 imm = (ctx->opcode >> 16) & 0x03FF;
12733 imm = (int16_t)(imm << 6) >> 6;
12734
12735 temp = ((uint64_t)(uint16_t)imm << 48) |
12736 ((uint64_t)(uint16_t)imm << 32) |
12737 ((uint64_t)(uint16_t)imm << 16) |
12738 (uint64_t)(uint16_t)imm;
12739 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12740 break;
12741 }
12742 case OPC_REPLV_OB:
12743 check_dsp(ctx);
12744 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12745 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12746 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12747 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12748 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12749 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12750 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12751 break;
12752 case OPC_REPLV_PW:
12753 check_dsp(ctx);
12754 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
12755 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12756 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12757 break;
12758 case OPC_REPLV_QH:
12759 check_dsp(ctx);
12760 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12761 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12762 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12763 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12764 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12765 break;
12766 }
12767 break;
12768#endif
12769 }
1cb6686c
JL
12770}
12771
26690560
JL
12772static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
12773 uint32_t op1, uint32_t op2,
12774 int ret, int v1, int v2, int check_ret)
12775{
26690560
JL
12776 TCGv t1;
12777 TCGv v1_t;
12778 TCGv v2_t;
12779
12780 if ((ret == 0) && (check_ret == 1)) {
12781 /* Treat as NOP. */
26690560
JL
12782 return;
12783 }
12784
26690560
JL
12785 t1 = tcg_temp_new();
12786 v1_t = tcg_temp_new();
12787 v2_t = tcg_temp_new();
12788
12789 gen_load_gpr(v1_t, v1);
12790 gen_load_gpr(v2_t, v2);
12791
12792 switch (op1) {
26690560
JL
12793 case OPC_CMPU_EQ_QB_DSP:
12794 switch (op2) {
12795 case OPC_CMPU_EQ_QB:
12796 check_dsp(ctx);
ad75a51e 12797 gen_helper_cmpu_eq_qb(v1_t, v2_t, tcg_env);
26690560
JL
12798 break;
12799 case OPC_CMPU_LT_QB:
12800 check_dsp(ctx);
ad75a51e 12801 gen_helper_cmpu_lt_qb(v1_t, v2_t, tcg_env);
26690560
JL
12802 break;
12803 case OPC_CMPU_LE_QB:
12804 check_dsp(ctx);
ad75a51e 12805 gen_helper_cmpu_le_qb(v1_t, v2_t, tcg_env);
26690560
JL
12806 break;
12807 case OPC_CMPGU_EQ_QB:
12808 check_dsp(ctx);
12809 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
12810 break;
12811 case OPC_CMPGU_LT_QB:
12812 check_dsp(ctx);
12813 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
12814 break;
12815 case OPC_CMPGU_LE_QB:
12816 check_dsp(ctx);
12817 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
12818 break;
12819 case OPC_CMPGDU_EQ_QB:
908f6be1 12820 check_dsp_r2(ctx);
26690560
JL
12821 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
12822 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12823 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12824 tcg_gen_shli_tl(t1, t1, 24);
12825 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12826 break;
12827 case OPC_CMPGDU_LT_QB:
908f6be1 12828 check_dsp_r2(ctx);
26690560
JL
12829 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
12830 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12831 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12832 tcg_gen_shli_tl(t1, t1, 24);
12833 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12834 break;
12835 case OPC_CMPGDU_LE_QB:
908f6be1 12836 check_dsp_r2(ctx);
26690560
JL
12837 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
12838 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12839 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12840 tcg_gen_shli_tl(t1, t1, 24);
12841 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12842 break;
12843 case OPC_CMP_EQ_PH:
12844 check_dsp(ctx);
ad75a51e 12845 gen_helper_cmp_eq_ph(v1_t, v2_t, tcg_env);
26690560
JL
12846 break;
12847 case OPC_CMP_LT_PH:
12848 check_dsp(ctx);
ad75a51e 12849 gen_helper_cmp_lt_ph(v1_t, v2_t, tcg_env);
26690560
JL
12850 break;
12851 case OPC_CMP_LE_PH:
12852 check_dsp(ctx);
ad75a51e 12853 gen_helper_cmp_le_ph(v1_t, v2_t, tcg_env);
26690560
JL
12854 break;
12855 case OPC_PICK_QB:
12856 check_dsp(ctx);
ad75a51e 12857 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12858 break;
12859 case OPC_PICK_PH:
12860 check_dsp(ctx);
ad75a51e 12861 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12862 break;
12863 case OPC_PACKRL_PH:
12864 check_dsp(ctx);
12865 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
12866 break;
12867 }
12868 break;
12869#ifdef TARGET_MIPS64
12870 case OPC_CMPU_EQ_OB_DSP:
12871 switch (op2) {
12872 case OPC_CMP_EQ_PW:
12873 check_dsp(ctx);
ad75a51e 12874 gen_helper_cmp_eq_pw(v1_t, v2_t, tcg_env);
26690560
JL
12875 break;
12876 case OPC_CMP_LT_PW:
12877 check_dsp(ctx);
ad75a51e 12878 gen_helper_cmp_lt_pw(v1_t, v2_t, tcg_env);
26690560
JL
12879 break;
12880 case OPC_CMP_LE_PW:
12881 check_dsp(ctx);
ad75a51e 12882 gen_helper_cmp_le_pw(v1_t, v2_t, tcg_env);
26690560
JL
12883 break;
12884 case OPC_CMP_EQ_QH:
12885 check_dsp(ctx);
ad75a51e 12886 gen_helper_cmp_eq_qh(v1_t, v2_t, tcg_env);
26690560
JL
12887 break;
12888 case OPC_CMP_LT_QH:
12889 check_dsp(ctx);
ad75a51e 12890 gen_helper_cmp_lt_qh(v1_t, v2_t, tcg_env);
26690560
JL
12891 break;
12892 case OPC_CMP_LE_QH:
12893 check_dsp(ctx);
ad75a51e 12894 gen_helper_cmp_le_qh(v1_t, v2_t, tcg_env);
26690560
JL
12895 break;
12896 case OPC_CMPGDU_EQ_OB:
908f6be1 12897 check_dsp_r2(ctx);
ad75a51e 12898 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12899 break;
12900 case OPC_CMPGDU_LT_OB:
908f6be1 12901 check_dsp_r2(ctx);
ad75a51e 12902 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12903 break;
12904 case OPC_CMPGDU_LE_OB:
908f6be1 12905 check_dsp_r2(ctx);
ad75a51e 12906 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12907 break;
12908 case OPC_CMPGU_EQ_OB:
12909 check_dsp(ctx);
12910 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
12911 break;
12912 case OPC_CMPGU_LT_OB:
12913 check_dsp(ctx);
12914 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
12915 break;
12916 case OPC_CMPGU_LE_OB:
12917 check_dsp(ctx);
12918 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
12919 break;
12920 case OPC_CMPU_EQ_OB:
12921 check_dsp(ctx);
ad75a51e 12922 gen_helper_cmpu_eq_ob(v1_t, v2_t, tcg_env);
26690560
JL
12923 break;
12924 case OPC_CMPU_LT_OB:
12925 check_dsp(ctx);
ad75a51e 12926 gen_helper_cmpu_lt_ob(v1_t, v2_t, tcg_env);
26690560
JL
12927 break;
12928 case OPC_CMPU_LE_OB:
12929 check_dsp(ctx);
ad75a51e 12930 gen_helper_cmpu_le_ob(v1_t, v2_t, tcg_env);
26690560
JL
12931 break;
12932 case OPC_PACKRL_PW:
12933 check_dsp(ctx);
12934 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
12935 break;
12936 case OPC_PICK_OB:
12937 check_dsp(ctx);
ad75a51e 12938 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12939 break;
12940 case OPC_PICK_PW:
12941 check_dsp(ctx);
ad75a51e 12942 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12943 break;
12944 case OPC_PICK_QH:
12945 check_dsp(ctx);
ad75a51e 12946 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
26690560
JL
12947 break;
12948 }
12949 break;
df6126a7
AJ
12950#endif
12951 }
df6126a7
AJ
12952}
12953
12954static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
12955 uint32_t op1, int rt, int rs, int sa)
12956{
df6126a7
AJ
12957 TCGv t0;
12958
908f6be1 12959 check_dsp_r2(ctx);
df6126a7
AJ
12960
12961 if (rt == 0) {
12962 /* Treat as NOP. */
df6126a7
AJ
12963 return;
12964 }
12965
12966 t0 = tcg_temp_new();
12967 gen_load_gpr(t0, rs);
12968
12969 switch (op1) {
12970 case OPC_APPEND_DSP:
12971 switch (MASK_APPEND(ctx->opcode)) {
12972 case OPC_APPEND:
12973 if (sa != 0) {
12974 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
12975 }
12976 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12977 break;
12978 case OPC_PREPEND:
12979 if (sa != 0) {
12980 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
12981 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
12982 tcg_gen_shli_tl(t0, t0, 32 - sa);
12983 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12984 }
12985 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12986 break;
12987 case OPC_BALIGN:
12988 sa &= 3;
12989 if (sa != 0 && sa != 2) {
12990 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
12991 tcg_gen_ext32u_tl(t0, t0);
12992 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
12993 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12994 }
12995 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12996 break;
12997 default: /* Invalid */
12998 MIPS_INVAL("MASK APPEND");
3a4ef3b7 12999 gen_reserved_instruction(ctx);
df6126a7
AJ
13000 break;
13001 }
13002 break;
13003#ifdef TARGET_MIPS64
26690560 13004 case OPC_DAPPEND_DSP:
df6126a7 13005 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 13006 case OPC_DAPPEND:
df6126a7
AJ
13007 if (sa != 0) {
13008 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
13009 }
26690560
JL
13010 break;
13011 case OPC_PREPENDD:
df6126a7
AJ
13012 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
13013 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
13014 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
13015 break;
13016 case OPC_PREPENDW:
df6126a7
AJ
13017 if (sa != 0) {
13018 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
13019 tcg_gen_shli_tl(t0, t0, 64 - sa);
13020 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13021 }
26690560
JL
13022 break;
13023 case OPC_DBALIGN:
df6126a7
AJ
13024 sa &= 7;
13025 if (sa != 0 && sa != 2 && sa != 4) {
13026 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
13027 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
13028 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13029 }
26690560
JL
13030 break;
13031 default: /* Invalid */
13032 MIPS_INVAL("MASK DAPPEND");
3a4ef3b7 13033 gen_reserved_instruction(ctx);
26690560
JL
13034 break;
13035 }
13036 break;
13037#endif
13038 }
26690560
JL
13039}
13040
b53371ed
JL
13041static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13042 int ret, int v1, int v2, int check_ret)
13043
13044{
b53371ed
JL
13045 TCGv t0;
13046 TCGv t1;
13047 TCGv v1_t;
b53371ed
JL
13048 int16_t imm;
13049
13050 if ((ret == 0) && (check_ret == 1)) {
13051 /* Treat as NOP. */
b53371ed
JL
13052 return;
13053 }
13054
13055 t0 = tcg_temp_new();
13056 t1 = tcg_temp_new();
13057 v1_t = tcg_temp_new();
b53371ed
JL
13058
13059 gen_load_gpr(v1_t, v1);
b53371ed
JL
13060
13061 switch (op1) {
13062 case OPC_EXTR_W_DSP:
13063 check_dsp(ctx);
13064 switch (op2) {
13065 case OPC_EXTR_W:
13066 tcg_gen_movi_tl(t0, v2);
13067 tcg_gen_movi_tl(t1, v1);
ad75a51e 13068 gen_helper_extr_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13069 break;
13070 case OPC_EXTR_R_W:
13071 tcg_gen_movi_tl(t0, v2);
13072 tcg_gen_movi_tl(t1, v1);
ad75a51e 13073 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13074 break;
13075 case OPC_EXTR_RS_W:
13076 tcg_gen_movi_tl(t0, v2);
13077 tcg_gen_movi_tl(t1, v1);
ad75a51e 13078 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13079 break;
13080 case OPC_EXTR_S_H:
13081 tcg_gen_movi_tl(t0, v2);
13082 tcg_gen_movi_tl(t1, v1);
ad75a51e 13083 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13084 break;
13085 case OPC_EXTRV_S_H:
13086 tcg_gen_movi_tl(t0, v2);
ad75a51e 13087 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13088 break;
13089 case OPC_EXTRV_W:
13090 tcg_gen_movi_tl(t0, v2);
ad75a51e 13091 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13092 break;
13093 case OPC_EXTRV_R_W:
13094 tcg_gen_movi_tl(t0, v2);
ad75a51e 13095 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13096 break;
13097 case OPC_EXTRV_RS_W:
13098 tcg_gen_movi_tl(t0, v2);
ad75a51e 13099 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13100 break;
13101 case OPC_EXTP:
13102 tcg_gen_movi_tl(t0, v2);
13103 tcg_gen_movi_tl(t1, v1);
ad75a51e 13104 gen_helper_extp(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13105 break;
13106 case OPC_EXTPV:
13107 tcg_gen_movi_tl(t0, v2);
ad75a51e 13108 gen_helper_extp(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13109 break;
13110 case OPC_EXTPDP:
13111 tcg_gen_movi_tl(t0, v2);
13112 tcg_gen_movi_tl(t1, v1);
ad75a51e 13113 gen_helper_extpdp(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13114 break;
13115 case OPC_EXTPDPV:
13116 tcg_gen_movi_tl(t0, v2);
ad75a51e 13117 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13118 break;
13119 case OPC_SHILO:
13120 imm = (ctx->opcode >> 20) & 0x3F;
13121 tcg_gen_movi_tl(t0, ret);
13122 tcg_gen_movi_tl(t1, imm);
ad75a51e 13123 gen_helper_shilo(t0, t1, tcg_env);
b53371ed
JL
13124 break;
13125 case OPC_SHILOV:
13126 tcg_gen_movi_tl(t0, ret);
ad75a51e 13127 gen_helper_shilo(t0, v1_t, tcg_env);
b53371ed
JL
13128 break;
13129 case OPC_MTHLIP:
13130 tcg_gen_movi_tl(t0, ret);
ad75a51e 13131 gen_helper_mthlip(t0, v1_t, tcg_env);
b53371ed
JL
13132 break;
13133 case OPC_WRDSP:
13134 imm = (ctx->opcode >> 11) & 0x3FF;
13135 tcg_gen_movi_tl(t0, imm);
ad75a51e 13136 gen_helper_wrdsp(v1_t, t0, tcg_env);
b53371ed
JL
13137 break;
13138 case OPC_RDDSP:
13139 imm = (ctx->opcode >> 16) & 0x03FF;
13140 tcg_gen_movi_tl(t0, imm);
ad75a51e 13141 gen_helper_rddsp(cpu_gpr[ret], t0, tcg_env);
b53371ed
JL
13142 break;
13143 }
13144 break;
13145#ifdef TARGET_MIPS64
13146 case OPC_DEXTR_W_DSP:
13147 check_dsp(ctx);
13148 switch (op2) {
13149 case OPC_DMTHLIP:
13150 tcg_gen_movi_tl(t0, ret);
ad75a51e 13151 gen_helper_dmthlip(v1_t, t0, tcg_env);
b53371ed
JL
13152 break;
13153 case OPC_DSHILO:
13154 {
13155 int shift = (ctx->opcode >> 19) & 0x7F;
13156 int ac = (ctx->opcode >> 11) & 0x03;
13157 tcg_gen_movi_tl(t0, shift);
13158 tcg_gen_movi_tl(t1, ac);
ad75a51e 13159 gen_helper_dshilo(t0, t1, tcg_env);
b53371ed
JL
13160 break;
13161 }
13162 case OPC_DSHILOV:
13163 {
13164 int ac = (ctx->opcode >> 11) & 0x03;
13165 tcg_gen_movi_tl(t0, ac);
ad75a51e 13166 gen_helper_dshilo(v1_t, t0, tcg_env);
b53371ed
JL
13167 break;
13168 }
13169 case OPC_DEXTP:
13170 tcg_gen_movi_tl(t0, v2);
13171 tcg_gen_movi_tl(t1, v1);
13172
ad75a51e 13173 gen_helper_dextp(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13174 break;
13175 case OPC_DEXTPV:
13176 tcg_gen_movi_tl(t0, v2);
ad75a51e 13177 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13178 break;
13179 case OPC_DEXTPDP:
13180 tcg_gen_movi_tl(t0, v2);
13181 tcg_gen_movi_tl(t1, v1);
ad75a51e 13182 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13183 break;
13184 case OPC_DEXTPDPV:
13185 tcg_gen_movi_tl(t0, v2);
ad75a51e 13186 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13187 break;
13188 case OPC_DEXTR_L:
13189 tcg_gen_movi_tl(t0, v2);
13190 tcg_gen_movi_tl(t1, v1);
ad75a51e 13191 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13192 break;
13193 case OPC_DEXTR_R_L:
13194 tcg_gen_movi_tl(t0, v2);
13195 tcg_gen_movi_tl(t1, v1);
ad75a51e 13196 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13197 break;
13198 case OPC_DEXTR_RS_L:
13199 tcg_gen_movi_tl(t0, v2);
13200 tcg_gen_movi_tl(t1, v1);
ad75a51e 13201 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13202 break;
13203 case OPC_DEXTR_W:
13204 tcg_gen_movi_tl(t0, v2);
13205 tcg_gen_movi_tl(t1, v1);
ad75a51e 13206 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13207 break;
13208 case OPC_DEXTR_R_W:
13209 tcg_gen_movi_tl(t0, v2);
13210 tcg_gen_movi_tl(t1, v1);
ad75a51e 13211 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13212 break;
13213 case OPC_DEXTR_RS_W:
13214 tcg_gen_movi_tl(t0, v2);
13215 tcg_gen_movi_tl(t1, v1);
ad75a51e 13216 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13217 break;
13218 case OPC_DEXTR_S_H:
13219 tcg_gen_movi_tl(t0, v2);
13220 tcg_gen_movi_tl(t1, v1);
ad75a51e 13221 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
b53371ed
JL
13222 break;
13223 case OPC_DEXTRV_S_H:
13224 tcg_gen_movi_tl(t0, v2);
ad75a51e 13225 gen_helper_dextr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13226 break;
13227 case OPC_DEXTRV_L:
13228 tcg_gen_movi_tl(t0, v2);
ad75a51e 13229 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13230 break;
13231 case OPC_DEXTRV_R_L:
13232 tcg_gen_movi_tl(t0, v2);
ad75a51e 13233 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13234 break;
13235 case OPC_DEXTRV_RS_L:
13236 tcg_gen_movi_tl(t0, v2);
ad75a51e 13237 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13238 break;
13239 case OPC_DEXTRV_W:
13240 tcg_gen_movi_tl(t0, v2);
ad75a51e 13241 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13242 break;
13243 case OPC_DEXTRV_R_W:
13244 tcg_gen_movi_tl(t0, v2);
ad75a51e 13245 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13246 break;
13247 case OPC_DEXTRV_RS_W:
13248 tcg_gen_movi_tl(t0, v2);
ad75a51e 13249 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
b53371ed
JL
13250 break;
13251 }
13252 break;
13253#endif
13254 }
b53371ed
JL
13255}
13256
9b1a1d68
JL
13257/* End MIPSDSP functions. */
13258
10dc65db
LA
13259static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
13260{
4267d3e6 13261 int rs, rt, rd, sa;
b42ee5e1 13262 uint32_t op1, op2;
10dc65db
LA
13263
13264 rs = (ctx->opcode >> 21) & 0x1f;
13265 rt = (ctx->opcode >> 16) & 0x1f;
13266 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 13267 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
13268
13269 op1 = MASK_SPECIAL(ctx->opcode);
13270 switch (op1) {
c2e19f3c
AM
13271 case OPC_MULT:
13272 case OPC_MULTU:
13273 case OPC_DIV:
13274 case OPC_DIVU:
b42ee5e1
LA
13275 op2 = MASK_R6_MULDIV(ctx->opcode);
13276 switch (op2) {
13277 case R6_OPC_MUL:
13278 case R6_OPC_MUH:
13279 case R6_OPC_MULU:
13280 case R6_OPC_MUHU:
13281 case R6_OPC_DIV:
13282 case R6_OPC_MOD:
13283 case R6_OPC_DIVU:
13284 case R6_OPC_MODU:
13285 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13286 break;
13287 default:
13288 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 13289 gen_reserved_instruction(ctx);
b42ee5e1
LA
13290 break;
13291 }
13292 break;
10dc65db
LA
13293 case OPC_SELEQZ:
13294 case OPC_SELNEZ:
13295 gen_cond_move(ctx, op1, rd, rs, rt);
13296 break;
4267d3e6
LA
13297 case R6_OPC_CLO:
13298 case R6_OPC_CLZ:
13299 if (rt == 0 && sa == 1) {
7480515f
AM
13300 /*
13301 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13302 * We need additionally to check other fields.
13303 */
4267d3e6
LA
13304 gen_cl(ctx, op1, rd, rs);
13305 } else {
3a4ef3b7 13306 gen_reserved_instruction(ctx);
4267d3e6
LA
13307 }
13308 break;
13309 case R6_OPC_SDBBP:
b35d7401 13310 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
d44971e7 13311 ctx->base.is_jmp = DISAS_SEMIHOST;
faf1f68b 13312 } else {
3b3c1694 13313 if (ctx->hflags & MIPS_HFLAG_SBRI) {
3a4ef3b7 13314 gen_reserved_instruction(ctx);
3b3c1694 13315 } else {
9c708c7f 13316 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13317 }
faf1f68b 13318 }
4267d3e6 13319 break;
b42ee5e1 13320#if defined(TARGET_MIPS64)
4267d3e6
LA
13321 case R6_OPC_DCLO:
13322 case R6_OPC_DCLZ:
13323 if (rt == 0 && sa == 1) {
7480515f
AM
13324 /*
13325 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13326 * We need additionally to check other fields.
13327 */
4267d3e6
LA
13328 check_mips_64(ctx);
13329 gen_cl(ctx, op1, rd, rs);
13330 } else {
3a4ef3b7 13331 gen_reserved_instruction(ctx);
4267d3e6
LA
13332 }
13333 break;
c2e19f3c
AM
13334 case OPC_DMULT:
13335 case OPC_DMULTU:
13336 case OPC_DDIV:
13337 case OPC_DDIVU:
13338
b42ee5e1
LA
13339 op2 = MASK_R6_MULDIV(ctx->opcode);
13340 switch (op2) {
13341 case R6_OPC_DMUL:
13342 case R6_OPC_DMUH:
13343 case R6_OPC_DMULU:
13344 case R6_OPC_DMUHU:
13345 case R6_OPC_DDIV:
13346 case R6_OPC_DMOD:
13347 case R6_OPC_DDIVU:
13348 case R6_OPC_DMODU:
13349 check_mips_64(ctx);
13350 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13351 break;
13352 default:
13353 MIPS_INVAL("special_r6 muldiv");
3a4ef3b7 13354 gen_reserved_instruction(ctx);
b42ee5e1
LA
13355 break;
13356 }
13357 break;
13358#endif
10dc65db
LA
13359 default: /* Invalid */
13360 MIPS_INVAL("special_r6");
3a4ef3b7 13361 gen_reserved_instruction(ctx);
10dc65db
LA
13362 break;
13363 }
13364}
13365
9dc324ce
FN
13366static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
13367{
13368 int rs = extract32(ctx->opcode, 21, 5);
13369 int rt = extract32(ctx->opcode, 16, 5);
13370 int rd = extract32(ctx->opcode, 11, 5);
13371 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
13372
13373 switch (op1) {
13374 case OPC_MOVN: /* Conditional move */
13375 case OPC_MOVZ:
13376 gen_cond_move(ctx, op1, rd, rs, rt);
13377 break;
13378 case OPC_MFHI: /* Move from HI/LO */
13379 case OPC_MFLO:
13380 gen_HILO(ctx, op1, 0, rd);
13381 break;
13382 case OPC_MTHI:
13383 case OPC_MTLO: /* Move to HI/LO */
13384 gen_HILO(ctx, op1, 0, rs);
13385 break;
13386 case OPC_MULT:
13387 case OPC_MULTU:
13388 gen_mul_txx9(ctx, op1, rd, rs, rt);
13389 break;
13390 case OPC_DIV:
13391 case OPC_DIVU:
13392 gen_muldiv(ctx, op1, 0, rs, rt);
13393 break;
13394#if defined(TARGET_MIPS64)
13395 case OPC_DMULT:
13396 case OPC_DMULTU:
13397 case OPC_DDIV:
13398 case OPC_DDIVU:
13399 check_insn_opc_user_only(ctx, INSN_R5900);
13400 gen_muldiv(ctx, op1, 0, rs, rt);
13401 break;
13402#endif
13403 case OPC_JR:
13404 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
13405 break;
13406 default: /* Invalid */
13407 MIPS_INVAL("special_tx79");
3a4ef3b7 13408 gen_reserved_instruction(ctx);
9dc324ce
FN
13409 break;
13410 }
13411}
13412
10dc65db
LA
13413static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
13414{
bf772002 13415 int rs, rt, rd;
10dc65db
LA
13416 uint32_t op1;
13417
13418 rs = (ctx->opcode >> 21) & 0x1f;
13419 rt = (ctx->opcode >> 16) & 0x1f;
13420 rd = (ctx->opcode >> 11) & 0x1f;
13421
13422 op1 = MASK_SPECIAL(ctx->opcode);
13423 switch (op1) {
13424 case OPC_MOVN: /* Conditional move */
13425 case OPC_MOVZ:
bbd5e4a2 13426 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
9dc324ce 13427 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
13428 gen_cond_move(ctx, op1, rd, rs, rt);
13429 break;
13430 case OPC_MFHI: /* Move from HI/LO */
13431 case OPC_MFLO:
13432 gen_HILO(ctx, op1, rs & 3, rd);
13433 break;
13434 case OPC_MTHI:
13435 case OPC_MTLO: /* Move to HI/LO */
13436 gen_HILO(ctx, op1, rd & 3, rs);
13437 break;
13438 case OPC_MOVCI:
bbd5e4a2 13439 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10dc65db
LA
13440 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13441 check_cp1_enabled(ctx);
13442 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
13443 (ctx->opcode >> 16) & 1);
13444 } else {
13445 generate_exception_err(ctx, EXCP_CpU, 1);
13446 }
13447 break;
b42ee5e1
LA
13448 case OPC_MULT:
13449 case OPC_MULTU:
bf772002 13450 gen_muldiv(ctx, op1, rd & 3, rs, rt);
b42ee5e1
LA
13451 break;
13452 case OPC_DIV:
13453 case OPC_DIVU:
13454 gen_muldiv(ctx, op1, 0, rs, rt);
13455 break;
13456#if defined(TARGET_MIPS64)
c2e19f3c
AM
13457 case OPC_DMULT:
13458 case OPC_DMULTU:
13459 case OPC_DDIV:
13460 case OPC_DDIVU:
b42ee5e1
LA
13461 check_insn(ctx, ISA_MIPS3);
13462 check_mips_64(ctx);
13463 gen_muldiv(ctx, op1, 0, rs, rt);
13464 break;
13465#endif
0aefa333 13466 case OPC_JR:
c8b69a2a 13467 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
0aefa333 13468 break;
4267d3e6
LA
13469 case OPC_SPIM:
13470#ifdef MIPS_STRICT_STANDARD
13471 MIPS_INVAL("SPIM");
3a4ef3b7 13472 gen_reserved_instruction(ctx);
4267d3e6
LA
13473#else
13474 /* Implemented as RI exception for now. */
13475 MIPS_INVAL("spim (unofficial)");
3a4ef3b7 13476 gen_reserved_instruction(ctx);
4267d3e6
LA
13477#endif
13478 break;
10dc65db
LA
13479 default: /* Invalid */
13480 MIPS_INVAL("special_legacy");
3a4ef3b7 13481 gen_reserved_instruction(ctx);
10dc65db
LA
13482 break;
13483 }
13484}
13485
099e5b4d 13486static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 13487{
3c824109 13488 int rs, rt, rd, sa;
099e5b4d 13489 uint32_t op1;
3c824109 13490
3c824109
NF
13491 rs = (ctx->opcode >> 21) & 0x1f;
13492 rt = (ctx->opcode >> 16) & 0x1f;
13493 rd = (ctx->opcode >> 11) & 0x1f;
13494 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
13495
13496 op1 = MASK_SPECIAL(ctx->opcode);
13497 switch (op1) {
13498 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
13499 if (sa == 5 && rd == 0 &&
13500 rs == 0 && rt == 0) { /* PAUSE */
2e211e0a 13501 if ((ctx->insn_flags & ISA_MIPS_R6) &&
339cd2a8 13502 (ctx->hflags & MIPS_HFLAG_BMASK)) {
3a4ef3b7 13503 gen_reserved_instruction(ctx);
339cd2a8
LA
13504 break;
13505 }
13506 }
13507 /* Fallthrough */
099e5b4d
LA
13508 case OPC_SRA:
13509 gen_shift_imm(ctx, op1, rd, rt, sa);
13510 break;
13511 case OPC_SRL:
13512 switch ((ctx->opcode >> 21) & 0x1f) {
13513 case 1:
13514 /* rotr is decoded as srl on non-R2 CPUs */
7a47bae5 13515 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 13516 op1 = OPC_ROTR;
ea63e2c3 13517 }
099e5b4d
LA
13518 /* Fallthrough */
13519 case 0:
13520 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 13521 break;
099e5b4d 13522 default:
3a4ef3b7 13523 gen_reserved_instruction(ctx);
ea63e2c3 13524 break;
099e5b4d
LA
13525 }
13526 break;
c2e19f3c
AM
13527 case OPC_ADD:
13528 case OPC_ADDU:
13529 case OPC_SUB:
13530 case OPC_SUBU:
099e5b4d
LA
13531 gen_arith(ctx, op1, rd, rs, rt);
13532 break;
13533 case OPC_SLLV: /* Shifts */
13534 case OPC_SRAV:
13535 gen_shift(ctx, op1, rd, rs, rt);
13536 break;
13537 case OPC_SRLV:
13538 switch ((ctx->opcode >> 6) & 0x1f) {
13539 case 1:
13540 /* rotrv is decoded as srlv on non-R2 CPUs */
7a47bae5 13541 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 13542 op1 = OPC_ROTRV;
26135ead 13543 }
099e5b4d
LA
13544 /* Fallthrough */
13545 case 0:
13546 gen_shift(ctx, op1, rd, rs, rt);
26135ead 13547 break;
099e5b4d 13548 default:
3a4ef3b7 13549 gen_reserved_instruction(ctx);
6af0bf9c 13550 break;
099e5b4d
LA
13551 }
13552 break;
13553 case OPC_SLT: /* Set on less than */
13554 case OPC_SLTU:
13555 gen_slt(ctx, op1, rd, rs, rt);
13556 break;
13557 case OPC_AND: /* Logic*/
13558 case OPC_OR:
13559 case OPC_NOR:
13560 case OPC_XOR:
13561 gen_logic(ctx, op1, rd, rs, rt);
13562 break;
0aefa333 13563 case OPC_JALR:
b231c103 13564 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 13565 break;
c2e19f3c
AM
13566 case OPC_TGE: /* Traps */
13567 case OPC_TGEU:
13568 case OPC_TLT:
13569 case OPC_TLTU:
13570 case OPC_TEQ:
099e5b4d 13571 case OPC_TNE:
d9224450 13572 check_insn(ctx, ISA_MIPS2);
0a3336f6 13573 gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
099e5b4d 13574 break;
0e9524af
PMD
13575 case OPC_PMON:
13576 /* Pmon entry point, also R4010 selsl */
b48cfdff 13577#ifdef MIPS_STRICT_STANDARD
0e9524af
PMD
13578 MIPS_INVAL("PMON / selsl");
13579 gen_reserved_instruction(ctx);
b48cfdff 13580#else
ad75a51e 13581 gen_helper_pmon(tcg_env, tcg_constant_i32(sa));
b48cfdff 13582#endif
099e5b4d
LA
13583 break;
13584 case OPC_SYSCALL:
9c708c7f 13585 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
13586 break;
13587 case OPC_BREAK:
6f3533dd 13588 generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
099e5b4d 13589 break;
099e5b4d 13590 case OPC_SYNC:
d9224450 13591 check_insn(ctx, ISA_MIPS2);
d208ac0c 13592 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 13593 break;
4ad40f36 13594
d26bc211 13595#if defined(TARGET_MIPS64)
099e5b4d
LA
13596 /* MIPS64 specific opcodes */
13597 case OPC_DSLL:
13598 case OPC_DSRA:
13599 case OPC_DSLL32:
13600 case OPC_DSRA32:
13601 check_insn(ctx, ISA_MIPS3);
13602 check_mips_64(ctx);
13603 gen_shift_imm(ctx, op1, rd, rt, sa);
13604 break;
13605 case OPC_DSRL:
13606 switch ((ctx->opcode >> 21) & 0x1f) {
13607 case 1:
13608 /* drotr is decoded as dsrl on non-R2 CPUs */
7a47bae5 13609 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 13610 op1 = OPC_DROTR;
ea63e2c3 13611 }
099e5b4d
LA
13612 /* Fallthrough */
13613 case 0:
d75c135e 13614 check_insn(ctx, ISA_MIPS3);
e189e748 13615 check_mips_64(ctx);
099e5b4d 13616 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 13617 break;
099e5b4d 13618 default:
3a4ef3b7 13619 gen_reserved_instruction(ctx);
460f00c4 13620 break;
099e5b4d
LA
13621 }
13622 break;
13623 case OPC_DSRL32:
13624 switch ((ctx->opcode >> 21) & 0x1f) {
13625 case 1:
13626 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
7a47bae5 13627 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 13628 op1 = OPC_DROTR32;
ea63e2c3 13629 }
099e5b4d
LA
13630 /* Fallthrough */
13631 case 0:
d75c135e 13632 check_insn(ctx, ISA_MIPS3);
e189e748 13633 check_mips_64(ctx);
099e5b4d 13634 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 13635 break;
099e5b4d 13636 default:
3a4ef3b7 13637 gen_reserved_instruction(ctx);
6af0bf9c
FB
13638 break;
13639 }
13640 break;
c2e19f3c
AM
13641 case OPC_DADD:
13642 case OPC_DADDU:
13643 case OPC_DSUB:
13644 case OPC_DSUBU:
099e5b4d
LA
13645 check_insn(ctx, ISA_MIPS3);
13646 check_mips_64(ctx);
13647 gen_arith(ctx, op1, rd, rs, rt);
13648 break;
13649 case OPC_DSLLV:
13650 case OPC_DSRAV:
13651 check_insn(ctx, ISA_MIPS3);
13652 check_mips_64(ctx);
13653 gen_shift(ctx, op1, rd, rs, rt);
13654 break;
13655 case OPC_DSRLV:
13656 switch ((ctx->opcode >> 6) & 0x1f) {
13657 case 1:
13658 /* drotrv is decoded as dsrlv on non-R2 CPUs */
7a47bae5 13659 if (ctx->insn_flags & ISA_MIPS_R2) {
099e5b4d 13660 op1 = OPC_DROTRV;
6af0bf9c 13661 }
099e5b4d
LA
13662 /* Fallthrough */
13663 case 0:
13664 check_insn(ctx, ISA_MIPS3);
e189e748 13665 check_mips_64(ctx);
099e5b4d 13666 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 13667 break;
099e5b4d 13668 default:
3a4ef3b7 13669 gen_reserved_instruction(ctx);
6af0bf9c
FB
13670 break;
13671 }
13672 break;
099e5b4d 13673#endif
10dc65db 13674 default:
2e211e0a 13675 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db 13676 decode_opc_special_r6(env, ctx);
9dc324ce
FN
13677 } else if (ctx->insn_flags & INSN_R5900) {
13678 decode_opc_special_tx79(env, ctx);
10dc65db
LA
13679 } else {
13680 decode_opc_special_legacy(env, ctx);
13681 }
13682 }
13683}
13684
d67da337 13685
10dc65db 13686static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
13687{
13688 int rs, rt, rd;
13689 uint32_t op1;
6c5c1e20 13690
099e5b4d
LA
13691 rs = (ctx->opcode >> 21) & 0x1f;
13692 rt = (ctx->opcode >> 16) & 0x1f;
13693 rd = (ctx->opcode >> 11) & 0x1f;
13694
13695 op1 = MASK_SPECIAL2(ctx->opcode);
13696 switch (op1) {
c2e19f3c
AM
13697 case OPC_MADD: /* Multiply and add/sub */
13698 case OPC_MADDU:
13699 case OPC_MSUB:
13700 case OPC_MSUBU:
bbd5e4a2 13701 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
13702 gen_muldiv(ctx, op1, rd & 3, rs, rt);
13703 break;
13704 case OPC_MUL:
099e5b4d
LA
13705 gen_arith(ctx, op1, rd, rs, rt);
13706 break;
fac5a073
LA
13707 case OPC_DIV_G_2F:
13708 case OPC_DIVU_G_2F:
13709 case OPC_MULT_G_2F:
13710 case OPC_MULTU_G_2F:
13711 case OPC_MOD_G_2F:
13712 case OPC_MODU_G_2F:
8e2d5831 13713 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
fac5a073
LA
13714 gen_loongson_integer(ctx, op1, rd, rs, rt);
13715 break;
099e5b4d
LA
13716 case OPC_CLO:
13717 case OPC_CLZ:
bbd5e4a2 13718 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
13719 gen_cl(ctx, op1, rd, rs);
13720 break;
13721 case OPC_SDBBP:
b35d7401 13722 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
d44971e7 13723 ctx->base.is_jmp = DISAS_SEMIHOST;
3b3c1694 13724 } else {
7480515f
AM
13725 /*
13726 * XXX: not clear which exception should be raised
3b3c1694
LA
13727 * when in debug mode...
13728 */
bbd5e4a2 13729 check_insn(ctx, ISA_MIPS_R1);
9c708c7f 13730 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13731 }
099e5b4d 13732 break;
9b1a1d68 13733#if defined(TARGET_MIPS64)
099e5b4d
LA
13734 case OPC_DCLO:
13735 case OPC_DCLZ:
bbd5e4a2 13736 check_insn(ctx, ISA_MIPS_R1);
099e5b4d
LA
13737 check_mips_64(ctx);
13738 gen_cl(ctx, op1, rd, rs);
13739 break;
4267d3e6
LA
13740 case OPC_DMULT_G_2F:
13741 case OPC_DMULTU_G_2F:
13742 case OPC_DDIV_G_2F:
13743 case OPC_DDIVU_G_2F:
13744 case OPC_DMOD_G_2F:
13745 case OPC_DMODU_G_2F:
8e2d5831 13746 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
4267d3e6
LA
13747 gen_loongson_integer(ctx, op1, rd, rs, rt);
13748 break;
10dc65db 13749#endif
4267d3e6
LA
13750 default: /* Invalid */
13751 MIPS_INVAL("special2_legacy");
3a4ef3b7 13752 gen_reserved_instruction(ctx);
4267d3e6 13753 break;
10dc65db
LA
13754 }
13755}
13756
13757static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
13758{
15eacb9b
YK
13759 int rs, rt, rd, sa;
13760 uint32_t op1, op2;
10dc65db
LA
13761 int16_t imm;
13762
13763 rs = (ctx->opcode >> 21) & 0x1f;
13764 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
13765 rd = (ctx->opcode >> 11) & 0x1f;
13766 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
13767 imm = (int16_t)ctx->opcode >> 7;
13768
13769 op1 = MASK_SPECIAL3(ctx->opcode);
13770 switch (op1) {
bf7910c6
LA
13771 case R6_OPC_PREF:
13772 if (rt >= 24) {
13773 /* hint codes 24-31 are reserved and signal RI */
3a4ef3b7 13774 gen_reserved_instruction(ctx);
bf7910c6
LA
13775 }
13776 /* Treat as NOP. */
13777 break;
13778 case R6_OPC_CACHE:
40d48212 13779 check_cp0_enabled(ctx);
0d74a222
LA
13780 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13781 gen_cache_operation(ctx, rt, rs, imm);
13782 }
bf7910c6 13783 break;
10dc65db 13784 case R6_OPC_SC:
33a07fa2 13785 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
10dc65db
LA
13786 break;
13787 case R6_OPC_LL:
13788 gen_ld(ctx, op1, rt, rs, imm);
13789 break;
15eacb9b
YK
13790 case OPC_BSHFL:
13791 {
13792 if (rd == 0) {
13793 /* Treat as NOP. */
13794 break;
13795 }
15eacb9b
YK
13796 op2 = MASK_BSHFL(ctx->opcode);
13797 switch (op2) {
c2e19f3c 13798 case OPC_ALIGN:
373ecd38
AM
13799 case OPC_ALIGN_1:
13800 case OPC_ALIGN_2:
13801 case OPC_ALIGN_3:
821f2008 13802 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
13803 break;
13804 case OPC_BITSWAP:
1f1b4c00 13805 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
13806 break;
13807 }
15eacb9b
YK
13808 }
13809 break;
99029be1
YK
13810#ifndef CONFIG_USER_ONLY
13811 case OPC_GINV:
13812 if (unlikely(ctx->gi <= 1)) {
3a4ef3b7 13813 gen_reserved_instruction(ctx);
99029be1
YK
13814 }
13815 check_cp0_enabled(ctx);
13816 switch ((ctx->opcode >> 6) & 3) {
13817 case 0: /* GINVI */
13818 /* Treat as NOP. */
13819 break;
13820 case 2: /* GINVT */
13821 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
13822 break;
13823 default:
3a4ef3b7 13824 gen_reserved_instruction(ctx);
99029be1
YK
13825 break;
13826 }
13827 break;
13828#endif
bf7910c6
LA
13829#if defined(TARGET_MIPS64)
13830 case R6_OPC_SCD:
fc313c64 13831 gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
bf7910c6
LA
13832 break;
13833 case R6_OPC_LLD:
13834 gen_ld(ctx, op1, rt, rs, imm);
13835 break;
15eacb9b
YK
13836 case OPC_DBSHFL:
13837 check_mips_64(ctx);
13838 {
13839 if (rd == 0) {
13840 /* Treat as NOP. */
13841 break;
13842 }
15eacb9b
YK
13843 op2 = MASK_DBSHFL(ctx->opcode);
13844 switch (op2) {
c2e19f3c 13845 case OPC_DALIGN:
373ecd38
AM
13846 case OPC_DALIGN_1:
13847 case OPC_DALIGN_2:
13848 case OPC_DALIGN_3:
13849 case OPC_DALIGN_4:
13850 case OPC_DALIGN_5:
13851 case OPC_DALIGN_6:
13852 case OPC_DALIGN_7:
821f2008 13853 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
13854 break;
13855 case OPC_DBITSWAP:
1f1b4c00 13856 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
13857 break;
13858 }
1f1b4c00 13859
15eacb9b
YK
13860 }
13861 break;
bf7910c6 13862#endif
10dc65db
LA
13863 default: /* Invalid */
13864 MIPS_INVAL("special3_r6");
3a4ef3b7 13865 gen_reserved_instruction(ctx);
10dc65db
LA
13866 break;
13867 }
13868}
13869
13870static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
13871{
fac5a073 13872 int rs, rt, rd;
099e5b4d 13873 uint32_t op1, op2;
099e5b4d
LA
13874
13875 rs = (ctx->opcode >> 21) & 0x1f;
13876 rt = (ctx->opcode >> 16) & 0x1f;
13877 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
13878
13879 op1 = MASK_SPECIAL3(ctx->opcode);
13880 switch (op1) {
c2e19f3c
AM
13881 case OPC_DIV_G_2E:
13882 case OPC_DIVU_G_2E:
13883 case OPC_MOD_G_2E:
13884 case OPC_MODU_G_2E:
13885 case OPC_MULT_G_2E:
13886 case OPC_MULTU_G_2E:
7480515f
AM
13887 /*
13888 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13889 * the same mask and op1.
13890 */
908f6be1 13891 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 13892 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 13893 switch (op2) {
099e5b4d
LA
13894 case OPC_ADDUH_QB:
13895 case OPC_ADDUH_R_QB:
13896 case OPC_ADDQH_PH:
13897 case OPC_ADDQH_R_PH:
13898 case OPC_ADDQH_W:
13899 case OPC_ADDQH_R_W:
13900 case OPC_SUBUH_QB:
13901 case OPC_SUBUH_R_QB:
13902 case OPC_SUBQH_PH:
13903 case OPC_SUBQH_R_PH:
13904 case OPC_SUBQH_W:
13905 case OPC_SUBQH_R_W:
461c08df
JL
13906 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13907 break;
099e5b4d
LA
13908 case OPC_MUL_PH:
13909 case OPC_MUL_S_PH:
13910 case OPC_MULQ_S_W:
13911 case OPC_MULQ_RS_W:
13912 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 13913 break;
461c08df 13914 default:
099e5b4d 13915 MIPS_INVAL("MASK ADDUH.QB");
3a4ef3b7 13916 gen_reserved_instruction(ctx);
461c08df
JL
13917 break;
13918 }
099e5b4d
LA
13919 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
13920 gen_loongson_integer(ctx, op1, rd, rs, rt);
13921 } else {
3a4ef3b7 13922 gen_reserved_instruction(ctx);
099e5b4d
LA
13923 }
13924 break;
13925 case OPC_LX_DSP:
13926 op2 = MASK_LX(ctx->opcode);
13927 switch (op2) {
13928#if defined(TARGET_MIPS64)
13929 case OPC_LDX:
13930#endif
13931 case OPC_LBUX:
13932 case OPC_LHX:
13933 case OPC_LWX:
4525ea7e 13934 gen_mips_lx(ctx, op2, rd, rs, rt);
099e5b4d
LA
13935 break;
13936 default: /* Invalid */
13937 MIPS_INVAL("MASK LX");
3a4ef3b7 13938 gen_reserved_instruction(ctx);
099e5b4d
LA
13939 break;
13940 }
13941 break;
13942 case OPC_ABSQ_S_PH_DSP:
13943 op2 = MASK_ABSQ_S_PH(ctx->opcode);
13944 switch (op2) {
13945 case OPC_ABSQ_S_QB:
13946 case OPC_ABSQ_S_PH:
13947 case OPC_ABSQ_S_W:
13948 case OPC_PRECEQ_W_PHL:
13949 case OPC_PRECEQ_W_PHR:
13950 case OPC_PRECEQU_PH_QBL:
13951 case OPC_PRECEQU_PH_QBR:
13952 case OPC_PRECEQU_PH_QBLA:
13953 case OPC_PRECEQU_PH_QBRA:
13954 case OPC_PRECEU_PH_QBL:
13955 case OPC_PRECEU_PH_QBR:
13956 case OPC_PRECEU_PH_QBLA:
13957 case OPC_PRECEU_PH_QBRA:
13958 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13959 break;
13960 case OPC_BITREV:
13961 case OPC_REPL_QB:
13962 case OPC_REPLV_QB:
13963 case OPC_REPL_PH:
13964 case OPC_REPLV_PH:
13965 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
13966 break;
13967 default:
13968 MIPS_INVAL("MASK ABSQ_S.PH");
3a4ef3b7 13969 gen_reserved_instruction(ctx);
099e5b4d
LA
13970 break;
13971 }
13972 break;
13973 case OPC_ADDU_QB_DSP:
13974 op2 = MASK_ADDU_QB(ctx->opcode);
13975 switch (op2) {
13976 case OPC_ADDQ_PH:
13977 case OPC_ADDQ_S_PH:
13978 case OPC_ADDQ_S_W:
13979 case OPC_ADDU_QB:
13980 case OPC_ADDU_S_QB:
13981 case OPC_ADDU_PH:
13982 case OPC_ADDU_S_PH:
13983 case OPC_SUBQ_PH:
13984 case OPC_SUBQ_S_PH:
13985 case OPC_SUBQ_S_W:
13986 case OPC_SUBU_QB:
13987 case OPC_SUBU_S_QB:
13988 case OPC_SUBU_PH:
13989 case OPC_SUBU_S_PH:
13990 case OPC_ADDSC:
13991 case OPC_ADDWC:
13992 case OPC_MODSUB:
13993 case OPC_RADDU_W_QB:
13994 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13995 break;
13996 case OPC_MULEU_S_PH_QBL:
13997 case OPC_MULEU_S_PH_QBR:
13998 case OPC_MULQ_RS_PH:
13999 case OPC_MULEQ_S_W_PHL:
14000 case OPC_MULEQ_S_W_PHR:
14001 case OPC_MULQ_S_PH:
14002 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14003 break;
14004 default: /* Invalid */
14005 MIPS_INVAL("MASK ADDU.QB");
3a4ef3b7 14006 gen_reserved_instruction(ctx);
461c08df 14007 break;
461c08df 14008
099e5b4d
LA
14009 }
14010 break;
14011 case OPC_CMPU_EQ_QB_DSP:
14012 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14013 switch (op2) {
14014 case OPC_PRECR_SRA_PH_W:
14015 case OPC_PRECR_SRA_R_PH_W:
14016 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 14017 break;
099e5b4d
LA
14018 case OPC_PRECR_QB_PH:
14019 case OPC_PRECRQ_QB_PH:
14020 case OPC_PRECRQ_PH_W:
14021 case OPC_PRECRQ_RS_PH_W:
14022 case OPC_PRECRQU_S_QB_PH:
14023 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 14024 break;
099e5b4d
LA
14025 case OPC_CMPU_EQ_QB:
14026 case OPC_CMPU_LT_QB:
14027 case OPC_CMPU_LE_QB:
14028 case OPC_CMP_EQ_PH:
14029 case OPC_CMP_LT_PH:
14030 case OPC_CMP_LE_PH:
14031 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 14032 break;
099e5b4d
LA
14033 case OPC_CMPGU_EQ_QB:
14034 case OPC_CMPGU_LT_QB:
14035 case OPC_CMPGU_LE_QB:
14036 case OPC_CMPGDU_EQ_QB:
14037 case OPC_CMPGDU_LT_QB:
14038 case OPC_CMPGDU_LE_QB:
14039 case OPC_PICK_QB:
14040 case OPC_PICK_PH:
14041 case OPC_PACKRL_PH:
14042 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14043 break;
14044 default: /* Invalid */
14045 MIPS_INVAL("MASK CMPU.EQ.QB");
3a4ef3b7 14046 gen_reserved_instruction(ctx);
099e5b4d
LA
14047 break;
14048 }
14049 break;
14050 case OPC_SHLL_QB_DSP:
14051 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14052 break;
14053 case OPC_DPA_W_PH_DSP:
14054 op2 = MASK_DPA_W_PH(ctx->opcode);
14055 switch (op2) {
14056 case OPC_DPAU_H_QBL:
14057 case OPC_DPAU_H_QBR:
14058 case OPC_DPSU_H_QBL:
14059 case OPC_DPSU_H_QBR:
14060 case OPC_DPA_W_PH:
14061 case OPC_DPAX_W_PH:
14062 case OPC_DPAQ_S_W_PH:
14063 case OPC_DPAQX_S_W_PH:
14064 case OPC_DPAQX_SA_W_PH:
14065 case OPC_DPS_W_PH:
14066 case OPC_DPSX_W_PH:
14067 case OPC_DPSQ_S_W_PH:
14068 case OPC_DPSQX_S_W_PH:
14069 case OPC_DPSQX_SA_W_PH:
14070 case OPC_MULSAQ_S_W_PH:
14071 case OPC_DPAQ_SA_L_W:
14072 case OPC_DPSQ_SA_L_W:
14073 case OPC_MAQ_S_W_PHL:
14074 case OPC_MAQ_S_W_PHR:
14075 case OPC_MAQ_SA_W_PHL:
14076 case OPC_MAQ_SA_W_PHR:
14077 case OPC_MULSA_W_PH:
14078 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14079 break;
14080 default: /* Invalid */
14081 MIPS_INVAL("MASK DPAW.PH");
3a4ef3b7 14082 gen_reserved_instruction(ctx);
099e5b4d
LA
14083 break;
14084 }
14085 break;
14086 case OPC_INSV_DSP:
14087 op2 = MASK_INSV(ctx->opcode);
14088 switch (op2) {
14089 case OPC_INSV:
14090 check_dsp(ctx);
14091 {
14092 TCGv t0, t1;
14093
14094 if (rt == 0) {
099e5b4d
LA
14095 break;
14096 }
14097
14098 t0 = tcg_temp_new();
14099 t1 = tcg_temp_new();
14100
14101 gen_load_gpr(t0, rt);
14102 gen_load_gpr(t1, rs);
14103
ad75a51e 14104 gen_helper_insv(cpu_gpr[rt], tcg_env, t1, t0);
a22260ae
JL
14105 break;
14106 }
099e5b4d
LA
14107 default: /* Invalid */
14108 MIPS_INVAL("MASK INSV");
3a4ef3b7 14109 gen_reserved_instruction(ctx);
099e5b4d
LA
14110 break;
14111 }
14112 break;
14113 case OPC_APPEND_DSP:
14114 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
14115 break;
14116 case OPC_EXTR_W_DSP:
14117 op2 = MASK_EXTR_W(ctx->opcode);
14118 switch (op2) {
14119 case OPC_EXTR_W:
14120 case OPC_EXTR_R_W:
14121 case OPC_EXTR_RS_W:
14122 case OPC_EXTR_S_H:
14123 case OPC_EXTRV_S_H:
14124 case OPC_EXTRV_W:
14125 case OPC_EXTRV_R_W:
14126 case OPC_EXTRV_RS_W:
14127 case OPC_EXTP:
14128 case OPC_EXTPV:
14129 case OPC_EXTPDP:
14130 case OPC_EXTPDPV:
14131 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14132 break;
14133 case OPC_RDDSP:
14134 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
14135 break;
14136 case OPC_SHILO:
14137 case OPC_SHILOV:
14138 case OPC_MTHLIP:
14139 case OPC_WRDSP:
14140 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14141 break;
14142 default: /* Invalid */
14143 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 14144 gen_reserved_instruction(ctx);
099e5b4d
LA
14145 break;
14146 }
14147 break;
099e5b4d 14148#if defined(TARGET_MIPS64)
c2e19f3c
AM
14149 case OPC_DDIV_G_2E:
14150 case OPC_DDIVU_G_2E:
14151 case OPC_DMULT_G_2E:
14152 case OPC_DMULTU_G_2E:
14153 case OPC_DMOD_G_2E:
14154 case OPC_DMODU_G_2E:
fac5a073
LA
14155 check_insn(ctx, INSN_LOONGSON2E);
14156 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 14157 break;
099e5b4d
LA
14158 case OPC_ABSQ_S_QH_DSP:
14159 op2 = MASK_ABSQ_S_QH(ctx->opcode);
14160 switch (op2) {
14161 case OPC_PRECEQ_L_PWL:
14162 case OPC_PRECEQ_L_PWR:
14163 case OPC_PRECEQ_PW_QHL:
14164 case OPC_PRECEQ_PW_QHR:
14165 case OPC_PRECEQ_PW_QHLA:
14166 case OPC_PRECEQ_PW_QHRA:
14167 case OPC_PRECEQU_QH_OBL:
14168 case OPC_PRECEQU_QH_OBR:
14169 case OPC_PRECEQU_QH_OBLA:
14170 case OPC_PRECEQU_QH_OBRA:
14171 case OPC_PRECEU_QH_OBL:
14172 case OPC_PRECEU_QH_OBR:
14173 case OPC_PRECEU_QH_OBLA:
14174 case OPC_PRECEU_QH_OBRA:
14175 case OPC_ABSQ_S_OB:
14176 case OPC_ABSQ_S_PW:
14177 case OPC_ABSQ_S_QH:
14178 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14179 break;
14180 case OPC_REPL_OB:
14181 case OPC_REPL_PW:
14182 case OPC_REPL_QH:
14183 case OPC_REPLV_OB:
14184 case OPC_REPLV_PW:
14185 case OPC_REPLV_QH:
14186 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14187 break;
14188 default: /* Invalid */
14189 MIPS_INVAL("MASK ABSQ_S.QH");
3a4ef3b7 14190 gen_reserved_instruction(ctx);
099e5b4d
LA
14191 break;
14192 }
14193 break;
14194 case OPC_ADDU_OB_DSP:
14195 op2 = MASK_ADDU_OB(ctx->opcode);
14196 switch (op2) {
14197 case OPC_RADDU_L_OB:
14198 case OPC_SUBQ_PW:
14199 case OPC_SUBQ_S_PW:
14200 case OPC_SUBQ_QH:
14201 case OPC_SUBQ_S_QH:
14202 case OPC_SUBU_OB:
14203 case OPC_SUBU_S_OB:
14204 case OPC_SUBU_QH:
14205 case OPC_SUBU_S_QH:
14206 case OPC_SUBUH_OB:
14207 case OPC_SUBUH_R_OB:
14208 case OPC_ADDQ_PW:
14209 case OPC_ADDQ_S_PW:
14210 case OPC_ADDQ_QH:
14211 case OPC_ADDQ_S_QH:
14212 case OPC_ADDU_OB:
14213 case OPC_ADDU_S_OB:
14214 case OPC_ADDU_QH:
14215 case OPC_ADDU_S_QH:
14216 case OPC_ADDUH_OB:
14217 case OPC_ADDUH_R_OB:
14218 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 14219 break;
099e5b4d
LA
14220 case OPC_MULEQ_S_PW_QHL:
14221 case OPC_MULEQ_S_PW_QHR:
14222 case OPC_MULEU_S_QH_OBL:
14223 case OPC_MULEU_S_QH_OBR:
14224 case OPC_MULQ_RS_QH:
14225 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 14226 break;
099e5b4d
LA
14227 default: /* Invalid */
14228 MIPS_INVAL("MASK ADDU.OB");
3a4ef3b7 14229 gen_reserved_instruction(ctx);
26690560 14230 break;
099e5b4d
LA
14231 }
14232 break;
14233 case OPC_CMPU_EQ_OB_DSP:
14234 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
14235 switch (op2) {
14236 case OPC_PRECR_SRA_QH_PW:
14237 case OPC_PRECR_SRA_R_QH_PW:
14238 /* Return value is rt. */
14239 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 14240 break;
099e5b4d
LA
14241 case OPC_PRECR_OB_QH:
14242 case OPC_PRECRQ_OB_QH:
14243 case OPC_PRECRQ_PW_L:
14244 case OPC_PRECRQ_QH_PW:
14245 case OPC_PRECRQ_RS_QH_PW:
14246 case OPC_PRECRQU_S_OB_QH:
14247 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 14248 break;
099e5b4d
LA
14249 case OPC_CMPU_EQ_OB:
14250 case OPC_CMPU_LT_OB:
14251 case OPC_CMPU_LE_OB:
14252 case OPC_CMP_EQ_QH:
14253 case OPC_CMP_LT_QH:
14254 case OPC_CMP_LE_QH:
14255 case OPC_CMP_EQ_PW:
14256 case OPC_CMP_LT_PW:
14257 case OPC_CMP_LE_PW:
14258 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 14259 break;
099e5b4d
LA
14260 case OPC_CMPGDU_EQ_OB:
14261 case OPC_CMPGDU_LT_OB:
14262 case OPC_CMPGDU_LE_OB:
14263 case OPC_CMPGU_EQ_OB:
14264 case OPC_CMPGU_LT_OB:
14265 case OPC_CMPGU_LE_OB:
14266 case OPC_PACKRL_PW:
14267 case OPC_PICK_OB:
14268 case OPC_PICK_PW:
14269 case OPC_PICK_QH:
14270 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 14271 break;
099e5b4d
LA
14272 default: /* Invalid */
14273 MIPS_INVAL("MASK CMPU_EQ.OB");
3a4ef3b7 14274 gen_reserved_instruction(ctx);
161f85e6 14275 break;
099e5b4d
LA
14276 }
14277 break;
14278 case OPC_DAPPEND_DSP:
14279 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
14280 break;
14281 case OPC_DEXTR_W_DSP:
14282 op2 = MASK_DEXTR_W(ctx->opcode);
14283 switch (op2) {
14284 case OPC_DEXTP:
14285 case OPC_DEXTPDP:
14286 case OPC_DEXTPDPV:
14287 case OPC_DEXTPV:
14288 case OPC_DEXTR_L:
14289 case OPC_DEXTR_R_L:
14290 case OPC_DEXTR_RS_L:
14291 case OPC_DEXTR_W:
14292 case OPC_DEXTR_R_W:
14293 case OPC_DEXTR_RS_W:
14294 case OPC_DEXTR_S_H:
14295 case OPC_DEXTRV_L:
14296 case OPC_DEXTRV_R_L:
14297 case OPC_DEXTRV_RS_L:
14298 case OPC_DEXTRV_S_H:
14299 case OPC_DEXTRV_W:
14300 case OPC_DEXTRV_R_W:
14301 case OPC_DEXTRV_RS_W:
14302 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 14303 break;
099e5b4d
LA
14304 case OPC_DMTHLIP:
14305 case OPC_DSHILO:
14306 case OPC_DSHILOV:
14307 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 14308 break;
099e5b4d
LA
14309 default: /* Invalid */
14310 MIPS_INVAL("MASK EXTR.W");
3a4ef3b7 14311 gen_reserved_instruction(ctx);
461c08df 14312 break;
099e5b4d
LA
14313 }
14314 break;
14315 case OPC_DPAQ_W_QH_DSP:
14316 op2 = MASK_DPAQ_W_QH(ctx->opcode);
14317 switch (op2) {
14318 case OPC_DPAU_H_OBL:
14319 case OPC_DPAU_H_OBR:
14320 case OPC_DPSU_H_OBL:
14321 case OPC_DPSU_H_OBR:
14322 case OPC_DPA_W_QH:
14323 case OPC_DPAQ_S_W_QH:
14324 case OPC_DPS_W_QH:
14325 case OPC_DPSQ_S_W_QH:
14326 case OPC_MULSAQ_S_W_QH:
14327 case OPC_DPAQ_SA_L_PW:
14328 case OPC_DPSQ_SA_L_PW:
14329 case OPC_MULSAQ_S_L_PW:
14330 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14331 break;
14332 case OPC_MAQ_S_W_QHLL:
14333 case OPC_MAQ_S_W_QHLR:
14334 case OPC_MAQ_S_W_QHRL:
14335 case OPC_MAQ_S_W_QHRR:
14336 case OPC_MAQ_SA_W_QHLL:
14337 case OPC_MAQ_SA_W_QHLR:
14338 case OPC_MAQ_SA_W_QHRL:
14339 case OPC_MAQ_SA_W_QHRR:
14340 case OPC_MAQ_S_L_PWL:
14341 case OPC_MAQ_S_L_PWR:
14342 case OPC_DMADD:
14343 case OPC_DMADDU:
14344 case OPC_DMSUB:
14345 case OPC_DMSUBU:
14346 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 14347 break;
099e5b4d
LA
14348 default: /* Invalid */
14349 MIPS_INVAL("MASK DPAQ.W.QH");
3a4ef3b7 14350 gen_reserved_instruction(ctx);
b53371ed 14351 break;
099e5b4d
LA
14352 }
14353 break;
14354 case OPC_DINSV_DSP:
14355 op2 = MASK_INSV(ctx->opcode);
14356 switch (op2) {
14357 case OPC_DINSV:
14358 {
14359 TCGv t0, t1;
14360
a071578b
PMD
14361 check_dsp(ctx);
14362
099e5b4d 14363 if (rt == 0) {
a22260ae
JL
14364 break;
14365 }
1cb6686c 14366
099e5b4d
LA
14367 t0 = tcg_temp_new();
14368 t1 = tcg_temp_new();
1cb6686c 14369
099e5b4d
LA
14370 gen_load_gpr(t0, rt);
14371 gen_load_gpr(t1, rs);
1cb6686c 14372
ad75a51e 14373 gen_helper_dinsv(cpu_gpr[rt], tcg_env, t1, t0);
77c5fa8b 14374 break;
099e5b4d 14375 }
7a387fff 14376 default: /* Invalid */
099e5b4d 14377 MIPS_INVAL("MASK DINSV");
3a4ef3b7 14378 gen_reserved_instruction(ctx);
7a387fff
TS
14379 break;
14380 }
14381 break;
099e5b4d
LA
14382 case OPC_SHLL_OB_DSP:
14383 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14384 break;
14385#endif
fac5a073
LA
14386 default: /* Invalid */
14387 MIPS_INVAL("special3_legacy");
3a4ef3b7 14388 gen_reserved_instruction(ctx);
fac5a073
LA
14389 break;
14390 }
14391}
14392
37b9aae2
MM
14393
14394#if defined(TARGET_MIPS64)
14395
874b2879 14396static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 14397{
c8341e00 14398 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
14399 int rs = extract32(ctx->opcode, 21, 5);
14400 int rt = extract32(ctx->opcode, 16, 5);
14401 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
14402
14403 switch (opc) {
baa609db
AM
14404 case MMI_OPC_MULT1:
14405 case MMI_OPC_MULTU1:
3b948f05
PMD
14406 case MMI_OPC_MADD:
14407 case MMI_OPC_MADDU:
a95c4c26
FN
14408 case MMI_OPC_MADD1:
14409 case MMI_OPC_MADDU1:
06de726b
FN
14410 gen_mul_txx9(ctx, opc, rd, rs, rt);
14411 break;
baa609db
AM
14412 case MMI_OPC_DIV1:
14413 case MMI_OPC_DIVU1:
c42171c3 14414 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 14415 break;
71b8a6b3
FN
14416 default:
14417 MIPS_INVAL("TX79 MMI class");
3a4ef3b7 14418 gen_reserved_instruction(ctx);
71b8a6b3
FN
14419 break;
14420 }
14421}
14422
874b2879 14423static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 14424{
3a4ef3b7 14425 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
14426}
14427
14428/*
14429 * The TX79-specific instruction Store Quadword
14430 *
14431 * +--------+-------+-------+------------------------+
14432 * | 011111 | base | rt | offset | SQ
14433 * +--------+-------+-------+------------------------+
14434 * 6 5 5 16
14435 *
14436 * has the same opcode as the Read Hardware Register instruction
14437 *
14438 * +--------+-------+-------+-------+-------+--------+
14439 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
14440 * +--------+-------+-------+-------+-------+--------+
14441 * 6 5 5 5 5 6
14442 *
14443 * that is required, trapped and emulated by the Linux kernel. However, all
14444 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
14445 * offset is odd. Therefore all valid SQ instructions can execute normally.
14446 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
14447 * between SQ and RDHWR, as the Linux kernel does.
14448 */
874b2879 14449static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
14450{
14451 int base = extract32(ctx->opcode, 21, 5);
14452 int rt = extract32(ctx->opcode, 16, 5);
14453 int offset = extract32(ctx->opcode, 0, 16);
14454
14455#ifdef CONFIG_USER_ONLY
14456 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
14457 uint32_t op2 = extract32(ctx->opcode, 6, 5);
14458
14459 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
14460 int rd = extract32(ctx->opcode, 11, 5);
14461
14462 gen_rdhwr(ctx, rt, rd, 0);
14463 return;
14464 }
14465#endif
14466
874b2879 14467 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
14468}
14469
37b9aae2
MM
14470#endif
14471
fac5a073
LA
14472static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
14473{
14474 int rs, rt, rd, sa;
14475 uint32_t op1, op2;
76964147 14476 int16_t imm;
fac5a073
LA
14477
14478 rs = (ctx->opcode >> 21) & 0x1f;
14479 rt = (ctx->opcode >> 16) & 0x1f;
14480 rd = (ctx->opcode >> 11) & 0x1f;
14481 sa = (ctx->opcode >> 6) & 0x1f;
76964147 14482 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
14483
14484 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
14485
14486 /*
14487 * EVA loads and stores overlap Loongson 2E instructions decoded by
14488 * decode_opc_special3_legacy(), so be careful to allow their decoding when
14489 * EVA is absent.
14490 */
14491 if (ctx->eva) {
14492 switch (op1) {
c2e19f3c
AM
14493 case OPC_LWLE:
14494 case OPC_LWRE:
c2e19f3c
AM
14495 case OPC_LBUE:
14496 case OPC_LHUE:
14497 case OPC_LBE:
14498 case OPC_LHE:
14499 case OPC_LLE:
14500 case OPC_LWE:
76964147
JH
14501 check_cp0_enabled(ctx);
14502 gen_ld(ctx, op1, rt, rs, imm);
14503 return;
c2e19f3c
AM
14504 case OPC_SWLE:
14505 case OPC_SWRE:
c2e19f3c
AM
14506 case OPC_SBE:
14507 case OPC_SHE:
76964147
JH
14508 case OPC_SWE:
14509 check_cp0_enabled(ctx);
14510 gen_st(ctx, op1, rt, rs, imm);
14511 return;
14512 case OPC_SCE:
14513 check_cp0_enabled(ctx);
33a07fa2 14514 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
76964147
JH
14515 return;
14516 case OPC_CACHEE:
84c2fdc3 14517 check_eva(ctx);
76964147
JH
14518 check_cp0_enabled(ctx);
14519 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14520 gen_cache_operation(ctx, rt, rs, imm);
14521 }
76964147
JH
14522 return;
14523 case OPC_PREFE:
14524 check_cp0_enabled(ctx);
14525 /* Treat as NOP. */
14526 return;
14527 }
14528 }
14529
fac5a073
LA
14530 switch (op1) {
14531 case OPC_EXT:
14532 case OPC_INS:
7a47bae5 14533 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
14534 gen_bitops(ctx, op1, rt, rs, sa, rd);
14535 break;
14536 case OPC_BSHFL:
fac5a073 14537 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 14538 switch (op2) {
c2e19f3c 14539 case OPC_ALIGN:
373ecd38
AM
14540 case OPC_ALIGN_1:
14541 case OPC_ALIGN_2:
14542 case OPC_ALIGN_3:
15eacb9b 14543 case OPC_BITSWAP:
2e211e0a 14544 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
14545 decode_opc_special3_r6(env, ctx);
14546 break;
14547 default:
7a47bae5 14548 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
14549 gen_bshfl(ctx, op2, rt, rd);
14550 break;
14551 }
fac5a073
LA
14552 break;
14553#if defined(TARGET_MIPS64)
c2e19f3c
AM
14554 case OPC_DEXTM:
14555 case OPC_DEXTU:
14556 case OPC_DEXT:
14557 case OPC_DINSM:
14558 case OPC_DINSU:
14559 case OPC_DINS:
7a47bae5 14560 check_insn(ctx, ISA_MIPS_R2);
fac5a073
LA
14561 check_mips_64(ctx);
14562 gen_bitops(ctx, op1, rt, rs, sa, rd);
14563 break;
14564 case OPC_DBSHFL:
fac5a073 14565 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 14566 switch (op2) {
c2e19f3c 14567 case OPC_DALIGN:
373ecd38
AM
14568 case OPC_DALIGN_1:
14569 case OPC_DALIGN_2:
14570 case OPC_DALIGN_3:
14571 case OPC_DALIGN_4:
14572 case OPC_DALIGN_5:
14573 case OPC_DALIGN_6:
14574 case OPC_DALIGN_7:
15eacb9b 14575 case OPC_DBITSWAP:
2e211e0a 14576 check_insn(ctx, ISA_MIPS_R6);
15eacb9b
YK
14577 decode_opc_special3_r6(env, ctx);
14578 break;
14579 default:
7a47bae5 14580 check_insn(ctx, ISA_MIPS_R2);
15eacb9b
YK
14581 check_mips_64(ctx);
14582 op2 = MASK_DBSHFL(ctx->opcode);
14583 gen_bshfl(ctx, op2, rt, rd);
14584 break;
14585 }
fac5a073
LA
14586 break;
14587#endif
14588 case OPC_RDHWR:
b00c7218 14589 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
14590 break;
14591 case OPC_FORK:
9affc1c5 14592 check_mt(ctx);
fac5a073
LA
14593 {
14594 TCGv t0 = tcg_temp_new();
14595 TCGv t1 = tcg_temp_new();
14596
14597 gen_load_gpr(t0, rt);
14598 gen_load_gpr(t1, rs);
14599 gen_helper_fork(t0, t1);
fac5a073
LA
14600 }
14601 break;
14602 case OPC_YIELD:
9affc1c5 14603 check_mt(ctx);
fac5a073
LA
14604 {
14605 TCGv t0 = tcg_temp_new();
14606
fac5a073 14607 gen_load_gpr(t0, rs);
ad75a51e 14608 gen_helper_yield(t0, tcg_env, t0);
fac5a073 14609 gen_store_gpr(t0, rd);
fac5a073
LA
14610 }
14611 break;
10dc65db 14612 default:
2e211e0a 14613 if (ctx->insn_flags & ISA_MIPS_R6) {
10dc65db
LA
14614 decode_opc_special3_r6(env, ctx);
14615 } else {
14616 decode_opc_special3_legacy(env, ctx);
14617 }
099e5b4d
LA
14618 }
14619}
14620
80e64a38 14621static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
4c789546 14622{
80e64a38
PMD
14623 int32_t offset;
14624 int rs, rt, rd, sa;
14625 uint32_t op, op1;
14626 int16_t imm;
4c789546 14627
80e64a38
PMD
14628 op = MASK_OP_MAJOR(ctx->opcode);
14629 rs = (ctx->opcode >> 21) & 0x1f;
14630 rt = (ctx->opcode >> 16) & 0x1f;
14631 rd = (ctx->opcode >> 11) & 0x1f;
14632 sa = (ctx->opcode >> 6) & 0x1f;
14633 imm = (int16_t)ctx->opcode;
14634 switch (op) {
14635 case OPC_SPECIAL:
14636 decode_opc_special(env, ctx);
4c789546 14637 break;
80e64a38
PMD
14638 case OPC_SPECIAL2:
14639#if defined(TARGET_MIPS64)
14640 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
14641 decode_mmi(env, ctx);
4f57f43c
PMD
14642 break;
14643 }
14644#endif
c7abe00a 14645 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
199fc7d2
SV
14646 if (decode_ase_mxu(ctx, ctx->opcode)) {
14647 break;
22345286 14648 }
4c789546 14649 }
4f57f43c 14650 decode_opc_special2_legacy(env, ctx);
4c789546 14651 break;
80e64a38
PMD
14652 case OPC_SPECIAL3:
14653#if defined(TARGET_MIPS64)
14654 if (ctx->insn_flags & INSN_R5900) {
14655 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
14656 } else {
14657 decode_opc_special3(env, ctx);
80e71591 14658 }
80e64a38
PMD
14659#else
14660 decode_opc_special3(env, ctx);
14661#endif
80e71591 14662 break;
80e64a38
PMD
14663 case OPC_REGIMM:
14664 op1 = MASK_REGIMM(ctx->opcode);
14665 switch (op1) {
14666 case OPC_BLTZL: /* REGIMM branches */
14667 case OPC_BGEZL:
14668 case OPC_BLTZALL:
14669 case OPC_BGEZALL:
14670 check_insn(ctx, ISA_MIPS2);
14671 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14672 /* Fallthrough */
14673 case OPC_BLTZ:
14674 case OPC_BGEZ:
14675 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
2e3eddb0 14676 break;
80e64a38
PMD
14677 case OPC_BLTZAL:
14678 case OPC_BGEZAL:
14679 if (ctx->insn_flags & ISA_MIPS_R6) {
14680 if (rs == 0) {
14681 /* OPC_NAL, OPC_BAL */
14682 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
14683 } else {
14684 gen_reserved_instruction(ctx);
14685 }
14686 } else {
14687 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
14688 }
2e3eddb0 14689 break;
80e64a38
PMD
14690 case OPC_TGEI: /* REGIMM traps */
14691 case OPC_TGEIU:
14692 case OPC_TLTI:
14693 case OPC_TLTIU:
14694 case OPC_TEQI:
80e64a38
PMD
14695 case OPC_TNEI:
14696 check_insn(ctx, ISA_MIPS2);
14697 check_insn_opc_removed(ctx, ISA_MIPS_R6);
0a3336f6 14698 gen_trap(ctx, op1, rs, -1, imm, 0);
2e3eddb0 14699 break;
80e64a38
PMD
14700 case OPC_SIGRIE:
14701 check_insn(ctx, ISA_MIPS_R6);
14702 gen_reserved_instruction(ctx);
2e3eddb0 14703 break;
80e64a38
PMD
14704 case OPC_SYNCI:
14705 check_insn(ctx, ISA_MIPS_R2);
14706 /*
14707 * Break the TB to be able to sync copied instructions
14708 * immediately.
14709 */
14710 ctx->base.is_jmp = DISAS_STOP;
2e3eddb0 14711 break;
80e64a38
PMD
14712 case OPC_BPOSGE32: /* MIPS DSP branch */
14713#if defined(TARGET_MIPS64)
14714 case OPC_BPOSGE64:
14715#endif
14716 check_dsp(ctx);
14717 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
a44d6d14 14718 break;
80e64a38
PMD
14719#if defined(TARGET_MIPS64)
14720 case OPC_DAHI:
14721 check_insn(ctx, ISA_MIPS_R6);
14722 check_mips_64(ctx);
14723 if (rs != 0) {
14724 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
14725 }
a44d6d14 14726 break;
80e64a38
PMD
14727 case OPC_DATI:
14728 check_insn(ctx, ISA_MIPS_R6);
14729 check_mips_64(ctx);
14730 if (rs != 0) {
14731 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
14732 }
a44d6d14 14733 break;
80e64a38
PMD
14734#endif
14735 default: /* Invalid */
14736 MIPS_INVAL("regimm");
14737 gen_reserved_instruction(ctx);
a44d6d14
AM
14738 break;
14739 }
14740 break;
80e64a38
PMD
14741 case OPC_CP0:
14742 check_cp0_enabled(ctx);
14743 op1 = MASK_CP0(ctx->opcode);
14744 switch (op1) {
14745 case OPC_MFC0:
14746 case OPC_MTC0:
14747 case OPC_MFTR:
14748 case OPC_MTTR:
14749 case OPC_MFHC0:
14750 case OPC_MTHC0:
14751#if defined(TARGET_MIPS64)
14752 case OPC_DMFC0:
14753 case OPC_DMTC0:
14754#endif
14755#ifndef CONFIG_USER_ONLY
14756 gen_cp0(env, ctx, op1, rt, rd);
14757#endif /* !CONFIG_USER_ONLY */
7a387fff 14758 break;
c38a1d52
AR
14759 case OPC_C0:
14760 case OPC_C0_1:
14761 case OPC_C0_2:
14762 case OPC_C0_3:
14763 case OPC_C0_4:
14764 case OPC_C0_5:
14765 case OPC_C0_6:
14766 case OPC_C0_7:
14767 case OPC_C0_8:
14768 case OPC_C0_9:
14769 case OPC_C0_A:
14770 case OPC_C0_B:
14771 case OPC_C0_C:
14772 case OPC_C0_D:
14773 case OPC_C0_E:
14774 case OPC_C0_F:
f1aa6320 14775#ifndef CONFIG_USER_ONLY
932e71cd 14776 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 14777#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
14778 break;
14779 case OPC_MFMC0:
8706c382 14780#ifndef CONFIG_USER_ONLY
932e71cd 14781 {
099e5b4d 14782 uint32_t op2;
35fbce2c 14783 TCGv t0 = tcg_temp_new();
6c5c1e20 14784
0eaef5aa 14785 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
14786 switch (op2) {
14787 case OPC_DMT:
9affc1c5 14788 check_cp0_mt(ctx);
9ed5726c 14789 gen_helper_dmt(t0);
35fbce2c 14790 gen_store_gpr(t0, rt);
6c5c1e20
TS
14791 break;
14792 case OPC_EMT:
9affc1c5 14793 check_cp0_mt(ctx);
9ed5726c 14794 gen_helper_emt(t0);
35fbce2c 14795 gen_store_gpr(t0, rt);
da80682b 14796 break;
6c5c1e20 14797 case OPC_DVPE:
9affc1c5 14798 check_cp0_mt(ctx);
ad75a51e 14799 gen_helper_dvpe(t0, tcg_env);
35fbce2c 14800 gen_store_gpr(t0, rt);
6c5c1e20
TS
14801 break;
14802 case OPC_EVPE:
9affc1c5 14803 check_cp0_mt(ctx);
ad75a51e 14804 gen_helper_evpe(t0, tcg_env);
35fbce2c 14805 gen_store_gpr(t0, rt);
6c5c1e20 14806 break;
01bc435b 14807 case OPC_DVP:
2e211e0a 14808 check_insn(ctx, ISA_MIPS_R6);
01bc435b 14809 if (ctx->vp) {
ad75a51e 14810 gen_helper_dvp(t0, tcg_env);
01bc435b
YK
14811 gen_store_gpr(t0, rt);
14812 }
14813 break;
14814 case OPC_EVP:
2e211e0a 14815 check_insn(ctx, ISA_MIPS_R6);
01bc435b 14816 if (ctx->vp) {
ad75a51e 14817 gen_helper_evp(t0, tcg_env);
01bc435b
YK
14818 gen_store_gpr(t0, rt);
14819 }
14820 break;
6c5c1e20 14821 case OPC_DI:
7a47bae5 14822 check_insn(ctx, ISA_MIPS_R2);
867abc7e 14823 save_cpu_state(ctx, 1);
ad75a51e 14824 gen_helper_di(t0, tcg_env);
35fbce2c 14825 gen_store_gpr(t0, rt);
7480515f
AM
14826 /*
14827 * Stop translation as we may have switched
14828 * the execution mode.
14829 */
eeb3bba8 14830 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
14831 break;
14832 case OPC_EI:
7a47bae5 14833 check_insn(ctx, ISA_MIPS_R2);
867abc7e 14834 save_cpu_state(ctx, 1);
ad75a51e 14835 gen_helper_ei(t0, tcg_env);
35fbce2c 14836 gen_store_gpr(t0, rt);
7480515f
AM
14837 /*
14838 * DISAS_STOP isn't sufficient, we need to ensure we break
14839 * out of translated code to check for pending interrupts.
14840 */
eeb3bba8
EC
14841 gen_save_pc(ctx->base.pc_next + 4);
14842 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
14843 break;
14844 default: /* Invalid */
14845 MIPS_INVAL("mfmc0");
3a4ef3b7 14846 gen_reserved_instruction(ctx);
6c5c1e20
TS
14847 break;
14848 }
7a387fff 14849 }
0eaef5aa 14850#endif /* !CONFIG_USER_ONLY */
6af0bf9c 14851 break;
7a387fff 14852 case OPC_RDPGPR:
7a47bae5 14853 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 14854 gen_load_srsgpr(rt, rd);
ead9360e 14855 break;
7a387fff 14856 case OPC_WRPGPR:
7a47bae5 14857 check_insn(ctx, ISA_MIPS_R2);
be24bb4f 14858 gen_store_srsgpr(rt, rd);
38121543 14859 break;
6af0bf9c 14860 default:
923617a3 14861 MIPS_INVAL("cp0");
3a4ef3b7 14862 gen_reserved_instruction(ctx);
6af0bf9c
FB
14863 break;
14864 }
14865 break;
31837be3 14866 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
2e211e0a 14867 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
14868 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
14869 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14870 } else {
14871 /* OPC_ADDI */
14872 /* Arithmetic with immediate opcode */
14873 gen_arith_imm(ctx, op, rt, rs, imm);
14874 }
14875 break;
324d9e32 14876 case OPC_ADDIU:
d75c135e 14877 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 14878 break;
324d9e32
AJ
14879 case OPC_SLTI: /* Set on less than with immediate opcode */
14880 case OPC_SLTIU:
d75c135e 14881 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
14882 break;
14883 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 14884 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
14885 case OPC_ORI:
14886 case OPC_XORI:
d75c135e 14887 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 14888 break;
c2e19f3c
AM
14889 case OPC_J: /* Jump */
14890 case OPC_JAL:
7a387fff 14891 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 14892 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 14893 break;
31837be3
YK
14894 /* Branch */
14895 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
2e211e0a 14896 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 14897 if (rt == 0) {
3a4ef3b7 14898 gen_reserved_instruction(ctx);
31837be3
YK
14899 break;
14900 }
14901 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
14902 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14903 } else {
14904 /* OPC_BLEZL */
b231c103 14905 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
14906 }
14907 break;
14908 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
2e211e0a 14909 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3 14910 if (rt == 0) {
3a4ef3b7 14911 gen_reserved_instruction(ctx);
31837be3
YK
14912 break;
14913 }
14914 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
14915 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14916 } else {
14917 /* OPC_BGTZL */
b231c103 14918 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
14919 }
14920 break;
14921 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
14922 if (rt == 0) {
14923 /* OPC_BLEZ */
b231c103 14924 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 14925 } else {
2e211e0a 14926 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
14927 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
14928 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14929 }
14930 break;
14931 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
14932 if (rt == 0) {
14933 /* OPC_BGTZ */
b231c103 14934 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3 14935 } else {
2e211e0a 14936 check_insn(ctx, ISA_MIPS_R6);
31837be3
YK
14937 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
14938 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14939 }
14940 break;
14941 case OPC_BEQL:
14942 case OPC_BNEL:
d9224450 14943 check_insn(ctx, ISA_MIPS2);
2e211e0a 14944 check_insn_opc_removed(ctx, ISA_MIPS_R6);
d9224450 14945 /* Fallthrough */
31837be3
YK
14946 case OPC_BEQ:
14947 case OPC_BNE:
b231c103 14948 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 14949 break;
d9224450
MR
14950 case OPC_LL: /* Load and stores */
14951 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
14952 if (ctx->insn_flags & INSN_R5900) {
14953 check_insn_opc_user_only(ctx, INSN_R5900);
14954 }
d9224450
MR
14955 /* Fallthrough */
14956 case OPC_LWL:
fecd2646 14957 case OPC_LWR:
c2e19f3c
AM
14958 case OPC_LB:
14959 case OPC_LH:
14960 case OPC_LW:
14961 case OPC_LWPC:
14962 case OPC_LBU:
14963 case OPC_LHU:
d75c135e 14964 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 14965 break;
fecd2646 14966 case OPC_SWL:
7a387fff 14967 case OPC_SWR:
c2e19f3c
AM
14968 case OPC_SB:
14969 case OPC_SH:
fecd2646 14970 case OPC_SW:
5c13fdfd 14971 gen_st(ctx, op, rt, rs, imm);
7a387fff 14972 break;
d66c7132 14973 case OPC_SC:
d9224450 14974 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
14975 if (ctx->insn_flags & INSN_R5900) {
14976 check_insn_opc_user_only(ctx, INSN_R5900);
14977 }
33a07fa2
LA
14978 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
14979 break;
7a387fff 14980 case OPC_CACHE:
2e15497c 14981 check_cp0_enabled(ctx);
bbd5e4a2 14982 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
0d74a222
LA
14983 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14984 gen_cache_operation(ctx, rt, rs, imm);
14985 }
ead9360e 14986 /* Treat as NOP. */
34ae7b51 14987 break;
7a387fff 14988 case OPC_PREF:
2e176eaf
PMD
14989 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 | INSN_R5900);
14990 /* Treat as NOP. */
6af0bf9c 14991 break;
4ad40f36 14992
923617a3 14993 /* Floating point (COP1). */
7a387fff
TS
14994 case OPC_LWC1:
14995 case OPC_LDC1:
14996 case OPC_SWC1:
14997 case OPC_SDC1:
5ab5c041 14998 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
14999 break;
15000
7a387fff 15001 case OPC_CP1:
5692c6e1
YK
15002 op1 = MASK_CP1(ctx->opcode);
15003
15004 switch (op1) {
15005 case OPC_MFHC1:
15006 case OPC_MTHC1:
5e755519 15007 check_cp1_enabled(ctx);
7a47bae5 15008 check_insn(ctx, ISA_MIPS_R2);
146dd620 15009 /* fall through */
5692c6e1
YK
15010 case OPC_MFC1:
15011 case OPC_CFC1:
15012 case OPC_MTC1:
15013 case OPC_CTC1:
15014 check_cp1_enabled(ctx);
15015 gen_cp1(ctx, op1, rt, rd);
15016 break;
d26bc211 15017#if defined(TARGET_MIPS64)
5692c6e1
YK
15018 case OPC_DMFC1:
15019 case OPC_DMTC1:
15020 check_cp1_enabled(ctx);
15021 check_insn(ctx, ISA_MIPS3);
d9224450 15022 check_mips_64(ctx);
5692c6e1
YK
15023 gen_cp1(ctx, op1, rt, rd);
15024 break;
e189e748 15025#endif
5692c6e1
YK
15026 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
15027 check_cp1_enabled(ctx);
2e211e0a 15028 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1 15029 /* OPC_BC1EQZ */
31837be3 15030 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 15031 rt, imm << 2, 4);
5692c6e1
YK
15032 } else {
15033 /* OPC_BC1ANY2 */
b8aa4598 15034 check_cop1x(ctx);
d75c135e 15035 check_insn(ctx, ASE_MIPS3D);
d75c135e 15036 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 15037 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
15038 }
15039 break;
15040 case OPC_BC1NEZ:
15041 check_cp1_enabled(ctx);
2e211e0a 15042 check_insn(ctx, ISA_MIPS_R6);
5692c6e1 15043 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 15044 rt, imm << 2, 4);
5692c6e1
YK
15045 break;
15046 case OPC_BC1ANY4:
15047 check_cp1_enabled(ctx);
2e211e0a 15048 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
15049 check_cop1x(ctx);
15050 check_insn(ctx, ASE_MIPS3D);
15051 /* fall through */
15052 case OPC_BC1:
15053 check_cp1_enabled(ctx);
2e211e0a 15054 check_insn_opc_removed(ctx, ISA_MIPS_R6);
5692c6e1
YK
15055 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15056 (rt >> 2) & 0x7, imm << 2);
15057 break;
15058 case OPC_PS_FMT:
e29c9628 15059 check_ps(ctx);
b6f3b233 15060 /* fall through */
5692c6e1
YK
15061 case OPC_S_FMT:
15062 case OPC_D_FMT:
15063 check_cp1_enabled(ctx);
15064 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15065 (imm >> 8) & 0x7);
15066 break;
15067 case OPC_W_FMT:
15068 case OPC_L_FMT:
15069 {
15070 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
15071 check_cp1_enabled(ctx);
2e211e0a 15072 if (ctx->insn_flags & ISA_MIPS_R6) {
5692c6e1
YK
15073 switch (r6_op) {
15074 case R6_OPC_CMP_AF_S:
15075 case R6_OPC_CMP_UN_S:
15076 case R6_OPC_CMP_EQ_S:
15077 case R6_OPC_CMP_UEQ_S:
15078 case R6_OPC_CMP_LT_S:
15079 case R6_OPC_CMP_ULT_S:
15080 case R6_OPC_CMP_LE_S:
15081 case R6_OPC_CMP_ULE_S:
15082 case R6_OPC_CMP_SAF_S:
15083 case R6_OPC_CMP_SUN_S:
15084 case R6_OPC_CMP_SEQ_S:
15085 case R6_OPC_CMP_SEUQ_S:
15086 case R6_OPC_CMP_SLT_S:
15087 case R6_OPC_CMP_SULT_S:
15088 case R6_OPC_CMP_SLE_S:
15089 case R6_OPC_CMP_SULE_S:
15090 case R6_OPC_CMP_OR_S:
15091 case R6_OPC_CMP_UNE_S:
15092 case R6_OPC_CMP_NE_S:
15093 case R6_OPC_CMP_SOR_S:
15094 case R6_OPC_CMP_SUNE_S:
15095 case R6_OPC_CMP_SNE_S:
15096 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15097 break;
15098 case R6_OPC_CMP_AF_D:
15099 case R6_OPC_CMP_UN_D:
15100 case R6_OPC_CMP_EQ_D:
15101 case R6_OPC_CMP_UEQ_D:
15102 case R6_OPC_CMP_LT_D:
15103 case R6_OPC_CMP_ULT_D:
15104 case R6_OPC_CMP_LE_D:
15105 case R6_OPC_CMP_ULE_D:
15106 case R6_OPC_CMP_SAF_D:
15107 case R6_OPC_CMP_SUN_D:
15108 case R6_OPC_CMP_SEQ_D:
15109 case R6_OPC_CMP_SEUQ_D:
15110 case R6_OPC_CMP_SLT_D:
15111 case R6_OPC_CMP_SULT_D:
15112 case R6_OPC_CMP_SLE_D:
15113 case R6_OPC_CMP_SULE_D:
15114 case R6_OPC_CMP_OR_D:
15115 case R6_OPC_CMP_UNE_D:
15116 case R6_OPC_CMP_NE_D:
15117 case R6_OPC_CMP_SOR_D:
15118 case R6_OPC_CMP_SUNE_D:
15119 case R6_OPC_CMP_SNE_D:
15120 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15121 break;
15122 default:
d2bfa6e6
MR
15123 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
15124 rt, rd, sa, (imm >> 8) & 0x7);
15125
5692c6e1 15126 break;
3f493883 15127 }
5692c6e1
YK
15128 } else {
15129 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15130 (imm >> 8) & 0x7);
36d23958 15131 }
5692c6e1
YK
15132 break;
15133 }
5692c6e1
YK
15134 default:
15135 MIPS_INVAL("cp1");
3a4ef3b7 15136 gen_reserved_instruction(ctx);
5692c6e1 15137 break;
6ea83fed 15138 }
4ad40f36
FB
15139 break;
15140
31837be3
YK
15141 /* Compact branches [R6] and COP2 [non-R6] */
15142 case OPC_BC: /* OPC_LWC2 */
15143 case OPC_BALC: /* OPC_SWC2 */
2e211e0a 15144 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
15145 /* OPC_BC, OPC_BALC */
15146 gen_compute_compact_branch(ctx, op, 0, 0,
15147 sextract32(ctx->opcode << 2, 0, 28));
e10a0ca1
JY
15148 } else if (ctx->insn_flags & ASE_LEXT) {
15149 gen_loongson_lswc2(ctx, rt, rs, rd);
31837be3
YK
15150 } else {
15151 /* OPC_LWC2, OPC_SWC2 */
15152 /* COP2: Not implemented. */
15153 generate_exception_err(ctx, EXCP_CpU, 2);
15154 }
15155 break;
15156 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
15157 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
2e211e0a 15158 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
15159 if (rs != 0) {
15160 /* OPC_BEQZC, OPC_BNEZC */
15161 gen_compute_compact_branch(ctx, op, rs, 0,
15162 sextract32(ctx->opcode << 2, 0, 23));
15163 } else {
15164 /* OPC_JIC, OPC_JIALC */
15165 gen_compute_compact_branch(ctx, op, 0, rt, imm);
15166 }
90e22a57
JY
15167 } else if (ctx->insn_flags & ASE_LEXT) {
15168 gen_loongson_lsdc2(ctx, rt, rs, rd);
31837be3
YK
15169 } else {
15170 /* OPC_LWC2, OPC_SWC2 */
15171 /* COP2: Not implemented. */
15172 generate_exception_err(ctx, EXCP_CpU, 2);
15173 }
4ad40f36 15174 break;
bd277fa1 15175 case OPC_CP2:
8e2d5831 15176 check_insn(ctx, ASE_LMMI);
bd277fa1
RH
15177 /* Note that these instructions use different fields. */
15178 gen_loongson_multimedia(ctx, sa, rd, rt);
15179 break;
4ad40f36 15180
7a387fff 15181 case OPC_CP3:
5ab5c041 15182 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 15183 check_cp1_enabled(ctx);
36d23958
TS
15184 op1 = MASK_CP3(ctx->opcode);
15185 switch (op1) {
d9224450
MR
15186 case OPC_LUXC1:
15187 case OPC_SUXC1:
7a47bae5 15188 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 15189 /* Fallthrough */
5a5012ec
TS
15190 case OPC_LWXC1:
15191 case OPC_LDXC1:
5a5012ec
TS
15192 case OPC_SWXC1:
15193 case OPC_SDXC1:
7a47bae5 15194 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
93b12ccc 15195 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 15196 break;
e0c84da7 15197 case OPC_PREFX:
7a47bae5 15198 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
ead9360e 15199 /* Treat as NOP. */
e0c84da7 15200 break;
5a5012ec 15201 case OPC_ALNV_PS:
7a47bae5 15202 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
d9224450 15203 /* Fallthrough */
5a5012ec
TS
15204 case OPC_MADD_S:
15205 case OPC_MADD_D:
15206 case OPC_MADD_PS:
15207 case OPC_MSUB_S:
15208 case OPC_MSUB_D:
15209 case OPC_MSUB_PS:
15210 case OPC_NMADD_S:
15211 case OPC_NMADD_D:
15212 case OPC_NMADD_PS:
15213 case OPC_NMSUB_S:
15214 case OPC_NMSUB_D:
15215 case OPC_NMSUB_PS:
7a47bae5 15216 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
5a5012ec
TS
15217 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15218 break;
36d23958 15219 default:
923617a3 15220 MIPS_INVAL("cp3");
3a4ef3b7 15221 gen_reserved_instruction(ctx);
36d23958
TS
15222 break;
15223 }
15224 } else {
e397ee33 15225 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 15226 }
4ad40f36
FB
15227 break;
15228
d26bc211 15229#if defined(TARGET_MIPS64)
7a387fff 15230 /* MIPS64 opcodes */
96631327 15231 case OPC_LLD:
55fc7a69
FN
15232 if (ctx->insn_flags & INSN_R5900) {
15233 check_insn_opc_user_only(ctx, INSN_R5900);
15234 }
96631327 15235 /* fall through */
c2e19f3c
AM
15236 case OPC_LDL:
15237 case OPC_LDR:
fecd2646 15238 case OPC_LWU:
7a387fff 15239 case OPC_LD:
d75c135e 15240 check_insn(ctx, ISA_MIPS3);
5c13fdfd 15241 check_mips_64(ctx);
d75c135e 15242 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 15243 break;
c2e19f3c
AM
15244 case OPC_SDL:
15245 case OPC_SDR:
7a387fff 15246 case OPC_SD:
d75c135e 15247 check_insn(ctx, ISA_MIPS3);
e189e748 15248 check_mips_64(ctx);
5c13fdfd 15249 gen_st(ctx, op, rt, rs, imm);
7a387fff 15250 break;
d66c7132 15251 case OPC_SCD:
d75c135e 15252 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
15253 if (ctx->insn_flags & INSN_R5900) {
15254 check_insn_opc_user_only(ctx, INSN_R5900);
15255 }
d66c7132 15256 check_mips_64(ctx);
fc313c64 15257 gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
d66c7132 15258 break;
31837be3 15259 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
2e211e0a 15260 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
15261 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
15262 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15263 } else {
15264 /* OPC_DADDI */
15265 check_insn(ctx, ISA_MIPS3);
15266 check_mips_64(ctx);
15267 gen_arith_imm(ctx, op, rt, rs, imm);
15268 }
15269 break;
324d9e32 15270 case OPC_DADDIU:
d75c135e 15271 check_insn(ctx, ISA_MIPS3);
e189e748 15272 check_mips_64(ctx);
d75c135e 15273 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 15274 break;
31837be3
YK
15275#else
15276 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
2e211e0a 15277 if (ctx->insn_flags & ISA_MIPS_R6) {
31837be3
YK
15278 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15279 } else {
15280 MIPS_INVAL("major opcode");
3a4ef3b7 15281 gen_reserved_instruction(ctx);
31837be3
YK
15282 }
15283 break;
6af0bf9c 15284#endif
d4ea6acd 15285 case OPC_DAUI: /* OPC_JALX */
2e211e0a 15286 if (ctx->insn_flags & ISA_MIPS_R6) {
d4ea6acd
LA
15287#if defined(TARGET_MIPS64)
15288 /* OPC_DAUI */
15289 check_mips_64(ctx);
db77d852
LA
15290 if (rs == 0) {
15291 generate_exception(ctx, EXCP_RI);
15292 } else if (rt != 0) {
d4ea6acd
LA
15293 TCGv t0 = tcg_temp_new();
15294 gen_load_gpr(t0, rs);
15295 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
d4ea6acd 15296 }
d4ea6acd 15297#else
3a4ef3b7 15298 gen_reserved_instruction(ctx);
d4ea6acd
LA
15299 MIPS_INVAL("major opcode");
15300#endif
15301 } else {
15302 /* OPC_JALX */
15303 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
15304 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 15305 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 15306 }
364d4831 15307 break;
aaaa82a9
PMD
15308 case OPC_MDMX:
15309 /* MDMX: Not implemented. */
d4ea6acd
LA
15310 break;
15311 case OPC_PCREL:
2e211e0a 15312 check_insn(ctx, ISA_MIPS_R6);
eeb3bba8 15313 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 15314 break;
6af0bf9c 15315 default: /* Invalid */
923617a3 15316 MIPS_INVAL("major opcode");
311edee7 15317 return false;
6af0bf9c 15318 }
311edee7
PMD
15319 return true;
15320}
15321
15322static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
15323{
15324 /* make sure instructions are on a word boundary */
15325 if (ctx->base.pc_next & 0x3) {
15326 env->CP0_BadVAddr = ctx->base.pc_next;
15327 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
15328 return;
15329 }
15330
15331 /* Handle blikely not taken case */
15332 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
15333 TCGLabel *l1 = gen_new_label();
15334
15335 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
15336 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
15337 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
15338 gen_set_label(l1);
15339 }
15340
96e5b4c7
PMD
15341 /* Transition to the auto-generated decoder. */
15342
4919f69c
PMD
15343 /* Vendor specific extensions */
15344 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
15345 return;
15346 }
9d005392
PMD
15347 if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
15348 return;
15349 }
72d680e4 15350#if defined(TARGET_MIPS64)
03afdc28
JY
15351 if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
15352 return;
15353 }
72d680e4
PD
15354 if (cpu_supports_isa(env, INSN_OCTEON) && decode_ext_octeon(ctx, ctx->opcode)) {
15355 return;
15356 }
15357#endif
4919f69c 15358
96e5b4c7
PMD
15359 /* ISA extensions */
15360 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
15361 return;
15362 }
15363
3f7a9278
PMD
15364 /* ISA (from latest to oldest) */
15365 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
15366 return;
15367 }
15368
311edee7
PMD
15369 if (decode_opc_legacy(env, ctx)) {
15370 return;
15371 }
15372
15373 gen_reserved_instruction(ctx);
6af0bf9c
FB
15374}
15375
18f440ed 15376static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 15377{
18f440ed 15378 DisasContext *ctx = container_of(dcbase, DisasContext, base);
b77af26e 15379 CPUMIPSState *env = cpu_env(cs);
12be9258 15380
18f440ed 15381 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
15382 ctx->saved_pc = -1;
15383 ctx->insn_flags = env->insn_flags;
0cfd392d 15384 ctx->CP0_Config0 = env->CP0_Config0;
12be9258 15385 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 15386 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
15387 ctx->CP0_Config3 = env->CP0_Config3;
15388 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
15389 ctx->btarget = 0;
15390 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
15391 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
15392 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
15393 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
15394 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
15395 ctx->PAMask = env->PAMask;
15396 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
15397 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
15398 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
15399 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
15400 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 15401 /* Restore delay slot state from the tb context. */
12be9258
EC
15402 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
15403 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
15404 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 15405 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
15406 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
15407 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
15408 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
15409 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
feafe82c 15410 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
99029be1 15411 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
12be9258 15412 restore_cpu_state(env, ctx);
932e71cd 15413#ifdef CONFIG_USER_ONLY
12be9258 15414 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 15415#else
12be9258 15416 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 15417#endif
db759698
DM
15418 ctx->default_tcg_memop_mask = (!(ctx->insn_flags & ISA_NANOMIPS32) &&
15419 (ctx->insn_flags & (ISA_MIPS_R6 |
15420 INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN;
190ce7fb 15421
ef00cd4a
RH
15422 /*
15423 * Execute a branch and its delay slot as a single instruction.
15424 * This is what GDB expects and is consistent with what the
15425 * hardware does (e.g. if a delay slot instruction faults, the
15426 * reported PC is the PC of the branch).
15427 */
15428 if (ctx->base.singlestep_enabled && (ctx->hflags & MIPS_HFLAG_BMASK)) {
15429 ctx->base.max_insns = 2;
15430 }
15431
18f440ed
EC
15432 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
15433 ctx->hflags);
15434}
12be9258 15435
18f440ed
EC
15436static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
15437{
15438}
b933066a 15439
18f440ed
EC
15440static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
15441{
15442 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 15443
18f440ed
EC
15444 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
15445 ctx->btarget);
15446}
31837be3 15447
18f440ed
EC
15448static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
15449{
b77af26e 15450 CPUMIPSState *env = cpu_env(cs);
18f440ed
EC
15451 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15452 int insn_bytes;
15453 int is_slot;
4ad40f36 15454
18f440ed 15455 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4 15456 if (ctx->insn_flags & ISA_NANOMIPS32) {
4e116893 15457 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
3f178b8d 15458 insn_bytes = decode_isa_nanomips(env, ctx);
c533c0f4 15459 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
4e116893 15460 ctx->opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next);
18f440ed
EC
15461 insn_bytes = 4;
15462 decode_opc(env, ctx);
15463 } else if (ctx->insn_flags & ASE_MICROMIPS) {
4e116893 15464 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
bf52c45a 15465 insn_bytes = decode_isa_micromips(env, ctx);
18f440ed 15466 } else if (ctx->insn_flags & ASE_MIPS16) {
4e116893 15467 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
3230bad9 15468 insn_bytes = decode_ase_mips16e(env, ctx);
18f440ed 15469 } else {
3a4ef3b7 15470 gen_reserved_instruction(ctx);
18f440ed
EC
15471 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
15472 return;
15473 }
faf7aaa9 15474
18f440ed
EC
15475 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15476 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
15477 MIPS_HFLAG_FBNSLOT))) {
7480515f
AM
15478 /*
15479 * Force to generate branch as there is neither delay nor
15480 * forbidden slot.
15481 */
18f440ed
EC
15482 is_slot = 1;
15483 }
15484 if ((ctx->hflags & MIPS_HFLAG_M16) &&
15485 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
7480515f
AM
15486 /*
15487 * Force to generate branch as microMIPS R6 doesn't restrict
15488 * branches in the forbidden slot.
15489 */
18f440ed 15490 is_slot = 1;
eeb3bba8 15491 }
18f440ed
EC
15492 }
15493 if (is_slot) {
15494 gen_branch(ctx, insn_bytes);
15495 }
d44971e7
RH
15496 if (ctx->base.is_jmp == DISAS_SEMIHOST) {
15497 generate_exception_err(ctx, EXCP_SEMIHOST, insn_bytes);
15498 }
18f440ed 15499 ctx->base.pc_next += insn_bytes;
1b530a6d 15500
18f440ed
EC
15501 if (ctx->base.is_jmp != DISAS_NEXT) {
15502 return;
6af0bf9c 15503 }
ef00cd4a 15504
7480515f 15505 /*
ef00cd4a
RH
15506 * End the TB on (most) page crossings.
15507 * See mips_tr_init_disas_context about single-stepping a branch
15508 * together with its delay slot.
7480515f 15509 */
ef00cd4a
RH
15510 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE
15511 && !ctx->base.singlestep_enabled) {
18f440ed 15512 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 15513 }
18f440ed
EC
15514}
15515
15516static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
15517{
15518 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15519
1a79c413
RH
15520 switch (ctx->base.is_jmp) {
15521 case DISAS_STOP:
15522 gen_save_pc(ctx->base.pc_next);
15523 tcg_gen_lookup_and_goto_ptr();
15524 break;
15525 case DISAS_NEXT:
15526 case DISAS_TOO_MANY:
15527 save_cpu_state(ctx, 0);
15528 gen_goto_tb(ctx, 0, ctx->base.pc_next);
15529 break;
15530 case DISAS_EXIT:
15531 tcg_gen_exit_tb(NULL, 0);
15532 break;
15533 case DISAS_NORETURN:
15534 break;
15535 default:
15536 g_assert_not_reached();
6af0bf9c 15537 }
18f440ed
EC
15538}
15539
8eb806a7
RH
15540static void mips_tr_disas_log(const DisasContextBase *dcbase,
15541 CPUState *cs, FILE *logfile)
18f440ed 15542{
8eb806a7
RH
15543 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
15544 target_disas(logfile, cs, dcbase->pc_first, dcbase->tb->size);
18f440ed
EC
15545}
15546
15547static const TranslatorOps mips_tr_ops = {
15548 .init_disas_context = mips_tr_init_disas_context,
15549 .tb_start = mips_tr_tb_start,
15550 .insn_start = mips_tr_insn_start,
18f440ed
EC
15551 .translate_insn = mips_tr_translate_insn,
15552 .tb_stop = mips_tr_tb_stop,
15553 .disas_log = mips_tr_disas_log,
15554};
15555
597f9b2d 15556void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
32f0c394 15557 vaddr pc, void *host_pc)
18f440ed
EC
15558{
15559 DisasContext ctx;
15560
306c8721 15561 translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base);
6af0bf9c
FB
15562}
15563
959c5da2
PMD
15564void mips_tcg_init(void)
15565{
959c5da2 15566 cpu_gpr[0] = NULL;
92e0ef7d 15567 for (unsigned i = 1; i < 32; i++)
ad75a51e 15568 cpu_gpr[i] = tcg_global_mem_new(tcg_env,
959c5da2
PMD
15569 offsetof(CPUMIPSState,
15570 active_tc.gpr[i]),
15571 regnames[i]);
cefd68f6
PMD
15572#if defined(TARGET_MIPS64)
15573 cpu_gpr_hi[0] = NULL;
15574
15575 for (unsigned i = 1; i < 32; i++) {
b5b63d43
PMD
15576 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
15577
ad75a51e 15578 cpu_gpr_hi[i] = tcg_global_mem_new_i64(tcg_env,
cefd68f6
PMD
15579 offsetof(CPUMIPSState,
15580 active_tc.gpr_hi[i]),
b5b63d43 15581 rname);
cefd68f6
PMD
15582 }
15583#endif /* !TARGET_MIPS64 */
92e0ef7d 15584 for (unsigned i = 0; i < 32; i++) {
959c5da2 15585 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
863f264d 15586
ad75a51e 15587 fpu_f64[i] = tcg_global_mem_new_i64(tcg_env, off, fregnames[i]);
959c5da2
PMD
15588 }
15589 msa_translate_init();
ad75a51e 15590 cpu_PC = tcg_global_mem_new(tcg_env,
7db13fae 15591 offsetof(CPUMIPSState, active_tc.PC), "PC");
92e0ef7d 15592 for (unsigned i = 0; i < MIPS_DSP_ACC; i++) {
ad75a51e 15593 cpu_HI[i] = tcg_global_mem_new(tcg_env,
7db13fae 15594 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 15595 regnames_HI[i]);
ad75a51e 15596 cpu_LO[i] = tcg_global_mem_new(tcg_env,
7db13fae 15597 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 15598 regnames_LO[i]);
4b2eb8d2 15599 }
ad75a51e 15600 cpu_dspctrl = tcg_global_mem_new(tcg_env,
71375b59
AM
15601 offsetof(CPUMIPSState,
15602 active_tc.DSPControl),
4b2eb8d2 15603 "DSPControl");
ad75a51e 15604 bcond = tcg_global_mem_new(tcg_env,
7db13fae 15605 offsetof(CPUMIPSState, bcond), "bcond");
ad75a51e 15606 btarget = tcg_global_mem_new(tcg_env,
7db13fae 15607 offsetof(CPUMIPSState, btarget), "btarget");
ad75a51e 15608 hflags = tcg_global_mem_new_i32(tcg_env,
7db13fae 15609 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 15610
ad75a51e 15611 fpu_fcr0 = tcg_global_mem_new_i32(tcg_env,
7db13fae 15612 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 15613 "fcr0");
ad75a51e 15614 fpu_fcr31 = tcg_global_mem_new_i32(tcg_env,
7db13fae 15615 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 15616 "fcr31");
ad75a51e 15617 cpu_lladdr = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, lladdr),
33a07fa2 15618 "lladdr");
ad75a51e 15619 cpu_llval = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, llval),
33a07fa2 15620 "llval");
a168a796 15621
fe35ea94
PMD
15622 if (TARGET_LONG_BITS == 32) {
15623 mxu_translate_init();
eb5559f6 15624 }
39454628
TS
15625}
15626
3766855c
RH
15627void mips_restore_state_to_opc(CPUState *cs,
15628 const TranslationBlock *tb,
15629 const uint64_t *data)
d2856f1a 15630{
3766855c
RH
15631 MIPSCPU *cpu = MIPS_CPU(cs);
15632 CPUMIPSState *env = &cpu->env;
15633
bad729e2 15634 env->active_tc.PC = data[0];
d2856f1a 15635 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 15636 env->hflags |= data[1];
4636401d
AJ
15637 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
15638 case MIPS_HFLAG_BR:
15639 break;
15640 case MIPS_HFLAG_BC:
15641 case MIPS_HFLAG_BL:
15642 case MIPS_HFLAG_B:
bad729e2 15643 env->btarget = data[2];
4636401d
AJ
15644 break;
15645 }
d2856f1a 15646}